// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Register Top module auto-generated by `reggen`
<%
  from reggen import gen_rtl
  from reggen.access import HwAccess, SwRdAccess, SwWrAccess
  from reggen.lib import get_basename
  from reggen.register import Register
  from reggen.multi_register import MultiRegister
  from reggen.bits import Bits

  alias_impl = "_" + block.alias_impl if block.alias_impl else ""

  num_wins = len(rb.windows)
  num_reg_dsp = 1 if rb.all_regs else 0
  num_dsp  = num_wins + num_reg_dsp
  regs_flat = rb.flat_regs
  max_regs_char = len("{}".format(len(regs_flat) - 1))
  addr_width = rb.get_addr_width()

  # Used for the dev_select_i signal on a tlul_socket_1n with N =
  # num_wins + 1. This needs to be able to represent any value up to
  # N-1.
  steer_msb = ((num_wins).bit_length()) - 1

  lblock = block.name.lower()
  ublock = lblock.upper()

  u_mod_base = mod_base.upper()

  reg2hw_t = gen_rtl.get_iface_tx_type(block, if_name, False)
  hw2reg_t = gen_rtl.get_iface_tx_type(block, if_name, True)

  win_array_decl = f'  [{num_wins}]' if num_wins > 1 else ''

  # Calculate whether we're going to need an AW parameter. We use it if there
  # are any registers (obviously). We also use it if there are any windows that
  # don't start at zero and end at 1 << addr_width (see the "addr_checks"
  # calculation below for where that comes from).
  needs_aw = (bool(regs_flat) or
              num_wins > 1 or
              rb.windows and (
                rb.windows[0].offset != 0 or
                rb.windows[0].size_in_bytes != (1 << addr_width)))


  common_data_intg_gen = 0 if rb.has_data_intg_passthru else 1
  adapt_data_intg_gen = 1 if rb.has_data_intg_passthru else 0
  assert common_data_intg_gen != adapt_data_intg_gen

  # declare a fully asynchronous interface
  reg_clk_expr = "clk_i"
  reg_rst_expr = "rst_ni"
  tl_h2d_expr = "tl_i"
  tl_d2h_expr = "tl_o"
  if rb.async_if:
    tl_h2d_expr = "tl_async_h2d"
    tl_d2h_expr = "tl_async_d2h"
    for clock in rb.clocks.values():
      reg_clk_expr = clock.clock
      reg_rst_expr = clock.reset

  # A map from "register" (which might be a multiregister) to a pair (r0, srs)
  # where r0 is the prototype register and srs is a list of single registers
  # corresponding to the original register.
  r0_srs = {}

  # A big map from field to "finst names". These names are a pair (fld_pfx,
  # name), where fld_pfx is the name used to index into hw2reg / reg2hw
  # structures (something like "my_reg.my_field") and name is the name that
  # gets prefixed onto local signals (something like "my_reg_my_field").
  finst_names = {}

  for r in rb.all_regs:
    if isinstance(r, MultiRegister):
      r0 = r.reg
      srs = r.regs
    else:
      r0 = r
      srs = [r]

    r0_srs[r] = (r0, srs)

    reg_name = r0.name.lower()
    fld_count = 0
    for sr_idx, sr in enumerate(srs):
      sr_name = sr.name.lower()
      for fidx, field in enumerate(sr.fields):
        if isinstance(r, MultiRegister):
          sig_idx = fld_count if r.is_homogeneous() else sr_idx
          fsig_pfx = '{}[{}]'.format(reg_name, sig_idx)
        else:
          fsig_pfx = reg_name

        fld_count += 1

        fld_name = field.name.lower()
        if len(sr.fields) == 1:
          finst_name = sr_name
          fsig_name = fsig_pfx
        else:
          finst_name = sr_name + '_' + fld_name
          if isinstance(r, MultiRegister):
            if r.is_homogeneous():
              fsig_name = fsig_pfx
            else:
              fsig_name = '{}.{}'.format(fsig_pfx, get_basename(fld_name))
          else:
            fsig_name = '{}.{}'.format(fsig_pfx, fld_name)

        finst_names[field] = (fsig_name, finst_name)

