blob: add71220d82518d303e5b93412f4093a0d390d18 [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// Register Top module auto-generated by `reggen`
6<%
Rupert Swarbrick200d8b42021-03-08 12:32:11 +00007 from reggen import gen_rtl
8 from reggen.access import HwAccess, SwRdAccess, SwWrAccess
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +00009 from reggen.lib import get_basename
Rupert Swarbrick4d645362021-02-08 17:17:05 +000010 from reggen.register import Register
11 from reggen.multi_register import MultiRegister
Rupert Swarbrickede94802021-02-08 09:16:50 +000012
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000013 num_wins = len(rb.windows)
lowRISC Contributors802543a2019-08-31 12:12:56 +010014 num_wins_width = ((num_wins+1).bit_length()) - 1
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000015 num_reg_dsp = 1 if rb.all_regs else 0
16 num_dsp = num_wins + num_reg_dsp
17 regs_flat = rb.flat_regs
Rupert Swarbrick1db6fcd2021-02-11 14:56:20 +000018 max_regs_char = len("{}".format(len(regs_flat) - 1))
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000019 addr_width = rb.get_addr_width()
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +000020
21 lblock = block.name.lower()
22 ublock = lblock.upper()
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000023
24 u_mod_base = mod_base.upper()
25
26 reg2hw_t = gen_rtl.get_iface_tx_type(block, if_name, False)
27 hw2reg_t = gen_rtl.get_iface_tx_type(block, if_name, True)
28
29 # Calculate whether we're going to need an AW parameter. We use it if there
30 # are any registers (obviously). We also use it if there are any windows that
31 # don't start at zero and end at 1 << addr_width (see the "addr_checks"
32 # calculation below for where that comes from).
33 needs_aw = (bool(regs_flat) or
34 num_wins > 1 or
35 rb.windows and (
36 rb.windows[0].offset != 0 or
37 rb.windows[0].size_in_bytes != (1 << addr_width)))
38
Timothy Chen62dabf72021-03-24 12:09:27 -070039
40 common_data_intg_gen = 0 if rb.has_data_intg_passthru else 1
41 adapt_data_intg_gen = 1 if rb.has_data_intg_passthru else 0
42 assert common_data_intg_gen != adapt_data_intg_gen
lowRISC Contributors802543a2019-08-31 12:12:56 +010043%>
Greg Chadwickcf423082020-02-05 16:52:23 +000044`include "prim_assert.sv"
45
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000046module ${mod_name} (
lowRISC Contributors802543a2019-08-31 12:12:56 +010047 input clk_i,
48 input rst_ni,
49
lowRISC Contributors802543a2019-08-31 12:12:56 +010050 input tlul_pkg::tl_h2d_t tl_i,
51 output tlul_pkg::tl_d2h_t tl_o,
52% if num_wins != 0:
53
54 // Output port for window
55 output tlul_pkg::tl_h2d_t tl_win_o [${num_wins}],
56 input tlul_pkg::tl_d2h_t tl_win_i [${num_wins}],
57
58% endif
59 // To HW
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000060% if rb.get_n_bits(["q","qe","re"]):
61 output ${lblock}_reg_pkg::${reg2hw_t} reg2hw, // Write
Michael Schaffner9a92bea2019-09-30 18:13:14 -070062% endif
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000063% if rb.get_n_bits(["d","de"]):
64 input ${lblock}_reg_pkg::${hw2reg_t} hw2reg, // Read
Michael Schaffner9a92bea2019-09-30 18:13:14 -070065% endif
Eunchan Kimde88e3a2019-09-23 11:06:41 -070066
Timothy Chenaa6c1ed2021-03-01 16:20:11 -080067 // Integrity check errors
68 output logic intg_err_o,
69
Eunchan Kimde88e3a2019-09-23 11:06:41 -070070 // Config
71 input devmode_i // If 1, explicit error return for unmapped register access
lowRISC Contributors802543a2019-08-31 12:12:56 +010072);
73
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +000074 import ${lblock}_reg_pkg::* ;
lowRISC Contributors802543a2019-08-31 12:12:56 +010075
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000076% if needs_aw:
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +000077 localparam int AW = ${addr_width};
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000078% endif
79% if rb.all_regs:
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +000080 localparam int DW = ${block.regwidth};
Michael Schaffner1b5fa9f2020-01-17 17:43:42 -080081 localparam int DBW = DW/8; // Byte Width
lowRISC Contributors802543a2019-08-31 12:12:56 +010082
83 // register signals
Eunchan Kim819a4662019-09-04 21:44:36 -070084 logic reg_we;
85 logic reg_re;
86 logic [AW-1:0] reg_addr;
87 logic [DW-1:0] reg_wdata;
88 logic [DBW-1:0] reg_be;
89 logic [DW-1:0] reg_rdata;
90 logic reg_error;
lowRISC Contributors802543a2019-08-31 12:12:56 +010091
Eunchan Kim51461cd2019-09-18 14:00:49 -070092 logic addrmiss, wr_err;
lowRISC Contributors802543a2019-08-31 12:12:56 +010093
Eunchan Kim819a4662019-09-04 21:44:36 -070094 logic [DW-1:0] reg_rdata_next;
lowRISC Contributors802543a2019-08-31 12:12:56 +010095
96 tlul_pkg::tl_h2d_t tl_reg_h2d;
97 tlul_pkg::tl_d2h_t tl_reg_d2h;
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000098% endif
lowRISC Contributors802543a2019-08-31 12:12:56 +010099
Timothy Chend12569f2021-02-12 15:28:12 -0800100 // incoming payload check
Timothy Chenaa6c1ed2021-03-01 16:20:11 -0800101 logic intg_err;
102 tlul_cmd_intg_chk u_chk (
Timothy Chend12569f2021-02-12 15:28:12 -0800103 .tl_i,
Timothy Chen915df692021-03-05 13:16:36 -0800104 .err_o(intg_err)
Timothy Chend12569f2021-02-12 15:28:12 -0800105 );
106
Timothy Chen915df692021-03-05 13:16:36 -0800107 logic intg_err_q;
Timothy Chenaa6c1ed2021-03-01 16:20:11 -0800108 always_ff @(posedge clk_i or negedge rst_ni) begin
109 if (!rst_ni) begin
Timothy Chen915df692021-03-05 13:16:36 -0800110 intg_err_q <= '0;
Timothy Chenaa6c1ed2021-03-01 16:20:11 -0800111 end else if (intg_err) begin
Timothy Chen915df692021-03-05 13:16:36 -0800112 intg_err_q <= 1'b1;
Timothy Chenaa6c1ed2021-03-01 16:20:11 -0800113 end
114 end
115
Timothy Chen915df692021-03-05 13:16:36 -0800116 // integrity error output is permanent and should be used for alert generation
117 // register errors are transactional
118 assign intg_err_o = intg_err_q | intg_err;
119
Timothy Chenaa6c1ed2021-03-01 16:20:11 -0800120 // outgoing integrity generation
Timothy Chend12569f2021-02-12 15:28:12 -0800121 tlul_pkg::tl_d2h_t tl_o_pre;
Timothy Chen62dabf72021-03-24 12:09:27 -0700122 tlul_rsp_intg_gen #(
123 .EnableRspIntgGen(1),
124 .EnableDataIntgGen(${common_data_intg_gen})
125 ) u_rsp_intg_gen (
Timothy Chend12569f2021-02-12 15:28:12 -0800126 .tl_i(tl_o_pre),
127 .tl_o
128 );
129
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000130% if num_dsp == 1:
131 ## Either no windows (and just registers) or no registers and only
132 ## one window.
133 % if num_wins == 0:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100134 assign tl_reg_h2d = tl_i;
Timothy Chend12569f2021-02-12 15:28:12 -0800135 assign tl_o_pre = tl_reg_d2h;
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000136 % else:
137 assign tl_win_o[0] = tl_i;
138 assign tl_o_pre = tl_win_i[0];
139 % endif
lowRISC Contributors802543a2019-08-31 12:12:56 +0100140% else:
141 tlul_pkg::tl_h2d_t tl_socket_h2d [${num_dsp}];
142 tlul_pkg::tl_d2h_t tl_socket_d2h [${num_dsp}];
143
144 logic [${num_wins_width}:0] reg_steer;
145
146 // socket_1n connection
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000147 % if rb.all_regs:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100148 assign tl_reg_h2d = tl_socket_h2d[${num_wins}];
149 assign tl_socket_d2h[${num_wins}] = tl_reg_d2h;
150
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000151 % endif
152 % for i,t in enumerate(rb.windows):
lowRISC Contributors802543a2019-08-31 12:12:56 +0100153 assign tl_win_o[${i}] = tl_socket_h2d[${i}];
Timothy Chen62dabf72021-03-24 12:09:27 -0700154 % if common_data_intg_gen == 0 and rb.windows[i].data_intg_passthru == False:
155 ## If there are multiple windows, and not every window has data integrity
156 ## passthrough, we must generate data integrity for it here.
157 tlul_rsp_intg_gen #(
158 .EnableRspIntgGen(0),
159 .EnableDataIntgGen(1)
160 ) u_win${i}_data_intg_gen (
161 .tl_i(tl_win_i[${i}]),
162 .tl_o(tl_socket_d2h[${i}])
163 );
164 % else:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100165 assign tl_socket_d2h[${i}] = tl_win_i[${i}];
Timothy Chen62dabf72021-03-24 12:09:27 -0700166 % endif
lowRISC Contributors802543a2019-08-31 12:12:56 +0100167 % endfor
168
169 // Create Socket_1n
170 tlul_socket_1n #(
171 .N (${num_dsp}),
172 .HReqPass (1'b1),
173 .HRspPass (1'b1),
174 .DReqPass ({${num_dsp}{1'b1}}),
175 .DRspPass ({${num_dsp}{1'b1}}),
Eunchan Kim32dd11b2019-11-05 15:15:33 -0800176 .HReqDepth (4'h0),
177 .HRspDepth (4'h0),
178 .DReqDepth ({${num_dsp}{4'h0}}),
179 .DRspDepth ({${num_dsp}{4'h0}})
lowRISC Contributors802543a2019-08-31 12:12:56 +0100180 ) u_socket (
181 .clk_i,
182 .rst_ni,
183 .tl_h_i (tl_i),
Timothy Chend12569f2021-02-12 15:28:12 -0800184 .tl_h_o (tl_o_pre),
lowRISC Contributors802543a2019-08-31 12:12:56 +0100185 .tl_d_o (tl_socket_h2d),
186 .tl_d_i (tl_socket_d2h),
Scott Johnson204d98d2020-07-17 12:06:05 -0700187 .dev_select_i (reg_steer)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100188 );
189
190 // Create steering logic
191 always_comb begin
192 reg_steer = ${num_dsp-1}; // Default set to register
193
194 // TODO: Can below codes be unique case () inside ?
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000195 % for i,w in enumerate(rb.windows):
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +0000196<%
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000197 base_addr = w.offset
198 limit_addr = w.offset + w.size_in_bytes
199
200 hi_check = 'tl_i.a_address[AW-1:0] < {}'.format(limit_addr)
201 addr_checks = []
202 if base_addr > 0:
203 addr_checks.append('tl_i.a_address[AW-1:0] >= {}'.format(base_addr))
204 if limit_addr < 2**addr_width:
205 addr_checks.append('tl_i.a_address[AW-1:0] < {}'.format(limit_addr))
206
207 addr_test = ' && '.join(addr_checks)
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +0000208%>\
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000209 % if addr_test:
210 if (${addr_test}) begin
lowRISC Contributors802543a2019-08-31 12:12:56 +0100211 % endif
212 reg_steer = ${i};
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000213 % if addr_test:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100214 end
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000215 % endif
lowRISC Contributors802543a2019-08-31 12:12:56 +0100216 % endfor
Timothy Chenaa6c1ed2021-03-01 16:20:11 -0800217 if (intg_err) begin
Timothy Chend12569f2021-02-12 15:28:12 -0800218 reg_steer = ${num_dsp-1};
219 end
lowRISC Contributors802543a2019-08-31 12:12:56 +0100220 end
221% endif
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000222% if rb.all_regs:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100223
Eunchan Kim819a4662019-09-04 21:44:36 -0700224 tlul_adapter_reg #(
225 .RegAw(AW),
Timothy Chen62dabf72021-03-24 12:09:27 -0700226 .RegDw(DW),
227 .EnableDataIntgGen(${adapt_data_intg_gen})
Eunchan Kim819a4662019-09-04 21:44:36 -0700228 ) u_reg_if (
229 .clk_i,
230 .rst_ni,
lowRISC Contributors802543a2019-08-31 12:12:56 +0100231
Eunchan Kim819a4662019-09-04 21:44:36 -0700232 .tl_i (tl_reg_h2d),
233 .tl_o (tl_reg_d2h),
lowRISC Contributors802543a2019-08-31 12:12:56 +0100234
Eunchan Kim819a4662019-09-04 21:44:36 -0700235 .we_o (reg_we),
236 .re_o (reg_re),
237 .addr_o (reg_addr),
238 .wdata_o (reg_wdata),
239 .be_o (reg_be),
240 .rdata_i (reg_rdata),
241 .error_i (reg_error)
242 );
lowRISC Contributors802543a2019-08-31 12:12:56 +0100243
Eunchan Kim819a4662019-09-04 21:44:36 -0700244 assign reg_rdata = reg_rdata_next ;
Timothy Chenaa6c1ed2021-03-01 16:20:11 -0800245 assign reg_error = (devmode_i & addrmiss) | wr_err | intg_err;
lowRISC Contributors802543a2019-08-31 12:12:56 +0100246
247 // Define SW related signals
248 // Format: <reg>_<field>_{wd|we|qs}
249 // or <reg>_{wd|we|qs} if field == 1 or 0
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700250 % for r in regs_flat:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100251 % if len(r.fields) == 1:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000252${sig_gen(r.fields[0], r.name.lower(), r.hwext, r.shadowed)}\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100253 % else:
254 % for f in r.fields:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000255${sig_gen(f, r.name.lower() + "_" + f.name.lower(), r.hwext, r.shadowed)}\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100256 % endfor
257 % endif
258 % endfor
259
260 // Register instances
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000261 % for r in rb.all_regs:
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700262 ######################## multiregister ###########################
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000263 % if isinstance(r, MultiRegister):
lowRISC Contributors802543a2019-08-31 12:12:56 +0100264<%
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700265 k = 0
266%>
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000267 % for sr in r.regs:
268 // Subregister ${k} of Multireg ${r.reg.name.lower()}
269 // R[${sr.name.lower()}]: V(${str(sr.hwext)})
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700270 % if len(sr.fields) == 1:
271<%
272 f = sr.fields[0]
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000273 finst_name = sr.name.lower()
274 fsig_name = r.reg.name.lower() + "[%d]" % k
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700275 k = k + 1
lowRISC Contributors802543a2019-08-31 12:12:56 +0100276%>
Rupert Swarbrickede94802021-02-08 09:16:50 +0000277${finst_gen(f, finst_name, fsig_name, sr.hwext, sr.regwen, sr.shadowed)}
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700278 % else:
279 % for f in sr.fields:
280<%
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000281 finst_name = sr.name.lower() + "_" + f.name.lower()
282 if r.is_homogeneous():
283 fsig_name = r.reg.name.lower() + "[%d]" % k
Michael Schaffnera2c51d92019-09-27 16:38:24 -0700284 k = k + 1
285 else:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000286 fsig_name = r.reg.name.lower() + "[%d]" % k + "." + get_basename(f.name.lower())
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700287%>
Rupert Swarbrickede94802021-02-08 09:16:50 +0000288 // F[${f.name.lower()}]: ${f.bits.msb}:${f.bits.lsb}
289${finst_gen(f, finst_name, fsig_name, sr.hwext, sr.regwen, sr.shadowed)}
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700290 % endfor
Michael Schaffnera2c51d92019-09-27 16:38:24 -0700291<%
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000292 if not r.is_homogeneous():
Michael Schaffnera2c51d92019-09-27 16:38:24 -0700293 k += 1
294%>
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700295 % endif
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000296 ## for: mreg_flat
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700297 % endfor
298######################## register with single field ###########################
299 % elif len(r.fields) == 1:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000300 // R[${r.name.lower()}]: V(${str(r.hwext)})
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700301<%
302 f = r.fields[0]
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000303 finst_name = r.name.lower()
304 fsig_name = r.name.lower()
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700305%>
Rupert Swarbrickede94802021-02-08 09:16:50 +0000306${finst_gen(f, finst_name, fsig_name, r.hwext, r.regwen, r.shadowed)}
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700307######################## register with multiple fields ###########################
lowRISC Contributors802543a2019-08-31 12:12:56 +0100308 % else:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000309 // R[${r.name.lower()}]: V(${str(r.hwext)})
lowRISC Contributors802543a2019-08-31 12:12:56 +0100310 % for f in r.fields:
311<%
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000312 finst_name = r.name.lower() + "_" + f.name.lower()
313 fsig_name = r.name.lower() + "." + f.name.lower()
lowRISC Contributors802543a2019-08-31 12:12:56 +0100314%>
Rupert Swarbrickede94802021-02-08 09:16:50 +0000315 // F[${f.name.lower()}]: ${f.bits.msb}:${f.bits.lsb}
316${finst_gen(f, finst_name, fsig_name, r.hwext, r.regwen, r.shadowed)}
lowRISC Contributors802543a2019-08-31 12:12:56 +0100317 % endfor
318 % endif
319
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000320 ## for: rb.all_regs
lowRISC Contributors802543a2019-08-31 12:12:56 +0100321 % endfor
322
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700323
324 logic [${len(regs_flat)-1}:0] addr_hit;
lowRISC Contributors802543a2019-08-31 12:12:56 +0100325 always_comb begin
326 addr_hit = '0;
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700327 % for i,r in enumerate(regs_flat):
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +0000328 addr_hit[${"{}".format(i).rjust(max_regs_char)}] = (reg_addr == ${ublock}_${r.name.upper()}_OFFSET);
lowRISC Contributors802543a2019-08-31 12:12:56 +0100329 % endfor
330 end
331
Eunchan Kim244a1d52019-09-23 15:46:43 -0700332 assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
lowRISC Contributors802543a2019-08-31 12:12:56 +0100333
Rupert Swarbrickce8e3932021-04-21 11:45:34 +0100334% if regs_flat:
335<%
336 # We want to signal wr_err if reg_be (the byte enable signal) is true for
337 # any bytes that aren't supported by a register. That's true if a
338 # addr_hit[i] and a bit is set in reg_be but not in *_PERMIT[i].
339
340 wr_err_terms = ['(addr_hit[{idx}] & (|({mod}_PERMIT[{idx}] & ~reg_be)))'
341 .format(idx=str(i).rjust(max_regs_char),
342 mod=u_mod_base)
343 for i in range(len(regs_flat))]
344 wr_err_expr = (' |\n' + (' ' * 15)).join(wr_err_terms)
345%>\
Eunchan Kim51461cd2019-09-18 14:00:49 -0700346 // Check sub-word write is permitted
347 always_comb begin
Rupert Swarbrickce8e3932021-04-21 11:45:34 +0100348 wr_err = (reg_we &
349 (${wr_err_expr}));
Eunchan Kim51461cd2019-09-18 14:00:49 -0700350 end
Rupert Swarbrickce8e3932021-04-21 11:45:34 +0100351% else:
352 assign wr_error = 1'b0;
353% endif\
354
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700355 % for i, r in enumerate(regs_flat):
lowRISC Contributors802543a2019-08-31 12:12:56 +0100356 % if len(r.fields) == 1:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000357${we_gen(r.fields[0], r.name.lower(), r.hwext, r.shadowed, i)}\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100358 % else:
359 % for f in r.fields:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000360${we_gen(f, r.name.lower() + "_" + f.name.lower(), r.hwext, r.shadowed, i)}\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100361 % endfor
362 % endif
363 % endfor
364
365 // Read data return
lowRISC Contributors802543a2019-08-31 12:12:56 +0100366 always_comb begin
367 reg_rdata_next = '0;
368 unique case (1'b1)
Michael Schaffner9a94b6c2019-09-25 16:17:35 -0700369 % for i, r in enumerate(regs_flat):
lowRISC Contributors802543a2019-08-31 12:12:56 +0100370 % if len(r.fields) == 1:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100371 addr_hit[${i}]: begin
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000372${rdata_gen(r.fields[0], r.name.lower())}\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100373 end
374
375 % else:
376 addr_hit[${i}]: begin
377 % for f in r.fields:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000378${rdata_gen(f, r.name.lower() + "_" + f.name.lower())}\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100379 % endfor
380 end
381
382 % endif
383 % endfor
384 default: begin
385 reg_rdata_next = '1;
386 end
387 endcase
388 end
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000389% endif
lowRISC Contributors802543a2019-08-31 12:12:56 +0100390
Timothy Chenac6af872021-02-22 17:17:52 -0800391 // Unused signal tieoff
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000392% if rb.all_regs:
Timothy Chenac6af872021-02-22 17:17:52 -0800393
394 // wdata / byte enable are not always fully used
395 // add a blanket unused statement to handle lint waivers
396 logic unused_wdata;
397 logic unused_be;
398 assign unused_wdata = ^reg_wdata;
399 assign unused_be = ^reg_be;
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000400% else:
401 // devmode_i is not used if there are no registers
402 logic unused_devmode;
403 assign unused_devmode = ^devmode_i;
404% endif
405% if rb.all_regs:
Timothy Chenac6af872021-02-22 17:17:52 -0800406
lowRISC Contributors802543a2019-08-31 12:12:56 +0100407 // Assertions for Register Interface
Greg Chadwick46ede4b2020-01-14 12:46:39 +0000408 `ASSERT_PULSE(wePulse, reg_we)
409 `ASSERT_PULSE(rePulse, reg_re)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100410
Greg Chadwick46ede4b2020-01-14 12:46:39 +0000411 `ASSERT(reAfterRv, $rose(reg_re || reg_we) |=> tl_o.d_valid)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100412
Greg Chadwick46ede4b2020-01-14 12:46:39 +0000413 `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit))
lowRISC Contributors802543a2019-08-31 12:12:56 +0100414
Michael Schaffneree9e8db2019-10-22 17:49:51 -0700415 // this is formulated as an assumption such that the FPV testbenches do disprove this
416 // property by mistake
Timothy Chen27b0a642021-02-16 14:02:08 -0800417 //`ASSUME(reqParity, tl_reg_h2d.a_valid |-> tl_reg_h2d.a_user.chk_en == tlul_pkg::CheckDis)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100418
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000419% endif
lowRISC Contributors802543a2019-08-31 12:12:56 +0100420endmodule
Rupert Swarbrickede94802021-02-08 09:16:50 +0000421<%def name="str_bits_sv(bits)">\
422% if bits.msb != bits.lsb:
423${bits.msb}:${bits.lsb}\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100424% else:
Rupert Swarbrickede94802021-02-08 09:16:50 +0000425${bits.msb}\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100426% endif
427</%def>\
Rupert Swarbrickede94802021-02-08 09:16:50 +0000428<%def name="str_arr_sv(bits)">\
429% if bits.msb != bits.lsb:
430[${bits.msb-bits.lsb}:0] \
lowRISC Contributors802543a2019-08-31 12:12:56 +0100431% endif
432</%def>\
Rupert Swarbrickede94802021-02-08 09:16:50 +0000433<%def name="sig_gen(field, sig_name, hwext, shadowed)">\
434 % if field.swaccess.allows_read():
435 logic ${str_arr_sv(field.bits)}${sig_name}_qs;
lowRISC Contributors802543a2019-08-31 12:12:56 +0100436 % endif
Rupert Swarbrickede94802021-02-08 09:16:50 +0000437 % if field.swaccess.allows_write():
438 logic ${str_arr_sv(field.bits)}${sig_name}_wd;
lowRISC Contributors802543a2019-08-31 12:12:56 +0100439 logic ${sig_name}_we;
440 % endif
Rupert Swarbrickede94802021-02-08 09:16:50 +0000441 % if (field.swaccess.allows_read() and hwext) or shadowed:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100442 logic ${sig_name}_re;
443 % endif
444</%def>\
Rupert Swarbrickede94802021-02-08 09:16:50 +0000445<%def name="finst_gen(field, finst_name, fsig_name, hwext, regwen, shadowed)">\
Rupert Swarbrickc5a68c92021-05-28 15:58:26 +0100446<%
447 re_expr = f'{finst_name}_re' if field.swaccess.allows_read() else "1'b0"
448
449 if field.swaccess.allows_write():
450 if regwen:
451 we_expr = f'{finst_name}_we & {regwen.lower()}_qs'
452 else:
453 we_expr = f'{finst_name}_we'
454 wd_expr = f'{finst_name}_wd'
455 else:
456 we_expr = "1'b0"
457 wd_expr = "'0"
458
459 if field.hwaccess.allows_write():
460 de_expr = f'hw2reg.{fsig_name}.de'
461 d_expr = f'hw2reg.{fsig_name}.d'
462 else:
463 de_expr = "1'b0"
464 d_expr = "'0"
465
466 qre_expr = f'reg2hw.{fsig_name}.re' if field.hwre or shadowed else ""
467
468 if field.hwaccess.allows_read():
469 qe_expr = f'reg2hw.{fsig_name}.qe' if field.hwqe else ''
470 q_expr = f'reg2hw.{fsig_name}.q'
471 else:
472 qe_expr = ''
473 q_expr = ''
474
475 qs_expr = f'{finst_name}_qs' if field.swaccess.allows_read() else ''
476%>\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100477 % if hwext: ## if hwext, instantiate prim_subreg_ext
478 prim_subreg_ext #(
Rupert Swarbrickede94802021-02-08 09:16:50 +0000479 .DW (${field.bits.width()})
lowRISC Contributors802543a2019-08-31 12:12:56 +0100480 ) u_${finst_name} (
Rupert Swarbrickc5a68c92021-05-28 15:58:26 +0100481 .re (${re_expr}),
482 .we (${we_expr}),
483 .wd (${wd_expr}),
484 .d (${d_expr}),
485 .qre (${qre_expr}),
486 .qe (${qe_expr}),
487 .q (${q_expr}),
488 .qs (${qs_expr})
lowRISC Contributors802543a2019-08-31 12:12:56 +0100489 );
Rupert Swarbrickc5a68c92021-05-28 15:58:26 +0100490 % else:
491<%
492 # This isn't a field in a hwext register. Instantiate prim_subreg,
493 # prim_subreg_shadow or constant assign.
494
495 resval_expr = f"{field.bits.width()}'h{field.resval or 0:x}"
496 is_const_reg = not (field.hwaccess.allows_read() or
497 field.hwaccess.allows_write() or
498 field.swaccess.allows_write() or
499 field.swaccess.swrd() != SwRdAccess.RD)
500
501 subreg_block = 'prim_subreg' + ('_shadowed' if shadowed else '')
502%>\
503 % if is_const_reg:
lowRISC Contributors802543a2019-08-31 12:12:56 +0100504 // constant-only read
Rupert Swarbrickc5a68c92021-05-28 15:58:26 +0100505 assign ${finst_name}_qs = ${resval_expr};
506 % else:
507 ${subreg_block} #(
Rupert Swarbrickede94802021-02-08 09:16:50 +0000508 .DW (${field.bits.width()}),
509 .SWACCESS("${field.swaccess.value[1].name.upper()}"),
Rupert Swarbrickc5a68c92021-05-28 15:58:26 +0100510 .RESVAL (${resval_expr})
lowRISC Contributors802543a2019-08-31 12:12:56 +0100511 ) u_${finst_name} (
Rupert Swarbrick359c1262021-05-28 16:03:57 +0100512 .clk_i (clk_i),
513 .rst_ni (rst_ni),
lowRISC Contributors802543a2019-08-31 12:12:56 +0100514
Rupert Swarbrick359c1262021-05-28 16:03:57 +0100515 // from register interface
Pirmin Vogelab9d1ca2020-05-25 14:52:55 +0200516 % if shadowed:
Rupert Swarbrickc5a68c92021-05-28 15:58:26 +0100517 .re (${re_expr}),
Pirmin Vogelab9d1ca2020-05-25 14:52:55 +0200518 % endif
Rupert Swarbrickc5a68c92021-05-28 15:58:26 +0100519 .we (${we_expr}),
520 .wd (${wd_expr}),
lowRISC Contributors802543a2019-08-31 12:12:56 +0100521
522 // from internal hardware
Rupert Swarbrickc5a68c92021-05-28 15:58:26 +0100523 .de (${de_expr}),
524 .d (${d_expr}),
lowRISC Contributors802543a2019-08-31 12:12:56 +0100525
526 // to internal hardware
Rupert Swarbrickc5a68c92021-05-28 15:58:26 +0100527 .qe (${qe_expr}),
528 .q (${q_expr}),
lowRISC Contributors802543a2019-08-31 12:12:56 +0100529
Rupert Swarbrick359c1262021-05-28 16:03:57 +0100530 // to register interface (read)
Pirmin Vogelab9d1ca2020-05-25 14:52:55 +0200531 % if not shadowed:
Rupert Swarbrickc5a68c92021-05-28 15:58:26 +0100532 .qs (${qs_expr})
Pirmin Vogelab9d1ca2020-05-25 14:52:55 +0200533 % else:
Rupert Swarbrickc5a68c92021-05-28 15:58:26 +0100534 .qs (${qs_expr}),
Pirmin Vogelab9d1ca2020-05-25 14:52:55 +0200535
536 // Shadow register error conditions
Rupert Swarbrick359c1262021-05-28 16:03:57 +0100537 .err_update (reg2hw.${fsig_name}.err_update),
Pirmin Vogelab9d1ca2020-05-25 14:52:55 +0200538 .err_storage (reg2hw.${fsig_name}.err_storage)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100539 % endif
540 );
541 % endif ## end non-constant prim_subreg
542 % endif
543</%def>\
Rupert Swarbrickede94802021-02-08 09:16:50 +0000544<%def name="we_gen(field, sig_name, hwext, shadowed, idx)">\
Rupert Swarbrick1032b472021-03-12 11:09:56 +0000545<%
546 needs_we = field.swaccess.allows_write()
547 needs_re = (field.swaccess.allows_read() and hwext) or shadowed
548 space = '\n' if needs_we or needs_re else ''
549%>\
550${space}\
551% if needs_we:
Rupert Swarbrickede94802021-02-08 09:16:50 +0000552 % if field.swaccess.swrd() != SwRdAccess.RC:
Timothy Chena6f58292021-03-02 14:02:47 -0800553 assign ${sig_name}_we = addr_hit[${idx}] & reg_we & !reg_error;
Rupert Swarbrickede94802021-02-08 09:16:50 +0000554 assign ${sig_name}_wd = reg_wdata[${str_bits_sv(field.bits)}];
lowRISC Contributors802543a2019-08-31 12:12:56 +0100555 % else:
556 ## Generate WE based on read request, read should clear
Timothy Chena6f58292021-03-02 14:02:47 -0800557 assign ${sig_name}_we = addr_hit[${idx}] & reg_re & !reg_error;
lowRISC Contributors802543a2019-08-31 12:12:56 +0100558 assign ${sig_name}_wd = '1;
559 % endif
560% endif
Rupert Swarbrick1032b472021-03-12 11:09:56 +0000561% if needs_re:
Timothy Chena6f58292021-03-02 14:02:47 -0800562 assign ${sig_name}_re = addr_hit[${idx}] & reg_re & !reg_error;
lowRISC Contributors802543a2019-08-31 12:12:56 +0100563% endif
564</%def>\
Rupert Swarbrickede94802021-02-08 09:16:50 +0000565<%def name="rdata_gen(field, sig_name)">\
566% if field.swaccess.allows_read():
567 reg_rdata_next[${str_bits_sv(field.bits)}] = ${sig_name}_qs;
lowRISC Contributors802543a2019-08-31 12:12:56 +0100568% else:
Rupert Swarbrickede94802021-02-08 09:16:50 +0000569 reg_rdata_next[${str_bits_sv(field.bits)}] = '0;
lowRISC Contributors802543a2019-08-31 12:12:56 +0100570% endif
571</%def>\