reg_file

extras/reg_file.vhdl

extras_2008/reg_file_2008.vhdl

Dependencies

muxing

Description

This package provides a general purpose register file. It is available in two variants. One is implemented in VHDL-93 syntax and the register width is fixed at 16-bits by default. The source must be modified to alter the size of the reg_word type if a register size other than 16-bits is needed. The implementation in reg_file_2008 uses a generic package to avoid this if tool support for VHDL-2008 is available.

The register file provides an addressable read write port for external access as well as a set of signals that allow simultaneous access to registers for internal logic. The register file has a number of special behaviors controlled by generics.

DIRECT_READ_BIT_MASK is an array of masks that establish which bits of each register are read directly from internal signals rather than registered bits. When set to ‘1’ a bit is accessed from the Direct_read port input rather than the register file on a read operation. The masks permit mixing these bits with registered bits within the same register. Direct-read register bits can still be written but their contents can’t be read back through the addressed port.

STROBE_BIT_MASK is an array of masks that establish which bits of each register are considered “strobe” bits. Strobe bits are used to initiate control actions from a momentary pulsed signal. They are self clearing when a ‘1’ is written to them. The ‘1’ bit is present for only one clock cycle. There is no effect when ‘0’ is written.

The REGISTER_INPUTS generic provides optional registration of the inputs on the external control port.

Synthesis note

This component creates a wide decoder and mux for accessing the register file from the external control port. Large register files will see significant combinational delay from these elements and care should be taken when using this component in high speed designs.

Example usage

-- Create a register with 4 16-bit words:
--    0: strobe bits in bit 0 & 1
--    1: normal
--    2: normal
--    3: direct read in bits 7-0

library extras; use extras.reg_file_pkg.all;
use extras.sizing.bit_size;

constant NUM_REGS : natural := 4;
subtype my_reg_array is reg_array(0 to NUM_REGS-1);

constant STROBE_BIT_MASK : my_reg_array := (
   0      => X"0003",
   1 to 3 => (others => '0')
 );

constant DIRECT_READ_BIT_MASK : my_reg_array := (
   0|1|2  => (others => '0'), -- Alternate selection of elements with |
   3      => X"00FF"
 );

