// (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. // (C) 2001-2011 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_slave_agent/altera_merlin_slave_agent.sv#1 $ // $Revision: #1 $ // $Date: 2015/08/09 $ // $Author: swbranch $ `timescale 1 ns / 1 ns module altera_merlin_slave_agent #( // Packet parameters parameter PKT_BEGIN_BURST = 81, parameter PKT_DATA_H = 31, parameter PKT_DATA_L = 0, parameter PKT_SYMBOL_W = 8, parameter PKT_BYTEEN_H = 71, parameter PKT_BYTEEN_L = 68, parameter PKT_ADDR_H = 63, parameter PKT_ADDR_L = 32, parameter PKT_TRANS_LOCK = 87, parameter PKT_TRANS_COMPRESSED_READ = 67, parameter PKT_TRANS_POSTED = 66, parameter PKT_TRANS_WRITE = 65, parameter PKT_TRANS_READ = 64, parameter PKT_SRC_ID_H = 74, parameter PKT_SRC_ID_L = 72, parameter PKT_DEST_ID_H = 77, parameter PKT_DEST_ID_L = 75, parameter PKT_BURSTWRAP_H = 85, parameter PKT_BURSTWRAP_L = 82, parameter PKT_BYTE_CNT_H = 81, parameter PKT_BYTE_CNT_L = 78, parameter PKT_PROTECTION_H = 86, parameter PKT_PROTECTION_L = 86, parameter PKT_RESPONSE_STATUS_H = 89, parameter PKT_RESPONSE_STATUS_L = 88, parameter PKT_BURST_SIZE_H = 92, parameter PKT_BURST_SIZE_L = 90, parameter PKT_ORI_BURST_SIZE_L = 93, parameter PKT_ORI_BURST_SIZE_H = 95, parameter ST_DATA_W = 96, parameter ST_CHANNEL_W = 32, // Slave parameters parameter ADDR_W = PKT_ADDR_H - PKT_ADDR_L + 1, parameter AVS_DATA_W = PKT_DATA_H - PKT_DATA_L + 1, parameter AVS_BURSTCOUNT_W = 4, parameter PKT_SYMBOLS = AVS_DATA_W / PKT_SYMBOL_W, // Slave agent parameters parameter PREVENT_FIFO_OVERFLOW = 0, parameter SUPPRESS_0_BYTEEN_CMD = 1, parameter USE_READRESPONSE = 0, parameter USE_WRITERESPONSE = 0, // Derived slave parameters parameter AVS_BE_W = PKT_BYTEEN_H - PKT_BYTEEN_L + 1, parameter BURST_SIZE_W = 3, // Derived FIFO width parameter FIFO_DATA_W = ST_DATA_W + 1, // ECC parameter parameter ECC_ENABLE = 0 ) ( input clk, input reset, // Universal-Avalon anti-slave output [ADDR_W-1:0] m0_address, output [AVS_BURSTCOUNT_W-1:0] m0_burstcount, output [AVS_BE_W-1:0] m0_byteenable, output m0_read, input [AVS_DATA_W-1:0] m0_readdata, input m0_waitrequest, output m0_write, output [AVS_DATA_W-1:0] m0_writedata, input m0_readdatavalid, output m0_debugaccess, output m0_lock, input [1:0] m0_response, input m0_writeresponsevalid, // Avalon-ST FIFO interfaces. // Note: there's no need to include the "data" field here, at least for // reads, since readdata is filled in from slave info. To keep life // simple, have a data field, but fill it with 0s. // Av-st response fifo source interface output reg [FIFO_DATA_W-1:0] rf_source_data, output rf_source_valid, output rf_source_startofpacket, output rf_source_endofpacket, input rf_source_ready, // Av-st response fifo sink interface input [FIFO_DATA_W-1:0] rf_sink_data, input rf_sink_valid, input rf_sink_startofpacket, input rf_sink_endofpacket, output rf_sink_ready, // Av-st readdata fifo src interface, data and response // extra 2 bits for storing RESPONSE STATUS output [AVS_DATA_W+1:0] rdata_fifo_src_data, output rdata_fifo_src_valid, input rdata_fifo_src_ready, // Av-st readdata fifo sink interface input [AVS_DATA_W+1:0] rdata_fifo_sink_data, input rdata_fifo_sink_valid, output rdata_fifo_sink_ready, input rdata_fifo_sink_error, // Av-st sink command packet interface output cp_ready, input cp_valid, input [ST_DATA_W-1:0] cp_data, input [ST_CHANNEL_W-1:0] cp_channel, input cp_startofpacket, input cp_endofpacket, // Av-st source response packet interface input rp_ready, output reg rp_valid, output reg [ST_DATA_W-1:0] rp_data, output rp_startofpacket, output rp_endofpacket ); // -------------------------------------------------- // Ceil(log2()) function log2ceil of 4 = 2 // -------------------------------------------------- function integer 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 // ------------------------------------------------ // Local Parameters // ------------------------------------------------ localparam DATA_W = PKT_DATA_H - PKT_DATA_L + 1; localparam BE_W = PKT_BYTEEN_H - PKT_BYTEEN_L + 1; localparam MID_W = PKT_SRC_ID_H - PKT_SRC_ID_L + 1; localparam SID_W = PKT_DEST_ID_H - PKT_DEST_ID_L + 1; localparam BYTE_CNT_W = PKT_BYTE_CNT_H - PKT_BYTE_CNT_L + 1; localparam BURSTWRAP_W = PKT_BURSTWRAP_H - PKT_BURSTWRAP_L + 1; localparam BURSTSIZE_W = PKT_BURST_SIZE_H - PKT_BURST_SIZE_L + 1; localparam BITS_TO_MASK = log2ceil(PKT_SYMBOLS); localparam MAX_BURST = 1 << (AVS_BURSTCOUNT_W - 1); localparam BURSTING = (MAX_BURST > PKT_SYMBOLS); // ------------------------------------------------ // Signals // ------------------------------------------------ wire [DATA_W-1:0] cmd_data; wire [BE_W-1:0] cmd_byteen; wire [ADDR_W-1:0] cmd_addr; wire [MID_W-1:0] cmd_mid; wire [SID_W-1:0] cmd_sid; wire cmd_read; wire cmd_write; wire cmd_compressed; wire cmd_posted; wire [BYTE_CNT_W-1:0] cmd_byte_cnt; wire [BURSTWRAP_W-1:0] cmd_burstwrap; wire [BURSTSIZE_W-1:0] cmd_burstsize; wire cmd_debugaccess; wire suppress_cmd; wire byteen_asserted; wire suppress_read; wire suppress_write; wire needs_response_synthesis; wire generate_response; // Assign command fields assign cmd_data = cp_data[PKT_DATA_H :PKT_DATA_L ]; assign cmd_byteen = cp_data[PKT_BYTEEN_H:PKT_BYTEEN_L]; assign cmd_addr = cp_data[PKT_ADDR_H :PKT_ADDR_L ]; assign cmd_compressed = cp_data[PKT_TRANS_COMPRESSED_READ]; assign cmd_posted = cp_data[PKT_TRANS_POSTED]; assign cmd_write = cp_data[PKT_TRANS_WRITE]; assign cmd_read = cp_data[PKT_TRANS_READ]; assign cmd_mid = cp_data[PKT_SRC_ID_H :PKT_SRC_ID_L]; assign cmd_sid = cp_data[PKT_DEST_ID_H:PKT_DEST_ID_L]; assign cmd_byte_cnt = cp_data[PKT_BYTE_CNT_H:PKT_BYTE_CNT_L]; assign cmd_burstwrap = cp_data[PKT_BURSTWRAP_H:PKT_BURSTWRAP_L]; assign cmd_burstsize = cp_data[PKT_BURST_SIZE_H:PKT_BURST_SIZE_L]; assign cmd_debugaccess = cp_data[PKT_PROTECTION_L]; // Local "ready_for_command" signal: deasserted when the agent is unable to accept // another command, e.g. rdv FIFO is full, (local readdata storage is full && // ~rp_ready), ... // Say, this could depend on the type of command, for example, even if the // rdv FIFO is full, a write request can be accepted. For later. wire ready_for_command; wire local_lock = cp_valid & cp_data[PKT_TRANS_LOCK]; wire local_write = cp_valid & cp_data[PKT_TRANS_WRITE]; wire local_read = cp_valid & cp_data[PKT_TRANS_READ]; wire local_compressed_read = cp_valid & cp_data[PKT_TRANS_COMPRESSED_READ]; wire nonposted_write_endofpacket = ~cp_data[PKT_TRANS_POSTED] & local_write & cp_endofpacket; // num_symbols is PKT_SYMBOLS, appropriately sized. wire [31:0] int_num_symbols = PKT_SYMBOLS; wire [BYTE_CNT_W-1:0] num_symbols = int_num_symbols[BYTE_CNT_W-1:0]; generate if (PREVENT_FIFO_OVERFLOW) begin : prevent_fifo_overflow_block // --------------------------------------------------- // Backpressure if the slave says to, or if FIFO overflow may occur. // // All commands are backpressured once the FIFO is full // even if they don't need storage. This breaks a long // combinatorial path from the master read/write through // this logic and back to the master via the backpressure // path. // // To avoid a loss of throughput the FIFO will be parameterized // one slot deeper. The extra slot should never be used in normal // operation, but should a slave misbehave and accept one more // read than it should then backpressure will kick in. // // An example: assume a slave with MPRT = 2. It can accept a // command sequence RRWW without backpressuring. If the FIFO is // only 2 deep, we'd backpressure the writes leading to loss of // throughput. If the FIFO is 3 deep, we'll only backpressure when // RRR... which is an illegal condition anyway. // --------------------------------------------------- assign ready_for_command = rf_source_ready; assign cp_ready = (~m0_waitrequest | suppress_cmd) && ready_for_command; end else begin : no_prevent_fifo_overflow_block // Do not suppress the command or the slave will // not be able to waitrequest assign ready_for_command = 1'b1; // Backpressure only if the slave says to. assign cp_ready = ~m0_waitrequest | suppress_cmd; end endgenerate generate if (SUPPRESS_0_BYTEEN_CMD && !BURSTING) begin : suppress_0_byteen_cmd_non_bursting assign byteen_asserted = |cmd_byteen; assign suppress_read = ~byteen_asserted; assign suppress_write = ~byteen_asserted; assign suppress_cmd = ~byteen_asserted; end else if (SUPPRESS_0_BYTEEN_CMD && BURSTING) begin: suppress_0_byteen_cmd_bursting assign byteen_asserted = |cmd_byteen; assign suppress_read = ~byteen_asserted; assign suppress_write = 1'b0; assign suppress_cmd = ~byteen_asserted && cmd_read; end else begin : no_suppress_0_byteen_cmd assign suppress_read = 1'b0; assign suppress_write = 1'b0; assign suppress_cmd = 1'b0; end endgenerate // ------------------------------------------------------------------- // Extract avalon signals from command packet. // ------------------------------------------------------------------- // Mask off the lower bits of address. // The burst adapter before this component will break narrow sized packets // into sub-bursts of length 1. However, the packet addresses are preserved, // which means this component may see size-aligned addresses. // // Masking ensures that the addresses seen by an Avalon slave are aligned to // the full data width instead of the size. // // Example: // output from burst adapter (datawidth=4, size=2 bytes): // subburst1 addr=0, subburst2 addr=2, subburst3 addr=4, subburst4 addr=6 // expected output from slave agent: // subburst1 addr=0, subburst2 addr=0, subburst3 addr=4, subburst4 addr=4 generate if (BITS_TO_MASK > 0) begin : mask_address assign m0_address = { cmd_addr[ADDR_W-1:BITS_TO_MASK], {BITS_TO_MASK{1'b0}} }; end else begin : no_mask_address assign m0_address = cmd_addr; end endgenerate assign m0_byteenable = cmd_byteen; assign m0_writedata = cmd_data; // Note: no Avalon-MM slave in existence accepts uncompressed read bursts - // this sort of burst exists only in merlin fabric ST packets. What to do // if we see such a burst? All beats in that burst need to be transmitted // to the slave so we have enough space-time for byteenable expression. // // There can be multiple bursts in a packet, but only one beat per burst // in cases. The exception is when we've decided not to insert a // burst adapter for efficiency reasons, in which case this agent is also // responsible for driving burstcount to 1 on each beat of an uncompressed // read burst. assign m0_read = ready_for_command & !suppress_read & (local_compressed_read | local_read); generate // AVS_BURSTCOUNT_W and BYTE_CNT_W may not be equal. Assign m0_burstcount // from a sub-range, or 0-pad, as appropriate. if (AVS_BURSTCOUNT_W > BYTE_CNT_W) begin : m0_burstcount_zero_pad wire [AVS_BURSTCOUNT_W - BYTE_CNT_W - 1 : 0] zero_pad = {(AVS_BURSTCOUNT_W - BYTE_CNT_W) {1'b0}}; assign m0_burstcount = (local_read & ~local_compressed_read) ? {zero_pad, num_symbols} : {zero_pad, cmd_byte_cnt}; end else begin : m0_burstcount_no_pad assign m0_burstcount = (local_read & ~local_compressed_read) ? num_symbols[AVS_BURSTCOUNT_W-1:0] : cmd_byte_cnt[AVS_BURSTCOUNT_W-1:0]; end endgenerate assign m0_write = ready_for_command & local_write & !suppress_write; assign m0_lock = ready_for_command & local_lock & (m0_read | m0_write); assign m0_debugaccess = cmd_debugaccess; // ------------------------------------------------------------------- // Indirection layer for response packet values. Some may always wire // directly from the slave translator; others will no doubt emerge from // various FIFOs. // What to put in resp_data when a write occured? Answer: it does not // matter, because only response status is needed for non-posted writes, // and the packet already has a field for that. // // We use the rdata_fifo to store write responses as well. This allows us // to handle backpressure on the response path, and allows write response // merging. assign rdata_fifo_src_valid = m0_readdatavalid | m0_writeresponsevalid; assign rdata_fifo_src_data = {m0_response, m0_readdata}; // ------------------------------------------------------------------ // Generate a token when read commands are suppressed. The token // is stored in the response FIFO, and will be used to synthesize // a read response. The same token is used for non-posted write // response synthesis. // // Note: this token is not generated for suppressed uncompressed read cycles; // the burst uncompression logic at the read side of the response FIFO // generates the correct number of responses. // // When the slave can return the response, let it do its job. Don't // synthesize a response in that case, unless we've suppressed the // the last transfer in a write sub-burst. // ------------------------------------------------------------------ wire write_end_of_subburst; assign needs_response_synthesis = ((local_read | local_compressed_read) & suppress_read) || (!USE_WRITERESPONSE && nonposted_write_endofpacket) || (USE_WRITERESPONSE && write_end_of_subburst && suppress_write); // Avalon-ST interfaces to external response FIFO. // // For efficiency, when synthesizing a write response we only store a non-posted write // transaction at its endofpacket, even if it was split into multiple sub-bursts. // // When not synthesizing write responses, we store each sub-burst in the FIFO. // Each sub-burst to the slave will return a response, which corresponds to one // entry in the FIFO. We merge all the sub-burst responses on the final // sub-burst and send it on the response channel. wire internal_cp_endofburst; wire [31:0] minimum_bytecount_wire = PKT_SYMBOLS; // to solve qis warning wire [AVS_BURSTCOUNT_W-1:0] minimum_bytecount; assign minimum_bytecount = minimum_bytecount_wire[AVS_BURSTCOUNT_W-1:0]; assign internal_cp_endofburst = (cmd_byte_cnt == minimum_bytecount); assign write_end_of_subburst = local_write & internal_cp_endofburst; assign rf_source_valid = (local_read | local_compressed_read | (nonposted_write_endofpacket && !USE_WRITERESPONSE) | (USE_WRITERESPONSE && internal_cp_endofburst && local_write)) & ready_for_command & cp_ready; assign rf_source_startofpacket = cp_startofpacket; assign rf_source_endofpacket = cp_endofpacket; always @* begin // default: assign every command packet field to the response FIFO... rf_source_data = {1'b0, cp_data}; // ... and override select fields as needed. rf_source_data[FIFO_DATA_W-1] = needs_response_synthesis; rf_source_data[PKT_DATA_H :PKT_DATA_L] = {DATA_W {1'b0}}; rf_source_data[PKT_BYTEEN_H :PKT_BYTEEN_L] = cmd_byteen; rf_source_data[PKT_ADDR_H :PKT_ADDR_L] = cmd_addr; rf_source_data[PKT_TRANS_COMPRESSED_READ] = cmd_compressed; rf_source_data[PKT_TRANS_POSTED] = cmd_posted; rf_source_data[PKT_TRANS_WRITE] = cmd_write; rf_source_data[PKT_TRANS_READ] = cmd_read; rf_source_data[PKT_SRC_ID_H :PKT_SRC_ID_L] = cmd_mid; rf_source_data[PKT_DEST_ID_H:PKT_DEST_ID_L] = cmd_sid; rf_source_data[PKT_BYTE_CNT_H:PKT_BYTE_CNT_L] = cmd_byte_cnt; rf_source_data[PKT_BURSTWRAP_H:PKT_BURSTWRAP_L] = cmd_burstwrap; rf_source_data[PKT_BURST_SIZE_H:PKT_BURST_SIZE_L] = cmd_burstsize; rf_source_data[PKT_PROTECTION_H:PKT_PROTECTION_L] = '0; rf_source_data[PKT_PROTECTION_L] = cmd_debugaccess; end wire uncompressor_source_valid; wire [BURSTSIZE_W-1:0] uncompressor_burstsize; wire last_write_response; // last_write_response indicates the last response of the broken-up write burst (sub-bursts). // At this time, the final merged response is sent, and rp_valid is only asserted // once for the whole burst. generate if (USE_WRITERESPONSE) begin assign last_write_response = rf_sink_data[PKT_TRANS_WRITE] & rf_sink_endofpacket; always @* begin if (rf_sink_data[PKT_TRANS_WRITE] == 1) rp_valid = (rdata_fifo_sink_valid | generate_response) & last_write_response & !rf_sink_data[PKT_TRANS_POSTED]; else rp_valid = rdata_fifo_sink_valid | uncompressor_source_valid; end end else begin assign last_write_response = 1'b0; always @* begin rp_valid = rdata_fifo_sink_valid | uncompressor_source_valid; end end endgenerate // ------------------------------------------------------------------ // Response merging // ------------------------------------------------------------------ reg [1:0] current_response; reg [1:0] response_merged; generate if (USE_WRITERESPONSE) begin : response_merging_all reg first_write_response; reg reset_merged_output; reg [1:0] previous_response_in; reg [1:0] previous_response; always_ff @(posedge clk, posedge reset) begin if (reset) begin first_write_response <= 1'b1; end else begin // Merging work for write response, for read: previous_response_in = current_response if (rf_sink_valid & (rdata_fifo_sink_valid | generate_response) & rf_sink_data[PKT_TRANS_WRITE]) begin first_write_response <= 1'b0; if (rf_sink_endofpacket) first_write_response <= 1'b1; end end end always_comb begin current_response = generate_response ? 2'b00 : rdata_fifo_sink_data[AVS_DATA_W+1:AVS_DATA_W] | {2{rdata_fifo_sink_error}}; reset_merged_output = first_write_response && (rdata_fifo_sink_valid || generate_response); previous_response_in = reset_merged_output ? current_response : previous_response; response_merged = current_response >= previous_response ? current_response: previous_response_in; end always_ff @(posedge clk or posedge reset) begin if (reset) begin previous_response <= 2'b00; end else begin if (rf_sink_valid & (rdata_fifo_sink_valid || generate_response)) begin previous_response <= response_merged; end end end end else begin : response_merging_read_only always @* begin current_response = generate_response ? 2'b00: rdata_fifo_sink_data[AVS_DATA_W+1:AVS_DATA_W] | {2{rdata_fifo_sink_error}}; response_merged = current_response; end end endgenerate assign generate_response = rf_sink_data[FIFO_DATA_W-1]; wire [BYTE_CNT_W-1:0] rf_sink_byte_cnt = rf_sink_data[PKT_BYTE_CNT_H:PKT_BYTE_CNT_L]; wire rf_sink_compressed = rf_sink_data[PKT_TRANS_COMPRESSED_READ]; wire [BURSTWRAP_W-1:0] rf_sink_burstwrap = rf_sink_data[PKT_BURSTWRAP_H:PKT_BURSTWRAP_L]; wire [BURSTSIZE_W-1:0] rf_sink_burstsize = rf_sink_data[PKT_BURST_SIZE_H:PKT_BURST_SIZE_L]; wire [ADDR_W-1:0] rf_sink_addr = rf_sink_data[PKT_ADDR_H:PKT_ADDR_L]; // a non posted write response is always completed in 1 cycle. Modify the startofpacket signal to 1'b1 instead of taking whatever is in the rf_fifo wire rf_sink_startofpacket_wire = rf_sink_data[PKT_TRANS_WRITE] ? 1'b1 : rf_sink_startofpacket; wire [BYTE_CNT_W-1:0] burst_byte_cnt; wire [BURSTWRAP_W-1:0] rp_burstwrap; wire [ADDR_W-1:0] rp_address; wire rp_is_compressed; wire ready_for_response; // ------------------------------------------------------------------ // We're typically ready for a response if the network is ready. There // is one exception: // // If the slave issues write responses, we only issue a merged response on // the final sub-burst. As a result, we only care about response channel // availability on the final burst when we send out the merged response. // ------------------------------------------------------------------ assign ready_for_response = (USE_WRITERESPONSE) ? rp_ready || (rf_sink_data[PKT_TRANS_WRITE] && !last_write_response) || rf_sink_data[PKT_TRANS_POSTED]: rp_ready; // ------------------------------------------------------------------ // Backpressure the readdata fifo if we're supposed to synthesize a response. // This may be a read response (for suppressed reads) or a write response // (for non-posted writes). // ------------------------------------------------------------------ assign rdata_fifo_sink_ready = rdata_fifo_sink_valid & ready_for_response & ~(rf_sink_valid & generate_response); always @* begin // By default, return all fields... rp_data = rf_sink_data[ST_DATA_W - 1 : 0]; // ... and override specific fields. rp_data[PKT_DATA_H :PKT_DATA_L] = rdata_fifo_sink_data[AVS_DATA_W-1:0]; // Assignments directly from the response fifo. rp_data[PKT_TRANS_POSTED] = rf_sink_data[PKT_TRANS_POSTED]; rp_data[PKT_TRANS_WRITE] = rf_sink_data[PKT_TRANS_WRITE]; rp_data[PKT_SRC_ID_H :PKT_SRC_ID_L] = rf_sink_data[PKT_DEST_ID_H : PKT_DEST_ID_L]; rp_data[PKT_DEST_ID_H:PKT_DEST_ID_L] = rf_sink_data[PKT_SRC_ID_H : PKT_SRC_ID_L]; rp_data[PKT_BYTEEN_H :PKT_BYTEEN_L] = rf_sink_data[PKT_BYTEEN_H : PKT_BYTEEN_L]; rp_data[PKT_PROTECTION_H:PKT_PROTECTION_L] = rf_sink_data[PKT_PROTECTION_H:PKT_PROTECTION_L]; // Burst uncompressor assignments rp_data[PKT_ADDR_H :PKT_ADDR_L] = rp_address; rp_data[PKT_BURSTWRAP_H:PKT_BURSTWRAP_L] = rp_burstwrap; rp_data[PKT_BYTE_CNT_H:PKT_BYTE_CNT_L] = burst_byte_cnt; rp_data[PKT_TRANS_READ] = rf_sink_data[PKT_TRANS_READ] | rf_sink_data[PKT_TRANS_COMPRESSED_READ]; rp_data[PKT_TRANS_COMPRESSED_READ] = rp_is_compressed; rp_data[PKT_RESPONSE_STATUS_H:PKT_RESPONSE_STATUS_L] = response_merged; rp_data[PKT_BURST_SIZE_H:PKT_BURST_SIZE_L] = uncompressor_burstsize; // bounce the original size back to the master untouched rp_data[PKT_ORI_BURST_SIZE_H:PKT_ORI_BURST_SIZE_L] = rf_sink_data[PKT_ORI_BURST_SIZE_H:PKT_ORI_BURST_SIZE_L]; end // ------------------------------------------------------------------ // Note: the burst uncompressor may be asked to generate responses for // write packets; these are treated the same as single-cycle uncompressed // reads. // ------------------------------------------------------------------ altera_merlin_burst_uncompressor #( .ADDR_W (ADDR_W), .BURSTWRAP_W (BURSTWRAP_W), .BYTE_CNT_W (BYTE_CNT_W), .PKT_SYMBOLS (PKT_SYMBOLS), .BURST_SIZE_W (BURSTSIZE_W) ) uncompressor ( .clk (clk), .reset (reset), .sink_startofpacket (rf_sink_startofpacket_wire), .sink_endofpacket (rf_sink_endofpacket), .sink_valid (rf_sink_valid & (rdata_fifo_sink_valid | generate_response)), .sink_ready (rf_sink_ready), .sink_addr (rf_sink_addr), .sink_burstwrap (rf_sink_burstwrap), .sink_byte_cnt (rf_sink_byte_cnt), .sink_is_compressed (rf_sink_compressed), .sink_burstsize (rf_sink_burstsize), .source_startofpacket (rp_startofpacket), .source_endofpacket (rp_endofpacket), .source_valid (uncompressor_source_valid), .source_ready (ready_for_response), .source_addr (rp_address), .source_burstwrap (rp_burstwrap), .source_byte_cnt (burst_byte_cnt), .source_is_compressed (rp_is_compressed), .source_burstsize (uncompressor_burstsize) ); //-------------------------------------- // Assertion: In case slave support response. The slave needs return response in order // Ex: non-posted write followed by a read: write response must complete before read data //-------------------------------------- // synthesis translate_off ERROR_write_response_and_read_response_cannot_happen_same_time: assert property ( @(posedge clk) disable iff (reset) !(m0_writeresponsevalid && m0_readdatavalid) ); // synthesis translate_on endmodule