%>
`include "prim_assert.sv"

module ${mod_name} (
  input clk_i,
  input rst_ni,
% if rb.has_internal_shadowed_reg():
  input rst_shadowed_ni,
% endif
% for clock in rb.clocks.values():
  input ${clock.clock},
  input ${clock.reset},
% endfor
  input  tlul_pkg::tl_h2d_t tl_i,
  output tlul_pkg::tl_d2h_t tl_o,
% if num_wins != 0:

  // Output port for window
  output tlul_pkg::tl_h2d_t tl_win_o${win_array_decl},
  input  tlul_pkg::tl_d2h_t tl_win_i${win_array_decl},

% endif
  // To HW
% if rb.get_n_bits(["q","qe","re"]):
  output ${lblock}${alias_impl}_reg_pkg::${reg2hw_t} reg2hw, // Write
% endif
% if rb.get_n_bits(["d","de"]):
  input  ${lblock}${alias_impl}_reg_pkg::${hw2reg_t} hw2reg, // Read
% endif

% if rb.has_internal_shadowed_reg():
  output logic shadowed_storage_err_o,
  output logic shadowed_update_err_o,

%endif
  // Integrity check errors
  output logic intg_err_o,

  // Config
  input devmode_i // If 1, explicit error return for unmapped register access
);

  import ${lblock}${alias_impl}_reg_pkg::* ;

% if needs_aw:
  localparam int AW = ${addr_width};
% endif
% if rb.all_regs:
  localparam int DW = ${block.regwidth};
  localparam int DBW = DW/8;                    // Byte Width

  // register signals
  logic           reg_we;
  logic           reg_re;
  logic [AW-1:0]  reg_addr;
  logic [DW-1:0]  reg_wdata;
  logic [DBW-1:0] reg_be;
  logic [DW-1:0]  reg_rdata;
  logic           reg_error;

  logic          addrmiss, wr_err;

  logic [DW-1:0] reg_rdata_next;
  logic reg_busy;

  tlul_pkg::tl_h2d_t tl_reg_h2d;
  tlul_pkg::tl_d2h_t tl_reg_d2h;
% endif

## The clock and reset inputs aren't used if this device interface has no
## registers, only one window and isn't marked asynchronous. In that case, add
## an unused_ signal to avoid lint warnings.
% if not rb.all_regs and num_wins == 1 and not rb.async_if:
  // Add an unloaded flop to make use of clock / reset
  // This is done to specifically address lint complaints of unused clocks/resets
  // Since the flop is unloaded it will be removed during synthesis
  logic unused_reg;
  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      unused_reg <= '0;
    end else begin
      unused_reg <= tl_i.a_valid;
    end
  end


% endif
% if rb.async_if:
  tlul_pkg::tl_h2d_t tl_async_h2d;
  tlul_pkg::tl_d2h_t tl_async_d2h;
  tlul_fifo_async #(
    .ReqDepth(2),
    .RspDepth(2)
  ) u_if_sync (
    .clk_h_i(clk_i),
    .rst_h_ni(rst_ni),
    .clk_d_i(${reg_clk_expr}),
    .rst_d_ni(${reg_rst_expr}),
    .tl_h_i(tl_i),
    .tl_h_o(tl_o),
    .tl_d_o(${tl_h2d_expr}),
    .tl_d_i(${tl_d2h_expr})
  );
% endif

% if rb.all_regs:
  // incoming payload check
  logic intg_err;
  tlul_cmd_intg_chk u_chk (
    .tl_i(${tl_h2d_expr}),
    .err_o(intg_err)
  );

  // also check for spurious write enables
  logic reg_we_err;
  ## Note that the write-enables are per register.
  ## Hence, we reduce the byte address to a word address here.
  logic [${len(regs_flat)-1}:0] reg_we_check;
  prim_reg_we_check #(
    .OneHotWidth(${len(regs_flat)})
  ) u_prim_reg_we_check (
    .clk_i(${reg_clk_expr}),
    .rst_ni(${reg_rst_expr}),
    .oh_i  (reg_we_check),
    .en_i  (reg_we && !addrmiss),
    .err_o (reg_we_err)
  );

  logic err_q;
  always_ff @(posedge ${reg_clk_expr} or negedge ${reg_rst_expr}) begin
    if (!${reg_rst_expr}) begin
      err_q <= '0;
    end else if (intg_err || reg_we_err) begin
      err_q <= 1'b1;
    end
  end

  // integrity error output is permanent and should be used for alert generation
  // register errors are transactional
  assign intg_err_o = err_q | intg_err | reg_we_err;
% else:
  // Since there are no registers in this block, commands are routed through to windows which
  // can report their own integrity errors.
  assign intg_err_o = 1'b0;
% endif

  // outgoing integrity generation
  tlul_pkg::tl_d2h_t tl_o_pre;
  tlul_rsp_intg_gen #(
    .EnableRspIntgGen(1),
    .EnableDataIntgGen(${common_data_intg_gen})
  ) u_rsp_intg_gen (
    .tl_i(tl_o_pre),
    .tl_o(${tl_d2h_expr})
  );

% if num_dsp <= 1:
  ## Either no windows (and just registers) or no registers and only
  ## one window.
  % if num_wins == 0:
  assign tl_reg_h2d = ${tl_h2d_expr};
  assign tl_o_pre   = tl_reg_d2h;
  % else:
  assign tl_win_o = ${tl_h2d_expr};
  assign tl_o_pre = tl_win_i;
  % endif
% else:
  tlul_pkg::tl_h2d_t tl_socket_h2d [${num_dsp}];
  tlul_pkg::tl_d2h_t tl_socket_d2h [${num_dsp}];

  logic [${steer_msb}:0] reg_steer;

  // socket_1n connection
  % if rb.all_regs:
  assign tl_reg_h2d = tl_socket_h2d[${num_wins}];
  assign tl_socket_d2h[${num_wins}] = tl_reg_d2h;

  % endif
  % for i,t in enumerate(rb.windows):
<%
      win_suff = f'[{i}]' if num_wins > 1 else ''
%>\
  assign tl_win_o${win_suff} = tl_socket_h2d[${i}];
    % if common_data_intg_gen == 0 and rb.windows[i].data_intg_passthru == False:
    ## If there are multiple windows, and not every window has data integrity
    ## passthrough, we must generate data integrity for it here.
  tlul_rsp_intg_gen #(
    .EnableRspIntgGen(0),
    .EnableDataIntgGen(1)
  ) u_win${i}_data_intg_gen (
    .tl_i(tl_win_i${win_suff}),
    .tl_o(tl_socket_d2h[${i}])
  );
    % else:
  assign tl_socket_d2h[${i}] = tl_win_i${win_suff};
    % endif
  % endfor

  // Create Socket_1n
  tlul_socket_1n #(
    .N            (${num_dsp}),
    .HReqPass     (1'b1),
    .HRspPass     (1'b1),
    .DReqPass     ({${num_dsp}{1'b1}}),
    .DRspPass     ({${num_dsp}{1'b1}}),
    .HReqDepth    (4'h0),
    .HRspDepth    (4'h0),
    .DReqDepth    ({${num_dsp}{4'h0}}),
    .DRspDepth    ({${num_dsp}{4'h0}}),
    .ExplicitErrs (1'b0)
  ) u_socket (
    .clk_i  (${reg_clk_expr}),
    .rst_ni (${reg_rst_expr}),
    .tl_h_i (${tl_h2d_expr}),
    .tl_h_o (tl_o_pre),
    .tl_d_o (tl_socket_h2d),
    .tl_d_i (tl_socket_d2h),
    .dev_select_i (reg_steer)
  );

  // Create steering logic
  always_comb begin
    unique case (${f'{tl_h2d_expr}.a_address[AW-1:0]'}) inside
  % for i,w in enumerate(rb.windows):
<%
      base_addr = w.offset
      limit_addr = w.offset + w.size_in_bytes
      assert (limit_addr-1 >= base_addr)
      addr_test = f"[{base_addr}:{limit_addr-1}]"
%>\
      ${addr_test}: begin
        reg_steer = ${i};
      end
  % endfor
      default: begin
        // Default set to register
        reg_steer = ${num_dsp-1};
      end
    endcase

    // Override this in case of an integrity error
    if (intg_err) begin
      reg_steer = ${num_dsp-1};
    end
  end
% endif
% if rb.all_regs:

  tlul_adapter_reg #(
    .RegAw(AW),
    .RegDw(DW),
    .EnableDataIntgGen(${adapt_data_intg_gen})
  ) u_reg_if (
    .clk_i  (${reg_clk_expr}),
    .rst_ni (${reg_rst_expr}),

    .tl_i (tl_reg_h2d),
    .tl_o (tl_reg_d2h),

    .we_o    (reg_we),
    .re_o    (reg_re),
    .addr_o  (reg_addr),
    .wdata_o (reg_wdata),
    .be_o    (reg_be),
    .busy_i  (reg_busy),
    .rdata_i (reg_rdata),
    .error_i (reg_error)
  );

  // cdc oversampling signals

  % if block.expose_reg_if:
  assign reg2hw.reg_if.reg_we    = reg_we;
  assign reg2hw.reg_if.reg_re    = reg_re;
  assign reg2hw.reg_if.reg_addr  = reg_addr;
  assign reg2hw.reg_if.reg_wdata = reg_wdata;
  assign reg2hw.reg_if.reg_be    = reg_be;

  % endif
  assign reg_rdata = reg_rdata_next ;
  assign reg_error = (devmode_i & addrmiss) | wr_err | intg_err;

  // Define SW related signals
  // Format: <reg>_<field>_{wd|we|qs}
  //        or <reg>_{wd|we|qs} if field == 1 or 0
  % for r in regs_flat:
${reg_sig_decl(r)}\
    % for f in r.fields:
<%
        fld_suff = '_' + f.name.lower() if len(r.fields) > 1 else ''
        sig_name = r.name.lower() + fld_suff
%>\
${field_sig_decl(f, sig_name, r.hwext, r.shadowed, r.async_clk)}\
    % endfor
  % endfor
  % if len(rb.clocks.values()) > 0:
  // Define register CDC handling.
  // CDC handling is done on a per-reg instead of per-field boundary.
  % endif
  % for r in regs_flat:
    % if r.async_clk:
<%
  base_name = r.async_clk.clock_base_name
  r_name = r.name.lower()
  comb_name = f"{base_name}_{r_name}"
  src_we_expr = f"{r_name}_we" if r.needs_we() else "'0"
  src_wd_expr = f"reg_wdata[{r.get_width()-1}:0]" if r.needs_we() else "'0"
  src_re_expr = f"{r_name}_re" if r.needs_re() else "'0"
  src_regwen_expr = f"{r.regwen.lower()}_qs" if r.regwen else "'0"
  dst_we_expr = f"{comb_name}_we" if r.needs_we() else ""
  dst_wd_expr = f"{comb_name}_wdata" if r.needs_we() else ""
  dst_re_expr = f"{comb_name}_re" if r.needs_re() else ""
  dst_regwen_expr = f"{comb_name}_regwen" if r.regwen else ""
  dst_qe_expr = f"{comb_name}_qe" if r.is_hw_writable() else "'0"
  dst_wr_req = "1" if r.is_hw_writable() else "0"
  dst_ds_expr = f"{comb_name}_ds" if r.is_hw_writable() else "'0"
  reset_val = format(r.resval, "x")
  reset_val_expr = f"{r.get_width()}'h{reset_val}"
%>
      % if len(r.fields) > 1:
        % for f in r.fields:
          % if r.is_hw_writable():
  logic ${str_arr_sv(f.bits)} ${comb_name}_${f.name.lower()}_ds_int;
          % endif
          % if f.swaccess.allows_read():
  logic ${str_arr_sv(f.bits)} ${comb_name}_${f.name.lower()}_qs_int;
          % endif
        % endfor
      % else:
          % if r.is_hw_writable():
  logic ${str_arr_sv(r.fields[0].bits)} ${comb_name}_ds_int;
          % endif
        % if r.fields[0].swaccess.allows_read():
  logic ${str_arr_sv(r.fields[0].bits)} ${comb_name}_qs_int;
        % endif
      % endif
      % if r.is_hw_writable():
  logic [${r.get_width()-1}:0] ${comb_name}_ds;
  logic ${dst_qe_expr};
      % endif
  logic [${r.get_width()-1}:0] ${comb_name}_qs;
      % if r.needs_we():
  logic [${r.get_width()-1}:0] ${comb_name}_wdata;
  logic ${dst_we_expr};
  logic unused_${comb_name}_wdata;
      % endif
      % if r.needs_re():
  logic ${dst_re_expr};
      % endif
      % if r.regwen:
  logic ${dst_regwen_expr};
      % endif

  ## Since prim_reg_cdc operates at the level of the register, the registers
  ## hw writability is used to determine whether the ds is needed.
  always_comb begin
    ${comb_name}_qs = ${reset_val_expr};
    % if r.is_hw_writable():
    ${comb_name}_ds = ${reset_val_expr};
    % endif
      % if len(r.fields) > 1:
        % for f in r.fields:
          % if r.is_hw_writable() and f.swaccess.allows_read():
    ${comb_name}_ds[${str_bits_sv(f.bits)}] = ${comb_name}_${f.name.lower()}_ds_int;
          % endif
          % if f.swaccess.allows_read():
    ${comb_name}_qs[${str_bits_sv(f.bits)}] = ${comb_name}_${f.name.lower()}_qs_int;
          % endif
        % endfor
      % else:
          % if r.is_hw_writable() and r.fields[0].swaccess.allows_read():
    ${comb_name}_ds = ${comb_name}_ds_int;
          % endif
          % if r.fields[0].swaccess.allows_read():
    ${comb_name}_qs = ${comb_name}_qs_int;
          % endif
      % endif
  end

  prim_reg_cdc #(
    .DataWidth(${r.get_width()}),
    .ResetVal(${reset_val_expr}),
    .BitMask(${r.get_width()}'h${r.bitmask()}),
    .DstWrReq(${dst_wr_req})
  ) u_${r_name}_cdc (
    .clk_src_i    (${reg_clk_expr}),
    .rst_src_ni   (${reg_rst_expr}),
    .clk_dst_i    (${r.async_clk.clock}),
    .rst_dst_ni   (${r.async_clk.reset}),
    .src_regwen_i (${src_regwen_expr}),
    .src_we_i     (${src_we_expr}),
    .src_re_i     (${src_re_expr}),
    .src_wd_i     (${src_wd_expr}),
    .src_busy_o   (${r_name}_busy),
    .src_qs_o     (${r_name}_qs), // for software read back
    .dst_update_i (${dst_qe_expr}),
    .dst_ds_i     (${dst_ds_expr}),
    .dst_qs_i     (${comb_name}_qs),
    .dst_we_o     (${dst_we_expr}),
    .dst_re_o     (${dst_re_expr}),
    .dst_regwen_o (${dst_regwen_expr}),
    .dst_wd_o     (${dst_wd_expr})
  );
      % if r.needs_we():
  assign unused_${comb_name}_wdata =
      ^${comb_name}_wdata;
      % endif
    % endif
  % endfor

  // Register instances
  % for r in rb.all_regs:
<%
      r0, srs = r0_srs[r]
      reg_name = r0.name.lower()
%>\
    % for sr_idx, sr in enumerate(srs):
<%
        sr_name = sr.name.lower()

        if isinstance(r, MultiRegister):
          reg_hdr = (f'  // Subregister {sr_idx} of Multireg {reg_name}\n' +
                     f'  // R[{sr_name}]: V({sr.hwext})')
        else:
          reg_hdr = (f'  // R[{sr_name}]: V({sr.hwext})')
        clk_expr = sr.async_clk.clock if sr.async_clk else reg_clk_expr
        rst_expr = sr.async_clk.reset if sr.async_clk else reg_rst_expr
%>\
${reg_hdr}
      % if sr.needs_qe():
  logic ${sr_name}_qe;
      % endif
      % if sr.needs_int_qe():
  logic [${len(sr.fields)-1}:0] ${sr_name}_flds_we;
      % endif
      % if sr.needs_qe() and sr.hwext:
  assign ${sr_name}_qe = &${sr_name}_flds_we;
      % elif sr.needs_qe():
  prim_flop #(
    .Width(1),
    .ResetValue(0)
  ) u_${reg_name}${sr_idx}_qe (
    .clk_i(${clk_expr}),
    .rst_ni(${rst_expr}),
    .d_i(&${sr_name}_flds_we),
    .q_o(${sr_name}_qe)
  );
      % endif
<%
  # We usually use the REG_we signal, but use REG_re for RC fields
  # (which get updated on a read, not a write)
  clk_base_name = f"{sr.async_clk.clock_base_name}_" if sr.async_clk else ""
  we_suffix = 're' if field.swaccess.swrd() == SwRdAccess.RC else 'we'
  we_signal = f'{clk_base_name}{sr_name}_{we_suffix}'

  if sr.async_clk and sr.regwen:
    we_expr = f'{we_signal} & {clk_base_name}{sr_name}_regwen'
  elif sr.regwen:
    we_expr = f'{we_signal} & {sr.regwen.lower()}_qs'
  else:
    we_expr = we_signal

  we_expr_regwen_gated = f'{clk_base_name}{sr_name}_gated_{we_suffix}'
%>\
  % if sr.async_clk and sr.is_hw_writable():
  assign ${clk_base_name}${sr_name}_qe = |${sr_name}_flds_we;
  % endif
  ## Only create this helper signal if there actually is a REGWEN gate.
  ## Otherwise the WE signal is connected directly to the register.
  % if sr.regwen and sr.needs_we():
  // Create REGWEN-gated WE signal
  logic ${we_expr_regwen_gated};
<%
    # Wrap the assignment if the statement is too long
    assignment = f'assign {we_expr_regwen_gated} = {we_expr};'
    if len(assignment) > 100-2:
      assignment = f'assign {we_expr_regwen_gated} =\n    {we_expr};'
%>\
  ${assignment}
  % endif
      % for fidx, field in enumerate(sr.fields):
<%
          fld_name = field.name.lower()
          fsig_name, finst_name = finst_names[field]
%>\
        % if len(sr.fields) > 1:
  //   F[${fld_name}]: ${field.bits.msb}:${field.bits.lsb}
        % endif
${finst_gen(sr, field, finst_name, fsig_name, fidx)}
      % endfor

    % endfor
  % endfor

  logic [${len(regs_flat)-1}:0] addr_hit;
  always_comb begin
    addr_hit = '0;
    % for i,r in enumerate(regs_flat):
    addr_hit[${"{}".format(i).rjust(max_regs_char)}] = (reg_addr == ${ublock}_${r.name.upper()}_OFFSET);
    % endfor
  end

  assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;

  % if regs_flat:
<%
    # We want to signal wr_err if reg_be (the byte enable signal) is true for
    # any bytes that aren't supported by a register. That's true if a
    # addr_hit[i] and a bit is set in reg_be but not in *_PERMIT[i].

    wr_err_terms = ['(addr_hit[{idx}] & (|({mod}_PERMIT[{idx}] & ~reg_be)))'
                    .format(idx=str(i).rjust(max_regs_char),
                            mod=u_mod_base)
                    for i in range(len(regs_flat))]
    wr_err_expr = (' |\n' + (' ' * 15)).join(wr_err_terms)
%>\
  // Check sub-word write is permitted
  always_comb begin
    wr_err = (reg_we &
              (${wr_err_expr}));
  end
  % else:
  assign wr_error = 1'b0;
  % endif\


  // Generate write-enables
  % for i, r in enumerate(regs_flat):
${reg_enable_gen(r, i)}\
    % if len(r.fields) == 1:
${field_wd_gen(r.fields[0], r.name.lower(), r.hwext, r.shadowed, r.async_clk, r.name, i)}\
    % else:
      % for f in r.fields:
${field_wd_gen(f, r.name.lower() + "_" + f.name.lower(), r.hwext, r.shadowed, r.async_clk, r.name, i)}\
      % endfor
    % endif
  % endfor

  // Assign write-enables to checker logic vector.
  always_comb begin
    reg_we_check = '0;
    % for i, r in enumerate(regs_flat):
<%
    # The WE checking logic does NOT protect RC fields.
    if r.needs_we():
      # In case this is an asynchronous register, the WE signal is taken from
      # the CDC primitive input. This could be enhanced in the future to provide
      # more protection for asynchronous registers.
      if r.async_clk or not r.regwen:
        we_expr = f'{r.name.lower()}_we'
      else:
        we_expr = f'{r.name.lower()}_gated_we'
    else:
      we_expr = "1'b0"

    assignment = f'reg_we_check[{i}] = {we_expr};'

    # Wrap the assignment if the statement is too long
    if len(assignment) > 100-4:
      assignment = f'reg_we_check[{i}] =\n        {we_expr};'
%>\
    ${assignment}
    % endfor
  end

  // Read data return
  always_comb begin
    reg_rdata_next = '0;
    unique case (1'b1)
  % for i, r in enumerate(regs_flat):
    % if r.async_clk:
      addr_hit[${i}]: begin
        reg_rdata_next = DW'(${r.name.lower()}_qs);
      end
    % elif len(r.fields) == 1:
      addr_hit[${i}]: begin
${rdata_gen(r.fields[0], r.name.lower())}\
      end

    % else:
      addr_hit[${i}]: begin
      % for f in r.fields:
${rdata_gen(f, r.name.lower() + "_" + f.name.lower())}\
      % endfor
      end

    % endif
  % endfor
      default: begin
        reg_rdata_next = '1;
      end
    endcase
  end

  // shadow busy
  logic shadow_busy;
  % if rb.has_internal_shadowed_reg():
  logic rst_done;
  logic shadow_rst_done;
  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      rst_done <= '0;
    end else begin
      rst_done <= 1'b1;
    end
  end

  always_ff @(posedge clk_i or negedge rst_shadowed_ni) begin
    if (!rst_shadowed_ni) begin
      shadow_rst_done <= '0;
    end else begin
      shadow_rst_done <= 1'b1;
    end
  end

  // both shadow and normal resets have been released
  assign shadow_busy = ~(rst_done & shadow_rst_done);
  % else:
  assign shadow_busy = 1'b0;
  % endif

  % if rb.has_internal_shadowed_reg():
  // Collect up storage and update errors
<%
    shadowed_field_pfxs = []
    for r in rb.all_regs:
      r0, srs = r0_srs[r]

      if not (r0.shadowed and not r0.hwext):
        continue

      for sr in srs:
        for field in sr.fields:
          _, pfx = finst_names[field]
          shadowed_field_pfxs.append(pfx)
%>\
  assign shadowed_storage_err_o = |{
  % for pfx in shadowed_field_pfxs:
    ${pfx}_storage_err${"" if loop.last else ","}
  % endfor
  };
  assign shadowed_update_err_o = |{
  % for pfx in shadowed_field_pfxs:
    ${pfx}_update_err${"" if loop.last else ","}
  % endfor
  };

  % endif
  // register busy
<%
  async_busy_signals = {}
  for i, r in enumerate(regs_flat):
    if r.async_clk:
      async_busy_signals[i] = r.name.lower() + "_busy"
%>\
  % if rb.async_if or not async_busy_signals:
  assign reg_busy = shadow_busy;
  % else:
  logic reg_busy_sel;
  assign reg_busy = reg_busy_sel | shadow_busy;
  always_comb begin
    reg_busy_sel = '0;
    unique case (1'b1)
    % for i, busy_signal in async_busy_signals.items():
      addr_hit[${i}]: begin
        reg_busy_sel = ${busy_signal};
      end
    % endfor
      default: begin
        reg_busy_sel  = '0;
      end
    endcase
  end

  % endif
% endif

  // Unused signal tieoff
% if rb.all_regs:

  // wdata / byte enable are not always fully used
  // add a blanket unused statement to handle lint waivers
  logic unused_wdata;
  logic unused_be;
  assign unused_wdata = ^reg_wdata;
  assign unused_be = ^reg_be;
% else:
  // devmode_i is not used if there are no registers
  logic unused_devmode;
  assign unused_devmode = ^devmode_i;
% endif
% if rb.all_regs:

  // Assertions for Register Interface
  `ASSERT_PULSE(wePulse, reg_we, ${reg_clk_expr}, !${reg_rst_expr})
  `ASSERT_PULSE(rePulse, reg_re, ${reg_clk_expr}, !${reg_rst_expr})

  `ASSERT(reAfterRv, $rose(reg_re || reg_we) |=> tl_o_pre.d_valid, ${reg_clk_expr}, !${reg_rst_expr})

  `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit), ${reg_clk_expr}, !${reg_rst_expr})

  // this is formulated as an assumption such that the FPV testbenches do disprove this
  // property by mistake
  //`ASSUME(reqParity, tl_reg_h2d.a_valid |-> tl_reg_h2d.a_user.chk_en == tlul_pkg::CheckDis)

