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
control
with a 1-bitena
field and an 16-bitconfig
field - A status register called
status
with an 8-bitstate
field - An interrupt register called
irq
with two 1-bitoverflow
andunderflow
fields
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
BASEADDR
allows 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_aresetn
and thes_axi_*
ports form the AXI4-lite interface of the register bank.The user ports are the interface to the user logic:
- The
control_strobe
port is pulsed every time thecontrol
register is written from the bus. - The
control_ena
port reflects the value of thecontrol.ena
field. - The
control_config
port reflects the value of theconfig.control
field. - The
status_strobe
port is pulsed every time thestatus
register is read from the bus. - The
status_state
port drives the value of thestatus.state
field. - The
irq_overflow_set
port can be used to set theirq.overflow
field 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_set
port can be used to set theirq.underflow
field 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;