Skip to content

Commit d4fdbe2

Browse files
committed
add initial version of dpram template
1 parent 23a39f0 commit d4fdbe2

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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+
// Determine which memory to select
53+
localparam MEM_PROP = (PROP != "DEFAULT") ? PROP :{% for aw, dw_select in selection_table.items() %}
54+
{% 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 %}
55+
56+
localparam MEM_WIDTH = {% for memory, width in width_table %}
57+
(MEM_PROP == "{{ memory }}") ? {{ width }} :{% endfor %}
58+
0;
59+
60+
localparam MEM_DEPTH = {% for memory, depth in depth_table %}
61+
(MEM_PROP == "{{ memory }}") ? {{ depth }} :{% endfor %}
62+
0;
63+
64+
generate
65+
if (MEM_PROP == "SOFT") begin: isoft
66+
la_dpram_impl #(
67+
.DW(DW),
68+
.AW(AW),
69+
.PROP(PROP),
70+
.CTRLW(CTRLW),
71+
.TESTW(TESTW)
72+
) memory(
73+
.clk(clk),
74+
.ce(ce),
75+
.we(we),
76+
.wmask(wmask),
77+
.addr(addr),
78+
.din(din),
79+
.dout(dout),
80+
.vss(vss),
81+
.vdd(vdd),
82+
.vddio(vddio),
83+
.ctrl(ctrl),
84+
.test(test)
85+
);
86+
end
87+
if (MEM_PROP != "SOFT") begin: itech
88+
// Create memories
89+
localparam MEM_ADDRS = 2**(AW - MEM_DEPTH) < 1 ? 1 : 2**(AW - MEM_DEPTH);
90+
91+
{% if control_signals %}// Control signals{% for line in control_signals %}
92+
{{ line }}{% endfor %}{% endif %}
93+
94+
genvar o;
95+
for (o = 0; o < DW; o = o + 1) begin: OUTPUTS
96+
wire [MEM_ADDRS-1:0] mem_outputs;
97+
assign rd_dout[o] = |mem_outputs;
98+
end
99+
100+
genvar a;
101+
for (a = 0; a < MEM_ADDRS; a = a + 1) begin: ADDR
102+
wire selected;
103+
wire [MEM_DEPTH-1:0] wr_mem_addr;
104+
wire [MEM_DEPTH-1:0] rd_mem_addr;
105+
106+
if (MEM_ADDRS == 1) begin: FITS
107+
assign selected = 1'b1;
108+
assign wr_mem_addr = wr_addr;
109+
assign rd_mem_addr = rd_addr;
110+
end else begin: NOFITS
111+
assign selected = addr[AW-1:MEM_DEPTH] == a;
112+
assign wr_mem_addr = wr_addr[MEM_DEPTH-1:0];
113+
assign rd_mem_addr = rd_addr[MEM_DEPTH-1:0];
114+
end
115+
116+
genvar n;
117+
for (n = 0; n < DW; n = n + MEM_WIDTH) begin: WORD
118+
wire [MEM_WIDTH-1:0] mem_din;
119+
wire [MEM_WIDTH-1:0] mem_dout;
120+
wire [MEM_WIDTH-1:0] mem_wmask;
121+
122+
genvar i;
123+
for (i = 0; i < MEM_WIDTH; i = i + 1) begin: WORD_SELECT
124+
if (n + i < DW) begin: ACTIVE
125+
assign mem_din[i] = wr_din[n + i];
126+
assign mem_wmask[i] = wr_wmask[n + i];
127+
assign OUTPUTS[n + i].mem_outputs[a] = selected ? mem_dout[i] : 1'b0;
128+
end
129+
else begin: INACTIVE
130+
assign mem_din[i] = 1'b0;
131+
assign mem_wmask[i] = 1'b0;
132+
end
133+
end
134+
135+
wire ce_in;
136+
wire we_in;
137+
assign wr_ce_in = wr_ce && selected;
138+
assign rd_ce_in = rd_ce && selected;
139+
assign we_in = wr_we && selected;
140+
{% for memory, inst_name in inst_map.items() %}
141+
if (MEM_PROP == "{{ memory }}") begin: i{{ memory }}
142+
{{ inst_name }} memory ({% for port, net in port_mapping[memory] %}
143+
.{{ port }}({{ net }}){% if loop.nextitem is defined %},{% endif %}{% endfor %}
144+
);
145+
end{% endfor %}
146+
end
147+
end
148+
end
149+
endgenerate
150+
endmodule

0 commit comments

Comments
 (0)