% endif
endmodule
<%def name="str_bits_sv(bits)">\
% if bits.msb != bits.lsb:
${bits.msb}:${bits.lsb}\
% else:
${bits.msb}\
% endif
</%def>\
<%def name="str_arr_sv(bits)">\
% if bits.msb != bits.lsb:
[${bits.msb-bits.lsb}:0] \
% endif
</%def>\
<%def name="reg_sig_decl(reg)">\
  % if reg.needs_re():
  logic ${reg.name.lower()}_re;
  % endif
  % if reg.needs_we():
  logic ${reg.name.lower()}_we;
  % endif
  % if reg.async_clk:
  logic [${reg.get_width()-1}:0] ${reg.name.lower()}_qs;
  logic ${reg.name.lower()}_busy;
  % endif
</%def>\
<%def name="field_sig_decl(field, sig_name, hwext, shadowed, async_clk)">\
  % if not async_clk and field.swaccess.allows_read():
  logic ${str_arr_sv(field.bits)}${sig_name}_qs;
  % endif
  % if not async_clk and field.swaccess.allows_write():
  logic ${str_arr_sv(field.bits)}${sig_name}_wd;
  % endif
  % if shadowed and not hwext:
  logic ${sig_name}_storage_err;
  logic ${sig_name}_update_err;
  % endif
