Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add passthrough mode for mem_to_banks with NumBanks==1 #226

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
237 changes: 129 additions & 108 deletions src/mem_to_banks_detailed.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading