hw/ip/prim_generic/rtl/prim_generic_ram_1p.sv Cov: 100%
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 single-port SRAM model
6:
7: module prim_generic_ram_1p #(
8: parameter int Width = 32, // bit
9: parameter int Depth = 128,
10: parameter int DataBitsPerMask = 1, // Number of data bits per bit of write mask
11: localparam int Aw = $clog2(Depth) // derived parameter
12: ) (
13: input clk_i,
14: input rst_ni, // Memory content reset
15:
16: input req_i,
17: input write_i,
18: input [Aw-1:0] addr_i,
19: input [Width-1:0] wdata_i,
20: input [Width-1:0] wmask_i,
21: output logic rvalid_o,
22: output logic [Width-1:0] rdata_o
23: );
24:
25: // Width of internal write mask. Note wmask_i input into the module is always assumed
26: // to be the full bit mask
27: localparam int MaskWidth = Width / DataBitsPerMask;
28:
29: logic [Width-1:0] mem [Depth];
30: logic [MaskWidth-1:0] wmask;
31:
32: always_comb begin
33: for (int i=0; i < MaskWidth; i = i + 1) begin : create_wmask
34: wmask[i] = &wmask_i[i*DataBitsPerMask +: DataBitsPerMask];
35: end
36: end
37:
38: // using always instead of always_ff to avoid 'ICPD - illegal combination of drivers' error
39: // thrown when using $readmemh system task to backdoor load an image
40: always @(posedge clk_i) begin
41: if (req_i) begin
42: if (write_i) begin
43: for (int i=0; i < MaskWidth; i = i + 1) begin
44: if (wmask[i]) begin
45: mem[addr_i][i*DataBitsPerMask +: DataBitsPerMask] <=
46: wdata_i[i*DataBitsPerMask +: DataBitsPerMask];
47: end
48: end
49: end else begin
50: rdata_o <= mem[addr_i];
51: end
52: end
53: end
54:
55: always_ff @(posedge clk_i, negedge rst_ni) begin
56: if (!rst_ni) begin
57: rvalid_o <= '0;
58: end else begin
59: rvalid_o <= req_i & ~write_i;
60: end
61: end
62:
63: `ifdef VERILATOR
64: // Task for loading 'mem' with SystemVerilog system task $readmemh()
65: export "DPI-C" task simutil_verilator_memload;
66: // Function for setting a specific 32 bit element in |mem|
67: // Returns 1 (true) for success, 0 (false) for errors.
68: export "DPI-C" function simutil_verilator_set_mem;
69:
70: task simutil_verilator_memload;
71: input string file;
72: $readmemh(file, mem);
73: endtask
74:
75: // TODO: Allow 'val' to have other widths than 32 bit
76: function int simutil_verilator_set_mem(input int index,
77: input logic[31:0] val);
78: if (index >= Depth) begin
79: return 0;
80: end
81:
82: mem[index] = val;
83: return 1;
84: endfunction
85: `endif
86:
87: `ifdef SRAM_INIT_FILE
88: localparam MEM_FILE = `"`SRAM_INIT_FILE`";
89: initial begin
90: $display("Initializing SRAM from %s", MEM_FILE);
91: $readmemh(MEM_FILE, mem);
92: end
93: `endif
94: endmodule
95: