ibex/shared/rtl/ram_2p.sv
Pirmin Vogel db926e5ef5 [ram_2p] Set DataBitsPerMask parameter for prim_ram_2p
It turned out that with the default value of 1, Vivado infers a separate
18 Kbit BRAM instance for each bit of the 32-bit word for the FPGA
examples. This can be very wasteful in terms of resource utilization
especially for smaller configurations.

As our examples don't use ECC or parity and mainly target simualation
and FPGA, it's better to use a value of 8 for the DataBitsPerMask
parameter. Vivado will then not distribute words across different BRAM
instances which results in more efficient FPGA resource utilization.

For a detailed analysis and explanation, please refer to
lowRISC/Ibex#1587.

Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
2022-04-01 16:32:45 +02:00

91 lines
2.2 KiB
Systemverilog

// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
/**
* Dual-port RAM with 1 cycle read/write delay, 32 bit words.
*/
`include "prim_assert.sv"
module ram_2p #(
parameter int Depth = 128,
parameter MemInitFile = ""
) (
input clk_i,
input rst_ni,
input a_req_i,
input a_we_i,
input [ 3:0] a_be_i,
input [31:0] a_addr_i,
input [31:0] a_wdata_i,
output logic a_rvalid_o,
output logic [31:0] a_rdata_o,
input b_req_i,
input b_we_i,
input [ 3:0] b_be_i,
input [31:0] b_addr_i,
input [31:0] b_wdata_i,
output logic b_rvalid_o,
output logic [31:0] b_rdata_o
);
localparam int Aw = $clog2(Depth);
logic [Aw-1:0] a_addr_idx;
assign a_addr_idx = a_addr_i[Aw-1+2:2];
logic [31-Aw:0] unused_a_addr_parts;
assign unused_a_addr_parts = {a_addr_i[31:Aw+2], a_addr_i[1:0]};
logic [Aw-1:0] b_addr_idx;
assign b_addr_idx = b_addr_i[Aw-1+2:2];
logic [31-Aw:0] unused_b_addr_parts;
assign unused_b_addr_parts = {b_addr_i[31:Aw+2], b_addr_i[1:0]};
// Convert byte mask to SRAM bit mask.
logic [31:0] a_wmask;
logic [31:0] b_wmask;
always_comb begin
for (int i = 0 ; i < 4 ; i++) begin
// mask for read data
a_wmask[8*i+:8] = {8{a_be_i[i]}};
b_wmask[8*i+:8] = {8{b_be_i[i]}};
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
a_rvalid_o <= '0;
b_rvalid_o <= '0;
end else begin
a_rvalid_o <= a_req_i;
b_rvalid_o <= b_req_i;
end
end
prim_ram_2p #(
.Width(32),
.Depth(Depth),
.DataBitsPerMask(8),
.MemInitFile(MemInitFile)
) u_ram (
.clk_a_i (clk_i),
.clk_b_i (clk_i),
.cfg_i ('0),
.a_req_i (a_req_i),
.a_write_i (a_we_i),
.a_addr_i (a_addr_idx),
.a_wdata_i (a_wdata_i),
.a_wmask_i (a_wmask),
.a_rdata_o (a_rdata_o),
.b_req_i (b_req_i),
.b_write_i (b_we_i),
.b_wmask_i (b_wmask),
.b_addr_i (b_addr_idx),
.b_wdata_i (b_wdata_i),
.b_rdata_o (b_rdata_o)
);
endmodule