</%def>\
<%def name="finst_gen(reg, field, finst_name, fsig_name, fidx)">\
<%

    clk_base_name = f"{reg.async_clk.clock_base_name}_" if reg.async_clk else ""
    reg_name = reg.name.lower()
    clk_expr = reg.async_clk.clock if reg.async_clk else reg_clk_expr
    rst_expr = reg.async_clk.reset if reg.async_clk else reg_rst_expr
    re_expr = f'{clk_base_name}{reg_name}_re' if field.swaccess.allows_read() or reg.shadowed else "1'b0"

    # software inputs to field instance, write enable, read enable, write data
    if field.swaccess.allows_write():
      # We usually use the REG_we signal, but use REG_re for RC fields
      # (which get updated on a read, not a write)
      we_suffix = 're' if field.swaccess.swrd() == SwRdAccess.RC else 'we'
      # If this is a REGWEN gated field, need to use the gated WE signal.
      gated_suffix = '_gated' if reg.regwen else ''
      we_expr = f'{clk_base_name}{reg_name}{gated_suffix}_{we_suffix}'

      # when async, pick from the cdc handled data
      wd_expr = f'{finst_name}_wd'
      if reg.async_clk:
        if field.bits.msb == field.bits.lsb:
          bit_sel = f'{field.bits.msb}'
        else:
          bit_sel = f'{field.bits.msb}:{field.bits.lsb}'
        wd_expr = f'{clk_base_name}{reg_name}_wdata[{bit_sel}]'

    else:
      we_expr = "1'b0"
      wd_expr = "'0"

    # hardware inputs to field instance
    if field.hwaccess.allows_write():
      de_expr = f'hw2reg.{fsig_name}.de'
      d_expr = f'hw2reg.{fsig_name}.d'
    else:
      de_expr = "1'b0"
      d_expr = "'0"

    # field instance outputs
    qre_expr = f'reg2hw.{fsig_name}.re' if reg.hwre or reg.shadowed else ""

    if reg.needs_int_qe() or field.hwaccess.allows_read():
      qe_expr = f'{reg_name}_flds_we[{fidx}]' if reg.needs_int_qe() else ''
    else:
      qe_expr = ''

    if field.hwaccess.allows_read():
      qe_reg_expr = f'reg2hw.{fsig_name}.qe'
      q_expr = f'reg2hw.{fsig_name}.q'
    else:
      q_expr = ''

    # when async, the outputs are aggregated first by the cdc module
    async_suffix = '_int' if reg.async_clk else ''
    qs_expr = f'{clk_base_name}{finst_name}_qs{async_suffix}' if field.swaccess.allows_read() else ''
    ds_expr = f'{clk_base_name}{finst_name}_ds{async_suffix}' if reg.async_clk and reg.is_hw_writable() else ''

