../src/lowrisc_prim_generic_ram_2p_0/rtl/prim_generic_ram_2p.sv Cov: 89.8%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4: //
5: // Synchronous dual-port SRAM register model
6: // This module is for simulation and small size SRAM.
7: // Implementing ECC should be done inside wrapper not this model.
8:
9: module prim_generic_ram_2p #(
10: parameter int Width = 32, // bit
11: parameter int Depth = 128,
12: parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask
13: parameter MemInitFile = "", // VMEM file to initialize the memory with
14:
15: localparam int Aw = $clog2(Depth) // derived parameter
16: ) (
17: input clk_a_i,
18: input clk_b_i,
19:
20: input a_req_i,
21: input a_write_i,
22: input [Aw-1:0] a_addr_i,
23: input [Width-1:0] a_wdata_i,
24: input logic [Width-1:0] a_wmask_i,
25: output logic [Width-1:0] a_rdata_o,
26:
27:
28: input b_req_i,
29: input b_write_i,
30: input [Aw-1:0] b_addr_i,
31: input [Width-1:0] b_wdata_i,
32: input logic [Width-1:0] b_wmask_i,
33: output logic [Width-1:0] b_rdata_o
34: );
35: // Width of internal write mask. Note *_wmask_i input into the module is always assumed
36: // to be the full bit mask.
37: localparam int MaskWidth = Width / DataBitsPerMask;
38:
39: logic [Width-1:0] mem [Depth];
40: logic [MaskWidth-1:0] a_wmask;
41: logic [MaskWidth-1:0] b_wmask;
42:
43: always_comb begin
44: for (int i=0; i < MaskWidth; i = i + 1) begin : create_wmask
45: a_wmask[i] = &a_wmask_i[i*DataBitsPerMask +: DataBitsPerMask];
46: b_wmask[i] = &b_wmask_i[i*DataBitsPerMask +: DataBitsPerMask];
47: end
48: end
49:
50:
51: // Xilinx FPGA specific Dual-port RAM coding style
52: // using always instead of always_ff to avoid 'ICPD - illegal combination of drivers' error
53: // thrown due to 'mem' being driven by two always processes below
54: always @(posedge clk_a_i) begin
55: if (a_req_i) begin
56: if (a_write_i) begin
57: for (int i=0; i < MaskWidth; i = i + 1) begin
58: if (a_wmask[i]) begin
59: mem[a_addr_i][i*DataBitsPerMask +: DataBitsPerMask] <=
60: a_wdata_i[i*DataBitsPerMask +: DataBitsPerMask];
61: end
62: end
63: end else begin
64: a_rdata_o <= mem[a_addr_i];
65: end
66: end
67: end
68:
69: always @(posedge clk_b_i) begin
70: if (b_req_i) begin
71: if (b_write_i) begin
72: for (int i=0; i < MaskWidth; i = i + 1) begin
73: if (b_wmask[i]) begin
74: mem[b_addr_i][i*DataBitsPerMask +: DataBitsPerMask] <=
75: b_wdata_i[i*DataBitsPerMask +: DataBitsPerMask];
76: end
77: end
78: end else begin
79: b_rdata_o <= mem[b_addr_i];
80: end
81: end
82: end
83:
84: `include "prim_util_memload.sv"
85:
86: endmodule
87: