Module reg_file

This document contains technical documentation for the reg_file module. To browse the source code, please visit the repository on GitHub.

The hdl-modules project contains many components that together form everything you need to set up a register bus. Below is a diagram of the typical layout for a register bus.

digraph my_graph {
graph [ dpi = 300 splines=ortho ];
rankdir="LR";

cpu [ label="AXI master\n(CPU)" shape=box ];
cpu -> axi_to_axi_lite [label="AXI"];

axi_to_axi_lite [ label="axi_to_axi_lite" shape=box ];
axi_to_axi_lite -> axi_lite_mux  [label="AXI-Lite" ];

axi_lite_mux [ label="axi_lite_mux" shape=box height=3.5 ];

axi_lite_mux -> axi_lite_reg_file0;
axi_lite_reg_file0 [ label="axi_lite_reg_file" shape=box ];

axi_lite_mux -> axi_lite_reg_file1;
axi_lite_reg_file1 [ label="axi_lite_reg_file" shape=box ];

axi_lite_mux -> axi_lite_cdc2;
axi_lite_cdc2 [ label="axi_lite_cdc" shape=box ];
axi_lite_cdc2 -> axi_lite_reg_file2;
axi_lite_reg_file2 [ label="axi_lite_reg_file" shape=box ];

axi_lite_mux -> axi_lite_cdc3;
axi_lite_cdc3 [ label="axi_lite_cdc" shape=box ];
axi_lite_cdc3 -> axi_lite_reg_file3;
axi_lite_reg_file3 [ label="axi_lite_reg_file" shape=box ];

dots [ shape=none label="..."];
axi_lite_mux -> dots;
}

In hdl-modules, the register bus used is is AXI-Lite. In cases where a module uses a different clock than the AXI master (CPU), the bus must be resynchronized. This makes sure that each module’s register values are always in the clock domain where they are used. This means that the module design does not have to worry about metastability, vector coherency, pulse resynchronization, etc.

  • axi_to_axi_lite.vhd is a simple protocol converter between AXI and AXI-Lite. It does not perform any burst splitting or handling of write strobes, but instead assumes the master to be well behaved. If this is not the case, AXI slave error (SLVERR) will be sent on the response channel (R/B).

  • axi_lite_mux.vhd is a 1-to-N AXI-Lite multiplexer that operates based on base addresses specified via a generic. If the address requested by the master does not match any slave, AXI decode error (DECERR) will be sent on the response channel (R/B). There will still be proper AXI handshaking done, so the master will not be stalled.

  • axi_lite_cdc.vhd is an asynchronous FIFO-based clock domain crossing (CDC) for AXI-Lite buses. It must be used in the cases where the axi_lite_reg_file (i.e. your module) is in a different clock domain than the CPU AXI master.

  • axi_lite_reg_file.vhd is a generic, parameterizable, register file for AXI-Lite register buses. It is parameterizable via a generic that sets the list of registers, with their modes and their default values. If the address requested by the master does not match any register, or there is a mode mismatch (e.g. write to a read-only register), AXI slave error (SLVERR) will be sent on the response channel (R/B).

Note that there is also a convenience wrapper axi_to_axi_lite_vec.vhd that instantiates axi_to_axi_lite.vhd, axi_lite_mux.vhd and any necessary axi_lite_cdc.vhd based on the appropriate generics.

axi_lite_reg_file.vhd

View source code on GitHub.

component axi_lite_reg_file is
  generic (
    regs : reg_definition_vec_t;
    default_values : reg_vec_t
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    axi_lite_m2s : in axi_lite_m2s_t;
    axi_lite_s2m : out axi_lite_s2m_t;
    --# {{}}
    regs_up : in reg_vec_t;
    regs_down : out reg_vec_t;
    --# {{}}
    reg_was_read : out std_ulogic_vector;
    reg_was_written : out std_ulogic_vector
  );
end component;

Generic, parameterizable, register file for AXI-Lite register buses. Is parameterizable via a generic that sets the list of registers, with their modes and their default values.

Will respond with SLVERR on the R channel when attempting to read a register that

  1. Does not exists (ARADDR out of range), or

  2. Is not of a register type that can be read by the bus (e.g. write only).

Similarly, it will respond with SLVERR on the B channel when attempting to write a register that

  1. Does not exists (AWADDR out of range), or

  2. Is not of a register type that can be written by the bus (e.g. read only).

Both cases are handled cleanly without stalling or hanging the AXI-Lite bus.

The regs and default_values generics are designed to get their values from a package generated by the hdl-registers VHDL generator: VhdlRegisterPackageGenerator. The values can be constructed by hand as well, of course.

Resource utilization

This entity has netlist builds set up with automatic size checkers in module_reg_file.py. The following table lists the resource utilization for the entity, depending on generic configuration.

Resource utilization for axi_lite_reg_file netlist builds.

Generics

Total LUTs

FFs

RAMB36

RAMB18

Maximum logic level

(Using wrapper

axi_lite_reg_file_netlist_wrapper.vhd)

202

447

0

0

4

interrupt_register.vhd

View source code on GitHub.

component interrupt_register is
  port (
    clk : in std_ulogic;
    --# {{}}
    sources : in reg_t;
    mask : in reg_t;
    clear : in reg_t;
    --# {{}}
    status : out reg_t;
    trigger : out std_ulogic
  );
end component;

Generic interrupt register for producing a sticky interrupt bit.

Each bit in status is raised, and kept high, if the corresponding bit in sources is ever '1'. A status bit is cleared to zero if the corresponding clear bit is ever asserted.

The trigger pin is asserted if any bit is '1' in both status and mask. I.e. status always shows the sticky interrupt value, but the trigger pin is only asserted if the bit is also mask ed.

Clearing all asserted status bits, or mask ing out all bits, will also clear trigger.

Resource utilization

This entity has netlist builds set up with automatic size checkers in module_reg_file.py. The following table lists the resource utilization for the entity, depending on generic configuration.

Resource utilization for interrupt_register netlist builds.

Generics

Total LUTs

FFs

Maximum logic level

39

33

5

reg_file_pkg.vhd

View source code on GitHub.

Package with constants/types/functions for generic register file ecosystem.

reg_operations_pkg.vhd

View source code on GitHub.

Various helper functions for reading/writing/checking registers.

Note

This file is largely unused, and replaced by simulation support packages produced by the hdl-registers register interface code generator: https://hdl-registers.com The file is kept for legacy reasons in case someone out there is still using it.

There is an intentional asymmetry in the default value for other_bits_value between check_reg_equal_bit(s) and wait_until_reg_equals_bit(s). For the former it is '0' while it is '-' for the latter. This is based on the philosophy that a false positive is better than a hidden error. False positives, when discovered, can be worked around by e.g. changing the default value.

Consider the example of check ing an error status register. When we want to check that the expected error bit has been set, we would like to be informed if any further errors have also occurred. This would not happen unless other_bits_value value to check_reg_equal_bit(s) is '0'.

Consider furthermore the situation where we are wait ing for a certain error bit to be asserted in a test, but ten other errors occur. In this scenario we would like the wait to end, and for the errors to have consequences. This would not occur unless other_bits_value value to wait_until_reg_equals_bit(s) is '-'.