Register Maps
A register map is a collection of register map elements such as registers, register arrays and memories.
In the generated code, a register map translates to a VHDL component or a SystemVerilog module with an AXI4-lite interface on the host-facing side. On the user logic side, one or more dedicated ports are available for every register field. The direction of the port depends on the type of the register field:
- Control (read-write or write-only) register fields are mapped to output ports
- Status (read-only) and interrupt register fields are mapped to input ports
The following listing shows the generated VHDL entity for a register map called my_map with a default base address of 0xA000_0000 that is organized as follows:
- A control register called
controlwith a 1-bitenafield and an 16-bitconfigfield - A status register called
statuswith an 8-bitstatefield - An interrupt register called
irqwith two 1-bitoverflowandunderflowfields
The SytemVerilog code looks very similar to the VHDL code shown below.
entity my_map_regs is
generic(
AXI_ADDR_WIDTH : integer := 32; -- width of the AXI address bus
BASEADDR : std_logic_vector(31 downto 0) := x"A0000000" -- the register file's system base address
);
port(
-- Clock and Reset
axi_aclk : in std_logic;
axi_aresetn : in std_logic;
-- AXI Write Address Channel
s_axi_awaddr : in std_logic_vector(AXI_ADDR_WIDTH - 1 downto 0);
s_axi_awprot : in std_logic_vector(2 downto 0); -- sigasi @suppress "Unused port"
s_axi_awvalid : in std_logic;
s_axi_awready : out std_logic;
-- AXI Write Data Channel
s_axi_wdata : in std_logic_vector(31 downto 0);
s_axi_wstrb : in std_logic_vector(3 downto 0);
s_axi_wvalid : in std_logic;
s_axi_wready : out std_logic;
-- AXI Read Address Channel
s_axi_araddr : in std_logic_vector(AXI_ADDR_WIDTH - 1 downto 0);
s_axi_arprot : in std_logic_vector(2 downto 0); -- sigasi @suppress "Unused port"
s_axi_arvalid : in std_logic;
s_axi_arready : out std_logic;
-- AXI Read Data Channel
s_axi_rdata : out std_logic_vector(31 downto 0);
s_axi_rresp : out std_logic_vector(1 downto 0);
s_axi_rvalid : out std_logic;
s_axi_rready : in std_logic;
-- AXI Write Response Channel
s_axi_bresp : out std_logic_vector(1 downto 0);
s_axi_bvalid : out std_logic;
s_axi_bready : in std_logic;
-- User Ports
control_strobe : out std_logic; -- Strobe signal for register 'control' (pulsed when the register is written from the bus)
control_ena : out std_logic_vector(0 downto 0); -- Value of register 'control', field 'ena'
control_config : out std_logic_vector(15 downto 0); -- Value of register 'control', field 'config'
status_strobe : out std_logic; -- Strobe signal for register 'status' (pulsed when the register is read from the bus)
status_state : in std_logic_vector(7 downto 0); -- Value of register 'status', field 'state'
irq_overflow_set : in std_logic; -- Set signal for register 'irq', field 'overflow' (pulse to set the field to '1')
irq_underflow_set : in std_logic -- Set signal for register 'irq', field 'underflow' (pulse to set the field to '1')
);
end entity my_map_regs;
Let's have a look at this entity:
The generic parameter
BASEADDRallows you to set the base address of the register bank in the system address space; this is particularly useful for systems where you have several instances of the same register bank.The
axi_aclk,axi_aresetnand thes_axi_*ports form the AXI4-lite interface of the register bank.The user ports are the interface to the user logic:
- The
control_strobeport is pulsed every time thecontrolregister is written from the bus. - The
control_enaport reflects the value of thecontrol.enafield. - The
control_configport reflects the value of theconfig.controlfield. - The
status_strobeport is pulsed every time thestatusregister is read from the bus. - The
status_stateport drives the value of thestatus.statefield. - The
irq_overflow_setport can be used to set theirq.overflowfield from the user logic (note that this field cannot be reset from the user logic, it can only be reset from the bus by writing a 1 to it). - The
irq_underflow_setport can be used to set theirq.underflowfield from the user logic.
- The
To avoid excessive port proliferation in larger register maps, you can group the user ports into VHDL records. In that case, the VHDL entity looks like this:
entity my_map_regs is
generic(
AXI_ADDR_WIDTH : integer := 32; -- width of the AXI address bus
BASEADDR : std_logic_vector(31 downto 0) := x"A0000000" -- the register file's system base address
);
port(
-- Clock and Reset
axi_aclk : in std_logic;
axi_aresetn : in std_logic;
-- AXI Write Address Channel
s_axi_awaddr : in std_logic_vector(AXI_ADDR_WIDTH - 1 downto 0);
s_axi_awprot : in std_logic_vector(2 downto 0); -- sigasi @suppress "Unused port"
s_axi_awvalid : in std_logic;
s_axi_awready : out std_logic;
-- AXI Write Data Channel
s_axi_wdata : in std_logic_vector(31 downto 0);
s_axi_wstrb : in std_logic_vector(3 downto 0);
s_axi_wvalid : in std_logic;
s_axi_wready : out std_logic;
-- AXI Read Address Channel
s_axi_araddr : in std_logic_vector(AXI_ADDR_WIDTH - 1 downto 0);
s_axi_arprot : in std_logic_vector(2 downto 0); -- sigasi @suppress "Unused port"
s_axi_arvalid : in std_logic;
s_axi_arready : out std_logic;
-- AXI Read Data Channel
s_axi_rdata : out std_logic_vector(31 downto 0);
s_axi_rresp : out std_logic_vector(1 downto 0);
s_axi_rvalid : out std_logic;
s_axi_rready : in std_logic;
-- AXI Write Response Channel
s_axi_bresp : out std_logic_vector(1 downto 0);
s_axi_bvalid : out std_logic;
s_axi_bready : in std_logic;
-- User Ports
user2regs : in user2regs_t;
regs2user : out regs2user_t
);
end entity my_map_regs;
The user2regs_t and regs2user_t types are VHDL records; they are defined in the VHDL package corresponding to the generated component:
-- User-logic ports (from user-logic to register file)
type user2regs_t is record
status_state : std_logic_vector(7 downto 0); -- value of register 'status', field 'state'
irq_overflow_set : std_logic; -- set signal for register 'irq', field 'overflow' (pulse to set the field to '1')
irq_underflow_set : std_logic; -- set signal for register 'irq', field 'underflow' (pulse to set the field to '1')
end record;
-- User-logic ports (from register file to user-logic)
type regs2user_t is record
control_strobe : std_logic; -- Strobe signal for register 'control' (pulsed when the register is written from the bus}
control_ena : std_logic_vector(0 downto 0); -- Value of register 'control', field 'ena'
control_config : std_logic_vector(15 downto 0); -- Value of register 'control', field 'config'
status_strobe : std_logic; -- Strobe signal for register 'status' (pulsed when the register is read from the bus}
end record;