%>\
  % if reg.hwext:       ## if hwext, instantiate prim_subreg_ext
<%
    subreg_block = "prim_subreg_ext"
%>\
  ${subreg_block} #(
    .DW    (${field.bits.width()})
  ) u_${finst_name} (
    .re     (${re_expr}),
    .we     (${we_expr}),
    .wd     (${wd_expr}),
    .d      (${d_expr}),
    .qre    (${qre_expr}),
    .qe     (${qe_expr}),
    .q      (${q_expr}),
    .ds     (${ds_expr}),
    .qs     (${qs_expr})
  );
  % else:
<%
      # This isn't a field in a hwext register. Instantiate prim_subreg,
      # prim_subreg_shadow or constant assign.

      resval_expr = f"{field.bits.width()}'h{field.resval or 0:x}"
      is_const_reg = not (field.hwaccess.allows_read() or
                          field.hwaccess.allows_write() or
                          field.swaccess.allows_write() or
                          field.swaccess.swrd() != SwRdAccess.RD)

      subreg_block = 'prim_subreg' + ('_shadow' if reg.shadowed else '')
%>\
    % if is_const_reg:
  // constant-only read
  assign ${finst_name}_qs = ${resval_expr};
    % else:
      % if reg.async_clk and reg.shadowed:
  logic async_${finst_name}_err_update;
  logic async_${finst_name}_err_storage;

  // storage error is persistent and can be sampled at any time
  prim_flop_2sync #(
    .Width(1),
    .ResetValue('0)
  ) u_${finst_name}_err_storage_sync (
    .clk_i,
    .rst_ni,
    .d_i(async_${finst_name}_err_storage),
    .q_o(${finst_name}_storage_err)
  );

  // update error is transient and must be immediately captured
  prim_pulse_sync u_${finst_name}_err_update_sync (
    .clk_src_i(${reg.async_clk.clock}),
    .rst_src_ni(${reg.async_clk.reset}),
    .src_pulse_i(async_${finst_name}_err_update),
    .clk_dst_i(clk_i),
    .rst_dst_ni(rst_ni),
    .dst_pulse_o(${finst_name}_update_err)
  );
      % endif
  ${subreg_block} #(
    .DW      (${field.bits.width()}),
    .SwAccess(prim_subreg_pkg::SwAccess${field.swaccess.value[1].name.upper()}),
    .RESVAL  (${resval_expr})
  ) u_${finst_name} (
    .clk_i   (${clk_expr}),
    .rst_ni  (${rst_expr}),
      % if reg.shadowed and not reg.hwext:
    .rst_shadowed_ni (rst_shadowed_ni),
      % endif

    // from register interface
      % if reg.shadowed:
    .re     (${re_expr}),
      % endif
    .we     (${we_expr}),
    .wd     (${wd_expr}),

    // from internal hardware
    .de     (${de_expr}),
    .d      (${d_expr}),

    // to internal hardware
    .qe     (${qe_expr}),
    .q      (${q_expr}),
    .ds     (${ds_expr}),

    // to register interface (read)
      % if not reg.shadowed:
    .qs     (${qs_expr})
      % else:
    .qs     (${qs_expr}),

    // Shadow register phase. Relevant for hwext only.
    .phase  (),

    // Shadow register error conditions
        % if reg.async_clk:
    .err_update  (async_${finst_name}_err_update),
    .err_storage (async_${finst_name}_err_storage)
        % else:
    .err_update  (${finst_name}_update_err),
    .err_storage (${finst_name}_storage_err)
        % endif
      % endif
  );
    % endif  ## end non-constant prim_subreg
  % endif
  % if field.hwaccess.allows_read() and field.hwqe:
  assign ${qe_reg_expr} = ${reg_name}_qe;
  % endif
