Module reg_file

This document contains technical documentation for the reg_file module.

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 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 and address masks 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

component axi_lite_reg_file is
  generic (
    regs : reg_definition_vec_t;
    default_values : reg_vec_t
  );
  port (
    clk : in std_logic;
    --# {{}}
    --# Register control bus
    axi_lite_m2s : in axi_lite_m2s_t;
    axi_lite_s2m : out axi_lite_s2m_t;
    --# {{}}
    -- Register values
    regs_up : in reg_vec_t;
    regs_down : out reg_vec_t;
    --# {{}}
    -- Each bit is pulsed for one cycle when the corresponding register is read/written.
    -- For read, the bit is asserted the exact same cycle as the AXI-Lite R transaction occurs.
    -- For write, the bit is asserted the cycle after the AXI-Lite W transaction occurs, so that
    -- 'regs_down' is updated with the new value.
    reg_was_read : out std_logic_vector;
    reg_was_written : out std_logic_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 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: RegisterVhdlGenerator. 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.vhd netlist builds.

Generics

Total LUTs

Logic LUTs

FFs

RAMB36

RAMB18

Maximum logic level

(Using wrapper

axi_lite_reg_file_wrapper.vhd)

197

197

447

0

0

4

interrupt_register.vhd

component interrupt_register is
  port (
    clk : in std_logic;
    --# {{}}
    sources : in reg_t;
    mask : in reg_t;
    clear : in reg_t;
    --# {{}}
    status : out reg_t;
    trigger : out std_logic
  );
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.vhd netlist builds.

Generics

Total LUTs

FFs

Maximum logic level

39

33

5

reg_file_pkg.vhd

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

reg_operations_pkg.vhd

Various helper functions for reading/writing/checking registers.

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 '-'.