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