// (C) 2001-2015 Altera Corporation. All rights reserved. // Your use of Altera Corporation's design tools, logic functions and other // software and tools, and its AMPP partner logic functions, and any output // files any of the foregoing (including device programming or simulation // files), and any associated documentation or information are expressly subject // to the terms and conditions of the Altera Program License Subscription // Agreement, Altera MegaCore Function License Agreement, or other applicable // license agreement, including, without limitation, that your use is for the // sole purpose of programming logic devices manufactured by Altera and sold by // Altera or its authorized distributors. Please refer to the applicable // agreement for further details. // $Id: //acds/rel/15.1/ip/merlin/altera_merlin_burst_adapter/new_source/altera_merlin_burst_adapter_new.sv#1 $ // $Revision: #1 $ // $Date: 2015/08/09 $ // $Author: swbranch $ `timescale 1 ns / 1 ns // ------------------------------------------------------------------- // Merlin Burst Adapter: converts incoming burst packets to fit slave burst // capabilities. // ------------------------------------------------------------------- module altera_merlin_burst_adapter_new #( parameter // Standard merlin packet parameters that indicate // field position within the packet PKT_BEGIN_BURST = 81, PKT_ADDR_H = 79, PKT_ADDR_L = 48, PKT_BYTE_CNT_H = 5, PKT_BYTE_CNT_L = 0, PKT_BURSTWRAP_H = 11, PKT_BURSTWRAP_L = 6, PKT_TRANS_COMPRESSED_READ = 14, PKT_TRANS_WRITE = 13, PKT_TRANS_READ = 12, PKT_BYTEEN_H = 83, PKT_BYTEEN_L = 80, PKT_BURST_TYPE_H = 88, PKT_BURST_TYPE_L = 87, PKT_BURST_SIZE_H = 86, PKT_BURST_SIZE_L = 84, ST_DATA_W = 89, ST_CHANNEL_W = 8, // The values here are used to infer the slave's maximum // burst count and constant wrapping boundary (if it exists) OUT_BYTE_CNT_H = 5, OUT_BURSTWRAP_H = 11, // Indicates if incoming packets can have sizes less // than the data width IN_NARROW_SIZE = 0, // Indicates if the endpoint slave can accept packets // with sizes less than the data width OUT_NARROW_SIZE = 0, // Indicates if the endpoint slave can accept fixed bursts OUT_FIXED = 0, // Indicates if the endpoint slave can accept wrap bursts OUT_COMPLETE_WRAP = 0, // Enables byteenable synthesis, used to convert size to // byteenables BYTEENABLE_SYNTHESIS = 0, // A mask that indicates which bits of the burstwrap field are // constant. Used for optimization purposes. BURSTWRAP_CONST_MASK = 0, // Indicates the value of burstwrap bits that are constant when // used with BURSTWRAP_CONST_MASK BURSTWRAP_CONST_VALUE = -1, // Controls wrapping support. For optimization purposes. NO_WRAP_SUPPORT = 0, INCOMPLETE_WRAP_SUPPORT = 1, // Pipelining options PIPE_INPUTS = 0, PIPE_INTERNAL = 0 ) ( input clk, input reset, // ------------------- // Command Sink (Input) // ------------------- input sink0_valid, input [ST_DATA_W - 1 : 0] sink0_data, input [ST_CHANNEL_W - 1 : 0] sink0_channel, input sink0_startofpacket, input sink0_endofpacket, output reg sink0_ready, // ------------------- // Command Source (Output) // ------------------- output reg source0_valid, output reg [ST_DATA_W - 1 : 0] source0_data, output reg [ST_CHANNEL_W - 1 : 0] source0_channel, output reg source0_startofpacket, output reg source0_endofpacket, input source0_ready ); // Widths of various fields in the packet localparam PKT_BYTE_CNT_W = PKT_BYTE_CNT_H - PKT_BYTE_CNT_L + 1, PKT_ADDR_W = PKT_ADDR_H - PKT_ADDR_L + 1, PKT_BYTEEN_W = PKT_BYTEEN_H - PKT_BYTEEN_L + 1, OUT_BYTE_CNT_W = OUT_BYTE_CNT_H - PKT_BYTE_CNT_L + 1, OUT_BURSTWRAP_W = OUT_BURSTWRAP_H - PKT_BURSTWRAP_L + 1, PKT_BURSTWRAP_W = PKT_BURSTWRAP_H - PKT_BURSTWRAP_L + 1, PKT_BURST_SIZE_W = PKT_BURST_SIZE_H - PKT_BURST_SIZE_L + 1, PKT_BURST_TYPE_W = PKT_BURST_TYPE_H - PKT_BURST_TYPE_L + 1; localparam NUM_SYMBOLS = PKT_BYTEEN_H - PKT_BYTEEN_L + 1, LOG2_NUM_SYMBOLS = log2ceil(NUM_SYMBOLS), ADDR_MASK_SEL = (NUM_SYMBOLS == 1) ? 1 : log2ceil(NUM_SYMBOLS); // We try to keep everything in terms of words (transfers) instead of // bytes in this implementation. Cognitive ease! localparam IN_LEN_W = PKT_BYTE_CNT_W - LOG2_NUM_SYMBOLS, MAX_IN_LEN = 1 << (IN_LEN_W - 1), OUT_LEN_W = OUT_BYTE_CNT_W - LOG2_NUM_SYMBOLS, MAX_OUT_LEN = 1 << (OUT_LEN_W - 1), BNDRY_WIDTH = PKT_BURSTWRAP_W, OUT_BOUNDARY = MAX_OUT_LEN * NUM_SYMBOLS, BYTE_TO_WORD_SHIFT = log2ceil(NUM_SYMBOLS), BYTE_TO_WORD_SHIFT_W = log2ceil(BYTE_TO_WORD_SHIFT) + 1; // Determines the protocol from the features that are enabled or disabled. // Should be moved to the code that parameterizes this adapter. localparam AXI_SLAVE = OUT_FIXED & OUT_NARROW_SIZE & OUT_COMPLETE_WRAP, IS_WRAP_AVALON_SLAVE = !AXI_SLAVE & (PKT_BURSTWRAP_H != OUT_BURSTWRAP_H), IS_INCR_SLAVE = !AXI_SLAVE & !IS_WRAP_AVALON_SLAVE, NON_BURSTING_SLAVE = (MAX_OUT_LEN == 1), // This parameter indicates that the system is purely INCR avalon master/slave INCR_AVALON_SYS = IS_INCR_SLAVE && (PKT_BURSTWRAP_W == 1) && (OUT_BURSTWRAP_W == 1) && (IN_NARROW_SIZE == 0); // --------------------------------------------------- // State definitions // --------------------------------------------------- typedef enum bit [1:0] { // The idle state. ST_IDLE = 2'b00, // Adapter enters this state when the converters accept a compressed // transaction (read). Address and burst length is calculated // for every output transfer. ST_COMP_TRANS = 2'b01, // Adapter enters this state when the converters accept uncompressed // transactions (writes, generally). Address is passed through and // burst length is decremented according to the conventions of the // packet format. ST_UNCOMP_TRANS = 2'b10 } t_state; t_state state, next_state; // --------------------------------------------------- // Merlin packet burst type encoding // --------------------------------------------------- typedef enum bit[1:0] { FIXED = 2'b00, INCR = 2'b01, WRAP = 2'b10, REP_WRAP = 2'b11 } BurstType; // --------------------------------------------------- // Here we go! // // An optional input pipeline stage. We typically do not use this // because the interconnect allows users to add pipelines just // before the burst adapter inputs. // // Signal prefix entering this stage: sink0_* // Signal prefix exiting this stage: sink0_pipe_* // --------------------------------------------------- wire sink0_pipe_valid; wire [ST_DATA_W - 1 : 0] sink0_pipe_data; wire [ST_CHANNEL_W - 1 : 0] sink0_pipe_channel; wire sink0_pipe_sop; wire sink0_pipe_eop; wire sink0_pipe_ready; generate if (PIPE_INPUTS == 1) begin : input_pipeline altera_avalon_st_pipeline_stage #( .SYMBOLS_PER_BEAT (1), .BITS_PER_SYMBOL (ST_DATA_W), .USE_PACKETS (1), .USE_EMPTY (0), .EMPTY_WIDTH (0), .CHANNEL_WIDTH (ST_CHANNEL_W), .PACKET_WIDTH (2), .ERROR_WIDTH (0), .PIPELINE_READY (1) ) input_pipe ( .clk (clk), .reset (reset), .in_ready (sink0_ready), .in_valid (sink0_valid), .in_startofpacket (sink0_startofpacket), .in_endofpacket (sink0_endofpacket), .in_data (sink0_data), .in_channel (sink0_channel), .out_ready (sink0_pipe_ready), .out_valid (sink0_pipe_valid), .out_startofpacket (sink0_pipe_sop), .out_endofpacket (sink0_pipe_eop), .out_data (sink0_pipe_data), .out_channel (sink0_pipe_channel), .in_empty (1'b0), .in_error (1'b0), .out_empty (), .out_error () ); end else begin : no_input_pipeline assign sink0_pipe_valid = sink0_valid; assign sink0_pipe_data = sink0_data; assign sink0_pipe_channel = sink0_channel; assign sink0_pipe_sop = sink0_startofpacket; assign sink0_pipe_eop = sink0_endofpacket; assign sink0_ready = sink0_pipe_ready; end endgenerate // -------------------------------------------------- // Signal extraction stage. We extract signals from // the packet payload and compute some values. // // Signal prefix entering this stage: sink0_pipe_* // Signal prefix exiting this stage: in_* // -------------------------------------------------- wire [PKT_BURST_TYPE_W - 1 : 0] in_bursttype = sink0_pipe_data[PKT_BURST_TYPE_H : PKT_BURST_TYPE_L]; wire [PKT_BYTE_CNT_W - 1 : 0] in_bytecount = sink0_pipe_data[PKT_BYTE_CNT_H : PKT_BYTE_CNT_L]; wire [PKT_ADDR_W - 1 : 0] in_addr = sink0_pipe_data[PKT_ADDR_H : PKT_ADDR_L]; wire [63 : 0] log2_numsymbols = log2ceil(NUM_SYMBOLS); wire [PKT_BYTE_CNT_W - 1 : 0] in_burstcount = in_bytecount >> log2_numsymbols[PKT_BYTE_CNT_W - 1 : 0]; wire [IN_LEN_W - 1 : 0] in_len = in_burstcount[IN_LEN_W - 1 : 0]; wire [PKT_BURST_SIZE_W - 1 : 0] in_size = sink0_pipe_data[PKT_BURST_SIZE_H : PKT_BURST_SIZE_L]; wire in_write = sink0_pipe_data[PKT_TRANS_WRITE]; wire in_compressed_read = sink0_pipe_data[PKT_TRANS_COMPRESSED_READ]; wire in_read = sink0_pipe_data[PKT_TRANS_READ]; wire in_uncompressed_read = in_read & ~sink0_pipe_data[PKT_TRANS_COMPRESSED_READ]; wire in_sop = sink0_pipe_sop; wire in_eop = sink0_pipe_eop; wire [PKT_BYTEEN_W - 1 : 0] in_byteen = sink0_pipe_data[PKT_BYTEEN_H : PKT_BYTEEN_L]; wire in_passthru = in_burstcount <= 16; wire in_valid; reg in_ready_hold; wire in_narrow; wire [PKT_BURSTWRAP_W - 1 : 0] in_burstwrap; wire [PKT_ADDR_W - 1 : 0] in_aligned_addr; wire [PKT_BURSTWRAP_W - 1 : 0] in_boundary; // Used to keep ready low during reset always_ff @(posedge clk or posedge reset) begin if (reset) begin in_ready_hold <= '0; end else begin in_ready_hold <= '1; end end assign in_valid = sink0_pipe_valid & in_ready_hold; assign in_narrow = in_size < log2_numsymbols[PKT_BYTE_CNT_W - 1 : 0]; // Optimization: extract burstwrap, and drive the constant bits to // their constant values to help the synthesis tool. genvar i; generate for (i = 0; i < PKT_BURSTWRAP_W; i = i+1) begin: assign_burstwrap_bit if (BURSTWRAP_CONST_MASK[i]) begin assign in_burstwrap[i] = BURSTWRAP_CONST_VALUE[i]; end else begin assign in_burstwrap[i] = sink0_pipe_data[PKT_BURSTWRAP_L + i]; end end endgenerate // Addresses in the packet can be unaligned. Here we align the address // for ease of internal calculations. The initial output address may // still be unaligned to preserve the original transaction intention. wire [PKT_ADDR_W + LOG2_NUM_SYMBOLS - 1 : 0] out_mask_and_aligned_addr; altera_merlin_address_alignment #( .ADDR_W (PKT_ADDR_W), .BURSTWRAP_W (1), // unused because we just want to align address .TYPE_W (0), // unused because we just want to align address .SIZE_W (PKT_BURST_SIZE_W), .INCREMENT_ADDRESS (0), .NUMSYMBOLS (NUM_SYMBOLS) ) align_address_to_size ( // Not used when INCREMENT_ADDRESS = 0 .clk (1'b0), .reset (1'b0), .in_valid (1'b0), .in_sop (1'b0), .in_eop (1'b0), .out_ready (), .in_data ({ in_addr, in_size }), .out_data (out_mask_and_aligned_addr) ); assign in_aligned_addr = out_mask_and_aligned_addr[PKT_ADDR_W - 1 : 0]; // Incrementing the burstwrap provides the wrapping boundary for // wrapping transactions. altera_merlin_burst_adapter_burstwrap_increment #( .WIDTH (PKT_BURSTWRAP_W) ) the_burstwrap_increment ( .mask (in_burstwrap), .inc (in_boundary) ); localparam OUT_BNDRY_ADDR_SEL_W = log2ceil(OUT_BOUNDARY); localparam OUT_BOUNDARY_WIDTH = OUT_BNDRY_ADDR_SEL_W + 1; // address to use for distance calculations when the transaction // boundary is less than the slave's wrapping boundary. wire [PKT_ADDR_W - 1 : 0] in_bndry_addr_sel; // the length (in words) to the transaction boundary (if it exists) wire [IN_LEN_W - 1 : 0] len_to_in_bndry; // the length (in words) to the slave's boundary (if it exists) wire [OUT_BOUNDARY_WIDTH - 1 : 0] len_to_out_bndry; reg [IN_LEN_W - 1 : 0] first_len; wire [BYTE_TO_WORD_SHIFT_W - 1 : 0] byte_to_word_shift; assign byte_to_word_shift = BYTE_TO_WORD_SHIFT[BYTE_TO_WORD_SHIFT_W - 1 : 0]; // This part calculates the length that is required to align the burst to // the transaction's wrapping boundary (if it exists), or to the slave's // wrapping boundary (if it exists). We pre-compute this ahead of the // converters to minimize the logic loops in determining the output // burst lengths. Note that incoming addresses for wrapping transactions // are always aligned to size by definition. assign in_bndry_addr_sel = in_addr & in_burstwrap; assign len_to_in_bndry = (in_boundary - in_bndry_addr_sel) >> byte_to_word_shift; generate if (OUT_BNDRY_ADDR_SEL_W > 0) begin : len_to_out_bndry_calc wire [OUT_BNDRY_ADDR_SEL_W - 1 : 0] out_bndry_addr_sel; // We have to use the aligned address, because this part may // handle incoming incrementing bursts which can be unaligned. assign out_bndry_addr_sel = in_aligned_addr[OUT_BNDRY_ADDR_SEL_W - 1 : 0]; assign len_to_out_bndry = (OUT_BOUNDARY - out_bndry_addr_sel) >> byte_to_word_shift; end // A nonsensical corner-case of a wrapping slave with // MAX_OUT_LEN = 1, NUM_SYMBOLS = 1 else begin : len_to_out_bndry_calc_corner assign len_to_out_bndry = OUT_BOUNDARY >> byte_to_word_shift; end endgenerate // -------------------------------------------------- // Optional internal pipeline stage. // // Note that we still buffer the transfer if the pipeline stage is // unused, because the adapter must accept read transactions before // converting them. Failure to do this will lead to masters receiving // responses before their commands have been accepted in unpipelined // systems. The buffering registers are named in_*_reg. // // Notes on signal naming convention used: // // in_* --> These signals are coming directly from the previous stage. // --> Timing - zero cycle delta // d0_in_* --> Signals that are outputs of this stage. // --> Timing - zero cycle delta (IF PIPE_INTERNAL == 0) else 1 clock // d1_in_* --> Signals that are outputs of this stage. // --> Timing - always delayed by 1 clock. (vs the input) // -------------------------------------------------- reg in_sop_reg; reg in_eop_reg; reg in_valid_reg; reg in_compressed_read_reg; reg in_uncompressed_read_reg; reg in_write_reg; reg in_passthru_reg; reg [PKT_BURST_SIZE_W - 1 : 0] in_size_reg; reg [ST_DATA_W - 1 : 0] in_data_reg; reg [ST_CHANNEL_W - 1 : 0] in_channel_reg; reg [PKT_BURST_TYPE_W - 1 : 0] in_bursttype_reg; reg [PKT_BURSTWRAP_W - 1 : 0] in_burstwrap_reg; reg [PKT_BYTEEN_W - 1 : 0] in_byteen_reg; reg [PKT_ADDR_W - 1 : 0] in_addr_reg; reg [PKT_ADDR_W - 1 : 0] in_aligned_addr_reg; reg [IN_LEN_W - 1 : 0] in_len_reg; reg in_narrow_reg; reg [PKT_ADDR_W - 1 : 0] d0_in_addr; reg [PKT_ADDR_W - 1 : 0] d0_in_aligned_addr; reg d0_in_sop; reg d0_in_compressed_read; reg d0_in_uncompressed_read; reg d0_in_write; reg [PKT_BURST_TYPE_W - 1 : 0] d0_in_bursttype; reg [PKT_BURSTWRAP_W - 1 : 0] d0_in_burstwrap; reg [PKT_BURSTWRAP_W - 1 : 0] d0_in_burstwrap_value; reg [PKT_BURST_SIZE_W - 1 : 0] d0_in_size; reg [PKT_BURST_SIZE_W - 1 : 0] d0_in_size_value; reg [IN_LEN_W - 1 : 0] d0_in_len; reg d0_in_valid; reg d1_in_narrow; reg [PKT_ADDR_W - 1 : 0] d1_in_aligned_addr; reg d1_in_eop; reg d1_in_compressed_read; reg d1_in_uncompressed_read; reg [ST_DATA_W - 1 : 0] d1_in_data; reg [ST_CHANNEL_W - 1 : 0] d1_in_channel; reg d1_in_write; reg [PKT_BURST_TYPE_W - 1 : 0] d1_in_bursttype; reg [PKT_BURSTWRAP_W - 1 : 0] d1_in_burstwrap; reg d1_in_passthru; reg [PKT_BURST_SIZE_W - 1 : 0] d1_in_size; reg [PKT_BYTEEN_W - 1 : 0] d1_in_byteen; reg nb; generate if (PIPE_INTERNAL == 0) begin : no_internal_pipeline always_ff @(posedge clk or posedge reset) begin if (reset) begin in_eop_reg <= '0; in_compressed_read_reg <= '0; in_uncompressed_read_reg <= '0; in_data_reg <= '0; in_channel_reg <= '0; in_write_reg <= '0; in_bursttype_reg <= '0; in_burstwrap_reg <= '0; in_passthru_reg <= '0; in_size_reg <= '0; in_byteen_reg <= '0; in_aligned_addr_reg <= '0; in_narrow_reg <= '0; end else begin if (sink0_pipe_valid & sink0_pipe_ready) begin in_eop_reg <= in_eop; in_data_reg <= sink0_pipe_data; in_channel_reg <= sink0_pipe_channel; in_compressed_read_reg <= in_compressed_read; in_uncompressed_read_reg <= in_uncompressed_read; in_write_reg <= in_write; in_bursttype_reg <= in_bursttype; in_burstwrap_reg <= in_burstwrap; in_size_reg <= in_size; in_byteen_reg <= in_byteen; in_aligned_addr_reg <= in_aligned_addr; in_narrow_reg <= in_narrow; end // length changes during packets, so sample // length-dependent signals at the start if (sink0_pipe_valid & sink0_pipe_ready & in_sop) begin in_passthru_reg <= in_passthru; end end // else: !if(reset) end // always_ff @ always_comb begin d0_in_sop = in_sop; d0_in_compressed_read = in_compressed_read; d0_in_uncompressed_read = in_uncompressed_read; d0_in_write = in_write; d0_in_burstwrap = in_burstwrap; d0_in_size = in_size; d0_in_addr = in_addr; d0_in_aligned_addr = in_aligned_addr; d0_in_len = in_len; d0_in_valid = in_valid; d1_in_eop = in_eop_reg; d1_in_compressed_read = in_compressed_read_reg; d1_in_uncompressed_read = in_uncompressed_read_reg; d1_in_write = in_write_reg; d1_in_burstwrap = in_burstwrap_reg; d1_in_size = in_size_reg; d1_in_aligned_addr = in_aligned_addr_reg; d1_in_data = in_data_reg; d1_in_channel = in_channel_reg; d1_in_bursttype = in_bursttype_reg; d1_in_passthru = in_passthru_reg; d1_in_byteen = in_byteen_reg; d1_in_narrow = in_narrow_reg; // Assign after the related d1_in_* signals have been assigned. d0_in_size_value = nb ? d0_in_size : d1_in_size; d0_in_burstwrap_value = nb ? d0_in_burstwrap : d1_in_burstwrap; end end // block: no_internal_pipeline else begin : internal_pipeline reg [PKT_BURST_SIZE_W - 1 : 0] d0_in_size_dl; reg [PKT_BURSTWRAP_W - 1 : 0] d0_in_burstwrap_dl; always_ff @(posedge clk or posedge reset) begin if (reset) begin in_eop_reg <= '0; in_sop_reg <= '0; in_compressed_read_reg <= '0; in_uncompressed_read_reg <= '0; in_data_reg <= '0; in_channel_reg <= '0; in_write_reg <= '0; in_bursttype_reg <= '0; in_burstwrap_reg <= '0; in_passthru_reg <= '0; in_size_reg <= '0; in_byteen_reg <= '0; in_addr_reg <= '0; in_aligned_addr_reg <= '0; in_len_reg <= '0; in_narrow_reg <= '0; in_valid_reg <= '0; d1_in_eop <= '0; d1_in_compressed_read <= '0; d1_in_data <= '0; d1_in_channel <= '0; d1_in_write <= '0; d1_in_bursttype <= '0; d1_in_burstwrap <= '0; d1_in_passthru <= '0; d1_in_size <= '0; d0_in_size_dl <= '0; d0_in_burstwrap_dl <= '0; d1_in_byteen <= '0; end else begin if (sink0_pipe_valid & sink0_pipe_ready) begin in_eop_reg <= in_eop; in_sop_reg <= in_sop; in_data_reg <= sink0_pipe_data; in_channel_reg <= sink0_pipe_channel; in_compressed_read_reg <= in_compressed_read; in_uncompressed_read_reg <= in_uncompressed_read; in_write_reg <= in_write; in_bursttype_reg <= in_bursttype; in_burstwrap_reg <= in_burstwrap; in_size_reg <= in_size; in_byteen_reg <= in_byteen; in_addr_reg <= in_addr; in_aligned_addr_reg <= in_aligned_addr; in_len_reg <= in_len; in_narrow_reg <= in_narrow; end // length changes during packets, so sample // length-dependent signals at the start if (in_valid & sink0_pipe_ready & in_sop) in_passthru_reg <= in_passthru; if (sink0_pipe_ready) in_valid_reg <= in_valid; if (((state != ST_COMP_TRANS) & (~source0_valid | source0_ready)) | ( (state == ST_COMP_TRANS) & (~source0_valid | source0_ready & source0_endofpacket) )) begin d1_in_eop <= in_eop_reg; d1_in_compressed_read <= in_compressed_read_reg; d1_in_data <= in_data_reg; d1_in_channel <= in_channel_reg; d1_in_write <= in_write_reg; d1_in_bursttype <= in_bursttype_reg; d1_in_burstwrap <= in_burstwrap_reg; d0_in_burstwrap_dl <= in_burstwrap_reg; d1_in_passthru <= in_passthru_reg; d1_in_size <= in_size_reg; d0_in_size_dl <= in_size_reg; d1_in_byteen <= in_byteen_reg; d1_in_aligned_addr <= in_aligned_addr_reg; d1_in_narrow <= in_narrow_reg; d1_in_uncompressed_read <= in_uncompressed_read_reg; end // if (((state != ST_COMP_TRANS) & (~source0_valid | source0_ready)) |... end // else: !if(reset) end // always_ff @ always_comb begin d0_in_valid = in_valid_reg; d0_in_sop = in_sop_reg; d0_in_compressed_read = in_compressed_read_reg; d0_in_uncompressed_read = in_uncompressed_read_reg; d0_in_write = in_write_reg; d0_in_burstwrap = in_burstwrap_reg; d0_in_size = in_size_reg; d0_in_size_value = nb ? in_size_reg : d0_in_size_dl; d0_in_burstwrap_value = nb ? in_burstwrap_reg : d0_in_burstwrap_dl; d0_in_addr = in_addr_reg; d0_in_aligned_addr = in_aligned_addr_reg; d0_in_len = in_len_reg; end // always_comb end // block: internal_pipeline endgenerate // -------------------------------------------------- // Control logic stage: state machine // -------------------------------------------------- always_ff @(posedge clk or posedge reset) begin if (reset) begin state <= ST_IDLE; end else begin if (~source0_valid | source0_ready) begin state <= next_state; end end end always_comb begin : state_transition next_state = ST_IDLE; // default case (state) ST_IDLE : begin next_state = ST_IDLE; if (d0_in_valid) begin if (d0_in_write | d0_in_uncompressed_read) next_state = ST_UNCOMP_TRANS; if (d0_in_compressed_read) next_state = ST_COMP_TRANS; end end ST_UNCOMP_TRANS : begin next_state = ST_UNCOMP_TRANS; if (source0_endofpacket) begin if (!d0_in_valid) next_state = ST_IDLE; else begin if (d0_in_write | d0_in_uncompressed_read) next_state = ST_UNCOMP_TRANS; if (d0_in_compressed_read) next_state = ST_COMP_TRANS; end end end ST_COMP_TRANS : begin next_state = ST_COMP_TRANS; if (source0_endofpacket) begin if (!d0_in_valid) begin next_state = ST_IDLE; end else begin if (d0_in_write | d0_in_uncompressed_read) next_state = ST_UNCOMP_TRANS; if (d0_in_compressed_read) next_state = ST_COMP_TRANS; end end end endcase end // -------------------------------------------------- // Control logic stage: signals for the converters. These signals // enable the correct converter for a burst type, and act as a // select line when muxing the converter outputs. // // Each type of slave receives its own control logic stage, optimized // for that particular type. // -------------------------------------------------- wire [PKT_BYTE_CNT_W - 1 : 0] out_byte_cnt; wire [IN_LEN_W - 1 : 0] incr_out_len; wire [IN_LEN_W - 1 : 0] wrap_out_len; wire [IN_LEN_W - 1 : 0] incr_uncompr_out_len; wire [IN_LEN_W - 1 : 0] wrap_uncompr_out_len; wire [PKT_ADDR_W - 1 : 0] incr_out_addr; wire [PKT_ADDR_W - 1 : 0] wrap_out_addr; wire [PKT_ADDR_W - 1 : 0] fixed_out_addr; reg [PKT_ADDR_W - 1 : 0] uncompr_out_addr; wire [IN_LEN_W - 1 : 0] fixed_out_len; wire [PKT_ADDR_W - 1 : 0] out_addr; wire in_full_size_write_wrap; wire in_full_size_read_wrap; wire in_default_converter; wire in_full_size_incr; reg in_default_converter_reg; reg in_full_size_incr_reg; reg in_full_size_write_wrap_reg; reg in_full_size_read_wrap_reg; wire new_burst; wire fixed_new_burst; wire wrap_new_burst; wire incr_new_burst; wire next_out_sop; wire next_out_eop; wire is_passthru; wire enable_incr_converter; wire enable_fixed_converter; wire enable_write_wrap_converter; wire enable_read_wrap_converter; wire enable_incr_write_converter; wire enable_incr_read_converter; reg [IN_LEN_W - 1 : 0] d0_first_len; // ----------------------------------------------------------------------- // Enable the converters when: // - (sink0_pipe_valid && (source0_ready | ~source0_valid): // : when the BA is in idle (!source_valid) and there is a packet coming at input // or the outpacket has been accepted and there is a packet coming // - (source0_endofpacket ? 1'b0 :(state == ST_COMP_TRANS) && (!source0_valid | source0_ready)) // : For compressed read, need something consider at end_of_packet, only when seeing // end_of_packet then turn off converter. // Each converter will be turned on with its own enable based on different type of incoming burst // ----------------------------------------------------------------------- generate if (NON_BURSTING_SLAVE) begin : non_bursting_converter_control wire [PKT_BYTE_CNT_W - 1 : 0] fixed_out_byte_cnt; assign fixed_out_byte_cnt = fixed_out_len << log2_numsymbols; if (PIPE_INTERNAL == 0) begin : NO_PIPELINE_INPUT always_comb begin d0_in_bursttype = nb ? in_bursttype : in_bursttype_reg; end end else begin : PIPELINE_INPUT reg [PKT_BURST_TYPE_W - 1 :0] d0_in_bursttype_dl; always_ff @(posedge clk or posedge reset) begin if (reset) begin d0_in_bursttype_dl <= '0; end else begin if (((state != ST_COMP_TRANS) & (~source0_valid | source0_ready)) | ( (state == ST_COMP_TRANS) & (~source0_valid | source0_ready & source0_endofpacket) ) ) begin d0_in_bursttype_dl <= in_bursttype_reg; end end // else: !if(reset) end // always_ff @ always_comb begin d0_in_bursttype = nb ? in_bursttype_reg : d0_in_bursttype_dl; end end //nb: new burst signal assign nb = fixed_new_burst; // ----------------------------------------------------------------------- // I. Conveter enable signals: Turn on/off each conveter accordingly // ----------------------------------------------------------------------- assign enable_fixed_converter = (d0_in_valid && (source0_ready | !source0_valid) || (source0_endofpacket ? 1'b0 :(state == ST_COMP_TRANS) && (!source0_valid | source0_ready))); // ----------------------------------------------------------------------- // II. Packet signals // ----------------------------------------------------------------------- assign next_out_sop = ((state == ST_COMP_TRANS) & source0_ready & !(fixed_new_burst)) ? 1'b0 : d0_in_sop; assign next_out_eop = (state == ST_COMP_TRANS) ? fixed_new_burst : d1_in_eop; // ----------------------------------------------------------------------- // III. Output select // ----------------------------------------------------------------------- assign out_byte_cnt = fixed_out_byte_cnt; assign out_addr = fixed_out_addr; end else if (INCR_AVALON_SYS) begin : incr_avalon_converter_control wire [PKT_BYTE_CNT_W - 1 : 0] incr_out_byte_cnt; assign incr_out_byte_cnt = (d1_in_compressed_read ? incr_out_len : incr_uncompr_out_len) << log2_numsymbols; //nb: new burst signal assign nb = incr_new_burst; // ----------------------------------------------------------------------- // I. Conveter enable signals: Turn on/off each conveter accordingly // ----------------------------------------------------------------------- assign enable_incr_converter = (d0_in_valid && (source0_ready | !source0_valid) || (source0_endofpacket ? 1'b0 :(state == ST_COMP_TRANS) && (!source0_valid | source0_ready))); // ----------------------------------------------------------------------- // II. Packet signals // ----------------------------------------------------------------------- assign next_out_sop = ((state == ST_COMP_TRANS) & source0_ready & !(incr_new_burst)) ? 1'b0 : d0_in_sop; assign next_out_eop = (state == ST_COMP_TRANS) ? incr_new_burst : d1_in_eop; // ----------------------------------------------------------------------- // III. Output select // ----------------------------------------------------------------------- assign out_byte_cnt = incr_out_byte_cnt; assign out_addr = incr_out_addr; end else begin : other_converter_control if (IS_WRAP_AVALON_SLAVE) begin wire in_narrow_or_fixed; wire in_read_but_not_fixed_or_narrow; wire in_write_but_not_fixed_or_narrow; reg in_read_but_not_fixed_or_narrow_reg; reg in_write_but_not_fixed_or_narrow_reg; reg in_narrow_or_fixed_reg; reg d0_in_read_but_not_fixed_or_narrow; reg d0_in_write_but_not_fixed_or_narrow; reg d0_in_default_converter; reg d1_in_narrow_or_fixed; reg d1_in_read_but_not_fixed_or_narrow; reg d1_in_write_but_not_fixed_or_narrow; reg d1_in_default_converter; reg [IN_LEN_W - 1 : 0] first_len_reg; wire [PKT_BYTE_CNT_W - 1 : 0] fixed_out_byte_cnt; wire [PKT_BYTE_CNT_W - 1 : 0] incr_out_byte_cnt; wire in_fixed = (in_bursttype == 2'b00) || (in_bursttype == 2'b11); // nb: new burst assign nb = (d1_in_narrow_or_fixed ? fixed_new_burst : new_burst); assign in_read_but_not_fixed_or_narrow = in_compressed_read & !in_narrow_or_fixed; assign in_write_but_not_fixed_or_narrow = in_write & !in_narrow_or_fixed; assign in_narrow_or_fixed = in_narrow || in_fixed; assign in_default_converter = in_fixed || in_narrow || in_uncompressed_read; assign incr_out_byte_cnt = (d1_in_compressed_read ? incr_out_len : incr_uncompr_out_len) << log2_numsymbols; assign fixed_out_byte_cnt = fixed_out_len << log2_numsymbols; //---------------------------------------------------------------- // I. Pipeline input stage //---------------------------------------------------------------- if (PIPE_INTERNAL == 0) begin : NO_PIPELINE_INPUT always_ff @(posedge clk or posedge reset) begin if (reset) begin in_narrow_or_fixed_reg <= '0; in_read_but_not_fixed_or_narrow_reg <= '0; in_write_but_not_fixed_or_narrow_reg <= '0; in_default_converter_reg <= '0; end else begin if (sink0_pipe_ready & sink0_pipe_valid) begin in_narrow_or_fixed_reg <= in_narrow_or_fixed; in_read_but_not_fixed_or_narrow_reg <= in_read_but_not_fixed_or_narrow; in_write_but_not_fixed_or_narrow_reg <= in_write_but_not_fixed_or_narrow; in_default_converter_reg <= in_default_converter; end // if (sink0_pipe_ready & sink0_pipe_valid) end // else: !if(reset) end // always_ff @ always_comb begin d0_first_len = first_len; d0_in_read_but_not_fixed_or_narrow = in_read_but_not_fixed_or_narrow; d0_in_write_but_not_fixed_or_narrow = in_write_but_not_fixed_or_narrow; d0_in_default_converter = in_default_converter; d1_in_narrow_or_fixed = in_narrow_or_fixed_reg; d1_in_read_but_not_fixed_or_narrow = in_read_but_not_fixed_or_narrow_reg; d1_in_write_but_not_fixed_or_narrow = in_write_but_not_fixed_or_narrow_reg; d1_in_default_converter = in_default_converter_reg; end // always_comb end // block: NO_PIPELINE_INPUT else begin : PIPELINE_INPUT always_ff @(posedge clk or posedge reset) begin if (reset) begin in_narrow_or_fixed_reg <= '0; in_read_but_not_fixed_or_narrow_reg <= '0; in_write_but_not_fixed_or_narrow_reg <= '0; in_default_converter_reg <= '0; d1_in_narrow_or_fixed <= '0; d1_in_read_but_not_fixed_or_narrow <= '0; d1_in_write_but_not_fixed_or_narrow <= '0; d1_in_default_converter <= '0; first_len_reg <= '0; end else begin if (sink0_pipe_ready & sink0_pipe_valid) begin in_narrow_or_fixed_reg <= in_narrow_or_fixed; in_read_but_not_fixed_or_narrow_reg <= in_read_but_not_fixed_or_narrow; in_write_but_not_fixed_or_narrow_reg <= in_write_but_not_fixed_or_narrow; in_default_converter_reg <= in_default_converter; end // if (sink0_pipe_ready & sink0_pipe_valid) if (((state != ST_COMP_TRANS) & (~source0_valid | source0_ready)) | ( (state == ST_COMP_TRANS) & (~source0_valid | source0_ready & source0_endofpacket) ) ) begin first_len_reg <= first_len; d1_in_narrow_or_fixed <= in_narrow_or_fixed_reg; d1_in_read_but_not_fixed_or_narrow <= in_read_but_not_fixed_or_narrow_reg; d1_in_write_but_not_fixed_or_narrow <= in_write_but_not_fixed_or_narrow_reg; d1_in_default_converter <= in_default_converter_reg; end end // else: !if(reset) end // always_ff @ always_comb begin d0_in_default_converter = in_default_converter_reg; d0_first_len = first_len_reg; d0_in_read_but_not_fixed_or_narrow = in_read_but_not_fixed_or_narrow_reg; d0_in_write_but_not_fixed_or_narrow = in_write_but_not_fixed_or_narrow_reg; end end // block: PIPELINE_INPUT // ------------------------------------------------------------------------- // II. First length calculation // ------------------------------------------------------------------------- wire same_boundary; // ---------------------------------------------------------- // Slave is a wrapping slave, if in_burst wrap has same boundary // pass the burst untouched. // ---------------------------------------------------------- if (OUT_BNDRY_ADDR_SEL_W <= PKT_BURSTWRAP_W - 1) begin assign same_boundary = (in_boundary[OUT_BNDRY_ADDR_SEL_W] == 1); end else begin assign same_boundary = 0; end // -------------------------------------------------------------------------- // 1. If in_burst wrapping boundary is lager or INCR burst then always // send first sub_burst length is aligned to slave boudary, // 2. Else aligned to master boundary // Notes: // For INCR, it is tricky that the length can be any value but as the slave is // wrapping, still needs to convert the burst at slave boundary // (in_len <= len_to_out_bndry): can tell the in INCR burst can totally // fit in slave boundary -> pass thru // This works same way for INCOMPLETE wrap as well, so cannot make seperate // optimization when dont support INCOMPLETE wrap // -------------------------------------------------------------------------- wire in_len_smaller_not_cross_out_bndry; wire in_len_smaller_not_cross_in_bndry; assign in_len_smaller_not_cross_out_bndry = (in_len <= len_to_out_bndry); assign in_len_smaller_not_cross_in_bndry = (in_len <= len_to_in_bndry); always_comb begin if ((in_boundary > OUT_BOUNDARY) || (in_burstwrap[BNDRY_WIDTH - 1] == 1)) begin first_len = len_to_out_bndry; if (in_len_smaller_not_cross_out_bndry || same_boundary) first_len = in_len; end else begin first_len = len_to_in_bndry; if (in_len_smaller_not_cross_in_bndry || same_boundary) first_len = in_len; end end // always_comb // ----------------------------------------------------------------------- // III. Conveter enable signals: Turn on/off each conveter accordingly // ----------------------------------------------------------------------- // WRAPPING AVALON: two conveters: // 1. wrap_burst_conveter -> handle full_size INCR, WRAP // 2. default_burst_conveter -> handle narrow_size burst // opt, seperate enable for write and reach // ----------------------------------------------------------------------- // fixed_new_burst && new_burst : note this for incr_write as it is write_enable, cannot turn on incase a read happen before assign enable_incr_write_converter = (d0_in_valid && d0_in_write_but_not_fixed_or_narrow && fixed_new_burst && new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_write_but_not_fixed_or_narrow && !nb)); assign enable_incr_read_converter = (d0_in_valid && d0_in_read_but_not_fixed_or_narrow && fixed_new_burst && (source0_ready || !source0_valid) || (( state == ST_COMP_TRANS) && source0_ready && d1_in_read_but_not_fixed_or_narrow && !nb)); assign enable_fixed_converter = (d0_in_valid && d0_in_default_converter && new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_default_converter && !nb)); // ----------------------------------------------------------------------- // IV. Packet signals // ----------------------------------------------------------------------- assign next_out_sop = ((state == ST_COMP_TRANS) & source0_ready & !(d1_in_default_converter ? fixed_new_burst : new_burst)) ? 1'b0 : d0_in_sop; assign next_out_eop = (state == ST_COMP_TRANS) ? (d1_in_default_converter ? fixed_new_burst : new_burst) : d1_in_eop; // ----------------------------------------------------------------------- // V. Output select // ----------------------------------------------------------------------- assign out_byte_cnt = d1_in_default_converter ? fixed_out_byte_cnt : incr_out_byte_cnt; assign out_addr = d1_in_default_converter ? fixed_out_addr : incr_out_addr; end // if (IS_WRAP_AVALON_SLAVE) if (AXI_SLAVE) begin reg [IN_LEN_W - 1 : 0] first_len_reg; reg d0_in_incr; reg d1_in_incr; reg in_incr_reg; wire in_read_wrap_conveter; wire in_write_wrap_conveter; reg in_read_wrap_conveter_reg; reg in_write_wrap_conveter_reg; reg d0_in_read_wrap_conveter; reg d0_in_write_wrap_conveter; reg d0_in_default_converter; reg d1_in_read_wrap_conveter; reg d1_in_write_wrap_conveter; reg d1_in_default_converter; wire in_incr = (in_bursttype == 2'b01) && !in_uncompressed_read; wire in_wrap = (in_bursttype == 2'b10); wire in_fixed = (in_bursttype == 2'b00) || (in_bursttype == 2'b11); wire in_narrow_read_wrap_smaller_16 = in_narrow && in_wrap && is_passthru && in_compressed_read; wire in_narrow_write_wrap_smaller_16 = in_narrow && in_wrap && is_passthru && in_write; wire in_narrow_wrap_larger_16 = in_narrow && in_wrap && !is_passthru; wire [PKT_BYTE_CNT_W - 1 : 0] wrap_out_byte_cnt; wire [PKT_BYTE_CNT_W - 1 : 0] fixed_out_byte_cnt; wire [PKT_BYTE_CNT_W - 1 : 0] incr_out_byte_cnt; assign incr_out_byte_cnt = (d1_in_compressed_read ? incr_out_len : incr_uncompr_out_len) << log2_numsymbols; assign wrap_out_byte_cnt = (d1_in_compressed_read ? wrap_out_len : wrap_uncompr_out_len) << log2_numsymbols; assign fixed_out_byte_cnt = fixed_out_len << log2_numsymbols; assign in_full_size_read_wrap = in_compressed_read & in_wrap & !in_narrow; assign in_full_size_write_wrap = in_write & in_wrap & !in_narrow; assign in_read_wrap_conveter = in_full_size_read_wrap || in_narrow_read_wrap_smaller_16; assign in_write_wrap_conveter = in_full_size_write_wrap || in_narrow_write_wrap_smaller_16; assign in_default_converter = in_narrow_wrap_larger_16 || in_fixed || in_uncompressed_read; //nb: new burst signal assign nb = (d1_in_default_converter ? fixed_new_burst : (d1_in_incr ? incr_new_burst : wrap_new_burst)); // is_passthru : still read from real input, as we want to shift 1 clock here, all control signal and first len assign is_passthru = in_sop ? (in_passthru) : in_passthru_reg; //---------------------------------------------------------------- // I. Pipeline input stage //---------------------------------------------------------------- if(PIPE_INTERNAL == 0) begin : NO_PIPELINE_INPUT always_ff @(posedge clk or posedge reset) begin if (reset) begin in_write_wrap_conveter_reg <= '0; in_read_wrap_conveter_reg <= '0; in_default_converter_reg <= '0; in_incr_reg <= '0; end else begin if (sink0_pipe_ready & sink0_pipe_valid) begin in_write_wrap_conveter_reg <= in_write_wrap_conveter; in_read_wrap_conveter_reg <= in_read_wrap_conveter; in_default_converter_reg <= in_default_converter; in_incr_reg <= in_incr; end end // else: !if(reset) end // always_ff @ always_comb begin d0_in_incr = in_incr; d0_in_default_converter = in_default_converter; d0_in_read_wrap_conveter = in_read_wrap_conveter; d0_in_write_wrap_conveter = in_write_wrap_conveter; d0_first_len = first_len; d1_in_default_converter = in_default_converter_reg; d1_in_read_wrap_conveter = in_read_wrap_conveter_reg; d1_in_write_wrap_conveter = in_write_wrap_conveter_reg; d1_in_incr = in_incr_reg; d0_in_bursttype = nb ? in_bursttype : in_bursttype_reg; end end else begin : PIPELINE_INPUT reg [PKT_BURST_TYPE_W - 1 :0] d0_in_bursttype_dl; always_ff @(posedge clk or posedge reset) begin if (reset) begin in_write_wrap_conveter_reg <= '0; in_read_wrap_conveter_reg <= '0; in_default_converter_reg <= '0; d1_in_default_converter <= '0; d1_in_read_wrap_conveter <= '0; d1_in_write_wrap_conveter <= '0; first_len_reg <= '0; in_incr_reg <= '0; d0_in_bursttype_dl <= '0; end else begin if (sink0_pipe_ready & in_valid) begin in_write_wrap_conveter_reg <= in_write_wrap_conveter; in_read_wrap_conveter_reg <= in_read_wrap_conveter; in_default_converter_reg <= in_default_converter; first_len_reg <= first_len; in_incr_reg <= in_incr; end if (((state != ST_COMP_TRANS) & (~source0_valid | source0_ready)) | ( (state == ST_COMP_TRANS) & (~source0_valid | source0_ready & source0_endofpacket) ) ) begin d1_in_default_converter <= in_default_converter_reg; d1_in_read_wrap_conveter <= in_read_wrap_conveter_reg; d1_in_write_wrap_conveter <= in_write_wrap_conveter_reg; d1_in_incr <= in_incr_reg; d0_in_bursttype_dl <= in_bursttype_reg; end end // else: !if(reset) end // always_ff @ always_comb begin d0_in_incr = in_incr_reg; d0_in_default_converter = in_default_converter_reg; d0_in_read_wrap_conveter = in_read_wrap_conveter_reg; d0_in_write_wrap_conveter = in_write_wrap_conveter_reg; d0_first_len = first_len_reg; d0_in_bursttype = nb ? in_bursttype_reg : d0_in_bursttype_dl; end end // ------------------------------------------------------------------------- // II. First length calculation // ------------------------------------------------------------------------- // For AXI slave, avalon master must set alwaysBurstMaxBurst so // INCOMPLETE wrap burst will not happen // 1. If any wrapping burst that smaller than 16 -> pass thru // 2. Else first sub_burst length is aligned to slave boundary // ------------------------------------------------------------------------- //wire passthru = (in_len < len_to_out_bndry) || is_passthru; // why compare here? Keep this until we figure out why. always_comb begin if (in_boundary > OUT_BOUNDARY) begin first_len = is_passthru ? in_len : len_to_out_bndry; end else begin first_len = is_passthru ? in_len : len_to_in_bndry; end end // always_comb // ----------------------------------------------------------------------- // III. Conveter enable signals: Turn on/off each conveter accordingly // ----------------------------------------------------------------------- // AXI slave: three conveters: // 1. wrap_burst_conveter -> handle WRAP // 1.1 : full size wrap --> convert to fit in slave boundary // 1.2 : narrow size wrap // ---> <= 16 : pass thru // ---> > 16 : convert to non-bursting // 2. incr_burst_convter -> handle full/narrow size INCR // 3. default_burst_conveter -> handle FIXED // ----------------------------------------------------------------------- // Note: narrow wrap with length larger 16 can happen with Avalon narrow wraping // master to AXI slave. To support this, it will hurt fmax // also the WA adapter currently not pack data in this case, to be better support // need to start from WA first // ----------------------------------------------------------------------- assign new_burst = incr_new_burst && wrap_new_burst; assign enable_incr_converter = (d0_in_valid && d0_in_incr && fixed_new_burst && wrap_new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_incr && !nb)); assign enable_write_wrap_converter = (d0_in_valid && d0_in_write_wrap_conveter && fixed_new_burst && new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_write_wrap_conveter && !nb)); assign enable_read_wrap_converter = (d0_in_valid && d0_in_read_wrap_conveter && fixed_new_burst && new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_read_wrap_conveter && !nb)); assign enable_fixed_converter = (d0_in_valid && d0_in_default_converter && new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_default_converter && !nb)); // ----------------------------------------------------------------------- // IV. Packet signals // ----------------------------------------------------------------------- assign next_out_sop = ((state == ST_COMP_TRANS) & source0_ready & !(d1_in_default_converter ? fixed_new_burst : (d1_in_incr ? incr_new_burst : wrap_new_burst))) ? 1'b0 : d0_in_sop; assign next_out_eop = (state == ST_COMP_TRANS) ? (d1_in_default_converter ? fixed_new_burst : (d1_in_incr ? incr_new_burst : wrap_new_burst)) : d1_in_eop; // ----------------------------------------------------------------------- // V. Output select // ----------------------------------------------------------------------- assign out_byte_cnt = d1_in_default_converter ? fixed_out_byte_cnt : (d1_in_incr ? incr_out_byte_cnt : wrap_out_byte_cnt); assign out_addr = d1_in_default_converter ? fixed_out_addr : (d1_in_incr ? incr_out_addr : wrap_out_addr); end // if (AXI_SLAVE) if (IS_INCR_SLAVE) begin reg [IN_LEN_W - 1 : 0] first_len_reg; reg d0_in_default_converter; reg d0_in_full_size_incr; reg d0_in_full_size_write_wrap; reg d0_in_full_size_read_wrap; reg d1_in_default_converter; reg d1_in_full_size_incr; reg d1_in_full_size_write_wrap; reg d1_in_full_size_read_wrap; reg d1_in_incr; reg in_incr_reg; wire in_incr = (in_bursttype == 2'b01); wire in_wrap = (in_bursttype == 2'b10); wire [PKT_BYTE_CNT_W - 1 : 0] incr_out_byte_cnt; wire [PKT_BYTE_CNT_W - 1 : 0] fixed_out_byte_cnt; assign incr_out_byte_cnt = (d1_in_compressed_read ? incr_out_len : incr_uncompr_out_len) << log2_numsymbols; assign fixed_out_byte_cnt = fixed_out_len << log2_numsymbols; if (NO_WRAP_SUPPORT) begin assign in_default_converter = !in_full_size_incr; assign nb = d1_in_default_converter ? fixed_new_burst : incr_new_burst; end else begin wire in_narrow_incr; wire in_fixed = (in_bursttype == 2'b00) || (in_bursttype == 2'b11); assign in_narrow_incr = in_incr & in_narrow; assign in_default_converter = in_fixed || in_narrow || in_narrow_incr || in_uncompressed_read; assign nb = (d1_in_default_converter ? fixed_new_burst : (d1_in_incr ? incr_new_burst : wrap_new_burst)); end assign in_full_size_incr = in_incr & !in_narrow & !in_uncompressed_read; assign in_full_size_write_wrap = in_write & in_wrap & !in_narrow; assign in_full_size_read_wrap = in_compressed_read & in_wrap & !in_narrow; //---------------------------------------------------------------- // I. Pipeline input stage //---------------------------------------------------------------- if(PIPE_INTERNAL == 0) begin : NO_PIPELINE_INPUT always_ff @(posedge clk or posedge reset) begin if (reset) begin in_full_size_write_wrap_reg <= '0; in_full_size_read_wrap_reg <= '0; in_full_size_incr_reg <= '0; in_default_converter_reg <= '0; in_incr_reg <= '0; end else begin if (sink0_pipe_ready & sink0_pipe_valid) begin in_incr_reg <= in_incr; in_full_size_incr_reg <= in_full_size_incr; in_full_size_write_wrap_reg <= in_full_size_write_wrap; in_full_size_read_wrap_reg <= in_full_size_read_wrap; in_default_converter_reg <= in_default_converter; end end // else: !if(reset) end // always_ff @ always_comb begin d0_in_default_converter = in_default_converter; d0_in_full_size_incr = in_full_size_incr; d0_in_full_size_write_wrap = in_full_size_write_wrap; d0_in_full_size_read_wrap = in_full_size_read_wrap; d0_first_len = first_len; d1_in_incr = in_incr_reg; d1_in_default_converter = in_default_converter_reg; d1_in_full_size_incr = in_full_size_incr_reg; d1_in_full_size_write_wrap = in_full_size_write_wrap_reg; d1_in_full_size_read_wrap = in_full_size_read_wrap_reg; d0_in_bursttype = nb ? in_bursttype : in_bursttype_reg; end end else begin : PIPELINE_INPUT reg [PKT_BURST_TYPE_W - 1 :0] d0_in_bursttype_dl; always_ff @(posedge clk or posedge reset) begin if (reset) begin in_full_size_write_wrap_reg <= '0; in_full_size_read_wrap_reg <= '0; in_full_size_incr_reg <= '0; in_default_converter_reg <= '0; d1_in_default_converter <= '0; d1_in_full_size_incr <= '0; d1_in_full_size_write_wrap <= '0; d1_in_full_size_read_wrap <= '0; d1_in_incr <= '0; first_len_reg <= '0; in_incr_reg <= '0; d0_in_bursttype_dl <= '0; end else begin if (sink0_pipe_ready & in_valid) begin in_full_size_incr_reg <= in_full_size_incr; in_full_size_write_wrap_reg <= in_full_size_write_wrap; in_full_size_read_wrap_reg <= in_full_size_read_wrap; in_default_converter_reg <= in_default_converter; in_incr_reg <= in_incr; first_len_reg <= first_len; end if (((state != ST_COMP_TRANS) & (~source0_valid | source0_ready)) | ( (state == ST_COMP_TRANS) & (~source0_valid | source0_ready & source0_endofpacket) ) ) begin d1_in_default_converter <= in_default_converter_reg; d1_in_full_size_incr <= in_full_size_incr_reg; d1_in_full_size_write_wrap <= in_full_size_write_wrap_reg; d1_in_full_size_read_wrap <= in_full_size_read_wrap_reg; d1_in_incr <= in_incr_reg; d0_in_bursttype_dl <= in_bursttype_reg; end end // else: !if(reset) end // always_ff @ always_comb begin d0_in_default_converter = in_default_converter_reg; d0_in_full_size_incr = in_full_size_incr_reg; d0_in_full_size_write_wrap = in_full_size_write_wrap_reg; d0_in_full_size_read_wrap = in_full_size_read_wrap_reg; d0_first_len = first_len_reg; d0_in_bursttype = nb ? in_bursttype_reg : d0_in_bursttype_dl; end end // -------------------------------------------------------------------------------------- // II. First length calculation // -------------------------------------------------------------------------------------- // Note: the slave is INCR slave, in pratical is has no boundary so if in burst is wrap // the sub burst can send out "slave max length" first fs the in burst not yet wraps back // To simplify and optimize: the first sub_burst length stills send out aligned length first // -------------------------------------------------------------------------------------- // If no INCOMPLETE wrap burst // 1. in_boundary is larger out_boundary; first sub_burst length is: aligned to out boundary // 2. in_boundary is smaller out_boundary; first sub_burst length is: aligned to in boundary // -------------------------------------------------------------------------------------- if (!NO_WRAP_SUPPORT) begin : HAVE_WRAP_BURSTING_SUPPORT if (!INCOMPLETE_WRAP_SUPPORT) begin : no_incomplete_wrap_support assign first_len = (in_boundary > OUT_BOUNDARY) ? len_to_out_bndry : len_to_in_bndry; end else begin : incomplete_wrap_support // ------------------------------------------------------------------------- // If INCOMPLETE wrap support // 1. The idea is still same, based on boundary and select either aligned to in/out boundary // 2. But need to check if in_len is smaller to "aligned" in/out boundary for incomplete case // -> the burst is pass thru is in_len is smaller // ------------------------------------------------------------------------- wire in_len_smaller_aligned_out_bdry = (in_len <= len_to_out_bndry); wire in_len_smaller_aligned_in_bdry = (in_len <= len_to_in_bndry); always_comb begin if (in_boundary > OUT_BOUNDARY) begin first_len = (in_len_smaller_aligned_out_bdry) ? in_len : len_to_out_bndry; end else begin first_len = (in_len_smaller_aligned_in_bdry) ? in_len : len_to_in_bndry; end end end // block: incomplete_wrap_support end // ----------------------------------------------------------------------- // III. Conveter enable signals: Turn on/off each conveter accordingly // ----------------------------------------------------------------------- // INCR slave: three conveters: // 1. wrap_burst_conveter -> handle WRAP // 2. incr_burst_convter -> handle INCR // 2. default_burst_conveter -> handle narrow burst // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- // Purposely support AXI to Avalon: with no wrapping suppport // all wrapping transaction witll be converted to non-bursting sub-burst // 21-January-2014 // ----------------------------------------------------------------------- if (NO_WRAP_SUPPORT) begin assign enable_incr_converter = (d0_in_valid && d0_in_full_size_incr && fixed_new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_full_size_incr && !nb)); assign enable_fixed_converter = (d0_in_valid && d0_in_default_converter && incr_new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_default_converter && !nb)); // ----------------------------------------------------------------------- // IV. Packet signals // ----------------------------------------------------------------------- assign next_out_sop = (state == ST_COMP_TRANS) & source0_ready & !(d1_in_default_converter ? fixed_new_burst : incr_new_burst) ? 1'b0 : d0_in_sop; assign next_out_eop = (state == ST_COMP_TRANS) ? (d1_in_default_converter ? fixed_new_burst : incr_new_burst) : d1_in_eop; // ----------------------------------------------------------------------- // V. Output select // ----------------------------------------------------------------------- assign out_byte_cnt = d1_in_default_converter ? fixed_out_byte_cnt : incr_out_byte_cnt; assign out_addr = d1_in_default_converter ? fixed_out_addr : incr_out_addr; end else begin assign new_burst = incr_new_burst && wrap_new_burst; assign enable_incr_converter = (d0_in_valid && d0_in_full_size_incr && fixed_new_burst && wrap_new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_full_size_incr && !nb)); assign enable_fixed_converter = (d0_in_valid && d0_in_default_converter && new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_default_converter && !nb)); assign enable_write_wrap_converter = (d0_in_valid && d0_in_full_size_write_wrap && fixed_new_burst && incr_new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_full_size_write_wrap && !nb)); assign enable_read_wrap_converter = (d0_in_valid && d0_in_full_size_read_wrap && fixed_new_burst && incr_new_burst && (source0_ready || !source0_valid) || ((state == ST_COMP_TRANS) && source0_ready && d1_in_full_size_read_wrap && !nb)); // ----------------------------------------------------------------------- // IV. Packet signals // ----------------------------------------------------------------------- assign next_out_sop = ((state == ST_COMP_TRANS) & source0_ready & !(d1_in_default_converter ? fixed_new_burst : (d1_in_incr ? incr_new_burst : wrap_new_burst))) ? 1'b0 : d0_in_sop; assign next_out_eop = (state == ST_COMP_TRANS) ? (d1_in_default_converter ? fixed_new_burst : (d1_in_incr ? incr_new_burst : wrap_new_burst)) : d1_in_eop; // ----------------------------------------------------------------------- // V. Output select // ----------------------------------------------------------------------- wire [PKT_BYTE_CNT_W - 1 : 0] wrap_out_byte_cnt; assign wrap_out_byte_cnt = (d1_in_compressed_read ? wrap_out_len : wrap_uncompr_out_len) << log2_numsymbols; assign out_byte_cnt = d1_in_default_converter ? fixed_out_byte_cnt : (d1_in_incr ? incr_out_byte_cnt : wrap_out_byte_cnt); assign out_addr = d1_in_default_converter ? fixed_out_addr : (d1_in_incr ? incr_out_addr : wrap_out_addr); end end end endgenerate // -------------------------------------------------- // Control signals // -------------------------------------------------- reg source0_valid_reg; wire next_source0_valid; reg source0_startofpacket_reg; wire is_write; assign is_write = nb ? (d0_in_write) : d1_in_write; //------------------------------------------------------------------------- // Handshaking and packet signals // ----------------------------------------------------------------------- // source0_valid: takes from in sink_valid unless read then wait until end_of_packet assign next_source0_valid = ((state == ST_COMP_TRANS) & !source0_endofpacket) ? 1'b1 : d0_in_valid; // sink0_ready needs always to be asserted first, hold one after reset assign sink0_pipe_ready = (state == ST_UNCOMP_TRANS) ? source0_ready || !source0_valid : (state == ST_COMP_TRANS) ? nb && source0_ready || !source0_valid : in_ready_hold; always_ff @(posedge clk or posedge reset) begin if (reset) begin source0_valid_reg <= '0; source0_startofpacket_reg <= '1; end else begin if (~source0_valid | source0_ready) begin source0_valid_reg <= next_source0_valid; source0_startofpacket_reg <= next_out_sop; end end // else: !if(reset) end // always_ff @ // Assign output signals always_comb begin source0_endofpacket = next_out_eop; source0_startofpacket = source0_startofpacket_reg; source0_valid = source0_valid_reg; end // -------------------------------------------------- // Converters instantiation and signal mappings. // -------------------------------------------------- generate if (NON_BURSTING_SLAVE) begin : non_bursting_slave_converters_sel altera_default_burst_converter #( .PKT_BURST_TYPE_W (PKT_BURST_TYPE_W), .PKT_ADDR_W (PKT_ADDR_W), .PKT_BURSTWRAP_W (PKT_BURSTWRAP_W), .PKT_BURST_SIZE_W (PKT_BURST_SIZE_W), .LEN_W (IN_LEN_W), .IS_AXI_SLAVE (AXI_SLAVE) ) the_default_burst_converter ( .clk (clk), .reset (reset), .enable (enable_fixed_converter), // turn on if a fixed .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .in_bursttype (d0_in_bursttype), .in_burstwrap_reg (d1_in_burstwrap), .in_burstwrap_value (d0_in_burstwrap_value), .in_len (d0_in_len), .in_size_value (d0_in_size_value), .in_is_write (is_write), .out_len (fixed_out_len), .out_addr (fixed_out_addr), .new_burst (fixed_new_burst) ); end else if (INCR_AVALON_SYS) begin : system_purely_avalon_converter_sel //----------------------------------------------------------------- // When system is purely INCR, only need one converter. //----------------------------------------------------------------- altera_incr_burst_converter #( .MAX_IN_LEN (MAX_IN_LEN), .MAX_OUT_LEN (MAX_OUT_LEN), .ADDR_WIDTH (PKT_ADDR_W), .BNDRY_WIDTH (PKT_BURSTWRAP_W), .BURSTSIZE_WIDTH (PKT_BURST_SIZE_W), .IN_NARROW_SIZE (IN_NARROW_SIZE), .NUM_SYMBOLS (NUM_SYMBOLS), .PURELY_INCR_AVL_SYS (INCR_AVALON_SYS) ) the_converter_for_avalon_incr_slave ( .clk (clk), .reset (reset), .enable (enable_incr_converter), .in_len (d0_in_len), .in_sop (d0_in_sop), .in_burstwrap_reg (d1_in_burstwrap), .in_size_t (d0_in_size), .in_size_reg (d1_in_size), .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .is_write (is_write), .out_len (incr_out_len), .uncompr_out_len (incr_uncompr_out_len), .out_addr (incr_out_addr), .new_burst_export (incr_new_burst) ); end else begin : converters_selection if (IS_WRAP_AVALON_SLAVE) begin : wrapping_avalon_slave_converter_sel altera_wrap_burst_converter #( .MAX_IN_LEN (MAX_IN_LEN), .MAX_OUT_LEN (MAX_OUT_LEN), .ADDR_WIDTH (PKT_ADDR_W), .BNDRY_WIDTH (PKT_BURSTWRAP_W), .AXI_SLAVE (AXI_SLAVE), .NUM_SYMBOLS (NUM_SYMBOLS), .OPTIMIZE_WRITE_BURST (0) ) the_converter_for_avalon_wrap_slave ( .clk (clk), .reset (reset), .enable_read (enable_incr_read_converter), .enable_write (enable_incr_write_converter), .in_len (d0_in_len), .first_len (d0_first_len), .in_sop (d0_in_sop), .in_burstwrap (d0_in_burstwrap), .in_burstwrap_reg (d1_in_burstwrap), .in_boundary (in_boundary), .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .out_len (incr_out_len), .uncompr_out_len (incr_uncompr_out_len), .out_addr (incr_out_addr), .new_burst_export (new_burst) ); altera_default_burst_converter #( .PKT_BURST_TYPE_W (PKT_BURST_TYPE_W), .PKT_ADDR_W (PKT_ADDR_W), .PKT_BURSTWRAP_W (PKT_BURSTWRAP_W), .PKT_BURST_SIZE_W (PKT_BURST_SIZE_W), .LEN_W (IN_LEN_W), .IS_AXI_SLAVE (AXI_SLAVE) ) the_default_burst_converter ( .clk (clk), .reset (reset), .enable (enable_fixed_converter), // turn on if a fixed .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .in_bursttype (d0_in_bursttype), .in_burstwrap_reg (d1_in_burstwrap), .in_burstwrap_value (d0_in_burstwrap_value), .in_len (d0_in_len), .in_size_value (d0_in_size_value), .in_is_write (is_write), .out_len (fixed_out_len), .out_addr (fixed_out_addr), .new_burst (fixed_new_burst) ); end if (AXI_SLAVE) begin : axi_slave_converter_sel altera_wrap_burst_converter #( .MAX_IN_LEN (MAX_IN_LEN), .MAX_OUT_LEN (MAX_OUT_LEN), .ADDR_WIDTH (PKT_ADDR_W), .BNDRY_WIDTH (PKT_BURSTWRAP_W), .NUM_SYMBOLS (NUM_SYMBOLS), .AXI_SLAVE (AXI_SLAVE), .OPTIMIZE_WRITE_BURST (0) ) the_converter_for_avalon_wrap_slave ( .clk (clk), .reset (reset), .enable_read (enable_read_wrap_converter), .enable_write (enable_write_wrap_converter), .in_len (d0_in_len), .first_len (d0_first_len), .in_sop (d0_in_sop), .in_burstwrap (d0_in_burstwrap), .in_burstwrap_reg (d1_in_burstwrap), .in_boundary (in_boundary), .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .out_len (wrap_out_len), .uncompr_out_len (wrap_uncompr_out_len), .out_addr (wrap_out_addr), .new_burst_export (wrap_new_burst) ); altera_incr_burst_converter #( .MAX_IN_LEN (MAX_IN_LEN), .MAX_OUT_LEN (MAX_OUT_LEN), .ADDR_WIDTH (PKT_ADDR_W), .BNDRY_WIDTH (PKT_BURSTWRAP_W), .BURSTSIZE_WIDTH (PKT_BURST_SIZE_W), .IN_NARROW_SIZE (IN_NARROW_SIZE), .NUM_SYMBOLS (NUM_SYMBOLS), .PURELY_INCR_AVL_SYS (INCR_AVALON_SYS) ) the_converter_for_avalon_incr_slave ( .clk (clk), .reset (reset), .enable (enable_incr_converter), .in_len (d0_in_len), .in_sop (d0_in_sop), .in_burstwrap_reg (d1_in_burstwrap), .in_size_t (d0_in_size), .in_size_reg (d1_in_size), .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .is_write (is_write), .out_len (incr_out_len), .uncompr_out_len (incr_uncompr_out_len), .out_addr (incr_out_addr), .new_burst_export (incr_new_burst) ); // -------------------------------------------------- // The fixed burst converter module // -------------------------------------------------- altera_default_burst_converter #( .PKT_BURST_TYPE_W (PKT_BURST_TYPE_W), .PKT_ADDR_W (PKT_ADDR_W), .PKT_BURSTWRAP_W (PKT_BURSTWRAP_W), .PKT_BURST_SIZE_W (PKT_BURST_SIZE_W), .LEN_W (IN_LEN_W), .IS_AXI_SLAVE (AXI_SLAVE) ) the_default_burst_converter ( .clk (clk), .reset (reset), .enable (enable_fixed_converter), // turn on if a fixed .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .in_bursttype (d0_in_bursttype), .in_burstwrap_reg (d1_in_burstwrap), .in_burstwrap_value (d0_in_burstwrap_value), .in_len (d0_in_len), .in_size_value (d0_in_size_value), .in_is_write (is_write), .out_len (fixed_out_len), .out_addr (fixed_out_addr), .new_burst (fixed_new_burst) ); end if (IS_INCR_SLAVE) begin : incr_slave_converter_sel if (NO_WRAP_SUPPORT) begin : no_wrap_incr_slave_converter_sel altera_incr_burst_converter #( .MAX_IN_LEN (MAX_IN_LEN), .MAX_OUT_LEN (MAX_OUT_LEN), .ADDR_WIDTH (PKT_ADDR_W), .BNDRY_WIDTH (PKT_BURSTWRAP_W), .BURSTSIZE_WIDTH (PKT_BURST_SIZE_W), .IN_NARROW_SIZE (0), // not support narrow as this is INCR avalon slave .NUM_SYMBOLS (NUM_SYMBOLS), .PURELY_INCR_AVL_SYS (INCR_AVALON_SYS) ) the_converter_for_avalon_incr_slave ( .clk (clk), .reset (reset), .enable (enable_incr_converter), .in_len (d0_in_len), .in_sop (d0_in_sop), .in_burstwrap_reg (d1_in_burstwrap), .in_size_t (d0_in_size), .in_size_reg (d1_in_size), .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .is_write (is_write), .out_len (incr_out_len), .uncompr_out_len (incr_uncompr_out_len), .out_addr (incr_out_addr), .new_burst_export (incr_new_burst) ); // -------------------------------------------------- // The default converter // -------------------------------------------------- altera_default_burst_converter #( .PKT_BURST_TYPE_W (PKT_BURST_TYPE_W), .PKT_ADDR_W (PKT_ADDR_W), .PKT_BURSTWRAP_W (PKT_BURSTWRAP_W), .PKT_BURST_SIZE_W (PKT_BURST_SIZE_W), .LEN_W (IN_LEN_W), .IS_AXI_SLAVE (AXI_SLAVE) ) the_default_burst_converter ( .clk (clk), .reset (reset), .enable (enable_fixed_converter), // turn on if a fixed .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .in_bursttype (d0_in_bursttype), .in_burstwrap_reg (d1_in_burstwrap), .in_burstwrap_value (d0_in_burstwrap_value), .in_len (d0_in_len), .in_size_value (d0_in_size_value), .in_is_write (is_write), .out_len (fixed_out_len), .out_addr (fixed_out_addr), .new_burst (fixed_new_burst) ); end else begin : wrap_incr_slave_conveter_sel altera_wrap_burst_converter #( .MAX_IN_LEN (MAX_IN_LEN), .MAX_OUT_LEN (MAX_OUT_LEN), .ADDR_WIDTH (PKT_ADDR_W), .BNDRY_WIDTH (PKT_BURSTWRAP_W), .NUM_SYMBOLS (NUM_SYMBOLS), .AXI_SLAVE (AXI_SLAVE), .OPTIMIZE_WRITE_BURST (0) ) the_converter_for_avalon_wrap_slave ( .clk (clk), .reset (reset), .enable_read (enable_read_wrap_converter), .enable_write (enable_write_wrap_converter), .in_len (d0_in_len), .first_len (d0_first_len), .in_sop (d0_in_sop), .in_burstwrap (d0_in_burstwrap), .in_burstwrap_reg (d1_in_burstwrap), .in_boundary (in_boundary), .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .out_len (wrap_out_len), .uncompr_out_len (wrap_uncompr_out_len), .out_addr (wrap_out_addr), .new_burst_export (wrap_new_burst) ); altera_incr_burst_converter #( .MAX_IN_LEN (MAX_IN_LEN), .MAX_OUT_LEN (MAX_OUT_LEN), .ADDR_WIDTH (PKT_ADDR_W), .BNDRY_WIDTH (PKT_BURSTWRAP_W), .BURSTSIZE_WIDTH (PKT_BURST_SIZE_W), .IN_NARROW_SIZE (IN_NARROW_SIZE), .NUM_SYMBOLS (NUM_SYMBOLS), .PURELY_INCR_AVL_SYS (INCR_AVALON_SYS) ) the_converter_for_avalon_incr_slave ( .clk (clk), .reset (reset), .enable (enable_incr_converter), .in_len (d0_in_len), .in_sop (d0_in_sop), .in_burstwrap_reg (d1_in_burstwrap), .in_size_t (d0_in_size), .in_size_reg (d1_in_size), .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .is_write (is_write), .out_len (incr_out_len), .uncompr_out_len (incr_uncompr_out_len), .out_addr (incr_out_addr), .new_burst_export (incr_new_burst) ); // -------------------------------------------------- // The fixed burst converter module // -------------------------------------------------- altera_default_burst_converter #( .PKT_BURST_TYPE_W (PKT_BURST_TYPE_W), .PKT_ADDR_W (PKT_ADDR_W), .PKT_BURSTWRAP_W (PKT_BURSTWRAP_W), .PKT_BURST_SIZE_W (PKT_BURST_SIZE_W), .LEN_W (IN_LEN_W), .IS_AXI_SLAVE (AXI_SLAVE) ) the_default_burst_converter ( .clk (clk), .reset (reset), .enable (enable_fixed_converter), // turn on if a fixed .in_addr (d0_in_aligned_addr), .in_addr_reg (d1_in_aligned_addr), .in_bursttype (d0_in_bursttype), .in_burstwrap_reg (d1_in_burstwrap), .in_burstwrap_value (d0_in_burstwrap_value), .in_len (d0_in_len), .in_size_value (d0_in_size_value), .in_is_write (is_write), .out_len (fixed_out_len), .out_addr (fixed_out_addr), .new_burst (fixed_new_burst) ); end end end endgenerate // -------------------------------------------------- // Ceil(log2()) function // -------------------------------------------------- function unsigned[63:0] log2ceil; input reg [63:0] val; reg [63:0] i; begin i = 1; log2ceil = 0; while (i < val) begin log2ceil = log2ceil + 1; i = i << 1; end end endfunction // --------------------------------------------------- // Mapping of output signals. // --------------------------------------------------- wire load_next_output_pck = source0_ready | !source0_valid; always_ff @(posedge clk or posedge reset) begin if (reset) begin uncompr_out_addr <= '0; end else if (load_next_output_pck) begin uncompr_out_addr <= d0_in_addr; end end // --------------------------------------------------- // Out burstype // --------------------------------------------------- // If AXI slave, out_bursttype = INCR if either of the following 2 conditions is met: // 1) in_passthru (i.e. the input burst count < 16). // 2) input packet has bursttype == REP_WRAP (Repeated Wrap). // Else, out_bursttype = in_bursttype. // For all other slaves, change the bursttype to INCR. wire [PKT_BURST_TYPE_W - 1 : 0] out_bursttype; generate if (AXI_SLAVE) begin : AXI_SLAVE_out_bursttype assign out_bursttype = (!d1_in_passthru || d1_in_bursttype == REP_WRAP) ? INCR : d1_in_bursttype; end else begin : others_slave_out_bursttype assign out_bursttype = INCR; end endgenerate // At source0_startofpacket, out_addr_read is the in_addr. wire [PKT_ADDR_W - 1 : 0] out_addr_read; assign out_addr_read = source0_startofpacket_reg ? uncompr_out_addr : out_addr; // Choose between uncompressed or compressed trans address. wire [PKT_ADDR_W - 1 : 0] out_addr_assigned_to_packet; assign out_addr_assigned_to_packet = (d1_in_write || d1_in_uncompressed_read) ? uncompr_out_addr : out_addr_read; // --------------------------------------------------- // Byteenable Generation. // Passthrough unless compressed transaction. // --------------------------------------------------- reg [PKT_BYTEEN_W - 1 : 0 ] out_byteen; reg [ADDR_MASK_SEL - 1 : 0 ] out_addr_masked; wire [511:0] initial_byteen = set_byteenable_based_on_size(d1_in_size); // To fix quartus integration error. Unused bits are expected to be synthesized away // Unaligned address changes. // Assumption : Byte enable is calculated for all cycles coming out from BA, and needs to be based on aligned address. // Hence, it cannot take directly output address of BA (which sends out unaligned address for 1st cycle) always_comb begin // Addresses from the converters (out_addr) are always aligned. out_addr_masked = out_addr[ADDR_MASK_SEL-1:0]; end always_comb begin if (BYTEENABLE_SYNTHESIS == 1 && d1_in_narrow == 1 && (state == ST_COMP_TRANS)) out_byteen = initial_byteen[NUM_SYMBOLS-1:0] << out_addr_masked; else out_byteen = d1_in_byteen; end // -- End of Byteenable Generation -- always_comb begin : source0_out_assignments source0_data = d1_in_data; source0_channel = d1_in_channel; // Override fields the component is aware of. source0_data[PKT_BURST_TYPE_H : PKT_BURST_TYPE_L] = out_bursttype; source0_data[PKT_BYTE_CNT_H : PKT_BYTE_CNT_L ] = out_byte_cnt; source0_data[PKT_ADDR_H : PKT_ADDR_L ] = out_addr_assigned_to_packet; source0_data[PKT_BYTEEN_H : PKT_BYTEEN_L ] = out_byteen; end //---------------------------------------------------- // "min" operation on burstwrap values is a bitwise AND. //---------------------------------------------------- function [PKT_BURSTWRAP_W - 1 : 0] altera_merlin_burst_adapter_burstwrap_min; input [PKT_BURSTWRAP_W - 1 : 0] a, b; begin altera_merlin_burst_adapter_burstwrap_min = a & b; end endfunction //---------------------------------------------------- // AXSIZE encoding: run-time size of the transaction. // --------------------------------------------------- function reg[511:0] set_byteenable_based_on_size; input [3:0] axsize; begin case (axsize) 4'b0000: set_byteenable_based_on_size = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001; 4'b0001: set_byteenable_based_on_size = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003; 4'b0010: set_byteenable_based_on_size = 512'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F; 4'b0011: set_byteenable_based_on_size = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF; 4'b0100: set_byteenable_based_on_size = 512'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF; 4'b0101: set_byteenable_based_on_size = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF; 4'b0110: set_byteenable_based_on_size = 512'h0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF; 4'b0111: set_byteenable_based_on_size = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; 4'b1000: set_byteenable_based_on_size = 512'h0000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; 4'b1001: set_byteenable_based_on_size = 512'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; default: set_byteenable_based_on_size = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001; endcase end endfunction endmodule