blob: 9b146cd45ffcbc481f99d973694eaedc9b461a45 [file] [log] [blame]
lowRISC Contributors802543a2019-08-31 12:12:56 +01001// 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<% import re
6%>\
Eunchan Kim632c6f72019-09-30 11:11:51 -07007module top_${top["name"]} #(
Timothy Chen7ff53122019-09-19 15:20:43 -07008 parameter bit IbexPipeLine = 0
9) (
lowRISC Contributors802543a2019-08-31 12:12:56 +010010 // Clock and Reset
11 input clk_i,
12 input rst_ni,
13
14 // JTAG interface
15 input jtag_tck_i,
16 input jtag_tms_i,
17 input jtag_trst_ni,
18 input jtag_td_i,
19 output jtag_td_o,
20
21% for m in top["module"]:
22 // ${m["name"]}
23% for p_in in m["available_input_list"] + m["available_inout_list"]:
24 ## assume it passed validate and have available input list always
25% if "width" in p_in and int(p_in["width"]) != 1:
26 input [${int(p_in["width"])-1}:0] cio_${m["name"]}_${p_in["name"]}_p2d_i,
27% else:
28 input cio_${m["name"]}_${p_in["name"]}_p2d_i,
29% endif
30% endfor
31% for p_out in m["available_output_list"] + m["available_inout_list"]:
32 ## assume it passed validate and have available output list always
33% if "width" in p_out and int(p_out["width"]) != 1:
34 output [${int(p_out["width"])-1}:0] cio_${m["name"]}_${p_out["name"]}_d2p_o,
35 output [${int(p_out["width"])-1}:0] cio_${m["name"]}_${p_out["name"]}_en_d2p_o,
36% else:
37 output cio_${m["name"]}_${p_out["name"]}_d2p_o,
38 output cio_${m["name"]}_${p_out["name"]}_en_d2p_o,
39% endif
40% endfor
41% endfor
42
43 input scanmode_i // 1 for Scan
44);
45
46 import tlul_pkg::*;
47 import top_pkg::*;
48 import tl_main_pkg::*;
49 import flash_ctrl_pkg::*;
50
51 tl_h2d_t tl_corei_h_h2d;
52 tl_d2h_t tl_corei_h_d2h;
53
54 tl_h2d_t tl_cored_h_h2d;
55 tl_d2h_t tl_cored_h_d2h;
56
57 tl_h2d_t tl_dm_sba_h_h2d;
58 tl_d2h_t tl_dm_sba_h_d2h;
59
60 tl_h2d_t tl_debug_mem_d_h2d;
61 tl_d2h_t tl_debug_mem_d_d2h;
62
63## TL-UL device port declaration
64% for m in top["module"]:
65% if not m["bus_device"] in ["none", ""]:
66 tl_h2d_t tl_${m["name"]}_d_h2d;
67 tl_d2h_t tl_${m["name"]}_d_d2h;
68% endif
69% if not m["bus_host"] in ["none", ""]:
70 tl_h2d_t tl_${m["name"]}_h_h2d;
71 tl_d2h_t tl_${m["name"]}_h_d2h;
72% endif
73% endfor
74
75% for m in top["memory"]:
76 tl_h2d_t tl_${m["name"]}_d_h2d;
77 tl_d2h_t tl_${m["name"]}_d_d2h;
78% endfor
Timothy Chen3193b002019-10-04 16:56:05 -070079
80 //reset wires declaration
81% for reset in top['resets']:
82 logic ${reset['name']}_rst_n;
83% endfor
84
Timothy Chen80bd8aa2019-10-04 15:57:11 -070085 //clock wires declaration
86% for clock in top['clocks']:
87 logic ${clock['name']}_clk;
88% endfor
89
lowRISC Contributors802543a2019-08-31 12:12:56 +010090<%
91 interrupt_num = sum([x["width"] if "width" in x else 1 for x in top["interrupt"]])
92%>\
93 logic [${interrupt_num-1}:0] intr_vector;
94 // Interrupt source list
95% for m in top["module"]:
96 % for intr in m["interrupt_list"] if "interrupt_list" in m else []:
97 % if "width" in intr and int(intr["width"]) != 1:
98 logic [${int(intr["width"])-1}:0] intr_${m["name"]}_${intr["name"]};
99 % else:
100 logic intr_${m["name"]}_${intr["name"]};
101 % endif
102 % endfor
103% endfor
104
105
106 logic [0:0] irq_plic;
107 logic [${(interrupt_num).bit_length()-1}:0] irq_id[1];
108 logic [0:0] msip;
109
lowRISC Contributors802543a2019-08-31 12:12:56 +0100110
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700111 // clock assignments
112% for clock in top['clocks']:
113 assign ${clock['name']}_clk = clk_i;
114% endfor
115
Timothy Chen3193b002019-10-04 16:56:05 -0700116 // Non-debug module reset == reset for everything except for the debug module
117 logic ndmreset_req;
118
119 // root resets
120 // TODO: lc_rst_n is not the true root reset. It will be differentiated once the
121 // the reset controller logic is present
122 assign lc_rst_n = rst_ni;
123 assign sys_rst_n = (scanmode_i) ? lc_rst_n : ~ndmreset_req & lc_rst_n;
124
125 //non-root reset assignments
126% for reset in top['resets']:
127 % if reset['type'] in ['leaf']:
128 assign ${reset['name']}_rst_n = ${reset['root']}_rst_n;
129 % endif
130% endfor
131
132 // debug request from rv_dm to core
lowRISC Contributors802543a2019-08-31 12:12:56 +0100133 logic debug_req;
134
135 // processor core
136 rv_core_ibex #(
137 .MHPMCounterNum (8),
138 .MHPMCounterWidth (40),
139 .RV32E (0),
140 .RV32M (1),
141 .DmHaltAddr (ADDR_SPACE_DEBUG_MEM + dm::HaltAddress),
Timothy Chen7ff53122019-09-19 15:20:43 -0700142 .DmExceptionAddr (ADDR_SPACE_DEBUG_MEM + dm::ExceptionAddress),
143 .PipeLine (IbexPipeLine)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100144 ) core (
145 // clock and reset
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700146 .clk_i (main_clk),
Timothy Chen3193b002019-10-04 16:56:05 -0700147 .rst_ni (sys_rst_n),
lowRISC Contributors802543a2019-08-31 12:12:56 +0100148 .test_en_i (1'b0),
149 // static pinning
Greg Chadwick53ef2ec2019-09-03 14:53:54 +0100150 .hart_id_i (32'b0),
lowRISC Contributors802543a2019-08-31 12:12:56 +0100151 .boot_addr_i (ADDR_SPACE_ROM),
152 // TL-UL buses
153 .tl_i_o (tl_corei_h_h2d),
154 .tl_i_i (tl_corei_h_d2h),
155 .tl_d_o (tl_cored_h_h2d),
156 .tl_d_i (tl_cored_h_d2h),
157 // interrupts
158 .irq_software_i (msip),
159 .irq_timer_i (intr_rv_timer_timer_expired_0_0),
160 .irq_external_i (irq_plic),
161 .irq_fast_i (15'b0),// PLIC handles all peripheral interrupts
162 .irq_nm_i (1'b0),// TODO - add and connect alert responder
163 // debug interface
164 .debug_req_i (debug_req),
165 // CPU control signals
Pirmin Vogelffc9e832019-09-13 16:16:05 +0100166 .fetch_enable_i (1'b1),
167 .core_sleep_o ()
lowRISC Contributors802543a2019-08-31 12:12:56 +0100168 );
169
170 // Debug Module (RISC-V Debug Spec 0.13)
171 //
172
173 rv_dm #(
174 .NrHarts ( 1),
175 .IdcodeValue (32'h00000001) // Temporary value
176 // xxxx version
177 // xxxxxxxxxxxxxxxx part number
178 // xxxxxxxxxxx manufacturer id
179 // 1 required by standard
180 ) u_dm_top (
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700181 .clk_i (main_clk),
Timothy Chen3193b002019-10-04 16:56:05 -0700182 .rst_ni (lc_rst_n),
lowRISC Contributors802543a2019-08-31 12:12:56 +0100183 .testmode_i (1'b0),
Timothy Chen3193b002019-10-04 16:56:05 -0700184 .ndmreset_o (ndmreset_req),
lowRISC Contributors802543a2019-08-31 12:12:56 +0100185 .dmactive_o (),
186 .debug_req_o (debug_req),
187 .unavailable_i (1'b0),
188
189 // bus device with debug memory (for execution-based debug)
190 .tl_d_i (tl_debug_mem_d_h2d),
191 .tl_d_o (tl_debug_mem_d_d2h),
192
193 // bus host (for system bus accesses, SBA)
194 .tl_h_o (tl_dm_sba_h_h2d),
195 .tl_h_i (tl_dm_sba_h_d2h),
196
197 //JTAG
198 .tck_i (jtag_tck_i),
199 .tms_i (jtag_tms_i),
200 .trst_ni (jtag_trst_ni),
201 .td_i (jtag_td_i),
202 .td_o (jtag_td_o),
203 .tdo_oe_o ( )
204 );
205
206## Memory Instantiation
207% for m in top["memory"]:
Timothy Chen3193b002019-10-04 16:56:05 -0700208<%
209 resets = m['reset_connections']
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700210 clocks = m['clock_connections']
Timothy Chen3193b002019-10-04 16:56:05 -0700211%>\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100212 % if m["type"] == "ram_1p":
213<%
214 data_width = int(top["datawidth"])
215 dw_byte = data_width // 8
216 addr_width = ((int(m["size"], 0) // dw_byte) -1).bit_length()
217 sram_depth = (int(m["size"], 0) // dw_byte)
Timothy Chen3193b002019-10-04 16:56:05 -0700218
lowRISC Contributors802543a2019-08-31 12:12:56 +0100219%>\
220 // sram device
221 logic ${m["name"]}_req;
222 logic ${m["name"]}_we;
223 logic [${addr_width-1}:0] ${m["name"]}_addr;
224 logic [${data_width-1}:0] ${m["name"]}_wdata;
225 logic [${data_width-1}:0] ${m["name"]}_wmask;
226 logic [${data_width-1}:0] ${m["name"]}_rdata;
227 logic ${m["name"]}_rvalid;
228
229 tlul_adapter_sram #(
230 .SramAw(${addr_width}),
231 .SramDw(${data_width}),
232 .Outstanding(1)
233 ) tl_adapter_${m["name"]} (
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700234 % for key in clocks:
235 .${key} (${clocks[key]}_clk),
236 % endfor
Timothy Chen3193b002019-10-04 16:56:05 -0700237 % for key in resets:
238 .${key} (${resets[key]}_rst_n),
239 % endfor
lowRISC Contributors802543a2019-08-31 12:12:56 +0100240 .tl_i (tl_${m["name"]}_d_h2d),
241 .tl_o (tl_${m["name"]}_d_d2h),
242
243 .req_o (${m["name"]}_req),
244 .gnt_i (1'b1), // Always grant as only one requester exists
245 .we_o (${m["name"]}_we),
246 .addr_o (${m["name"]}_addr),
247 .wdata_o (${m["name"]}_wdata),
248 .wmask_o (${m["name"]}_wmask),
249 .rdata_i (${m["name"]}_rdata),
250 .rvalid_i (${m["name"]}_rvalid),
251 .rerror_i (2'b00)
252 );
253
254 ## TODO: Instantiate ram_1p model using RAMGEN (currently not available)
255 prim_ram_1p #(
256 .Width(${data_width}),
257 .Depth(${sram_depth}),
258 .DataBitsPerMask(${int(data_width/4)})
259 ) u_ram1p_${m["name"]} (
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700260 % for key in clocks:
261 .${key} (${clocks[key]}_clk),
262 % endfor
Timothy Chen3193b002019-10-04 16:56:05 -0700263 % for key in resets:
264 .${key} (${resets[key]}_rst_n),
265 % endfor
lowRISC Contributors802543a2019-08-31 12:12:56 +0100266
267 .req_i (${m["name"]}_req),
268 .write_i (${m["name"]}_we),
269 .addr_i (${m["name"]}_addr),
270 .wdata_i (${m["name"]}_wdata),
271 .wmask_i (${m["name"]}_wmask),
272 .rvalid_o (${m["name"]}_rvalid),
273 .rdata_o (${m["name"]}_rdata)
274 );
275 % elif m["type"] == "rom":
276<%
277 data_width = int(top["datawidth"])
278 dw_byte = data_width // 8
279 addr_width = ((int(m["size"], 0) // dw_byte) -1).bit_length()
280 rom_depth = (int(m["size"], 0) // dw_byte)
281%>\
282 // ROM device
283 logic ${m["name"]}_req;
284 logic [${addr_width-1}:0] ${m["name"]}_addr;
285 logic [${data_width-1}:0] ${m["name"]}_rdata;
286 logic ${m["name"]}_rvalid;
287
288 tlul_adapter_sram #(
289 .SramAw(${addr_width}),
290 .SramDw(${data_width}),
Timothy Chen5aec5282019-09-10 21:10:56 -0700291 .Outstanding(1),
292 .ErrOnWrite(1)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100293 ) tl_adapter_${m["name"]} (
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700294 % for key in clocks:
295 .${key} (${clocks[key]}_clk),
296 % endfor
Timothy Chen3193b002019-10-04 16:56:05 -0700297 % for key in resets:
298 .${key} (${resets[key]}_rst_n),
299 % endfor
lowRISC Contributors802543a2019-08-31 12:12:56 +0100300
301 .tl_i (tl_${m["name"]}_d_h2d),
302 .tl_o (tl_${m["name"]}_d_d2h),
303
304 .req_o (${m["name"]}_req),
305 .gnt_i (1'b1), // Always grant as only one requester exists
306 .we_o (),
307 .addr_o (${m["name"]}_addr),
308 .wdata_o (),
309 .wmask_o (),
310 .rdata_i (${m["name"]}_rdata),
311 .rvalid_i (${m["name"]}_rvalid),
312 .rerror_i (2'b00)
313 );
314
315 ## TODO: Replace emulated ROM to real ROM in ASIC SoC
316 prim_rom #(
317 .Width(${data_width}),
318 .Depth(${rom_depth})
319 ) u_rom_${m["name"]} (
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700320 % for key in clocks:
321 .${key} (${clocks[key]}_clk),
322 % endfor
Timothy Chen3193b002019-10-04 16:56:05 -0700323 % for key in resets:
324 .${key} (${resets[key]}_rst_n),
325 % endfor
lowRISC Contributors802543a2019-08-31 12:12:56 +0100326 .cs_i (${m["name"]}_req),
327 .addr_i (${m["name"]}_addr),
Timothy Chen44461032019-09-20 15:35:20 -0700328 .dout_o (${m["name"]}_rdata),
329 .dvalid_o (${m["name"]}_rvalid)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100330 );
331
lowRISC Contributors802543a2019-08-31 12:12:56 +0100332 % elif m["type"] == "eflash":
333
334 // flash controller to eflash communication
335 flash_c2m_t flash_c2m;
336 flash_m2c_t flash_m2c;
337
338 // host to flash communication
339 logic flash_host_req;
340 logic flash_host_req_rdy;
341 logic flash_host_req_done;
342 logic [FLASH_DW-1:0] flash_host_rdata;
343 logic [FLASH_AW-1:0] flash_host_addr;
344
Timothy Chen5aec5282019-09-10 21:10:56 -0700345 tlul_adapter_sram #(
346 .SramAw(FLASH_AW),
347 .SramDw(FLASH_DW),
348 .Outstanding(1),
349 .ByteAccess(0),
350 .ErrOnWrite(1)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100351 ) tl_adapter_${m["name"]} (
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700352 % for key in clocks:
353 .${key} (${clocks[key]}_clk),
354 % endfor
Timothy Chen3193b002019-10-04 16:56:05 -0700355 % for key in resets:
356 .${key} (${resets[key]}_rst_n),
357 % endfor
lowRISC Contributors802543a2019-08-31 12:12:56 +0100358
359 .tl_i (tl_${m["name"]}_d_h2d),
360 .tl_o (tl_${m["name"]}_d_d2h),
361
Timothy Chen5aec5282019-09-10 21:10:56 -0700362 .req_o (flash_host_req),
363 .gnt_i (flash_host_req_rdy),
364 .we_o (),
365 .addr_o (flash_host_addr),
366 .wdata_o (),
367 .wmask_o (),
368 .rdata_i (flash_host_rdata),
369 .rvalid_i (flash_host_req_done),
370 .rerror_i (2'b00)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100371 );
372
373 flash_phy #(
374 .NumBanks(FLASH_BANKS),
375 .PagesPerBank(FLASH_PAGES_PER_BANK),
376 .WordsPerPage(FLASH_WORDS_PER_PAGE),
377 .DataWidth(${data_width})
378 ) u_flash_${m["name"]} (
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700379 % for key in clocks:
380 .${key} (${clocks[key]}_clk),
381 % endfor
Timothy Chen3193b002019-10-04 16:56:05 -0700382 % for key in resets:
383 .${key} (${resets[key]}_rst_n),
384 % endfor
lowRISC Contributors802543a2019-08-31 12:12:56 +0100385 .host_req_i (flash_host_req),
386 .host_addr_i (flash_host_addr),
387 .host_req_rdy_o (flash_host_req_rdy),
388 .host_req_done_o (flash_host_req_done),
389 .host_rdata_o (flash_host_rdata),
390 .flash_ctrl_i (flash_c2m),
391 .flash_ctrl_o (flash_m2c)
392 );
393
394 % else:
395 // flash memory is embedded within controller
396 % endif
397% endfor
lowRISC Contributors802543a2019-08-31 12:12:56 +0100398## Peripheral Instantiation
Timothy Chen3193b002019-10-04 16:56:05 -0700399
lowRISC Contributors802543a2019-08-31 12:12:56 +0100400% for m in top["module"]:
Timothy Chen3193b002019-10-04 16:56:05 -0700401<%
402
403%>\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100404 % if "parameter" in m:
405 ${m["type"]} #(
406 % for k, v in m["parameter"].items():
407 % if loop.last:
408 .${k}(${parameterize(v)})
409 % else:
410 .${k}(${parameterize(v)}),
411 % endif
412 % endfor
413 ) ${m["name"]} (
414 % else:
415 ${m["type"]} ${m["name"]} (
416 % endif
417 % if not "bus_host" in m or m["bus_host"] in ["none", ""]:
418 ## Assume TL-UL
419 .tl_i (tl_${m["name"]}_d_h2d),
420 .tl_o (tl_${m["name"]}_d_d2h),
421 % else:
422 .tl_d_i (tl_${m["name"]}_d_h2d),
423 .tl_d_o (tl_${m["name"]}_d_d2h),
424 .tl_h_o (tl_${m["name"]}_h_h2d),
425 .tl_h_i (tl_${m["name"]}_h_d2h),
426 % endif
427 ## CIO
428 ## TODO: Find a way to handle `scanmode`. It is not cio_ but top-level signal
429 % for p_in in m["available_input_list"] + m["available_inout_list"]:
430 ## assume it passed validate and have available input list always
431 .cio_${p_in["name"]}_i (cio_${m["name"]}_${p_in["name"]}_p2d_i),
432 % endfor
433 % for p_in in m["available_output_list"] + m["available_inout_list"]:
434 ## assume it passed validate and have available output list always
435 .cio_${p_in["name"]}_o (cio_${m["name"]}_${p_in["name"]}_d2p_o),
436 .cio_${p_in["name"]}_en_o (cio_${m["name"]}_${p_in["name"]}_en_d2p_o),
437 % endfor
438 % for intr in m["interrupt_list"] if "interrupt_list" in m else []:
439 .intr_${intr["name"]}_o (intr_${m["name"]}_${intr["name"]}),
440 % endfor
441 % if m["type"] == "flash_ctrl":
442 .flash_o(flash_c2m),
443 .flash_i(flash_m2c),
444 % endif
445 % if m["type"] == "rv_plic":
446 .intr_src_i (intr_vector),
447 .irq_o (irq_plic),
448 .irq_id_o (irq_id),
449 .msip_o (msip),
450 % endif
Timothy Chen3193b002019-10-04 16:56:05 -0700451
Eunchan Kim2cfadab2019-10-02 12:41:11 -0700452 % if m["scan"] == "true":
453 .scanmode_i (scanmode_i),
454 % endif
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700455 % for k, v in m["clock_connections"].items():
456 .${k} (${v}_clk),
457 % endfor
Timothy Chen3193b002019-10-04 16:56:05 -0700458 % for k, v in m["reset_connections"].items():
459 % if loop.last:
460 .${k} (${v}_rst_n)
461 % else:
462 .${k} (${v}_rst_n),
463 % endif
464 % endfor
lowRISC Contributors802543a2019-08-31 12:12:56 +0100465 );
466
467% endfor
468 // interrupt assignments
469 assign intr_vector = {
470 % for intr in top["interrupt"][::-1]:
471 % if loop.last:
472 intr_${intr["name"]}
473 % else:
474 intr_${intr["name"]},
475 % endif
476 % endfor
477 };
478
479 // TL-UL Crossbar
lowRISC Contributors802543a2019-08-31 12:12:56 +0100480% for xbar in top["xbar"]:
481<%
482 name_len = max([len(x["name"]) for x in xbar["nodes"]]);
483%>\
484 xbar_${xbar["name"]} u_xbar_${xbar["name"]} (
Timothy Chen80bd8aa2019-10-04 15:57:11 -0700485 % for k, v in xbar["clock_connections"].items():
486 .${k} (${v}_clk),
lowRISC Contributors802543a2019-08-31 12:12:56 +0100487 % endfor
Timothy Chen3193b002019-10-04 16:56:05 -0700488 % for k, v in xbar["reset_connections"].items():
489 .${k} (${v}_rst_n),
490 % endfor
lowRISC Contributors802543a2019-08-31 12:12:56 +0100491 % for node in xbar["nodes"]:
492 % if node["type"] == "device":
493 .tl_${(node["name"]+"_o").ljust(name_len+2)} (tl_${node["name"]}_d_h2d),
494 .tl_${(node["name"]+"_i").ljust(name_len+2)} (tl_${node["name"]}_d_d2h),
495 % elif node["type"] == "host":
496 .tl_${(node["name"]+"_i").ljust(name_len+2)} (tl_${node["name"]}_h_h2d),
497 .tl_${(node["name"]+"_o").ljust(name_len+2)} (tl_${node["name"]}_h_d2h),
498 % endif
499 % endfor
500
501 .scanmode_i
502% endfor
503 );
504
Nils Graf78607aa2019-09-16 15:47:23 -0700505 // make sure scanmode_i is never X (including during reset)
506 `ASSERT_KNOWN(scanmodeKnown, scanmode_i, clk_i, 0)
507
lowRISC Contributors802543a2019-08-31 12:12:56 +0100508endmodule
509<%def name="parameterize(v)">\
510 ## value type
511 ## if it is integer, or bit'{h|d|b} digit, just put without quote
512 ## else return with quote
513 % if re.match('(\d+\'[hdb]\s*[0-9a-f_A-F]+|[0-9]+)',v) == None:
514"${v}"\
515 % else:
516${v}\
517 % endif
518</%def>\