|
| 1 | +/***************************************************************************** |
| 2 | + * Function: Dual Port Memory ({{ type }}) |
| 3 | + * Copyright: Lambda Project Authors. All rights Reserved. |
| 4 | + * License: MIT (see LICENSE file in Lambda repository) |
| 5 | + * |
| 6 | + * Docs: |
| 7 | + * |
| 8 | + * This is a wrapper for selecting from a set of hardened memory macros. |
| 9 | + * |
| 10 | + * A synthesizable reference model is used when the PROP is DEFAULT. The |
| 11 | + * synthesizable model does not implement the cfg and test interface and should |
| 12 | + * only be used for basic testing and for synthesizing for FPGA devices. |
| 13 | + * Advanced ASIC development should rely on complete functional models |
| 14 | + * supplied on a per macro basis. |
| 15 | + * |
| 16 | + * Technologoy specific implementations of "{{ type }}" would generally include |
| 17 | + * one or more hardcoded instantiations of {{ type }} modules with a generate |
| 18 | + * statement relying on the "PROP" to select between the list of modules |
| 19 | + * at build time. |
| 20 | + * |
| 21 | + ****************************************************************************/ |
| 22 | + |
| 23 | +module {{ type }} |
| 24 | + #(parameter DW = 32, // Memory width |
| 25 | + parameter AW = 10, // Address width (derived) |
| 26 | + parameter PROP = "DEFAULT", // Pass through variable for hard macro |
| 27 | + parameter CTRLW = 128, // Width of asic ctrl interface |
| 28 | + parameter TESTW = 128 // Width of asic test interface |
| 29 | + ) |
| 30 | + (// Memory interface |
| 31 | + // Write port |
| 32 | + input wr_clk, // write clock |
| 33 | + input wr_ce, // write chip-enable |
| 34 | + input wr_we, // write enable |
| 35 | + input [DW-1:0] wr_wmask, // write mask |
| 36 | + input [AW-1:0] wr_addr, // write address |
| 37 | + input [DW-1:0] wr_din, //write data in |
| 38 | + // Read port |
| 39 | + input rd_clk, // read clock |
| 40 | + input rd_ce, // read chip-enable |
| 41 | + input [AW-1:0] rd_addr, // read address |
| 42 | + output [DW-1:0] rd_dout, //read data out |
| 43 | + // Power signals |
| 44 | + input vss, // ground signal |
| 45 | + input vdd, // memory core array power |
| 46 | + input vddio, // periphery/io power |
| 47 | + // Generic interfaces |
| 48 | + input [CTRLW-1:0] ctrl, // pass through ASIC control interface |
| 49 | + input [TESTW-1:0] test // pass through ASIC test interface |
| 50 | + ); |
| 51 | + |
| 52 | + // Total number of bits |
| 53 | + localparam TOTAL_BITS = (2 ** AW) * DW; |
| 54 | + |
| 55 | + // Determine which memory to select |
| 56 | + localparam MEM_PROP = (PROP != "DEFAULT") ? PROP :{% if minsize > 0 %} ({{ minsize }} >= TOTAL_BITS) ? "SOFT" :{% endif %}{% for aw, dw_select in selection_table.items() %} |
| 57 | + {% if loop.nextitem is defined %}(AW >= {{ aw }}) ? {% endif %}{% for dw, memory in dw_select.items() %}{% if loop.nextitem is defined %}(DW >= {{dw}}) ? {% endif %}"{{ memory}}"{% if loop.nextitem is defined %} : {% endif%}{% endfor %}{% if loop.nextitem is defined %} :{% else %};{% endif %}{% endfor %} |
| 58 | + |
| 59 | + localparam MEM_WIDTH = {% for memory, width in width_table %} |
| 60 | + (MEM_PROP == "{{ memory }}") ? {{ width }} :{% endfor %} |
| 61 | + 0; |
| 62 | + |
| 63 | + localparam MEM_DEPTH = {% for memory, depth in depth_table %} |
| 64 | + (MEM_PROP == "{{ memory }}") ? {{ depth }} :{% endfor %} |
| 65 | + 0; |
| 66 | + |
| 67 | + generate |
| 68 | + if (MEM_PROP == "SOFT") begin: isoft |
| 69 | + la_dpram_impl #( |
| 70 | + .DW(DW), |
| 71 | + .AW(AW), |
| 72 | + .PROP(PROP), |
| 73 | + .CTRLW(CTRLW), |
| 74 | + .TESTW(TESTW) |
| 75 | + ) memory( |
| 76 | + .clk(clk), |
| 77 | + .ce(ce), |
| 78 | + .we(we), |
| 79 | + .wmask(wmask), |
| 80 | + .addr(addr), |
| 81 | + .din(din), |
| 82 | + .dout(dout), |
| 83 | + .vss(vss), |
| 84 | + .vdd(vdd), |
| 85 | + .vddio(vddio), |
| 86 | + .ctrl(ctrl), |
| 87 | + .test(test) |
| 88 | + ); |
| 89 | + end |
| 90 | + if (MEM_PROP != "SOFT") begin: itech |
| 91 | + // Create memories |
| 92 | + localparam MEM_ADDRS = 2**(AW - MEM_DEPTH) < 1 ? 1 : 2**(AW - MEM_DEPTH); |
| 93 | + |
| 94 | + {% if control_signals %}// Control signals{% for line in control_signals %} |
| 95 | + {{ line }}{% endfor %}{% endif %} |
| 96 | + |
| 97 | + genvar o; |
| 98 | + for (o = 0; o < DW; o = o + 1) begin: OUTPUTS |
| 99 | + wire [MEM_ADDRS-1:0] mem_outputs; |
| 100 | + assign rd_dout[o] = |mem_outputs; |
| 101 | + end |
| 102 | + |
| 103 | + genvar a; |
| 104 | + for (a = 0; a < MEM_ADDRS; a = a + 1) begin: ADDR |
| 105 | + wire selected; |
| 106 | + wire [MEM_DEPTH-1:0] wr_mem_addr; |
| 107 | + wire [MEM_DEPTH-1:0] rd_mem_addr; |
| 108 | + |
| 109 | + if (MEM_ADDRS == 1) begin: FITS |
| 110 | + assign selected = 1'b1; |
| 111 | + assign wr_mem_addr = wr_addr; |
| 112 | + assign rd_mem_addr = rd_addr; |
| 113 | + end else begin: NOFITS |
| 114 | + assign selected = addr[AW-1:MEM_DEPTH] == a; |
| 115 | + assign wr_mem_addr = wr_addr[MEM_DEPTH-1:0]; |
| 116 | + assign rd_mem_addr = rd_addr[MEM_DEPTH-1:0]; |
| 117 | + end |
| 118 | + |
| 119 | + genvar n; |
| 120 | + for (n = 0; n < DW; n = n + MEM_WIDTH) begin: WORD |
| 121 | + wire [MEM_WIDTH-1:0] mem_din; |
| 122 | + wire [MEM_WIDTH-1:0] mem_dout; |
| 123 | + wire [MEM_WIDTH-1:0] mem_wmask; |
| 124 | + |
| 125 | + genvar i; |
| 126 | + for (i = 0; i < MEM_WIDTH; i = i + 1) begin: WORD_SELECT |
| 127 | + if (n + i < DW) begin: ACTIVE |
| 128 | + assign mem_din[i] = wr_din[n + i]; |
| 129 | + assign mem_wmask[i] = wr_wmask[n + i]; |
| 130 | + assign OUTPUTS[n + i].mem_outputs[a] = selected ? mem_dout[i] : 1'b0; |
| 131 | + end |
| 132 | + else begin: INACTIVE |
| 133 | + assign mem_din[i] = 1'b0; |
| 134 | + assign mem_wmask[i] = 1'b0; |
| 135 | + end |
| 136 | + end |
| 137 | + |
| 138 | + wire ce_in; |
| 139 | + wire we_in; |
| 140 | + assign wr_ce_in = wr_ce && selected; |
| 141 | + assign rd_ce_in = rd_ce && selected; |
| 142 | + assign we_in = wr_we && selected; |
| 143 | + {% for memory, inst_name in inst_map.items() %} |
| 144 | + if (MEM_PROP == "{{ memory }}") begin: i{{ memory }} |
| 145 | + {{ inst_name }} memory ({% for port, net in port_mapping[memory] %} |
| 146 | + .{{ port }}({{ net }}){% if loop.nextitem is defined %},{% endif %}{% endfor %} |
| 147 | + ); |
| 148 | + end{% endfor %} |
| 149 | + end |
| 150 | + end |
| 151 | + end |
| 152 | + endgenerate |
| 153 | +endmodule |
0 commit comments