From d4f32ba87a38d03b81501dab63ea8186da0525a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Gendre?= <sebastien.gendre@etu.hesge.ch> Date: Thu, 20 Mar 2025 00:38:57 +0100 Subject: [PATCH] Add a testbench for the AXI4-lite periph and its deps --- .../axi4lite_interface_tb/sim_axi_rd_pkg.vhd | 130 ++++++++ .../axi4lite_interface_tb/sim_axi_wr_pkg.vhd | 146 +++++++++ .../tb_axi4lite_hog_build_info.vhd | 294 ++++++++++++++++++ 3 files changed, 570 insertions(+) create mode 100644 hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/sim_axi_rd_pkg.vhd create mode 100644 hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/sim_axi_wr_pkg.vhd create mode 100644 hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/tb_axi4lite_hog_build_info.vhd diff --git a/hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/sim_axi_rd_pkg.vhd b/hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/sim_axi_rd_pkg.vhd new file mode 100644 index 0000000..15282a7 --- /dev/null +++ b/hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/sim_axi_rd_pkg.vhd @@ -0,0 +1,130 @@ +---------------------------------------------------------------------------------- +-- _ _ +-- | |_ ___ _ __(_)__ _ +-- | ' \/ -_) '_ \ / _` | +-- |_||_\___| .__/_\__,_| +-- |_| +-- +---------------------------------------------------------------------------------- +-- +-- Company: hepia +-- Author: Laurent Gantel <laurent.gantel@hesge.ch> +-- +-- Module Name: sim_axi_rd_pkg - arch +-- Target Device: digilentinc.com:basys3:part0:1.1 xc7a35tcpg236-1 +-- Tool version: 2021.1 +-- Description: UART package +-- +-- Last update: 2022-01-14 +-- +--------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library std; +use std.textio.all; + +library sim_axi; + +package sim_axi_rd_pkg is + + --------------------------------------------------------------------------------- + -- Constants + --------------------------------------------------------------------------------- + + constant SIM_AXI_RD_CLK_PERIOD : time := 10 ns; + + --------------------------------------------------------------------------------- + -- Types + --------------------------------------------------------------------------------- + + -- AXI4-Lite Read channels inputs + type axi4lite_rd_bus_in is record + -- Address channel + arready : std_logic; + -- Data channel + rvalid : std_logic; + rdata : std_logic_vector(31 downto 0); + rresp : std_logic_vector(1 downto 0); + end record axi4lite_rd_bus_in; + + -- AXI4-Lite Read channels outputs + type axi4lite_rd_bus_out is record + -- Address channel + arvalid : std_logic; + araddr : std_logic_vector(31 downto 0); + -- Data channel + rready : std_logic; + end record axi4lite_rd_bus_out; + + --------------------------------------------------------------------------------- + -- Functions + --------------------------------------------------------------------------------- + + + --------------------------------------------------------------------------------- + -- Procedures + --------------------------------------------------------------------------------- + + -- Read from AXI4-Lite interface + procedure axi4lite_read ( + constant rd_addr : in integer; + signal rd_data : out std_logic_vector(31 downto 0); + -- AXI4-Lite interface + signal s_axi_i : in axi4lite_rd_bus_in; + signal s_axi_o : out axi4lite_rd_bus_out + ); + +end sim_axi_rd_pkg; + + +package body sim_axi_rd_pkg is + + --------------------------------------------------------------------------------- + -- Internal functions + --------------------------------------------------------------------------------- + + + --------------------------------------------------------------------------------- + -- Functions + --------------------------------------------------------------------------------- + + + --------------------------------------------------------------------------------- + -- Procedures + --------------------------------------------------------------------------------- + + -- Read from AXI4-Lite interface + procedure axi4lite_read ( + constant rd_addr : in integer; + signal rd_data : out std_logic_vector(31 downto 0); + -- AXI4-Lite interface + signal s_axi_i : in axi4lite_rd_bus_in; + signal s_axi_o : out axi4lite_rd_bus_out + ) is + begin + -- Set the address + s_axi_o.arvalid <= '1'; + s_axi_o.araddr <= std_logic_vector(to_unsigned(rd_addr, 32)); + if s_axi_i.arready = '0' then + wait until s_axi_i.arready = '1'; + end if; + wait for SIM_AXI_RD_CLK_PERIOD; + s_axi_o.arvalid <= '0'; + s_axi_o.araddr <= (others => '0'); + + -- Get the data + if s_axi_i.rvalid = '0' then + wait until s_axi_i.rvalid = '1'; + end if; + wait for SIM_AXI_RD_CLK_PERIOD; + s_axi_o.rready <= '1'; + rd_data <= s_axi_i.rdata; + wait for SIM_AXI_RD_CLK_PERIOD; + s_axi_o.rready <= '0'; + wait for SIM_AXI_RD_CLK_PERIOD; + end procedure axi4lite_read; + +end package body sim_axi_rd_pkg; diff --git a/hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/sim_axi_wr_pkg.vhd b/hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/sim_axi_wr_pkg.vhd new file mode 100644 index 0000000..035e51d --- /dev/null +++ b/hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/sim_axi_wr_pkg.vhd @@ -0,0 +1,146 @@ +---------------------------------------------------------------------------------- +-- _ _ +-- | |_ ___ _ __(_)__ _ +-- | ' \/ -_) '_ \ / _` | +-- |_||_\___| .__/_\__,_| +-- |_| +-- +---------------------------------------------------------------------------------- +-- +-- Company: hepia +-- Author: Laurent Gantel <laurent.gantel@hesge.ch> +-- +-- Module Name: sim_axi_wr_pkg - arch +-- Target Device: digilentinc.com:basys3:part0:1.1 xc7a35tcpg236-1 +-- Tool version: 2021.1 +-- Description: UART package +-- +-- Last update: 2022-01-14 +-- +--------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library std; +use std.textio.all; + +library sim_axi; + +package sim_axi_wr_pkg is + + --------------------------------------------------------------------------------- + -- Constants + --------------------------------------------------------------------------------- + constant SIM_AXI_WR_CLK_PERIOD : time := 10 ns; + + --------------------------------------------------------------------------------- + -- Types + --------------------------------------------------------------------------------- + -- AXI4-Lite Write channels inputs + type axi4lite_wr_bus_in is record + -- Address channel + awready : std_logic; + -- Data channel + wready : std_logic; + -- Response channel + bvalid : std_logic; + bresp : std_logic_vector(1 downto 0); + end record axi4lite_wr_bus_in; + + -- AXI4-Lite Write channels outputs + type axi4lite_wr_bus_out is record + -- Address channel + awvalid : std_logic; + awaddr : std_logic_vector(31 downto 0); + -- Data channel + wvalid : std_logic; + wstrb : std_logic_vector(3 downto 0); + wdata : std_logic_vector(31 downto 0); + -- Response channel + bready : std_logic; + end record axi4lite_wr_bus_out; + + --------------------------------------------------------------------------------- + -- Functions + --------------------------------------------------------------------------------- + + + --------------------------------------------------------------------------------- + -- Procedures + --------------------------------------------------------------------------------- + + -- Write to an AXI4-Lite interface + procedure axi4lite_write ( + constant wr_addr : in integer; + constant wr_data : in std_logic_vector(31 downto 0); + -- AXI4-Lite interface + signal s_axi_i : in axi4lite_wr_bus_in; + signal s_axi_o : out axi4lite_wr_bus_out + ); + +end sim_axi_wr_pkg; + + +package body sim_axi_wr_pkg is + + --------------------------------------------------------------------------------- + -- Internal functions + --------------------------------------------------------------------------------- + + + --------------------------------------------------------------------------------- + -- Functions + --------------------------------------------------------------------------------- + + + --------------------------------------------------------------------------------- + -- Procedures + --------------------------------------------------------------------------------- + + -- Write to an AXI4-Lite interface + procedure axi4lite_write ( + constant wr_addr : in integer; + constant wr_data : in std_logic_vector(31 downto 0); + -- AXI4-Lite interface + signal s_axi_i : in axi4lite_wr_bus_in; + signal s_axi_o : out axi4lite_wr_bus_out + ) is + begin + -- Set the address + s_axi_o.awvalid <= '1'; + s_axi_o.awaddr <= std_logic_vector(to_unsigned(wr_addr, 32)); + -- Set the data + s_axi_o.wvalid <= '1'; + s_axi_o.wdata <= wr_data; + s_axi_o.wstrb <= "1111"; + wait for SIM_AXI_WR_CLK_PERIOD; + + if s_axi_i.awready = '0' then + wait until s_axi_i.awready = '1'; + wait for SIM_AXI_WR_CLK_PERIOD; + end if; + s_axi_o.awvalid <= '0'; + s_axi_o.awaddr <= (others => '0'); + + if s_axi_i.wready = '0' then + wait until s_axi_i.wready = '1'; + wait for SIM_AXI_WR_CLK_PERIOD; + end if; + s_axi_o.wvalid <= '0'; + s_axi_o.wdata <= (others => '0'); + s_axi_o.wstrb <= "0000"; + + -- Validate the transaction + s_axi_o.bready <= '1'; + if s_axi_i.bvalid = '0' then + wait until s_axi_i.bvalid = '1'; + end if; + wait for SIM_AXI_WR_CLK_PERIOD; + s_axi_o.bready <= '0'; + wait for SIM_AXI_WR_CLK_PERIOD; + end procedure axi4lite_write; + + +end package body sim_axi_wr_pkg; diff --git a/hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/tb_axi4lite_hog_build_info.vhd b/hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/tb_axi4lite_hog_build_info.vhd new file mode 100644 index 0000000..2e05e4d --- /dev/null +++ b/hog-build-info/hog-build-info.srcs/sim/axi4lite_interface_tb/tb_axi4lite_hog_build_info.vhd @@ -0,0 +1,294 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 03/19/2025 10:06:52 PM +-- Design Name: Test bench for Hog build info AXI4-lite peripheral +-- Module Name: tb_axi4lite_hog_build_info - Behavioral +-- Project Name: Hog build info +-- Target Devices: +-- Tool Versions: +-- Description: Test bench for the Hog build info AXI4-lite peripheral +-- +-- Dependencies: +-- - axi4lite_hog_build_info +-- - axi4lite_if +-- - axi4lite_wr_channel_if +-- - axi4lite_rd_channel_if +-- - hog_build_info_regs +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; +use std.env.finish; + +-- Library for simulating AXI4-lite Read and Write +library sim_axi; +use sim_axi.sim_axi_rd_pkg.all; +use sim_axi.sim_axi_wr_pkg.all; + + +entity tb_axi4lite_hog_build_info is +end tb_axi4lite_hog_build_info; + +architecture Behavioral of tb_axi4lite_hog_build_info is + + -- External component to test + --- Hog build info AXI4-lite peripheral + component axi4lite_hog_build_info + generic ( + C_ADDR_WIDTH: integer := 32 -- Width of the addresses + ); + port ( + s_axi_aclk : in std_logic; + s_axi_aresetn : in std_logic; + -- AXI4-Lite Write interface + s_axi_awaddr : in std_logic_vector(31 downto 0); + s_axi_awvalid : in std_logic; + s_axi_awready : out std_logic; + 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; + s_axi_bresp : out std_logic_vector(1 downto 0); + s_axi_bvalid : out std_logic; + s_axi_bready : in std_logic; + -- AXI4-Lite Read interface + s_axi_araddr : in std_logic_vector(31 downto 0); + s_axi_arvalid : in std_logic; + s_axi_arready : out std_logic; + 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; + -- Hog build info interface + hog_global_date_i : in std_logic_vector(31 downto 0); -- Hog build global date + hog_global_time_i : in std_logic_vector(31 downto 0); -- Hog build global time + hog_global_ver_i : in std_logic_vector(31 downto 0); -- Hog build global version + hog_global_sha_i : in std_logic_vector(31 downto 0) -- Hog build global latest commit SHA + ); + end component axi4lite_hog_build_info; + + -- Clock signal and period + constant CLK_PERIOD : time := 10 ns; + signal clk_s : std_logic := '0'; + + -- Resetn signal + signal resetn_s : std_logic := '1'; + + -- Config + constant C_ADDR_WIDTH: integer := 32; + + -- Registers addresses + constant GDR_BASEADDR : integer := 0; -- Global date register + constant GTR_BASEADDR : integer := 4; -- Global time register + constant GVR_BASEADDR : integer := 8; -- Global version register + constant GSR_BASEADDR : integer := 12; -- Global SHA register + constant UNK_BASEADDR : integer := 14; -- Unknown register + + -- Fake Hog build info + constant hog_global_date : std_logic_vector(31 downto 0) := X"13032025"; + constant hog_global_time : std_logic_vector(31 downto 0) := X"00123456"; + constant hog_global_ver : std_logic_vector(31 downto 0) := X"01020006"; + constant hog_global_sha : std_logic_vector(31 downto 0) := X"A98B90F0"; + + -- Hog build info inputs + signal hog_global_date_s : std_logic_vector(31 downto 0) := (others => '0'); + signal hog_global_time_s : std_logic_vector(31 downto 0) := (others => '0'); + signal hog_global_ver_s : std_logic_vector(31 downto 0) := (others => '0'); + signal hog_global_sha_s : std_logic_vector(31 downto 0) := (others => '0'); + + -- Data get from the peripheral + signal rd_data_s : std_logic_vector(31 downto 0) := (others => '0'); + + -- AXI4-lite interface bus + signal axi4lite_rd_bus_i : axi4lite_rd_bus_in := ( + -- Address channel + arready => '0', + -- Data channel + rvalid => '0', + rdata => (others => '0'), + rresp => (others => '0') + ); + + signal axi4lite_rd_bus_o : axi4lite_rd_bus_out := ( + -- Address channel + arvalid => '0', + araddr => (others => '0'), + -- Data channel + rready => '0' + ); + + signal axi4lite_wr_bus_i : axi4lite_wr_bus_in := ( + -- Address channel + awready => '0', + -- Data channel + wready => '0', + -- Response channel + bvalid => '0', + bresp => (others => '0') + ); + + signal axi4lite_wr_bus_o : axi4lite_wr_bus_out := ( + -- Address channel + awvalid => '0', + awaddr => (others => '0'), + -- Data channel + wvalid => '0', + wstrb => (others => '0'), + wdata => (others => '0'), + -- Response channel + bready => '0' + ); + + -- Test bench steps + signal reset_done_s : std_logic := '0'; + signal check_reg_0_data_s : std_logic := '0'; + signal check_reg_1_data_s : std_logic := '0'; + signal check_reg_2_data_s : std_logic := '0'; + signal check_reg_3_data_s : std_logic := '0'; + signal check_reg_unk_data_s : std_logic := '0'; + +begin + + -- Instance of the peripheral + axi4lite_hog_build_info_inst : axi4lite_hog_build_info + generic map ( + C_ADDR_WIDTH => C_ADDR_WIDTH + ) + port map ( + s_axi_aclk => clk_s, + s_axi_aresetn => resetn_s, + -- AXI4-Lite Write interface + s_axi_awaddr => axi4lite_wr_bus_o.awaddr, + s_axi_awvalid => axi4lite_wr_bus_o.awvalid, + s_axi_awready => axi4lite_wr_bus_i.awready, + s_axi_wdata => axi4lite_wr_bus_o.wdata, + s_axi_wstrb => axi4lite_wr_bus_o.wstrb, + s_axi_wvalid => axi4lite_wr_bus_o.wvalid, + s_axi_wready => axi4lite_wr_bus_i.wready, + s_axi_bresp => axi4lite_wr_bus_i.bresp, + s_axi_bvalid => axi4lite_wr_bus_i.bvalid, + s_axi_bready => axi4lite_wr_bus_o.bready, + -- AXI4-Lite Read interface + s_axi_araddr => axi4lite_rd_bus_o.araddr, + s_axi_arvalid => axi4lite_rd_bus_o.arvalid, + s_axi_arready => axi4lite_rd_bus_i.arready, + s_axi_rdata => axi4lite_rd_bus_i.rdata, + s_axi_rresp => axi4lite_rd_bus_i.rresp, + s_axi_rvalid => axi4lite_rd_bus_i.rvalid, + s_axi_rready => axi4lite_rd_bus_o.rready, + -- Hog build info interface + hog_global_date_i => hog_global_date_s, + hog_global_time_i => hog_global_time_s, + hog_global_ver_i => hog_global_ver_s, + hog_global_sha_i => hog_global_sha_s + ); + + -- Feed the register bank with fake Hog build info + hog_global_date_s <= hog_global_date; + hog_global_time_s <= hog_global_time; + hog_global_ver_s <= hog_global_ver; + hog_global_sha_s <= hog_global_sha; + + + -- Clock generator process + clk_process : clk_s <= not clk_s after CLK_PERIOD / 2; + + -- Reset process + reset_process: process + begin + resetn_s <= '0'; + wait for CLK_PERIOD * 10; + resetn_s <= '1'; + wait for CLK_PERIOD; + reset_done_s <= '1'; + wait; + end process; + + -- Stimulus process + stimulus_process: process + begin + -- Wait until reset is done + wait until reset_done_s = '1'; + + -- Request to read register 0 + axi4lite_read(GDR_BASEADDR, rd_data_s, axi4lite_rd_bus_i, axi4lite_rd_bus_o); + check_reg_0_data_s <= '0'; + wait for CLK_PERIOD; + + -- Request to read register 1 + axi4lite_read(GTR_BASEADDR, rd_data_s, axi4lite_rd_bus_i, axi4lite_rd_bus_o); + check_reg_1_data_s <= '0'; + wait for CLK_PERIOD; + + -- Request to read register 2 + axi4lite_read(GVR_BASEADDR, rd_data_s, axi4lite_rd_bus_i, axi4lite_rd_bus_o); + check_reg_2_data_s <= '0'; + wait for CLK_PERIOD; + + -- Request to read register 3 + axi4lite_read(GSR_BASEADDR, rd_data_s, axi4lite_rd_bus_i, axi4lite_rd_bus_o); + check_reg_3_data_s <= '0'; + wait for CLK_PERIOD; + + -- Request to read unknown register + axi4lite_read(UNK_BASEADDR, rd_data_s, axi4lite_rd_bus_i, axi4lite_rd_bus_o); + check_reg_unk_data_s <= '0'; + wait for CLK_PERIOD; + + -- Wait endlessly + wait; + + end process stimulus_process; + + -- Monitor process + monitor_process: process + begin + + -- Check we get register 0 value on data out + wait until check_reg_0_data_s = '1'; + wait for CLK_PERIOD; + assert rd_data_s = hog_global_date + report ">>> register 0 value do not correspond to the value feed to the register bank. Instead, get: " & to_hstring(to_bitvector(rd_data_s)) + severity failure; + + -- Check we get register 1 value on data out + wait until check_reg_1_data_s = '1'; + assert rd_data_s = hog_global_time + report ">>> register 1 value do not correspond to the value feed to the register bank. Instead, get: " & to_hstring(to_bitvector(rd_data_s)) + severity failure; + + -- Check we get register 2 value on data out + wait until check_reg_2_data_s = '1'; + assert rd_data_s = hog_global_ver + report ">>> register 1 value do not correspond to the value feed to the register bank. Instead, get: " & to_hstring(to_bitvector(rd_data_s)) + severity failure; + + -- Check we get register 3 value on data out + wait until check_reg_3_data_s = '1'; + assert rd_data_s = hog_global_sha + report ">>> register 1 value do not correspond to the value feed to the register bank. Instead, get: " & to_hstring(to_bitvector(rd_data_s)) + severity failure; + + -- Check we get 0x0 on data out because of unknown register requested + wait until check_reg_unk_data_s = '1'; + assert rd_data_s = X"00000000" + report ">>> rd_data_s is not at 0x0 when unknown register is requested. Instead, get: " & to_hstring(to_bitvector(rd_data_s)) + severity failure; + + -- If arrive here, the simulation have completed successfully + wait for CLK_PERIOD * 10; + report ">>> Simulation completed successfully"; + finish; + + end process monitor_process; + +end Behavioral; -- GitLab