</%def>\
<%def name="reg_enable_gen(reg, idx)">\
  % if reg.needs_re():
  assign ${reg.name.lower()}_re = addr_hit[${idx}] & reg_re & !reg_error;
  % endif
  % if reg.needs_we():
  assign ${reg.name.lower()}_we = addr_hit[${idx}] & reg_we & !reg_error;
  % endif
</%def>\
<%def name="field_wd_gen(field, sig_name, hwext, shadowed, async_clk, reg_name, idx)">\
<%
    needs_wd = field.swaccess.allows_write()
    space = '\n' if needs_wd or needs_re else ''
%>\
${space}\
% if needs_wd and not async_clk:
  % if field.swaccess.swrd() == SwRdAccess.RC:
  assign ${sig_name}_wd = '1;
  % else:
  assign ${sig_name}_wd = reg_wdata[${str_bits_sv(field.bits)}];
  % endif
% endif
</%def>\
<%def name="rdata_gen(field, sig_name, rd_name='reg_rdata_next')">\
% if field.swaccess.allows_read():
        ${rd_name}[${str_bits_sv(field.bits)}] = ${sig_name}_qs;
% else:
        ${rd_name}[${str_bits_sv(field.bits)}] = '0;
% endif
</%def>\
<%def name="reg_cdc_gen(field, sig_name, hwext, shadowed, idx)">\
<%
    needs_wd = field.swaccess.allows_write()
    space = '\n' if needs_wd or needs_re else ''
%>\
${space}\
% if needs_wd:
  % if field.swaccess.swrd() == SwRdAccess.RC:
  assign ${sig_name}_wd = '1;
  % else:
  assign ${sig_name}_wd = reg_wdata[${str_bits_sv(field.bits)}];
  % endif
% endif
</%def>\