signal reg_sel     : unsigned(bit_size(NUM_REGS)-1 downto 0);
signal we          : std_ulogic;
signal wr_data, rd_data       : reg_word;
signal registers, direct_read : my_reg_array;
signal reg_written : std_ulogic_vector(my_reg_array'range);
...

rf : reg_file
 generic map (
   DIRECT_READ_BIT_MASK => DIRECT_READ_BIT_MASK,
   STROBE_BIT_MASK      => STROBE_BIT_MASK
 )
 port map (
   Clock => clock,
   Reset => reset,

   Clear => '0', -- No need to clear the registers

   Reg_sel => reg_sel,
   We      => we,
   Wr_data => wr_data,
   Rd_data => rd_data,

   Registers   => registers,
   Direct_Read => direct_read,
   Reg_written => reg_written
 );

...

pulse_control <= registers(0)(0); -- Access strobe bit-0

-- direct_read must be fully assigned (unused parts will optimize away
-- in synthesis)
direct_read(0 to 2) <= (others => (others => '0'));
direct_read(3)(7 downto 0) <= internal_byte; -- Connect internal signal
direct_read(3)(15 downto 8) <= (others => '0');

VHDL-2008 example

The VHDL-2008 version uses unconstrained arrays-of-arrays for the Registers and Direct_read signals. This permits you to use any word size without needing to modify the source of the register file. It is best to create subtypes to define the register word and array of words.

library extras_2008; use extras_2008.reg_file_pkg.all;
library extras; use extras.sizing.bit_size;

-- Create a register file with 12-bit registers
constant NUM_REGS : natural := 4;
subtype my_reg_word is std_ulogic_vector(11 downto 0);
subtype my_reg_array is reg_array(0 to NUM_REGS-1)(my_reg_word'range);

...

signal registers, direct_read : my_reg_array;
signal reg_written : std_ulogic_vector(my_reg_array'range);

...

rf : reg_file
  generic map (
    DIRECT_READ_BIT_MASK => DIRECT_READ_BIT_MASK,
    STROBE_BIT_MASK      => STROBE_BIT_MASK
  )
  port map (
    Clock => clock,
    Reset => reset,

    Clear => '0', -- No need to clear the registers

    Reg_sel => reg_sel,
    We      => we,
    Wr_data => wr_data,
    Rd_data => rd_data,

    Registers   => registers,
    Direct_Read => direct_read,
    Reg_written => reg_written
  );

...

Types

reg_file_pkg.reg_array

Array of register words.

Subtypes

reg_file_pkg.reg_word

Register word vector. Modify this to use different word sizes.

Components

reg_file

component reg_file is generic ( RESET_ACTIVE_LEVEL : std_ulogic; DIRECT_READ_BIT_MASK : reg_array; STROBE_BIT_MASK : reg_array; REGISTER_INPUTS : boolean ); port ( --# {{clocks|}} Clock : in std_ulogic; Reset : in std_ulogic; --# {{control|}} Clear : in std_ulogic; --# {{data|Addressed port}} Reg_sel : in unsigned; We : in std_ulogic; Wr_data : in reg_word; Rd_data : out reg_word; --# {{Registers}} Registers : out reg_array; Direct_read : in reg_array; Reg_written : out std_ulogic_vector ); end component;


reg_file_pkg.reg_file

Flexible register file with support for strobed outputs.

Generics:
  • RESET_ACTIVE_LEVEL (std_ulogic) – Asynch. reset control level
  • DIRECT_READ_BIT_MASK (reg_array) – Masks indicating which register bits are directly read
  • STROBE_BIT_MASK (reg_array) – Masks indicating which register bits clear themselves after a write of ‘1’
  • REGISTER_INPUTS (boolean) – Register the input ports when true
Port:
  • Clock (in std_ulogic) – System clock
  • Reset (in std_ulogic) – Asynchronous reset
  • Clear (in std_ulogic) – Initialize all registers to ‘0’
  • Reg_sel (in unsigned) – Register address for write and read
  • We (in std_ulogic) – Write to selected register
  • Wr_data (in reg_word) – Write port
  • Rd_data (out reg_word) – Read port
  • Registers (out reg_array) – Register file contents
  • Direct_read (in reg_array) – Read-only signals direct from external logic
  • Reg_written (out std_ulogic_vector) – Status flags indicating when each register is written

VHDL-2008 variant

Components

reg_file

component reg_file is generic ( RESET_ACTIVE_LEVEL : std_ulogic; DIRECT_READ_BIT_MASK : reg_array; STROBE_BIT_MASK : reg_array; REGISTER_INPUTS : boolean ); port ( --# {{clocks|}} Clock : in std_ulogic; Reset : in std_ulogic; --# {{control|}} Clear : in std_ulogic; --# {{data|Addressed port}} Reg_sel : in unsigned; We : in std_ulogic; Wr_data : in reg_word; Rd_data : out reg_word; --# {{Registers}} Registers : out reg_array; Direct_read : in reg_array; Reg_written : out std_ulogic_vector ); end component;


reg_file_pkg.reg_file

Flexible register file with support for strobed outputs. This variant uses VHDL-2008 syntax to define the reg_array type as an unconstrained array-of-arrays. Any register width can be instantiated without needing to modify the library.

Generics:
  • RESET_ACTIVE_LEVEL (std_ulogic) – Asynch. reset control level
  • DIRECT_READ_BIT_MASK (reg_array) – Masks indicating which register bits are directly read
  • STROBE_BIT_MASK (reg_array) – Masks indicating which register bits clear themselves after a write of ‘1’
  • REGISTER_INPUTS (boolean) – Register the input ports when true
Port:
  • Clock (in std_ulogic) – System clock
  • Reset (in std_ulogic) – Asynchronous reset
  • Clear (in std_ulogic) – Initialize all registers to ‘0’
  • Reg_sel (in unsigned) – Register address for write and read
  • We (in std_ulogic) – Write to selected register
  • Wr_data (in reg_word) – Write port
  • Rd_data (out reg_word) – Internal file contents
  • Registers (out reg_array) – Register file contents
  • Direct_read (in reg_array) – Read-only signals direct from external logic
  • Reg_written (out std_ulogic_vector) – Status flags indicating when each register is written