From c439813c28dda0d6b74e9b72539c546c9c15c5ae Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 20 Aug 2024 18:31:10 +0200 Subject: [PATCH] Add passthrough mode for mem_to_banks with NumBanks==1 --- src/mem_to_banks_detailed.sv | 237 +++++++++++++++++++---------------- 1 file changed, 129 insertions(+), 108 deletions(-) diff --git a/src/mem_to_banks_detailed.sv b/src/mem_to_banks_detailed.sv index 24160031..0d3eb7e8 100644 --- a/src/mem_to_banks_detailed.sv +++ b/src/mem_to_banks_detailed.sv @@ -104,118 +104,139 @@ module mem_to_banks_detailed #( logic we; } req_t; - logic req_valid; - logic [NumBanks-1:0] req_ready, - resp_valid, resp_ready; - req_t [NumBanks-1:0] bank_req, - bank_oup; - logic [NumBanks-1:0] bank_req_internal, - bank_gnt_internal, - zero_strobe, - dead_response, - dead_response_unmasked; - logic dead_write_fifo_full, - dead_write_fifo_empty; - - function automatic addr_t align_addr(input addr_t addr); - return (addr >> $clog2(DataBytes)) << $clog2(DataBytes); - endfunction - - // Handle requests. - assign req_valid = req_i & gnt_o; - for (genvar i = 0; unsigned'(i) < NumBanks; i++) begin : gen_reqs - assign bank_req[i].addr = align_addr(addr_i) + i * BytesPerBank; - assign bank_req[i].wdata = wdata_i[i*BitsPerBank+:BitsPerBank]; - assign bank_req[i].strb = strb_i[i*BytesPerBank+:BytesPerBank]; - assign bank_req[i].wuser = wuser_i; - assign bank_req[i].we = we_i; - stream_fifo #( - .FALL_THROUGH ( 1'b1 ), - .DATA_WIDTH ( $bits(req_t) ), - .DEPTH ( FifoDepth ), - .T ( req_t ) - ) i_ft_reg ( - .clk_i, - .rst_ni, - .flush_i ( 1'b0 ), - .testmode_i ( 1'b0 ), - .usage_o (), - .data_i ( bank_req[i] ), - .valid_i ( req_valid ), - .ready_o ( req_ready[i] ), - .data_o ( bank_oup[i] ), - .valid_o ( bank_req_internal[i] ), - .ready_i ( bank_gnt_internal[i] ) - ); - assign bank_addr_o[i] = bank_oup[i].addr; - assign bank_wdata_o[i] = bank_oup[i].wdata; - assign bank_strb_o[i] = bank_oup[i].strb; - assign bank_wuser_o[i] = bank_oup[i].wuser; - assign bank_we_o[i] = bank_oup[i].we; - - assign zero_strobe[i] = (bank_req[i].strb == '0); - - if (HideStrb) begin : gen_hide_strb - assign bank_req_o[i] = (bank_oup[i].we && (bank_oup[i].strb == '0)) ? - 1'b0 : bank_req_internal[i]; - assign bank_gnt_internal[i] = (bank_oup[i].we && (bank_oup[i].strb == '0)) ? - 1'b1 : bank_gnt_i[i]; - end else begin : gen_legacy_strb - assign bank_req_o[i] = bank_req_internal[i]; - assign bank_gnt_internal[i] = bank_gnt_i[i]; + if (NumBanks == 1) begin : gen_passthrough + + // Simply connects passthrough. + // Does not provide HideStrb functionality. + // Removes unnecessary buffers in the design. + + assign bank_req_o [0] = req_i; + assign gnt_o = bank_gnt_i [0]; + assign bank_addr_o [0] = addr_i; + assign bank_wdata_o[0] = wdata_i; + assign bank_strb_o [0] = strb_i; + assign bank_wuser_o[0] = wuser_i; + assign bank_we_o [0] = we_i; + assign rvalid_o = bank_rvalid_i[0]; + assign rdata_o = bank_rdata_i [0]; + assign ruser_o [0] = bank_ruser_i [0]; + + end else begin : gen_banking + + logic req_valid; + logic [NumBanks-1:0] req_ready, + resp_valid, resp_ready; + req_t [NumBanks-1:0] bank_req, + bank_oup; + logic [NumBanks-1:0] bank_req_internal, + bank_gnt_internal, + zero_strobe, + dead_response, + dead_response_unmasked; + logic dead_write_fifo_full, + dead_write_fifo_empty; + + function automatic addr_t align_addr(input addr_t addr); + return (addr >> $clog2(DataBytes)) << $clog2(DataBytes); + endfunction + + // Handle requests. + assign req_valid = req_i & gnt_o; + for (genvar i = 0; unsigned'(i) < NumBanks; i++) begin : gen_reqs + assign bank_req[i].addr = align_addr(addr_i) + i * BytesPerBank; + assign bank_req[i].wdata = wdata_i[i*BitsPerBank+:BitsPerBank]; + assign bank_req[i].strb = strb_i[i*BytesPerBank+:BytesPerBank]; + assign bank_req[i].wuser = wuser_i; + assign bank_req[i].we = we_i; + stream_fifo #( + .FALL_THROUGH ( 1'b1 ), + .DATA_WIDTH ( $bits(req_t) ), + .DEPTH ( FifoDepth ), + .T ( req_t ) + ) i_ft_reg ( + .clk_i, + .rst_ni, + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .usage_o (), + .data_i ( bank_req[i] ), + .valid_i ( req_valid ), + .ready_o ( req_ready[i] ), + .data_o ( bank_oup[i] ), + .valid_o ( bank_req_internal[i] ), + .ready_i ( bank_gnt_internal[i] ) + ); + assign bank_addr_o[i] = bank_oup[i].addr; + assign bank_wdata_o[i] = bank_oup[i].wdata; + assign bank_strb_o[i] = bank_oup[i].strb; + assign bank_wuser_o[i] = bank_oup[i].wuser; + assign bank_we_o[i] = bank_oup[i].we; + + assign zero_strobe[i] = (bank_req[i].strb == '0); + + if (HideStrb) begin : gen_hide_strb + assign bank_req_o[i] = (bank_oup[i].we && (bank_oup[i].strb == '0)) ? + 1'b0 : bank_req_internal[i]; + assign bank_gnt_internal[i] = (bank_oup[i].we && (bank_oup[i].strb == '0)) ? + 1'b1 : bank_gnt_i[i]; + end else begin : gen_legacy_strb + assign bank_req_o[i] = bank_req_internal[i]; + assign bank_gnt_internal[i] = bank_gnt_i[i]; + end end - end - // Grant output if all our requests have been granted. - assign gnt_o = (&req_ready) & (&resp_ready) & !dead_write_fifo_full; - - if (HideStrb) begin : gen_dead_write_fifo - fifo_v3 #( - .FALL_THROUGH ( 1'b0 ), - .DEPTH ( MaxTrans+1 ), - .DATA_WIDTH ( NumBanks ) - ) i_dead_write_fifo ( - .clk_i, - .rst_ni, - .flush_i ( 1'b0 ), - .testmode_i ( 1'b0 ), - .full_o ( dead_write_fifo_full ), - .empty_o ( dead_write_fifo_empty ), - .usage_o (), - .data_i ( {NumBanks{we_i}} & zero_strobe ), - .push_i ( req_i & gnt_o ), - .data_o ( dead_response_unmasked ), - .pop_i ( rvalid_o ) - ); - assign dead_response = dead_response_unmasked & {NumBanks{~dead_write_fifo_empty}}; - end else begin : gen_no_dead_write_fifo - assign dead_response_unmasked = '0; - assign dead_response = '0; - assign dead_write_fifo_full = 1'b0; - assign dead_write_fifo_empty = 1'b1; - end + // Grant output if all our requests have been granted. + assign gnt_o = (&req_ready) & (&resp_ready) & !dead_write_fifo_full; + + if (HideStrb) begin : gen_dead_write_fifo + fifo_v3 #( + .FALL_THROUGH ( 1'b0 ), + .DEPTH ( MaxTrans+1 ), + .DATA_WIDTH ( NumBanks ) + ) i_dead_write_fifo ( + .clk_i, + .rst_ni, + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .full_o ( dead_write_fifo_full ), + .empty_o ( dead_write_fifo_empty ), + .usage_o (), + .data_i ( {NumBanks{we_i}} & zero_strobe ), + .push_i ( req_i & gnt_o ), + .data_o ( dead_response_unmasked ), + .pop_i ( rvalid_o ) + ); + assign dead_response = dead_response_unmasked & {NumBanks{~dead_write_fifo_empty}}; + end else begin : gen_no_dead_write_fifo + assign dead_response_unmasked = '0; + assign dead_response = '0; + assign dead_write_fifo_full = 1'b0; + assign dead_write_fifo_empty = 1'b1; + end + + // Handle responses. + for (genvar i = 0; unsigned'(i) < NumBanks; i++) begin : gen_resp_regs + stream_fifo #( + .FALL_THROUGH ( 1'b1 ), + .DATA_WIDTH ( $bits(oup_data_t) + $bits(oup_ruser_t) ), + .DEPTH ( FifoDepth ) + ) i_ft_reg ( + .clk_i, + .rst_ni, + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .usage_o (), + .data_i ( {bank_rdata_i[i], bank_ruser_i[i]} ), + .valid_i ( bank_rvalid_i[i] ), + .ready_o ( resp_ready[i] ), + .data_o ( {rdata_o[i*BitsPerBank+:BitsPerBank], ruser_o[i]} ), + .valid_o ( resp_valid[i] ), + .ready_i ( rvalid_o & !dead_response[i] ) + ); + end + assign rvalid_o = &(resp_valid | dead_response); - // Handle responses. - for (genvar i = 0; unsigned'(i) < NumBanks; i++) begin : gen_resp_regs - stream_fifo #( - .FALL_THROUGH ( 1'b1 ), - .DATA_WIDTH ( $bits(oup_data_t) + $bits(oup_ruser_t) ), - .DEPTH ( FifoDepth ) - ) i_ft_reg ( - .clk_i, - .rst_ni, - .flush_i ( 1'b0 ), - .testmode_i ( 1'b0 ), - .usage_o (), - .data_i ( {bank_rdata_i[i], bank_ruser_i[i]} ), - .valid_i ( bank_rvalid_i[i] ), - .ready_o ( resp_ready[i] ), - .data_o ( {rdata_o[i*BitsPerBank+:BitsPerBank], ruser_o[i]} ), - .valid_o ( resp_valid[i] ), - .ready_i ( rvalid_o & !dead_response[i] ) - ); end - assign rvalid_o = &(resp_valid | dead_response); // Assertions `ifndef SYNTHESIS