|
| 1 | +/***************************************************************************** |
| 2 | + * Function: Single Port {{ 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 TYPE 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 "la_sp{{ type }}" would generally include |
| 17 | + * one ore more hardcoded instantiations of {{ type }} modules with a generate |
| 18 | + * statement relying on the "TYPE" to select between the list of modules |
| 19 | + * at build time. |
| 20 | + * |
| 21 | + ****************************************************************************/ |
| 22 | + |
| 23 | +module la_sp{{ type }} |
| 24 | + #(parameter DW = 32, // Memory width |
| 25 | + parameter AW = 10, // Address width (derived) |
| 26 | + parameter TYPE = "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 | + input clk, // write clock |
| 32 | + input ce, // chip enable |
| 33 | + input we, // write enable |
| 34 | + input [DW-1:0] wmask, //per bit write mask |
| 35 | + input [AW-1:0] addr, //write address |
| 36 | + input [DW-1:0] din, //write data |
| 37 | + output [DW-1:0] dout, //read output data |
| 38 | + // Power signals |
| 39 | + input vss, // ground signal |
| 40 | + input vdd, // memory core array power |
| 41 | + input vddio, // periphery/io power |
| 42 | + // Generic interfaces |
| 43 | + input [CTRLW-1:0] ctrl, // pass through ASIC control interface |
| 44 | + input [TESTW-1:0] test // pass through ASIC test interface |
| 45 | + ); |
| 46 | + |
| 47 | + // Determine which memory to select |
| 48 | + localparam MEM_TYPE = (TYPE != "DEFAULT") ? TYPE :{% for aw, dw_select in selection_table.items() %} |
| 49 | + {% if loop.nextitem is defined %}(AW {% if loop.previtem is defined %}=={% else %}>={% endif %} {{ aw }}) ? {% endif %}{% for dw, memory in dw_select.items() %}{% if loop.nextitem is defined %}(DW {% if loop.previtem is defined %}=={% else %}>={% endif %} {{dw}}) ? {% endif %}"{{ memory}}"{% if loop.nextitem is defined %} : {% endif%}{% endfor %}{% if loop.nextitem is defined %} :{% else %};{% endif %}{% endfor %} |
| 50 | + |
| 51 | + localparam MEM_WIDTH = {% for memory, width in width_table %} |
| 52 | + (MEM_TYPE == "{{ memory }}") ? {{ width }} :{% endfor %} |
| 53 | + 0; |
| 54 | + |
| 55 | + localparam MEM_DEPTH = {% for memory, depth in depth_table %} |
| 56 | + (MEM_TYPE == "{{ memory }}") ? {{ depth }} :{% endfor %} |
| 57 | + 0; |
| 58 | + |
| 59 | + // Create memories |
| 60 | + localparam MEM_ADDRS = 2**(AW - MEM_DEPTH) < 1 ? 1 : 2**(AW - MEM_DEPTH); |
| 61 | + |
| 62 | + {% if control_signals %}// Control signals{% for line in control_signals %} |
| 63 | + {{ line }}{% endfor %}{% endif %} |
| 64 | + |
| 65 | + generate |
| 66 | + genvar o; |
| 67 | + for (o = 0; o < DW; o = o + 1) begin: OUTPUTS |
| 68 | + wire [MEM_ADDRS-1:0] mem_outputs; |
| 69 | + assign dout[o] = |mem_outputs; |
| 70 | + end |
| 71 | + |
| 72 | + genvar a; |
| 73 | + for (a = 0; a < MEM_ADDRS; a = a + 1) begin: ADDR |
| 74 | + wire selected; |
| 75 | + wire [MEM_DEPTH-1:0] mem_addr; |
| 76 | + |
| 77 | + if (MEM_ADDRS == 1) begin: FITS |
| 78 | + assign selected = 1'b1; |
| 79 | + assign mem_addr = addr; |
| 80 | + end else begin: NOFITS |
| 81 | + assign selected = addr[AW-1:MEM_DEPTH] == a; |
| 82 | + assign mem_addr = addr[MEM_DEPTH-1:0]; |
| 83 | + end |
| 84 | + |
| 85 | + genvar n; |
| 86 | + for (n = 0; n < DW; n = n + MEM_WIDTH) begin: WORD |
| 87 | + wire [MEM_WIDTH-1:0] mem_din; |
| 88 | + wire [MEM_WIDTH-1:0] mem_dout; |
| 89 | + wire [MEM_WIDTH-1:0] mem_wmask; |
| 90 | + |
| 91 | + genvar i; |
| 92 | + for (i = 0; i < MEM_WIDTH; i = i + 1) begin: WORD_SELECT |
| 93 | + if (n + i < DW) begin: ACTIVE |
| 94 | + assign mem_din[i] = din[n + i]; |
| 95 | + assign mem_wmask[i] = wmask[n + i]; |
| 96 | + assign OUTPUTS[n + i].mem_outputs[a] = selected ? mem_dout[i] : 1'b0; |
| 97 | + end |
| 98 | + else begin: INACTIVE |
| 99 | + assign mem_din[i] = 1'b0; |
| 100 | + assign mem_wmask[i] = 1'b0; |
| 101 | + end |
| 102 | + end |
| 103 | + |
| 104 | + wire ce_in; |
| 105 | + wire we_in; |
| 106 | + assign ce_in = ce && selected; |
| 107 | + assign we_in = we && selected; |
| 108 | + {% for memory, inst_name in inst_map.items() %} |
| 109 | + {% if loop.previtem is defined %}else {% endif %}if (MEM_TYPE == "{{ memory }}") |
| 110 | + {{ inst_name }} memory ({% for port, net in port_mapping[memory] %} |
| 111 | + .{{ port }}({{ net }}){% if loop.nextitem is defined %},{% endif %}{% endfor %} |
| 112 | + );{% endfor %} |
| 113 | + end |
| 114 | + end |
| 115 | + endgenerate |
| 116 | +endmodule |
0 commit comments