1 |
48 |
alirezamon |
/**********************************************************************
|
2 |
|
|
** File: wb_dual_port_ram.v
|
3 |
|
|
**
|
4 |
|
|
**
|
5 |
|
|
** Copyright (C) 2014-2017 Alireza Monemi
|
6 |
|
|
**
|
7 |
|
|
** This file is part of ProNoC
|
8 |
|
|
**
|
9 |
|
|
** ProNoC ( stands for Prototype Network-on-chip) is free software:
|
10 |
|
|
** you can redistribute it and/or modify it under the terms of the GNU
|
11 |
|
|
** Lesser General Public License as published by the Free Software Foundation,
|
12 |
|
|
** either version 2 of the License, or (at your option) any later version.
|
13 |
|
|
**
|
14 |
|
|
** ProNoC is distributed in the hope that it will be useful, but WITHOUT
|
15 |
|
|
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
16 |
|
|
** or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
17 |
|
|
** Public License for more details.
|
18 |
|
|
**
|
19 |
|
|
** You should have received a copy of the GNU Lesser General Public
|
20 |
|
|
** License along with ProNoC. If not, see <http:**www.gnu.org/licenses/>.
|
21 |
|
|
**
|
22 |
|
|
**
|
23 |
|
|
** Description:
|
24 |
|
|
** wishbone based single port ram
|
25 |
|
|
**
|
26 |
|
|
**
|
27 |
|
|
*******************************************************************/
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
// synthesis translate_off
|
31 |
|
|
`timescale 1ns / 1ps
|
32 |
|
|
// synthesis translate_on
|
33 |
|
|
|
34 |
|
|
|
35 |
|
|
|
36 |
|
|
|
37 |
|
|
module wb_single_port_ram #(
|
38 |
|
|
parameter Dw=32, //RAM data_width in bits
|
39 |
|
|
parameter Aw=10, //RAM address width
|
40 |
|
|
parameter BYTE_WR_EN= "YES",//"YES","NO"
|
41 |
|
|
parameter FPGA_VENDOR= "ALTERA",//"XILINX",ALTERA","GENERIC"
|
42 |
|
|
parameter JTAG_CONNECT= "ALTERA_JTAG_WB",//"DISABLED","XILINX_JTAG_WB", "ALTERA_JTAG_WB" , "ALTERA_IMCE", if not disabled then the actual memory implements as a dual port RAM with the second port is connected either to In-System Memory Content Editor or Jtag_to_wb
|
43 |
|
|
parameter JTAG_INDEX= 0,
|
44 |
|
|
parameter INITIAL_EN= "NO",
|
45 |
|
|
parameter MEM_CONTENT_FILE_NAME= "ram0",// ram initial file name
|
46 |
|
|
parameter INIT_FILE_PATH = "path_to/sw", // The sw folder path. It will be used for finding initial file. The path will be rewriten by the top module.
|
47 |
|
|
parameter CORE_NUM=0,
|
48 |
|
|
// wishbon bus param
|
49 |
|
|
parameter BURST_MODE= "DISABLED", // "DISABLED" , "ENABLED" wisbone bus burst mode
|
50 |
|
|
parameter TAGw = 3,
|
51 |
|
|
parameter SELw = Dw/8,
|
52 |
|
|
parameter CTIw = 3,
|
53 |
|
|
parameter BTEw = 2,
|
54 |
|
|
//jtag to wishbobe interface
|
55 |
|
|
parameter JDw =Dw,// should be a fixed value for all IPs coneccting to JTAG
|
56 |
|
|
parameter JAw=32, // should be a fixed value for all IPs coneccting to JTAG
|
57 |
|
|
parameter JINDEXw=8,
|
58 |
|
|
parameter JSTATUSw=8,
|
59 |
|
|
/* verilator lint_off WIDTH */
|
60 |
|
|
parameter J2WBw = (JTAG_CONNECT== "XILINX_JTAG_WB") ? 1+1+JDw+JAw : 1,
|
61 |
|
|
parameter WB2Jw= (JTAG_CONNECT== "XILINX_JTAG_WB") ? 1+JSTATUSw+JINDEXw+1+JDw : 1,
|
62 |
|
|
/* verilator lint_on WIDTH */
|
63 |
|
|
parameter WB_Aw= 20 // Wishbon bus reserved address with range. WB_Aw >=Aw
|
64 |
|
|
)
|
65 |
|
|
(
|
66 |
|
|
clk,
|
67 |
|
|
reset,
|
68 |
|
|
|
69 |
|
|
//wishbone bus interface
|
70 |
|
|
sa_dat_i,
|
71 |
|
|
sa_sel_i,
|
72 |
|
|
sa_addr_i,
|
73 |
|
|
sa_tag_i,
|
74 |
|
|
sa_cti_i,
|
75 |
|
|
sa_bte_i,
|
76 |
|
|
sa_stb_i,
|
77 |
|
|
sa_cyc_i,
|
78 |
|
|
sa_we_i,
|
79 |
|
|
sa_dat_o,
|
80 |
|
|
sa_ack_o,
|
81 |
|
|
sa_err_o,
|
82 |
|
|
sa_rty_o,
|
83 |
|
|
|
84 |
|
|
//jtag o wb interface. Valid only for XILINX_JTAG_WB
|
85 |
|
|
jtag_to_wb,
|
86 |
|
|
wb_to_jtag
|
87 |
|
|
|
88 |
|
|
);
|
89 |
|
|
|
90 |
|
|
// synthesis translate_off
|
91 |
|
|
initial begin
|
92 |
|
|
if(WB_Aw<Aw)begin
|
93 |
|
|
$display("Error: The wishbon bus reserved address range width (%d) should be larger than ram width (%d): %m",WB_Aw,Aw);
|
94 |
|
|
$stop;
|
95 |
|
|
end
|
96 |
|
|
end
|
97 |
|
|
// synthesis translate_on
|
98 |
|
|
|
99 |
|
|
input clk;
|
100 |
|
|
input reset;
|
101 |
|
|
|
102 |
|
|
|
103 |
|
|
|
104 |
|
|
|
105 |
|
|
//wishbone bus interface
|
106 |
|
|
input [Dw-1 : 0] sa_dat_i;
|
107 |
|
|
input [SELw-1 : 0] sa_sel_i;
|
108 |
|
|
input [Aw-1 : 0] sa_addr_i;
|
109 |
|
|
input [TAGw-1 : 0] sa_tag_i;
|
110 |
|
|
input sa_stb_i;
|
111 |
|
|
input sa_cyc_i;
|
112 |
|
|
input sa_we_i;
|
113 |
|
|
input [CTIw-1 : 0] sa_cti_i;
|
114 |
|
|
input [BTEw-1 : 0] sa_bte_i;
|
115 |
|
|
|
116 |
|
|
output [Dw-1 : 0] sa_dat_o;
|
117 |
|
|
output sa_ack_o;
|
118 |
|
|
output sa_err_o;
|
119 |
|
|
output sa_rty_o;
|
120 |
|
|
|
121 |
|
|
input [J2WBw-1 : 0] jtag_to_wb;
|
122 |
|
|
output [WB2Jw-1: 0] wb_to_jtag;
|
123 |
|
|
|
124 |
|
|
wire [SELw-1 : 0] byteena_a;
|
125 |
|
|
wire [Dw-1 : 0] d;
|
126 |
|
|
wire [Aw-1 : 0] addr;
|
127 |
|
|
wire we;
|
128 |
|
|
wire [Dw-1 : 0] q;
|
129 |
|
|
|
130 |
|
|
`ifdef VERILATOR
|
131 |
|
|
// The verilator does not recognize altsyncram, use Generic Ram instead
|
132 |
|
|
localparam FPGA_VENDOR_MDFY= "GENERIC";
|
133 |
|
|
`else
|
134 |
|
|
`ifdef MODEL_TECH
|
135 |
|
|
localparam FPGA_VENDOR_MDFY= "GENERIC";
|
136 |
|
|
`else
|
137 |
|
|
localparam FPGA_VENDOR_MDFY= FPGA_VENDOR;
|
138 |
|
|
`endif
|
139 |
|
|
`endif
|
140 |
|
|
|
141 |
|
|
/* verilator lint_off WIDTH */
|
142 |
|
|
localparam MEM_NAME =
|
143 |
|
|
(FPGA_VENDOR_MDFY== "ALTERA")? {MEM_CONTENT_FILE_NAME,".mif"} :
|
144 |
|
|
(FPGA_VENDOR_MDFY== "XILINX")? {MEM_CONTENT_FILE_NAME,".mem"} :
|
145 |
|
|
{MEM_CONTENT_FILE_NAME,".hex"}; //Generic
|
146 |
|
|
|
147 |
|
|
|
148 |
|
|
localparam [7:0] N1 = (CORE_NUM%10) + 48;
|
149 |
|
|
localparam [7:0] N2 = ((CORE_NUM/10)%10) + 48;
|
150 |
|
|
localparam [7:0] N3 = ((CORE_NUM/100)%10) + 48;
|
151 |
|
|
|
152 |
|
|
localparam NN = (CORE_NUM<10) ? N1 : (CORE_NUM<100)? {N2,N1} : {N3,N2,N1};
|
153 |
|
|
|
154 |
|
|
|
155 |
|
|
localparam INIT_FILE =
|
156 |
|
|
(FPGA_VENDOR_MDFY== "XILINX")? {"tile",NN,MEM_NAME}:
|
157 |
|
|
{INIT_FILE_PATH,"/RAM/",MEM_NAME};
|
158 |
|
|
|
159 |
|
|
/* verilator lint_on WIDTH */
|
160 |
|
|
|
161 |
|
|
wb_bram_ctrl #(
|
162 |
|
|
.Dw(Dw),
|
163 |
|
|
.Aw(Aw),
|
164 |
|
|
.BURST_MODE(BURST_MODE),
|
165 |
|
|
.SELw(SELw),
|
166 |
|
|
.CTIw(CTIw),
|
167 |
|
|
.BTEw(BTEw)
|
168 |
|
|
)
|
169 |
|
|
ctrl
|
170 |
|
|
(
|
171 |
|
|
.clk(clk),
|
172 |
|
|
.reset(reset),
|
173 |
|
|
.d(d),
|
174 |
|
|
.addr(addr),
|
175 |
|
|
.we(we),
|
176 |
|
|
.q(q),
|
177 |
|
|
.byteena_a(byteena_a),
|
178 |
|
|
.sa_dat_i(sa_dat_i),
|
179 |
|
|
.sa_sel_i(sa_sel_i),
|
180 |
|
|
.sa_addr_i(sa_addr_i),
|
181 |
|
|
.sa_stb_i(sa_stb_i),
|
182 |
|
|
.sa_cyc_i(sa_cyc_i),
|
183 |
|
|
.sa_we_i(sa_we_i),
|
184 |
|
|
.sa_cti_i(sa_cti_i),
|
185 |
|
|
.sa_bte_i(sa_bte_i),
|
186 |
|
|
.sa_dat_o(sa_dat_o),
|
187 |
|
|
.sa_ack_o(sa_ack_o),
|
188 |
|
|
.sa_err_o(sa_err_o),
|
189 |
|
|
.sa_rty_o(sa_rty_o)
|
190 |
|
|
);
|
191 |
|
|
|
192 |
|
|
|
193 |
|
|
|
194 |
|
|
|
195 |
|
|
|
196 |
|
|
single_port_ram_top #(
|
197 |
|
|
.Dw(Dw),
|
198 |
|
|
.Aw(Aw),
|
199 |
|
|
.BYTE_WR_EN(BYTE_WR_EN),
|
200 |
|
|
.FPGA_VENDOR(FPGA_VENDOR_MDFY),
|
201 |
|
|
.JTAG_CONNECT(JTAG_CONNECT),
|
202 |
|
|
.JTAG_INDEX(JTAG_INDEX),
|
203 |
|
|
.INITIAL_EN(INITIAL_EN),
|
204 |
|
|
.INIT_FILE(INIT_FILE),
|
205 |
|
|
.JDw(JDw),
|
206 |
|
|
.JAw(JAw),
|
207 |
|
|
.JINDEXw(JINDEXw),
|
208 |
|
|
.JSTATUSw(JSTATUSw),
|
209 |
|
|
.J2WBw(J2WBw),
|
210 |
|
|
.WB2Jw(WB2Jw)
|
211 |
|
|
)
|
212 |
|
|
ram_top
|
213 |
|
|
(
|
214 |
|
|
.reset(reset),
|
215 |
|
|
.clk(clk),
|
216 |
|
|
.data_a(d),
|
217 |
|
|
.addr_a(addr),
|
218 |
|
|
.we_a(we),
|
219 |
|
|
.q_a(q),
|
220 |
|
|
.byteena_a(byteena_a),
|
221 |
|
|
.jtag_to_wb(jtag_to_wb),
|
222 |
|
|
.wb_to_jtag(wb_to_jtag)
|
223 |
|
|
);
|
224 |
|
|
|
225 |
|
|
|
226 |
|
|
endmodule
|
227 |
|
|
|
228 |
|
|
|
229 |
|
|
|
230 |
|
|
|
231 |
|
|
|
232 |
|
|
|
233 |
|
|
|
234 |
|
|
module single_port_ram_top #(
|
235 |
|
|
parameter Dw=32, //RAM data_width in bits
|
236 |
|
|
parameter Aw=10, //RAM address width
|
237 |
|
|
parameter BYTE_WR_EN= "YES",//"YES","NO"
|
238 |
|
|
parameter FPGA_VENDOR= "ALTERA",//"ALTERA","GENERIC"
|
239 |
|
|
parameter JTAG_CONNECT= "ALTERA_JTAG_WB",//"DISABLED", "XILINX_JTAG_WB","ALTERA_JTAG_WB" , "ALTERA_IMCE", if not disabled then the actual memory implements as a dual port RAM with the second port is connected either to In-System Memory Content Editor or Jtag_to_wb
|
240 |
|
|
parameter JTAG_INDEX= 0,
|
241 |
|
|
parameter INITIAL_EN= "NO",
|
242 |
|
|
parameter INIT_FILE= "sw/ram/ram0.txt",// ram initial file
|
243 |
|
|
//jtag to wishbobe interface
|
244 |
|
|
parameter JDw =Dw,// should be a fixed value for all IPs coneccting to JTAG
|
245 |
|
|
parameter JAw=32, // should be a fixed value for all IPs coneccting to JTAG
|
246 |
|
|
parameter JSTATUSw=8,
|
247 |
|
|
parameter JINDEXw =8,
|
248 |
|
|
parameter J2WBw = (JTAG_CONNECT== "XILINX_JTAG_WB") ? 1+1+JDw+JAw : 1,
|
249 |
|
|
parameter WB2Jw = (JTAG_CONNECT== "XILINX_JTAG_WB") ? 1+JSTATUSw+JINDEXw+1+JDw : 1
|
250 |
|
|
)
|
251 |
|
|
(
|
252 |
|
|
reset,
|
253 |
|
|
clk,
|
254 |
|
|
data_a,
|
255 |
|
|
addr_a,
|
256 |
|
|
byteena_a,
|
257 |
|
|
we_a,
|
258 |
|
|
q_a,
|
259 |
|
|
//jtag o wb interface. Valid only for XILINX_JTAG_WB
|
260 |
|
|
jtag_to_wb,
|
261 |
|
|
wb_to_jtag
|
262 |
|
|
);
|
263 |
|
|
/* verilator lint_off WIDTH */
|
264 |
|
|
localparam BYTE_ENw= ( BYTE_WR_EN == "YES")? Dw/8 : 1;
|
265 |
|
|
localparam XILINX_INIT_FILE = (INITIAL_EN == "NO") ? "none" : INIT_FILE;
|
266 |
|
|
localparam ALTERA_INIT_FILE = (INITIAL_EN == "NO") ? "UNUSED" : INIT_FILE;
|
267 |
|
|
/* verilator lint_on WIDTH */
|
268 |
|
|
|
269 |
|
|
input clk,reset;
|
270 |
|
|
input [Dw-1 : 0] data_a;
|
271 |
|
|
input [Aw-1 : 0] addr_a;
|
272 |
|
|
input we_a;
|
273 |
|
|
input [BYTE_ENw-1 : 0] byteena_a;
|
274 |
|
|
output [Dw-1 : 0] q_a;
|
275 |
|
|
|
276 |
|
|
input [J2WBw-1 : 0] jtag_to_wb;
|
277 |
|
|
output [WB2Jw-1 : 0] wb_to_jtag;
|
278 |
|
|
|
279 |
|
|
function [15:0]i2s;
|
280 |
|
|
input integer c; integer i; integer tmp; begin
|
281 |
|
|
tmp =0;
|
282 |
|
|
for (i=0; i<2; i=i+1) begin
|
283 |
|
|
tmp = tmp + (((c % 10) + 48) << i*8);
|
284 |
|
|
c = c/10;
|
285 |
|
|
end
|
286 |
|
|
i2s = tmp[15:0];
|
287 |
|
|
end
|
288 |
|
|
endfunction //i2s
|
289 |
|
|
|
290 |
|
|
function integer log2;
|
291 |
|
|
input integer number; begin
|
292 |
|
|
log2=0;
|
293 |
|
|
while(2**log2<number) begin
|
294 |
|
|
log2=log2+1;
|
295 |
|
|
end
|
296 |
|
|
end
|
297 |
|
|
endfunction // log2
|
298 |
|
|
|
299 |
|
|
wire [Dw-1 : 0] data_b;
|
300 |
|
|
wire [Aw-1 : 0] addr_b;
|
301 |
|
|
wire we_b;
|
302 |
|
|
wire [Dw-1 : 0] q_b;
|
303 |
|
|
|
304 |
|
|
|
305 |
|
|
|
306 |
|
|
|
307 |
|
|
generate
|
308 |
|
|
/***********************
|
309 |
|
|
* "ALTERA"
|
310 |
|
|
* *********************/
|
311 |
|
|
/* verilator lint_off WIDTH */
|
312 |
|
|
if(FPGA_VENDOR=="ALTERA")begin:altera_fpga
|
313 |
|
|
localparam RAM_TAG_STRING=i2s(JTAG_INDEX);
|
314 |
|
|
localparam RAM_ID =(JTAG_CONNECT== "ALTERA_IMCE") ? {"ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME=",RAM_TAG_STRING}
|
315 |
|
|
: {"ENABLE_RUNTIME_MOD=NO"};
|
316 |
|
|
|
317 |
|
|
if(JTAG_CONNECT== "ALTERA_JTAG_WB")begin:dual_ram
|
318 |
|
|
/* verilator lint_on WIDTH */
|
319 |
|
|
|
320 |
|
|
// aletra dual port ram
|
321 |
|
|
altsyncram #(
|
322 |
|
|
.operation_mode("BIDIR_DUAL_PORT"),
|
323 |
|
|
.address_reg_b("CLOCK0"),
|
324 |
|
|
.wrcontrol_wraddress_reg_b("CLOCK0"),
|
325 |
|
|
.indata_reg_b("CLOCK0"),
|
326 |
|
|
.outdata_reg_a("UNREGISTERED"),
|
327 |
|
|
.outdata_reg_b("UNREGISTERED"),
|
328 |
|
|
.width_a(Dw),
|
329 |
|
|
.width_b(Dw),
|
330 |
|
|
.lpm_hint(RAM_ID),
|
331 |
|
|
.read_during_write_mode_mixed_ports("DONT_CARE"),
|
332 |
|
|
.widthad_a(Aw),
|
333 |
|
|
.widthad_b(Aw),
|
334 |
|
|
.width_byteena_a(BYTE_ENw),
|
335 |
|
|
.init_file(ALTERA_INIT_FILE)
|
336 |
|
|
|
337 |
|
|
) ram_inst(
|
338 |
|
|
.clock0 (clk),
|
339 |
|
|
|
340 |
|
|
.address_a (addr_a),
|
341 |
|
|
.wren_a (we_a),
|
342 |
|
|
.data_a (data_a),
|
343 |
|
|
.q_a (q_a),
|
344 |
|
|
.byteena_a (byteena_a),
|
345 |
|
|
|
346 |
|
|
|
347 |
|
|
.address_b (addr_b),
|
348 |
|
|
.wren_b (we_b),
|
349 |
|
|
.data_b (data_b),
|
350 |
|
|
.q_b (q_b),
|
351 |
|
|
.byteena_b (1'b1),
|
352 |
|
|
|
353 |
|
|
|
354 |
|
|
.rden_a (1'b1),
|
355 |
|
|
.rden_b (1'b1),
|
356 |
|
|
.clock1 (1'b1),
|
357 |
|
|
.clocken0 (1'b1),
|
358 |
|
|
.clocken1 (1'b1),
|
359 |
|
|
.clocken2 (1'b1),
|
360 |
|
|
.clocken3 (1'b1),
|
361 |
|
|
.aclr0 (1'b0),
|
362 |
|
|
.aclr1 (1'b0),
|
363 |
|
|
.addressstall_a (1'b0),
|
364 |
|
|
.addressstall_b (1'b0),
|
365 |
|
|
.eccstatus ( )
|
366 |
|
|
|
367 |
|
|
);
|
368 |
|
|
|
369 |
|
|
// jtag_wb
|
370 |
|
|
end else begin: single_ram //JTAG_CONNECT= "DISABLED", "ALTERA_IMCE"
|
371 |
|
|
|
372 |
|
|
|
373 |
|
|
|
374 |
|
|
altsyncram #(
|
375 |
|
|
.operation_mode("SINGLE_PORT"),
|
376 |
|
|
.width_a(Dw),
|
377 |
|
|
.lpm_hint(RAM_ID),
|
378 |
|
|
.read_during_write_mode_mixed_ports("DONT_CARE"),
|
379 |
|
|
.widthad_a(Aw),
|
380 |
|
|
.width_byteena_a(BYTE_ENw),
|
381 |
|
|
.init_file(ALTERA_INIT_FILE)
|
382 |
|
|
)
|
383 |
|
|
ram_inst
|
384 |
|
|
(
|
385 |
|
|
.clock0 (clk),
|
386 |
|
|
.address_a (addr_a),
|
387 |
|
|
.wren_a (we_a),
|
388 |
|
|
.data_a (data_a),
|
389 |
|
|
.q_a (q_a),
|
390 |
|
|
.byteena_a (byteena_a),
|
391 |
|
|
|
392 |
|
|
.wren_b ( ),
|
393 |
|
|
.rden_a ( ),
|
394 |
|
|
.rden_b ( ),
|
395 |
|
|
.data_b ( ),
|
396 |
|
|
.address_b ( ),
|
397 |
|
|
.clock1 ( ),
|
398 |
|
|
.clocken0 ( ),
|
399 |
|
|
.clocken1 ( ),
|
400 |
|
|
.clocken2 ( ),
|
401 |
|
|
.clocken3 ( ),
|
402 |
|
|
.aclr0 ( ),
|
403 |
|
|
.aclr1 ( ),
|
404 |
|
|
.byteena_b ( ),
|
405 |
|
|
.addressstall_a ( ),
|
406 |
|
|
.addressstall_b ( ),
|
407 |
|
|
.q_b ( ),
|
408 |
|
|
.eccstatus ( )
|
409 |
|
|
);
|
410 |
|
|
|
411 |
|
|
end// single_ram
|
412 |
|
|
end//altera_fpga
|
413 |
|
|
/***********************
|
414 |
|
|
* "XILINX"
|
415 |
|
|
* *********************/
|
416 |
|
|
|
417 |
|
|
/* verilator lint_off WIDTH */
|
418 |
|
|
else if (FPGA_VENDOR=="XILINX")begin:xilinx_fpga
|
419 |
|
|
/* verilator lint_on WIDTH */
|
420 |
|
|
|
421 |
|
|
localparam MEMORY_SIZE = (2**Aw)*Dw;//total memory array size, in bits
|
422 |
|
|
wire [BYTE_ENw-1 : 0] xilinx_we_a = (we_a)? byteena_a : {BYTE_ENw{1'b0}};
|
423 |
|
|
|
424 |
|
|
/* verilator lint_off WIDTH */
|
425 |
|
|
if(JTAG_CONNECT == "XILINX_JTAG_WB")begin: xilinx_dual
|
426 |
|
|
/* verilator lint_on WIDTH */
|
427 |
|
|
|
428 |
|
|
wire [BYTE_ENw-1 : 0] xilinx_we_b = (we_b)? {BYTE_ENw{1'b1}} : {BYTE_ENw{1'b0}};
|
429 |
|
|
// xpm_memory_tdpram: True Dual Port RAM
|
430 |
|
|
// Xilinx Parameterized Macro, version 2019.1
|
431 |
|
|
|
432 |
|
|
xpm_memory_tdpram #(
|
433 |
|
|
.ADDR_WIDTH_A(Aw), // DECIMAL
|
434 |
|
|
.ADDR_WIDTH_B(Aw), // DECIMAL
|
435 |
|
|
.AUTO_SLEEP_TIME(0), // DECIMAL
|
436 |
|
|
.BYTE_WRITE_WIDTH_A(8), // DECIMAL
|
437 |
|
|
.BYTE_WRITE_WIDTH_B(8), // DECIMAL
|
438 |
|
|
// .CASCADE_HEIGHT(0), // DECIMAL
|
439 |
|
|
.CLOCKING_MODE("common_clock"), // String
|
440 |
|
|
.ECC_MODE("no_ecc"), // String
|
441 |
|
|
.MEMORY_INIT_FILE(XILINX_INIT_FILE), // String
|
442 |
|
|
.MEMORY_INIT_PARAM(""), // String
|
443 |
|
|
.MEMORY_OPTIMIZATION("true"), // String
|
444 |
|
|
.MEMORY_PRIMITIVE("auto"), // String
|
445 |
|
|
.MEMORY_SIZE(MEMORY_SIZE), // DECIMAL
|
446 |
|
|
.MESSAGE_CONTROL(0), // DECIMAL
|
447 |
|
|
.READ_DATA_WIDTH_A(Dw), // DECIMAL
|
448 |
|
|
.READ_DATA_WIDTH_B(Dw), // DECIMAL
|
449 |
|
|
.READ_LATENCY_A(1), // DECIMAL
|
450 |
|
|
.READ_LATENCY_B(1), // DECIMAL
|
451 |
|
|
.READ_RESET_VALUE_A("0"), // String
|
452 |
|
|
.READ_RESET_VALUE_B("0"), // String
|
453 |
|
|
//.RST_MODE_A("SYNC"), // String
|
454 |
|
|
//.RST_MODE_B("SYNC"), // String
|
455 |
|
|
// .SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
|
456 |
|
|
.USE_EMBEDDED_CONSTRAINT(0), // DECIMAL
|
457 |
|
|
.USE_MEM_INIT(1), // DECIMAL
|
458 |
|
|
.WAKEUP_TIME("disable_sleep"), // String
|
459 |
|
|
.WRITE_DATA_WIDTH_A(Dw), // DECIMAL
|
460 |
|
|
.WRITE_DATA_WIDTH_B(Dw), // DECIMAL
|
461 |
|
|
.WRITE_MODE_A("no_change"), // String
|
462 |
|
|
.WRITE_MODE_B("no_change") // String
|
463 |
|
|
)
|
464 |
|
|
xpm_memory_tdpram_inst
|
465 |
|
|
(
|
466 |
|
|
.dbiterra( ), // 1-bit output: Status signal to indicate double bit error occurrence
|
467 |
|
|
// on the data output of port A.
|
468 |
|
|
|
469 |
|
|
.dbiterrb( ), // 1-bit output: Status signal to indicate double bit error occurrence
|
470 |
|
|
// on the data output of port A.
|
471 |
|
|
|
472 |
|
|
.douta(q_a), // READ_DATA_WIDTH_A-bit output: Data output for port A read operations.
|
473 |
|
|
.doutb(q_b), // READ_DATA_WIDTH_B-bit output: Data output for port B read operations.
|
474 |
|
|
.sbiterra( ), // 1-bit output: Status signal to indicate single bit error occurrence
|
475 |
|
|
// on the data output of port A.
|
476 |
|
|
|
477 |
|
|
.sbiterrb( ), // 1-bit output: Status signal to indicate single bit error occurrence
|
478 |
|
|
// on the data output of port B.
|
479 |
|
|
|
480 |
|
|
.addra(addr_a), // ADDR_WIDTH_A-bit input: Address for port A write and read operations.
|
481 |
|
|
.addrb(addr_b), // ADDR_WIDTH_B-bit input: Address for port B write and read operations.
|
482 |
|
|
.clka(clk), // 1-bit input: Clock signal for port A. Also clocks port B when
|
483 |
|
|
// parameter CLOCKING_MODE is "common_clock".
|
484 |
|
|
|
485 |
|
|
.clkb(clk), // 1-bit input: Clock signal for port B when parameter CLOCKING_MODE is
|
486 |
|
|
// "independent_clock". Unused when parameter CLOCKING_MODE is
|
487 |
|
|
// "common_clock".
|
488 |
|
|
|
489 |
|
|
.dina(data_a), // WRITE_DATA_WIDTH_A-bit input: Data input for port A write operations.
|
490 |
|
|
.dinb(data_b), // WRITE_DATA_WIDTH_B-bit input: Data input for port B write operations.
|
491 |
|
|
.ena(1'b1), // 1-bit input: Memory enable signal for port A. Must be high on clock
|
492 |
|
|
// cycles when read or write operations are initiated. Pipelined
|
493 |
|
|
// internally.
|
494 |
|
|
|
495 |
|
|
.enb(1'b1), // 1-bit input: Memory enable signal for port B. Must be high on clock
|
496 |
|
|
// cycles when read or write operations are initiated. Pipelined
|
497 |
|
|
// internally.
|
498 |
|
|
|
499 |
|
|
.injectdbiterra(1'b0), // 1-bit input: Controls double bit error injection on input data when
|
500 |
|
|
// ECC enabled (Error injection capability is not available in
|
501 |
|
|
// "decode_only" mode).
|
502 |
|
|
|
503 |
|
|
.injectdbiterrb(1'b0), // 1-bit input: Controls double bit error injection on input data when
|
504 |
|
|
// ECC enabled (Error injection capability is not available in
|
505 |
|
|
// "decode_only" mode).
|
506 |
|
|
|
507 |
|
|
.injectsbiterra(1'b0), // 1-bit input: Controls single bit error injection on input data when
|
508 |
|
|
// ECC enabled (Error injection capability is not available in
|
509 |
|
|
// "decode_only" mode).
|
510 |
|
|
|
511 |
|
|
.injectsbiterrb(1'b0), // 1-bit input: Controls single bit error injection on input data when
|
512 |
|
|
// ECC enabled (Error injection capability is not available in
|
513 |
|
|
// "decode_only" mode).
|
514 |
|
|
|
515 |
|
|
.regcea(1'b1), // 1-bit input: Clock Enable for the last register stage on the output
|
516 |
|
|
// data path.
|
517 |
|
|
|
518 |
|
|
.regceb(1'b1), // 1-bit input: Clock Enable for the last register stage on the output
|
519 |
|
|
// data path.
|
520 |
|
|
|
521 |
|
|
.rsta(1'b0), // 1-bit input: Reset signal for the final port A output register stage.
|
522 |
|
|
// Synchronously resets output port douta to the value specified by
|
523 |
|
|
// parameter READ_RESET_VALUE_A.
|
524 |
|
|
|
525 |
|
|
.rstb(1'b0), // 1-bit input: Reset signal for the final port B output register stage.
|
526 |
|
|
// Synchronously resets output port doutb to the value specified by
|
527 |
|
|
// parameter READ_RESET_VALUE_B.
|
528 |
|
|
|
529 |
|
|
.sleep(1'b0), // 1-bit input: sleep signal to enable the dynamic power saving feature.
|
530 |
|
|
.wea(xilinx_we_a), // WRITE_DATA_WIDTH_A-bit input: Write enable vector for port A input
|
531 |
|
|
// data port dina. 1 bit wide when word-wide writes are used. In
|
532 |
|
|
// byte-wide write configurations, each bit controls the writing one
|
533 |
|
|
// byte of dina to address addra. For example, to synchronously write
|
534 |
|
|
// only bits [15-8] of dina when WRITE_DATA_WIDTH_A is 32, wea would be
|
535 |
|
|
// 4'b0010.
|
536 |
|
|
|
537 |
|
|
.web(xilinx_we_b) // WRITE_DATA_WIDTH_B-bit input: Write enable vector for port B input
|
538 |
|
|
// data port dinb. 1 bit wide when word-wide writes are used. In
|
539 |
|
|
// byte-wide write configurations, each bit controls the writing one
|
540 |
|
|
// byte of dinb to address addrb. For example, to synchronously write
|
541 |
|
|
// only bits [15-8] of dinb when WRITE_DATA_WIDTH_B is 32, web would be
|
542 |
|
|
// 4'b0010.
|
543 |
|
|
|
544 |
|
|
);
|
545 |
|
|
|
546 |
|
|
|
547 |
|
|
|
548 |
|
|
end // xilinx_dual
|
549 |
|
|
else begin : xilinx_single
|
550 |
|
|
|
551 |
|
|
|
552 |
|
|
|
553 |
|
|
xpm_memory_spram #(
|
554 |
|
|
.ADDR_WIDTH_A(Aw), // DECIMAL
|
555 |
|
|
.AUTO_SLEEP_TIME(0), // DECIMAL
|
556 |
|
|
.BYTE_WRITE_WIDTH_A(8), // DECIMAL
|
557 |
|
|
// .CASCADE_HEIGHT(0), // DECIMAL
|
558 |
|
|
.ECC_MODE("no_ecc"), // String
|
559 |
|
|
.MEMORY_INIT_FILE(XILINX_INIT_FILE), // String
|
560 |
|
|
.MEMORY_INIT_PARAM(""), // String
|
561 |
|
|
.MEMORY_OPTIMIZATION("true"), // String
|
562 |
|
|
.MEMORY_PRIMITIVE("auto"), // String
|
563 |
|
|
.MEMORY_SIZE(MEMORY_SIZE), // DECIMAL
|
564 |
|
|
.MESSAGE_CONTROL(0), // DECIMAL
|
565 |
|
|
.READ_DATA_WIDTH_A(Dw), // DECIMAL
|
566 |
|
|
.READ_LATENCY_A(1), // DECIMAL
|
567 |
|
|
.READ_RESET_VALUE_A("0"), // String
|
568 |
|
|
// .RST_MODE_A("SYNC"), // String
|
569 |
|
|
// .SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
|
570 |
|
|
.USE_MEM_INIT(1), // DECIMAL
|
571 |
|
|
.WAKEUP_TIME("disable_sleep"), // String
|
572 |
|
|
.WRITE_DATA_WIDTH_A(Dw), // DECIMAL
|
573 |
|
|
.WRITE_MODE_A("read_first") // String
|
574 |
|
|
)
|
575 |
|
|
xpm_memory_spram_inst
|
576 |
|
|
(
|
577 |
|
|
.dbiterra( ), // 1-bit output: Status signal to indicate double bit error occurrence
|
578 |
|
|
// on the data output of port A.
|
579 |
|
|
|
580 |
|
|
.douta(q_a), // READ_DATA_WIDTH_A-bit output: Data output for port A read operations.
|
581 |
|
|
.sbiterra( ), // 1-bit output: Status signal to indicate single bit error occurrence
|
582 |
|
|
// on the data output of port A.
|
583 |
|
|
|
584 |
|
|
.addra(addr_a), // ADDR_WIDTH_A-bit input: Address for port A write and read operations.
|
585 |
|
|
.clka(clk), // 1-bit input: Clock signal for port A.
|
586 |
|
|
.dina(data_a), // WRITE_DATA_WIDTH_A-bit input: Data input for port A write operations.
|
587 |
|
|
.ena(1'b1), // 1-bit input: Memory enable signal for port A. Must be high on clock
|
588 |
|
|
// cycles when read or write operations are initiated. Pipelined
|
589 |
|
|
// internally.
|
590 |
|
|
|
591 |
|
|
.injectdbiterra(1'b0 ), // 1-bit input: Controls double bit error injection on input data when
|
592 |
|
|
// ECC enabled (Error injection capability is not available in
|
593 |
|
|
// "decode_only" mode).
|
594 |
|
|
|
595 |
|
|
.injectsbiterra(1'b0), // 1-bit input: Controls single bit error injection on input data when
|
596 |
|
|
// ECC enabled (Error injection capability is not available in
|
597 |
|
|
// "decode_only" mode).
|
598 |
|
|
|
599 |
|
|
.regcea(1'b1), // 1-bit input: Clock Enable for the last register stage on the output
|
600 |
|
|
// data path.
|
601 |
|
|
|
602 |
|
|
.rsta(1'b0), // 1-bit input: Reset signal for the final port A output register stage.
|
603 |
|
|
// Synchronously resets output port douta to the value specified by
|
604 |
|
|
// parameter READ_RESET_VALUE_A.
|
605 |
|
|
|
606 |
|
|
.sleep(1'b0), // 1-bit input: sleep signal to enable the dynamic power saving feature.
|
607 |
|
|
.wea(xilinx_we_a) // WRITE_DATA_WIDTH_A-bit input: Write enable vector for port A input
|
608 |
|
|
// data port dina. 1 bit wide when word-wide writes are used. In
|
609 |
|
|
// byte-wide write configurations, each bit controls the writing one
|
610 |
|
|
// byte of dina to address addra. For example, to synchronously write
|
611 |
|
|
// only bits [15-8] of dina when WRITE_DATA_WIDTH_A is 32, wea would be
|
612 |
|
|
// 4'b0010.
|
613 |
|
|
|
614 |
|
|
);
|
615 |
|
|
|
616 |
|
|
|
617 |
|
|
|
618 |
|
|
end// xilinx_simgle
|
619 |
|
|
end//xilinx_fpga
|
620 |
|
|
|
621 |
|
|
|
622 |
|
|
/***********************
|
623 |
|
|
* "GENERIC"
|
624 |
|
|
* *********************/
|
625 |
|
|
/* verilator lint_off WIDTH */
|
626 |
|
|
else if(FPGA_VENDOR=="GENERIC")begin:generic_ram
|
627 |
|
|
if(JTAG_CONNECT== "ALTERA_JTAG_WB" || JTAG_CONNECT=="XILINX_JTAG_WB" )begin:dual_ram
|
628 |
|
|
/* verilator lint_on WIDTH */
|
629 |
|
|
|
630 |
|
|
generic_dual_port_ram #(
|
631 |
|
|
.Dw(Dw),
|
632 |
|
|
.Aw(Aw),
|
633 |
|
|
.BYTE_WR_EN(BYTE_WR_EN),
|
634 |
|
|
.INITIAL_EN(INITIAL_EN),
|
635 |
|
|
.INIT_FILE(INIT_FILE)
|
636 |
|
|
)
|
637 |
|
|
ram_inst
|
638 |
|
|
(
|
639 |
|
|
.data_a (data_a),
|
640 |
|
|
.data_b (data_b),
|
641 |
|
|
.addr_a (addr_a),
|
642 |
|
|
.addr_b (addr_b),
|
643 |
|
|
.byteena_a (byteena_a ),
|
644 |
|
|
.byteena_b ({BYTE_ENw{1'b1}}),
|
645 |
|
|
.we_a (we_a),
|
646 |
|
|
.we_b (we_b),
|
647 |
|
|
.clk (clk),
|
648 |
|
|
.q_a (q_a),
|
649 |
|
|
.q_b (q_b)
|
650 |
|
|
|
651 |
|
|
);
|
652 |
|
|
|
653 |
|
|
|
654 |
|
|
end else begin
|
655 |
|
|
|
656 |
|
|
|
657 |
|
|
|
658 |
|
|
generic_single_port_ram #(
|
659 |
|
|
.Dw(Dw),
|
660 |
|
|
.Aw(Aw),
|
661 |
|
|
.BYTE_WR_EN(BYTE_WR_EN),
|
662 |
|
|
.INITIAL_EN(INITIAL_EN),
|
663 |
|
|
.INIT_FILE(INIT_FILE)
|
664 |
|
|
)
|
665 |
|
|
ram_inst
|
666 |
|
|
(
|
667 |
|
|
.data (data_a),
|
668 |
|
|
.addr (addr_a),
|
669 |
|
|
.byteen (byteena_a),
|
670 |
|
|
.we (we_a),
|
671 |
|
|
.clk (clk),
|
672 |
|
|
.q (q_a)
|
673 |
|
|
|
674 |
|
|
);
|
675 |
|
|
|
676 |
|
|
end//jtag_wb
|
677 |
|
|
end //Generic
|
678 |
|
|
|
679 |
|
|
/* verilator lint_off WIDTH */
|
680 |
|
|
if(JTAG_CONNECT == "ALTERA_JTAG_WB")begin:altera_jwb
|
681 |
|
|
/* verilator lint_on WIDTH */
|
682 |
|
|
reg jtag_ack;
|
683 |
|
|
wire jtag_we_o, jtag_stb_o;
|
684 |
|
|
|
685 |
|
|
localparam Sw= log2(Aw+1);
|
686 |
|
|
localparam [Sw-1 : 0] ST = Aw;
|
687 |
|
|
vjtag_wb #(
|
688 |
|
|
.VJTAG_INDEX(JTAG_INDEX),
|
689 |
|
|
.DW(Dw),
|
690 |
|
|
.AW(Aw),
|
691 |
|
|
.SW(Sw),
|
692 |
|
|
|
693 |
|
|
//wishbone port parameters
|
694 |
|
|
.M_Aw(Aw),
|
695 |
|
|
.TAGw(3)
|
696 |
|
|
)
|
697 |
|
|
vjtag_inst
|
698 |
|
|
(
|
699 |
|
|
.clk(clk),
|
700 |
|
|
.reset(reset),
|
701 |
|
|
.status_i(ST), // Jtag can read memory size as status
|
702 |
|
|
//wishbone master interface signals
|
703 |
|
|
.m_sel_o(),
|
704 |
|
|
.m_dat_o(data_b),
|
705 |
|
|
.m_addr_o(addr_b),
|
706 |
|
|
.m_cti_o(),
|
707 |
|
|
.m_stb_o(jtag_stb_o),
|
708 |
|
|
.m_cyc_o(),
|
709 |
|
|
.m_we_o(jtag_we_o),
|
710 |
|
|
.m_dat_i(q_b),
|
711 |
|
|
.m_ack_i(jtag_ack)
|
712 |
|
|
|
713 |
|
|
);
|
714 |
|
|
|
715 |
|
|
assign we_b = jtag_stb_o & jtag_we_o;
|
716 |
|
|
|
717 |
|
|
always @(posedge clk )begin
|
718 |
|
|
jtag_ack<=jtag_stb_o;
|
719 |
|
|
end
|
720 |
|
|
assign wb_to_jtag = clk;
|
721 |
|
|
|
722 |
|
|
end//altera_jwb
|
723 |
|
|
|
724 |
|
|
/* verilator lint_off WIDTH */
|
725 |
|
|
else if(JTAG_CONNECT == "XILINX_JTAG_WB")begin: xilinx_jwb
|
726 |
|
|
/* verilator lint_on WIDTH */
|
727 |
|
|
|
728 |
|
|
localparam [JSTATUSw-1 : 0] ST1 = Aw;
|
729 |
|
|
|
730 |
|
|
wire [JSTATUSw-1 : 0] wb_to_jtag_status;
|
731 |
|
|
wire [JINDEXw-1 : 0] wb_to_jtag_index;
|
732 |
|
|
wire [JDw-1 : 0] jtag_to_wb_dat;
|
733 |
|
|
wire [JAw-1 : 0] jtag_to_wb_addr;
|
734 |
|
|
wire jtag_to_wb_stb;
|
735 |
|
|
wire jtag_to_wb_we;
|
736 |
|
|
wire [JDw-1 : 0] wb_to_jtag_dat;
|
737 |
|
|
wire wb_to_jtag_ack;
|
738 |
|
|
|
739 |
|
|
assign wb_to_jtag = {wb_to_jtag_status,wb_to_jtag_ack,wb_to_jtag_dat,wb_to_jtag_index,clk};
|
740 |
|
|
assign {jtag_to_wb_addr,jtag_to_wb_stb,jtag_to_wb_we,jtag_to_wb_dat} = jtag_to_wb;
|
741 |
|
|
|
742 |
|
|
|
743 |
|
|
reg ack_reg;
|
744 |
|
|
assign wb_to_jtag_status = ST1;
|
745 |
|
|
assign wb_to_jtag_index = JTAG_INDEX;
|
746 |
|
|
assign data_b = jtag_to_wb_dat;
|
747 |
|
|
assign addr_b = jtag_to_wb_addr[Aw-1:0];
|
748 |
|
|
assign we_b = jtag_to_wb_stb & jtag_to_wb_we;
|
749 |
|
|
assign wb_to_jtag_dat = q_b;
|
750 |
|
|
assign wb_to_jtag_ack = ack_reg;
|
751 |
|
|
always @(posedge clk )begin
|
752 |
|
|
ack_reg<=jtag_to_wb_stb;
|
753 |
|
|
end
|
754 |
|
|
end else begin
|
755 |
|
|
assign wb_to_jtag = clk;
|
756 |
|
|
end
|
757 |
|
|
|
758 |
|
|
endgenerate
|
759 |
|
|
|
760 |
|
|
|
761 |
|
|
|
762 |
|
|
endmodule
|
763 |
|
|
|
764 |
|
|
|
765 |
|
|
|
766 |
|
|
|
767 |
|
|
|
768 |
|
|
|
769 |
|
|
|
770 |
|
|
|
771 |
|
|
|