hw/ip/prim_xilinx/rtl/prim_xilinx_rom.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: /**
6: * Implementation of a Read-Only Memory (ROM) primitive for Xilinx FPGAs
7: *
8: * This implementation of a ROM primitive is coded as outlined in UG 901 to
9: * enable Xilinx Vivado infer Block RAM (BRAM) or LUT RAM from it. No mapping
10: * target is forced; depending on the Width, Depth and other factors Vivado
11: * chooses a mapping target.
12: *
13: * It is possible to force the mapping to BRAM or distributed RAM by using the
14: * ROM_STYLE directive in an XDC file.
15: */
16: module prim_xilinx_rom #(
17: parameter int Width = 32,
18: parameter int Depth = 2048, // 8kB default
19: parameter int Aw = $clog2(Depth)
20: ) (
21: input clk_i,
22: input [Aw-1:0] addr_i,
23: input cs_i,
24: output logic [Width-1:0] dout_o,
25: output logic dvalid_o
26:
27: );
28:
29: `ifdef ROM_INIT_FILE
30: // Only create an actual ROM block if ROM data is specified
31: //
32: // Xilinx Vivado infers a BRAM or LUTRAM from the ROM code below only if mem
33: // is actually being written to through $readmemh(). If no ROM_INIT_FILE is
34: // given and hence the mem initialization is missing, registers are inferred
35: // instead. This severely degrades the synthesis quality for no good reason.
36: logic [Width-1:0] mem [Depth];
37:
38: localparam MEM_FILE = `"`ROM_INIT_FILE`";
39: initial
40: begin
41: $display("Initializing ROM from %s", MEM_FILE);
42: $readmemh(MEM_FILE, mem);
43: end
44:
45: always_ff @(posedge clk_i) begin
46: if (cs_i) begin
47: dout_o <= mem[addr_i];
48: end
49: end
50: `else
51: // ROM is not initialized
52: always_ff @(posedge clk_i) begin
53: dout_o <= '0;
54: end
55: `endif
56:
57: always_ff @(posedge clk_i) begin
58: dvalid_o <= cs_i;
59: end
60:
61:
62: ////////////////
63: // ASSERTIONS //
64: ////////////////
65:
66: // Control Signals should never be X
67: `ASSERT(noXOnCsI, !$isunknown(cs_i), clk_i, '0)
68:
69: endmodule
70: