Commit 902c347a authored by Tristan Gingold's avatar Tristan Gingold

Merge branch 'proposed_master' into 'master'

Merge proposed master into master

See merge request !29
parents b84c76be a0e0f2e5
[submodule "testbench/osvvm/upstream"]
path = testbench/osvvm/upstream
url = https://github.com/OSVVM/OSVVM.git
......@@ -205,6 +205,11 @@ Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
interface to the digital thermometer.
- [wb_xc7_fw_update](modules/wishbone/wb_xc7_fw_update) is an SPI interface
to drive the xc7 bitstream spi flash (using the ht-flash tool).
- [wb_clock_monitor](modules/wishbone/wb_clock_monitor) is clock frequency
measurement/monitoring core with a programmable number of channels.
- [wb_lm32_mcs](modules/wishbone/wb_lm32_mcs) is a single-entity microcontroller
based on the LM32 softcore, featuring internal code/data RAM, UART, timer and
a pipelined Wishbone peripheral interface.
* There are utilities to handle a wishbone bus:
- [wb_clock_crossing](modules/wishbone/wb_clock_crossing) handle clock domain
......
-------------------------------------------------------------------------------
-- Title : AXI4Full64 to AXI4Lite32 bridge
-- Title : AXI4Lite to AXI4Full bridge
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : axi4lite32_axi4full64_bridge.vhd
-- File : axi4lite_axi4full_bridge.vhd
-- Company : CERN
-- Platform : FPGA-generics
-- Standard : VHDL '93
......@@ -230,8 +230,11 @@ begin
-- Read part.
m_araddr <= raddr;
s_rdata <= rdata;
s_rid <= rid;
s_rdata <= rdata;
s_rid <= rid;
s_rlast <= '1' when (unsigned(rlen)=0 and s_rready = '1' and s_rvalid = '1')
else '0';
process (clk_i)
begin
......@@ -240,7 +243,6 @@ begin
rstate <= RD_IDLE;
s_arready <= '1';
s_rvalid <= '0';
s_rlast <= '0';
m_arvalid <= '0';
m_rready <= '0';
raddr <= (others => 'X');
......@@ -275,6 +277,7 @@ begin
m_arvalid <= '0';
end if;
if m_rvalid = '1' then
m_rready <= '0';
-- Read data. Address must have been acked.
-- According to A3.4.3 of AXI4 spec, the AXI4 bus is little
-- endian.
......@@ -283,11 +286,6 @@ begin
-- To master.
rstate <= RD_SLAVE;
s_rresp <= RSP_OKAY;
if rlen = (g_LEN_WIDTH - 1 downto 0 => '0') then
s_rlast <= '1';
else
s_rlast <= '0';
end if;
s_rvalid <= '1';
end if;
......
......@@ -134,17 +134,17 @@ architecture behav of axi_gpio_expander is
return tmp;
end function;
-------------------------------------------
function f_update_gpio_in (orig : std_logic_vector; rdata : std_logic_vector; bank : integer)
function f_update_gpio_in (orig : std_logic_vector; rd_data : std_logic_vector; bank : integer)
return std_logic_vector is
variable tmp : std_logic_vector(g_num-1 downto 0);
begin
tmp := orig;
if (bank = 0 and g_num >= c_GPIOPS_BANK0) then
tmp(c_GPIOPS_BANK0-1 downto 0) := rdata;
tmp(c_GPIOPS_BANK0-1 downto 0) := rd_data;
elsif (bank = 0 and g_num < c_GPIOPS_BANK0) then
tmp := rdata(g_num-1 downto 0);
tmp := rd_data(g_num-1 downto 0);
else
tmp(g_num-1 downto c_GPIOPS_BANK0) := rdata(g_num-c_GPIOPS_BANK0-1 downto 0);
tmp(g_num-1 downto c_GPIOPS_BANK0) := rd_data(g_num-c_GPIOPS_BANK0-1 downto 0);
end if;
return tmp;
end function;
......@@ -295,7 +295,7 @@ begin
-- write accepted, let's proceed
BREADY <= '0';
state <= INIT_WRITE_OUT;
elsif (BVALID = '1' and BRESP = c_AXI4_RESP_OKAY) then
elsif (BVALID = '1' and BRESP = c_AXI4_RESP_OKAY) then
-- nothing to update in GPIO_OUT, skip to GPIO reading
BREADY <= '0';
state <= INIT_READ;
......@@ -409,7 +409,7 @@ begin
else -- current_bank = 0 and g_num =< c_GPIOPS_BANK0
-- Only Bank0 is used, reset refresh_all flag, Bank0 registers are
-- all set here.
refresh_all <= '0';
refresh_all <= '0';
end if;
state <= IDLE;
......
......@@ -6,7 +6,7 @@
-- Author : Wesley W. Terpstra
-- Company : GSI
-- Created : 2011-01-25
-- Last update: 2013-03-04
-- Last update: 2022-07-25
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -44,7 +44,9 @@ entity generic_dpram is
g_addr_conflict_resolution : string := "dont_care";
g_init_file : string := "none";
g_fail_if_file_not_found : boolean := true; -- dummy (exists in Xilinx/generic)
g_dual_clock : boolean := true);
g_dual_clock : boolean := true;
g_implementation_hint : string := "auto"
);
port(
rst_n_i : in std_logic := '1'; -- synchronous reset, active LO
......
......@@ -6,7 +6,7 @@
-- Author : C. Prados
-- Company : GSI
-- Created : 2014-08-25
-- Last update:
-- Last update: 2022-07-25
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -38,7 +38,9 @@ entity generic_dpram_mixed is
g_size : natural;
g_addr_conflict_resolution : string := "dont_care";
g_init_file : string := "none";
g_dual_clock : boolean := true);
g_dual_clock : boolean := true;
g_implementation_hint : string := "auto"
);
port(
rst_n_i : in std_logic := '1'; -- synchronous reset, active LO
......
......@@ -6,7 +6,7 @@
-- Author : Wesley W. Terpstra
-- Company : GSI
-- Created : 2013-03-04
-- Last update: 2013-03-04
-- Last update: 2022-07-25
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -38,7 +38,8 @@ entity generic_simple_dpram is
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "dont_care";
g_init_file : string := "none";
g_dual_clock : boolean := true);
g_dual_clock : boolean := true;
g_implementation_hint : string := "auto");
port(
rst_n_i : in std_logic := '1'; -- synchronous reset, active LO
......
......@@ -6,7 +6,7 @@
-- Author : Wesley W. Terpstra
-- Company : GSI
-- Created : 2011-01-25
-- Last update: 2013-03-04
-- Last update: 2022-07-25
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -39,7 +39,8 @@ entity generic_spram is
g_size : natural := 1024;
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "dont_care";
g_init_file : string := "");
g_init_file : string := "";
g_implementation_hint : string := "auto");
port(
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
......
......@@ -53,8 +53,9 @@ entity inferred_async_fifo is
g_with_wr_count : boolean := FALSE;
g_almost_empty_threshold : integer; -- threshold for almost empty flag
g_almost_full_threshold : integer -- threshold for almost full flag
);
g_almost_full_threshold : integer; -- threshold for almost full flag
g_memory_implementation_hint : string := "auto");
port (
rst_n_i : in std_logic := '1';
......@@ -116,11 +117,24 @@ architecture syn of inferred_async_fifo is
bin_x, gray_x : t_counter;
end record;
constant c_counters_reset_value : t_counter_block :=
( bin => (others => '0'),
bin_next => (others => '0'),
gray => (others => '0'),
gray_next => (others => '0'),
bin_x => (others => '0'),
gray_x => (others => '0') );
type t_mem_type is array (0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0);
signal mem : t_mem_type := (others => (others => '0'));
signal rcb, wcb : t_counter_block := (others =>(others => '0'));
attribute ram_type : string;
attribute ram_type of mem : signal is g_memory_implementation_hint;
signal rcb, wcb : t_counter_block := c_counters_reset_value;
signal full_int, empty_int : std_logic;
signal almost_full_int, almost_empty_int : std_logic;
signal going_full : std_logic;
......
......@@ -50,7 +50,8 @@ entity inferred_async_fifo_dual_rst is
g_with_wr_almost_full : boolean := FALSE;
g_with_wr_count : boolean := FALSE;
g_almost_empty_threshold : integer;
g_almost_full_threshold : integer);
g_almost_full_threshold : integer;
g_memory_implementation_hint : string := "auto");
port (
-- write port
rst_wr_n_i : in std_logic := '1';
......@@ -111,6 +112,9 @@ architecture arch of inferred_async_fifo_dual_rst is
signal rcb, wcb : t_counter_block := (others =>(others => '0'));
attribute ram_type : string;
attribute ram_type of mem : signal is g_memory_implementation_hint;
signal full_int, empty_int : std_logic;
signal almost_full_int, almost_empty_int : std_logic;
signal going_full : std_logic;
......
......@@ -54,7 +54,9 @@ entity inferred_sync_fifo is
g_almost_empty_threshold : integer := 0; -- threshold for almost empty flag
g_almost_full_threshold : integer := 0; -- threshold for almost full flag
g_register_flag_outputs : boolean := true
g_register_flag_outputs : boolean := true;
g_memory_implementation_hint : string := "auto"
);
port (
......@@ -105,7 +107,8 @@ begin -- syn
g_size => g_size,
g_with_byte_enable => false,
g_addr_conflict_resolution => "dont_care",
g_dual_clock => false)
g_dual_clock => false,
g_implementation_hint => g_memory_implementation_hint)
port map (
rst_n_i => rst_n_i,
clka_i => clk_i,
......
......@@ -53,7 +53,9 @@ entity generic_async_fifo is
g_with_wr_count : boolean := false;
g_almost_empty_threshold : integer; -- threshold for almost empty flag
g_almost_full_threshold : integer -- threshold for almost full flag
g_almost_full_threshold : integer; -- threshold for almost full flag
g_memory_implementation_hint : string := "auto"
);
port (
......@@ -104,7 +106,9 @@ architecture syn of generic_async_fifo is
g_with_wr_almost_full : boolean;
g_with_wr_count : boolean;
g_almost_empty_threshold : integer;
g_almost_full_threshold : integer);
g_almost_full_threshold : integer;
g_memory_implementation_hint : string
);
port (
rst_n_i : in std_logic := '1';
clk_wr_i : in std_logic;
......@@ -144,7 +148,8 @@ begin -- syn
g_with_wr_almost_full => g_with_wr_almost_full,
g_with_wr_count => g_with_wr_count,
g_almost_empty_threshold => g_almost_empty_threshold,
g_almost_full_threshold => g_almost_full_threshold)
g_almost_full_threshold => g_almost_full_threshold,
g_memory_implementation_hint => g_memory_implementation_hint )
port map (
rst_n_i => rst_n_i,
clk_wr_i => clk_wr_i,
......
......@@ -50,7 +50,8 @@ entity generic_async_fifo_dual_rst is
g_with_wr_almost_full : boolean := FALSE;
g_with_wr_count : boolean := FALSE;
g_almost_empty_threshold : integer := 0;
g_almost_full_threshold : integer := 0);
g_almost_full_threshold : integer := 0;
g_memory_implementation_hint : string := "auto" );
port (
-- write port
rst_wr_n_i : in std_logic := '1';
......@@ -96,7 +97,8 @@ begin -- arch
g_with_wr_almost_full => g_with_wr_almost_full,
g_with_wr_count => g_with_wr_count,
g_almost_empty_threshold => g_almost_empty_threshold,
g_almost_full_threshold => g_almost_full_threshold)
g_almost_full_threshold => g_almost_full_threshold,
g_memory_implementation_hint => g_memory_implementation_hint )
port map (
rst_wr_n_i => rst_wr_n_i,
clk_wr_i => clk_wr_i,
......
......@@ -53,7 +53,8 @@ entity generic_sync_fifo is
g_almost_empty_threshold : integer := 0; -- threshold for almost empty flag
g_almost_full_threshold : integer := 0; -- threshold for almost full flag
g_register_flag_outputs : boolean := true
g_register_flag_outputs : boolean := true;
g_memory_implementation_hint : string := "auto"
);
port (
......@@ -90,7 +91,8 @@ architecture syn of generic_sync_fifo is
g_with_count : boolean;
g_almost_empty_threshold : integer;
g_almost_full_threshold : integer;
g_register_flag_outputs : boolean);
g_register_flag_outputs : boolean;
g_memory_implementation_hint : string);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
......@@ -120,8 +122,8 @@ begin -- syn
g_with_count => g_with_count,
g_almost_empty_threshold => g_almost_empty_threshold,
g_almost_full_threshold => g_almost_full_threshold,
g_register_flag_outputs => g_register_flag_outputs)
g_register_flag_outputs => g_register_flag_outputs,
g_memory_implementation_hint => g_memory_implementation_hint )
port map (
rst_n_i => rst_n_i,
clk_i => clk_i,
......
......@@ -48,7 +48,8 @@ package genram_pkg is
g_size : natural;
g_with_byte_enable : boolean := false;
g_init_file : string := "none";
g_addr_conflict_resolution : string := "dont_care") ;
g_addr_conflict_resolution : string := "dont_care";
g_implementation_hint : string := "auto") ;
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
......@@ -66,7 +67,9 @@ package genram_pkg is
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "dont_care";
g_init_file : string := "none";
g_dual_clock : boolean := true);
g_dual_clock : boolean := true;
g_implementation_hint : string := "auto"
);
port (
rst_n_i : in std_logic := '1';
clka_i : in std_logic;
......@@ -87,7 +90,9 @@ package genram_pkg is
g_addr_conflict_resolution : string := "dont_care";
g_init_file : string := "none";
g_fail_if_file_not_found : boolean := true;
g_dual_clock : boolean := true);
g_dual_clock : boolean := true;
g_implementation_hint : string := "auto"
);
port (
rst_n_i : in std_logic := '1';
clka_i : in std_logic;
......@@ -111,7 +116,9 @@ package genram_pkg is
g_size : natural;
g_addr_conflict_resolution : string := "dont_care";
g_init_file : string := "none";
g_dual_clock : boolean := true);
g_dual_clock : boolean := true;
g_implementation_hint : string := "auto"
);
port (
rst_n_i : in std_logic := '1';
clka_i : in std_logic;
......@@ -144,7 +151,8 @@ package genram_pkg is
g_with_wr_almost_full : boolean := false;
g_with_wr_count : boolean := false;
g_almost_empty_threshold : integer := 0;
g_almost_full_threshold : integer := 0);
g_almost_full_threshold : integer := 0;
g_memory_implementation_hint : string := "auto");
port (
rst_wr_n_i : in std_logic := '1';
clk_wr_i : in std_logic;
......@@ -182,7 +190,9 @@ package genram_pkg is
g_with_wr_almost_full : boolean := false;
g_with_wr_count : boolean := false;
g_almost_empty_threshold : integer := 0;
g_almost_full_threshold : integer := 0);
g_almost_full_threshold : integer := 0;
g_memory_implementation_hint : string := "auto"
);
port (
rst_n_i : in std_logic := '1';
clk_wr_i : in std_logic;
......@@ -217,7 +227,9 @@ package genram_pkg is
g_with_count : boolean := false;
g_almost_empty_threshold : integer := 0;
g_almost_full_threshold : integer := 0;
g_register_flag_outputs : boolean := true);
g_register_flag_outputs : boolean := true;
g_memory_implementation_hint : string := "auto"
);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
......@@ -248,6 +260,29 @@ package genram_pkg is
q_valid_o : out std_logic
);
end component;
component generic_dpram_split is
generic (
g_size : natural;
g_init_file : string := "none";
g_addr_conflict_resolution : string := "dont_care";
g_fail_if_file_not_found : boolean := true;
g_implementation_hint : string := "auto"
);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
bwea_i : in std_logic_vector(3 downto 0);
wea_i : in std_logic;
aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
da_i : in std_logic_vector(31 downto 0);
qa_o : out std_logic_vector(31 downto 0);
bweb_i : in std_logic_vector(3 downto 0);
web_i : in std_logic;
ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
db_i : in std_logic_vector(31 downto 0);
qb_o : out std_logic_vector(31 downto 0));
end component generic_dpram_split;
end genram_pkg;
......
......@@ -49,7 +49,8 @@ entity generic_dpram is
g_addr_conflict_resolution : string := "read_first";
g_init_file : string := "";
g_dual_clock : boolean := true;
g_fail_if_file_not_found : boolean := true
g_fail_if_file_not_found : boolean := true;
g_implementation_hint : string := "auto"
);
port (
......@@ -89,7 +90,9 @@ architecture syn of generic_dpram is
g_size : natural;
g_addr_conflict_resolution : string := "dont_care";
g_init_file : string := "none";
g_fail_if_file_not_found : boolean := true);
g_fail_if_file_not_found : boolean := true;
g_implementation_hint : string := "auto"
);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
......@@ -112,7 +115,9 @@ architecture syn of generic_dpram is
g_with_byte_enable : boolean;
g_addr_conflict_resolution : string;
g_init_file : string;
g_fail_if_file_not_found : boolean);
g_fail_if_file_not_found : boolean;
g_implementation_hint : string
);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
......@@ -135,7 +140,9 @@ architecture syn of generic_dpram is
g_with_byte_enable : boolean;
g_addr_conflict_resolution : string;
g_init_file : string;
g_fail_if_file_not_found : boolean);
g_fail_if_file_not_found : boolean;
g_implementation_hint : string
);
port (
rst_n_i : in std_logic := '1';
clka_i : in std_logic;
......@@ -167,7 +174,8 @@ begin
g_size => g_size,
g_addr_conflict_resolution => g_addr_conflict_resolution,
g_init_file => g_init_file,
g_fail_if_file_not_found => g_fail_if_file_not_found)
g_fail_if_file_not_found => g_fail_if_file_not_found,
g_implementation_hint => g_implementation_hint)
port map(
rst_n_i => rst_n_i,
clk_i => clka_i,
......@@ -191,7 +199,8 @@ begin
g_with_byte_enable => g_with_byte_enable,
g_addr_conflict_resolution => g_addr_conflict_resolution,
g_init_file => g_init_file,
g_fail_if_file_not_found => g_fail_if_file_not_found)
g_fail_if_file_not_found => g_fail_if_file_not_found,
g_implementation_hint => g_implementation_hint)
port map (
rst_n_i => rst_n_i,
clk_i => clka_i,
......@@ -217,7 +226,8 @@ begin
g_with_byte_enable => g_with_byte_enable,
g_addr_conflict_resolution => g_addr_conflict_resolution,
g_init_file => g_init_file,
g_fail_if_file_not_found => g_fail_if_file_not_found)
g_fail_if_file_not_found => g_fail_if_file_not_found,
g_implementation_hint => g_implementation_hint)
port map (
rst_n_i => rst_n_i,
clka_i => clka_i,
......
......@@ -48,7 +48,8 @@ entity generic_dpram_dualclock is
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "read_first";
g_init_file : string := "";
g_fail_if_file_not_found : boolean := true
g_fail_if_file_not_found : boolean := true;
g_implementation_hint : string := "auto"
);
port (
......@@ -122,6 +123,9 @@ architecture syn of generic_dpram_dualclock is
shared variable ram : t_ram_type := f_file_to_ramtype;
attribute ram_type : string;
attribute ram_type of ram : variable is g_implementation_hint;
signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0);
signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0);
......
......@@ -47,7 +47,8 @@ entity generic_dpram_sameclock is
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "read_first";
g_init_file : string := "";
g_fail_if_file_not_found : boolean := true
g_fail_if_file_not_found : boolean := true;
g_implementation_hint : string := "auto"
);
port (
......@@ -122,6 +123,9 @@ architecture syn of generic_dpram_sameclock is
shared variable ram : t_ram_type := f_file_to_ramtype;
attribute ram_type : string;
attribute ram_type of ram : variable is g_implementation_hint;
signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0);
signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0);
......
......@@ -61,7 +61,8 @@ entity generic_dpram_split is
g_size : natural := 16384;
g_addr_conflict_resolution : string := "read_first";
g_init_file : string := "";
g_fail_if_file_not_found : boolean := true);
g_fail_if_file_not_found : boolean := true;
g_implementation_hint : string := "auto");
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
......@@ -112,6 +113,12 @@ architecture syn of generic_dpram_split is
shared variable ram2 : t_split_ram := f_file_to_ramtype(2);
shared variable ram3 : t_split_ram := f_file_to_ramtype(3);
attribute ram_type : string;
attribute ram_type of ram0 : variable is g_implementation_hint;
attribute ram_type of ram1 : variable is g_implementation_hint;
attribute ram_type of ram2 : variable is g_implementation_hint;
attribute ram_type of ram3 : variable is g_implementation_hint;
signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0);
signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0);
signal wea_rep : std_logic_vector(c_num_bytes-1 downto 0);
......
......@@ -6,7 +6,7 @@
-- Author : Wesley W. Terpstra
-- Company : GSI
-- Created : 2013-03-04
-- Last update: 2013-10-30
-- Last update: 2022-07-25
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -58,7 +58,8 @@ entity generic_simple_dpram is
g_addr_conflict_resolution : string := "read_first";
g_init_file : string := "";
g_dual_clock : boolean := true;
g_fail_if_file_not_found : boolean := true
g_fail_if_file_not_found : boolean := true;
g_implementation_hint : string := "auto"
);
port (
......@@ -93,7 +94,8 @@ begin
g_with_byte_enable => g_with_byte_enable,
g_addr_conflict_resolution => g_addr_conflict_resolution,
g_init_file => g_init_file,
g_dual_clock => g_dual_clock)
g_dual_clock => g_dual_clock,
g_implementation_hint => g_implementation_hint )
port map(
rst_n_i => rst_n_i,
clka_i => clka_i,
......
......@@ -19,7 +19,9 @@ entity generic_spram is
-- RAM read-on-write conflict resolution. Can be "read_first" (read-then-write)
-- or "write_first" (write-then-read)
g_addr_conflict_resolution : string := "write_first";
g_init_file : string := ""
g_init_file : string := "";
g_implementation_hint : string := "auto"
);
port (
......@@ -59,7 +61,10 @@ architecture syn of generic_spram is
signal s_ram_in : std_logic_vector(g_data_width-1 downto 0);
signal s_ram_out : std_logic_vector(g_data_width-1 downto 0);
attribute ram_type : string;
attribute ram_type of ram : signal is g_implementation_hint;
begin
assert (g_init_file = "" or g_init_file = "none")
......
......@@ -31,6 +31,8 @@ modules = { "local" : [
"wbgen2",
"wbgenplus",
"wb_xc7_fw_update",
"wb_lm32_mcs",
"wb_clock_monitor"
]}
files = [
......
files = [
"clock_monitor_wbgen2_pkg.vhd",
"clock_monitor_wb.vhd",
"xwb_clock_monitor.vhd"];
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for Clock Frequency Monitor
---------------------------------------------------------------------------------------
-- File : clock_monitor_wb.vhd
-- Author : auto-generated by wbgen2 from clock_monitor_wb.wb
-- Created : Mon Jun 17 18:28:42 2019
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE clock_monitor_wb.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.cm_wbgen2_pkg.all;
entity clock_monitor_wb is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
int_o : out std_logic;
regs_i : in t_cm_in_registers;
regs_o : out t_cm_out_registers
);
end clock_monitor_wb;
architecture syn of clock_monitor_wb is
signal cm_cr_cnt_rst_dly0 : std_logic ;
signal cm_cr_cnt_rst_int : std_logic ;
signal cm_cr_presc_int : std_logic_vector(7 downto 0);
signal cm_cr_refsel_int : std_logic_vector(3 downto 0);
signal cm_refdr_refdr_int : std_logic_vector(31 downto 0);
signal cm_cnt_sel_sel_int : std_logic_vector(3 downto 0);
signal ack_sreg : std_logic_vector(9 downto 0);
signal rddata_reg : std_logic_vector(31 downto 0);
signal wrdata_reg : std_logic_vector(31 downto 0);
signal bwsel_reg : std_logic_vector(3 downto 0);
signal rwaddr_reg : std_logic_vector(1 downto 0);
signal ack_in_progress : std_logic ;
signal wr_int : std_logic ;
signal rd_int : std_logic ;
signal allones : std_logic_vector(31 downto 0);
signal allzeros : std_logic_vector(31 downto 0);
begin
-- Some internal signals assignments
wrdata_reg <= slave_i.dat;
--
-- Main register bank access process.
process (clk_sys_i, rst_n_i)
begin
if (rst_n_i = '0') then
ack_sreg <= "0000000000";
ack_in_progress <= '0';
rddata_reg <= "00000000000000000000000000000000";
cm_cr_cnt_rst_int <= '0';
cm_cr_presc_int <= "00000000";
cm_cr_refsel_int <= "0000";
cm_refdr_refdr_int <= "00000000000000000000000000000000";
cm_cnt_sel_sel_int <= "0000";
regs_o.cnt_val_valid_load_o <= '0';
elsif rising_edge(clk_sys_i) then
-- advance the ACK generator shift register
ack_sreg(8 downto 0) <= ack_sreg(9 downto 1);
ack_sreg(9) <= '0';
if (ack_in_progress = '1') then
if (ack_sreg(0) = '1') then
cm_cr_cnt_rst_int <= '0';
regs_o.cnt_val_valid_load_o <= '0';
ack_in_progress <= '0';
else
regs_o.cnt_val_valid_load_o <= '0';
end if;
else
if ((slave_i.cyc = '1') and (slave_i.stb = '1')) then
case rwaddr_reg(1 downto 0) is
when "00" =>
if (slave_i.we = '1') then
cm_cr_cnt_rst_int <= wrdata_reg(0);
cm_cr_presc_int <= wrdata_reg(8 downto 1);
cm_cr_refsel_int <= wrdata_reg(12 downto 9);
end if;
rddata_reg(0) <= '0';
rddata_reg(8 downto 1) <= cm_cr_presc_int;
rddata_reg(12 downto 9) <= cm_cr_refsel_int;
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(2) <= '1';
ack_in_progress <= '1';
when "01" =>
if (slave_i.we = '1') then
cm_refdr_refdr_int <= wrdata_reg(31 downto 0);
end if;
rddata_reg(31 downto 0) <= cm_refdr_refdr_int;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "10" =>
if (slave_i.we = '1') then
cm_cnt_sel_sel_int <= wrdata_reg(3 downto 0);
end if;
rddata_reg(3 downto 0) <= cm_cnt_sel_sel_int;
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "11" =>
if (slave_i.we = '1') then
regs_o.cnt_val_valid_load_o <= '1';
end if;
rddata_reg(30 downto 0) <= regs_i.cnt_val_value_i;
rddata_reg(31) <= regs_i.cnt_val_valid_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when others =>
-- prevent the slave from hanging the bus on invalid address
ack_in_progress <= '1';
ack_sreg(0) <= '1';
end case;
end if;
end if;
end if;
end process;
-- Drive the data output bus
slave_o.dat <= rddata_reg;
-- Reset counters
process (clk_sys_i, rst_n_i)
begin
if (rst_n_i = '0') then
cm_cr_cnt_rst_dly0 <= '0';
regs_o.cr_cnt_rst_o <= '0';
elsif rising_edge(clk_sys_i) then
cm_cr_cnt_rst_dly0 <= cm_cr_cnt_rst_int;
regs_o.cr_cnt_rst_o <= cm_cr_cnt_rst_int and (not cm_cr_cnt_rst_dly0);
end if;
end process;
-- Prescaler
regs_o.cr_presc_o <= cm_cr_presc_int;
-- Reference Select
regs_o.cr_refsel_o <= cm_cr_refsel_int;
-- Reference Division Ratio
regs_o.refdr_refdr_o <= cm_refdr_refdr_int;
-- Counter Select
regs_o.cnt_sel_sel_o <= cm_cnt_sel_sel_int;
-- Counter Value
-- Counter Value Valid/Clear
regs_o.cnt_val_valid_o <= wrdata_reg(31);
rwaddr_reg <= slave_i.adr(3 downto 2);
slave_o.stall <= (not ack_sreg(0)) and (slave_i.stb and slave_i.cyc);
slave_o.err <= '0';
slave_o.rty <= '0';
-- ACK signal generation. Just pass the LSB of ACK counter.
slave_o.ack <= ack_sreg(0);
end syn;
-- -*- Mode: LUA; tab-width: 2 -*-
peripheral {
name = "Clock Frequency Monitor";
hdl_entity = "clock_monitor_wb";
prefix = "cm";
reg {
name = "Control Register";
prefix = "CR";
field {
name = "Reset counters";
description = "write 1: resets the counters\
write 0: no effect";
prefix = "CNT_RST";
type = MONOSTABLE;
};
field {
name = "Prescaler";
prefix = "PRESC";
type = SLV;
size = 8;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Reference Select";
prefix = "REFSEL"; -- 0..n-1: channel n, 14:ext PPS, 15:system clock
type = SLV;
size = 4;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Reference Divider Register";
prefix = "REFDR";
field {
name = "Reference Division Ratio";
prefix = "REFDR";
type = SLV;
size = 32;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Counter Select Register";
prefix = "CNT_SEL";
field {
name = "Counter Select";
prefix = "SEL";
type = SLV;
size = 4;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Counter Value Register";
prefix = "CNT_VAL";
field {
name = "Counter Value";
prefix = "VALUE";
type = SLV;
size = 31;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "Counter Value Valid/Clear";
prefix = "VALID";
type = BIT;
size = 1;
access_bus = READ_WRITE;
access_dev = READ_WRITE;
load = LOAD_EXT;
};
};
};
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for Clock Frequency Monitor
---------------------------------------------------------------------------------------
-- File : clock_monitor_wbgen2_pkg.vhd
-- Author : auto-generated by wbgen2 from clock_monitor_wb.wb
-- Created : Mon Jun 17 18:28:42 2019
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE clock_monitor_wb.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
package cm_wbgen2_pkg is
-- Input registers (user design -> WB slave)
type t_cm_in_registers is record
cnt_val_value_i : std_logic_vector(30 downto 0);
cnt_val_valid_i : std_logic;
end record;
constant c_cm_in_registers_init_value: t_cm_in_registers := (
cnt_val_value_i => (others => '0'),
cnt_val_valid_i => '0'
);
-- Output registers (WB slave -> user design)
type t_cm_out_registers is record
cr_cnt_rst_o : std_logic;
cr_presc_o : std_logic_vector(7 downto 0);
cr_refsel_o : std_logic_vector(3 downto 0);
refdr_refdr_o : std_logic_vector(31 downto 0);
cnt_sel_sel_o : std_logic_vector(3 downto 0);
cnt_val_valid_o : std_logic;
cnt_val_valid_load_o : std_logic;
end record;
constant c_cm_out_registers_init_value: t_cm_out_registers := (
cr_cnt_rst_o => '0',
cr_presc_o => (others => '0'),
cr_refsel_o => (others => '0'),
refdr_refdr_o => (others => '0'),
cnt_sel_sel_o => (others => '0'),
cnt_val_valid_o => '0',
cnt_val_valid_load_o => '0'
);
function "or" (left, right: t_cm_in_registers) return t_cm_in_registers;
function f_x_to_zero (x:std_logic) return std_logic;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector;
component clock_monitor_wb is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
int_o : out std_logic;
regs_i : in t_cm_in_registers;
regs_o : out t_cm_out_registers
);
end component;
end package;
package body cm_wbgen2_pkg is
function f_x_to_zero (x:std_logic) return std_logic is
begin
if x = '1' then
return '1';
else
return '0';
end if;
end function;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector is
variable tmp: std_logic_vector(x'length-1 downto 0);
begin
for i in 0 to x'length-1 loop
if(x(i) = 'X' or x(i) = 'U') then
tmp(i):= '0';
else
tmp(i):=x(i);
end if;
end loop;
return tmp;
end function;
function "or" (left, right: t_cm_in_registers) return t_cm_in_registers is
variable tmp: t_cm_in_registers;
begin
tmp.cnt_val_value_i := f_x_to_zero(left.cnt_val_value_i) or f_x_to_zero(right.cnt_val_value_i);
tmp.cnt_val_valid_i := f_x_to_zero(left.cnt_val_valid_i) or f_x_to_zero(right.cnt_val_valid_i);
return tmp;
end function;
end package body;
--------------------------------------------------------------------------------
-- CERN BE-CEM-EDL
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: xwb_clock_monitor
--
-- description: Multichannel clock frequency monitor with Wishbone interface.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2020-2021
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
use work.cm_wbgen2_pkg.all;
entity xwb_clock_monitor is
generic (
g_NUM_CLOCKS : integer := 1;
g_CLK_SYS_FREQ : integer := 62500000;
g_WITH_INTERNAL_TIMEBASE : boolean := TRUE
);
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
clk_in_i : in std_logic_vector(g_num_clocks-1 downto 0);
pps_p1_i : in std_logic := '0';
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out
);
end xwb_clock_monitor;
architecture rtl of xwb_clock_monitor is
signal regs_in : t_cm_in_registers;
signal regs_out : t_cm_out_registers;
type t_clock_state is record
presc_cnt : unsigned(4 downto 0);
clk_in : std_logic;
clk_presc : std_logic;
pulse : std_logic;
counter : unsigned(30 downto 0);
valid_sreg : std_logic_vector(1 downto 0);
freq : unsigned(30 downto 0);
ack : std_logic;
end record;
type t_clock_state_array is array (integer range <>) of t_clock_state;
signal clks : t_clock_state_array(0 to g_num_clocks);
signal rst_n_a : std_logic;
signal ref_pulse_p : std_logic;
signal gate_p : std_logic;
signal gate_cnt : unsigned(31 downto 0);
signal pps_p_sysclk : std_logic;
signal cntr_gate : unsigned(30 downto 0) := (others => '0');
signal gate_pulse, gate_pulse_synced : std_logic := '0';
begin
gen_ext_pps : if g_WITH_INTERNAL_TIMEBASE = false generate
U_PPS_Pulse_Detect : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_i,
data_i => pps_p1_i,
ppulse_o => pps_p_sysclk);
end generate gen_ext_pps;
gen_int_pps : if g_WITH_INTERNAL_TIMEBASE = true generate
p_gate_counter : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
cntr_gate <= (others => '0');
pps_p_sysclk <= '0';
else
if cntr_gate = g_CLK_SYS_FREQ-1 then
cntr_gate <= (others => '0');
pps_p_sysclk <= '1';
else
cntr_gate <= cntr_gate + 1;
pps_p_sysclk <= '0';
end if;
end if;
end if;
end process;
end generate gen_int_pps;
process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' or regs_out.cr_cnt_rst_o = '1' then
gate_cnt <= (others => '0');
gate_p <= '0';
else
ref_pulse_p <= clks(to_integer(unsigned(regs_out.cr_refsel_o))).pulse;
if unsigned(regs_out.cr_refsel_o) /= 15 then
if ref_pulse_p = '1' then
if gate_cnt = unsigned(regs_out.refdr_refdr_o) then
gate_cnt <= (others => '0');
gate_p <= '1';
else
gate_cnt <= gate_cnt + 1;
gate_p <= '0';
end if;
else
gate_p <= '0';
end if;
else
gate_p <= pps_p_sysclk;
end if;
end if;
end if;
end process;
rst_n_a <= rst_n_i;
U_WB_Slave : entity work.clock_monitor_wb
port map (
rst_n_i => rst_n_i,
clk_sys_i => clk_sys_i,
slave_i => slave_i,
slave_o => slave_o,
regs_i => regs_in,
regs_o => regs_out);
clks(g_num_clocks).clk_in <= clk_sys_i;
gen1 : for i in 0 to g_num_clocks-1 generate
clks(i).clk_in <= clk_in_i(i);
end generate gen1;
gen2 : for i in 0 to g_num_clocks generate
p_clk_prescaler : process(clks(i).clk_in, rst_n_a)
begin
if rst_n_a = '0' then
clks(i).presc_cnt <= (others => '0');
clks(i).clk_presc <= '0';
elsif rising_edge(clks(i).clk_in) then
if(clks(i).presc_cnt = unsigned(regs_out.cr_presc_o)) then
clks(i).presc_cnt <= (others => '0');
clks(i).clk_presc <= not clks(i).clk_presc;
else
clks(i).presc_cnt <= clks(i).presc_cnt + 1;
end if;
end if;
end process;
U_Edge_Detect : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_i,
data_i => clks(i).clk_presc,
ppulse_o => clks(i).pulse);
end generate gen2;
gen3 : for i in 0 to g_num_clocks generate
p_counter : process(clk_sys_i)
variable cnt_idx : integer range 0 to g_num_clocks;
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' or regs_out.cr_cnt_rst_o = '1' then
clks(i).counter <= (others => '0');
clks(i).valid_sreg <= (others => '0');
else
if(gate_p = '1') then
clks(i).valid_sreg <= clks(i).valid_sreg(0) & '1';
clks(i).freq <= clks(i).counter;
clks(i).counter <= (others => '0');
elsif clks(i).pulse = '1' then
clks(i).counter <= clks(i).counter + 1;
end if;
if clks(i).ack = '1' then
clks(i).valid_sreg(1) <= '0';
end if;
cnt_idx := to_integer(unsigned(regs_out.cnt_sel_sel_o));
if (i = cnt_idx) then
clks(i).ack <= regs_out.cnt_val_valid_o and regs_out.cnt_val_valid_load_o;
else
clks(i).ack <= '0';
end if;
end if;
end if;
end process;
end generate gen3;
p_regs : process(clk_sys_i)
variable cnt_idx : integer range 0 to g_num_clocks;
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
regs_in.cnt_val_valid_i <= '0';
else
cnt_idx := to_integer(unsigned(regs_out.cnt_sel_sel_o));
regs_in.cnt_val_value_i <= std_logic_vector(clks(cnt_idx).freq);
regs_in.cnt_val_valid_i <= clks(cnt_idx).valid_sreg(1);
end if;
end if;
end process;
end rtl;
files = [ "xwb_lm32_mcs.vhd" ];
--------------------------------------------------------------------------------
-- CERN BE-CEM-EDL
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: xwb_lm32_mcs
--
-- description: A minimal embedded microcontroller with some amount of RAM,
-- UART and a Wishbone bus for user peripherals. The code can
-- be preloaded or loaded on-the-fly through the Wishbone system bus.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2020-2021
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
use work.wishbone_pkg.all;
entity xwb_lm32_mcs is
generic(
-- size of the code/data memory in bytes
g_iram_size : integer;
-- timeout (in clock cycles) for the Wishbone master.
-- exceeding the timeout (e.g. due to an incorrect address/
-- unresponsive slave) causes a WB error after g_bus_timeout cycles.
g_bus_timeout : integer := 30;
-- file (.bram format) with the firmware to pre-load during synthesis.
g_preload_firmware : string := "";
-- Enable host interface (allows loading code from a system bus)
g_with_host_if : boolean := true;
-- Enable Virtual UART (serial console accessible from the system bus)
g_with_vuart : boolean := true
);
port(
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
irq_i : in std_logic_vector(31 downto 0) := x"00000000";
host_wb_i : in t_wishbone_slave_in := cc_dummy_slave_in;
host_wb_o : out t_wishbone_slave_out;
dbg_txd_o : out std_logic;
dbg_rxd_i : in std_logic := '0';
dwb_o : out t_wishbone_master_out;
dwb_i : in t_wishbone_master_in
);
end xwb_lm32_mcs;
architecture wrapper of xwb_lm32_mcs is
signal CONTROL0 : std_logic_vector(35 downto 0);
signal TRIG0 : std_logic_vector(31 downto 0);
signal TRIG1 : std_logic_vector(31 downto 0);
signal TRIG2 : std_logic_vector(31 downto 0);
signal TRIG3 : std_logic_vector(31 downto 0);
component chipscope_icon is
port (
CONTROL0 : inout std_logic_vector(35 downto 0));
end component chipscope_icon;
component chipscope_ila is
port (
CONTROL : inout std_logic_vector(35 downto 0);
CLK : in std_logic;
TRIG0 : in std_logic_vector(31 downto 0);
TRIG1 : in std_logic_vector(31 downto 0);
TRIG2 : in std_logic_vector(31 downto 0);
TRIG3 : in std_logic_vector(31 downto 0));
end component chipscope_ila;
constant c_iram_addr_width : integer := f_log2_size(g_iram_size)-2;
component lm32_cpu_wr_node is
generic (
eba_reset : std_logic_vector(31 downto 0) := x"00000000"
);
port (
clk_i : in std_logic;
enable_i : in std_logic := '1';
rst_i : in std_logic;
interrupt : in std_logic_vector(31 downto 0) := x"00000000";
-- dbg_csr_write_enable_i : in std_logic := '0';
-- dbg_csr_write_data_i : in std_logic_vector(31 downto 0) := x"00000000";
-- dbg_csr_addr_i : in std_logic_vector(4 downto 0) := "00000";
-- dbg_exception_o : out std_logic;
-- dbg_reset_i : in std_logic := '0';
-- dbg_break_i : in std_logic := '0';
iram_i_adr_o : out std_logic_vector(31 downto 0);
iram_i_dat_i : in std_logic_vector(31 downto 0);
iram_i_en_o : out std_logic;
iram_d_adr_o : out std_logic_vector(31 downto 0);
iram_d_dat_o : out std_logic_vector(31 downto 0);
iram_d_dat_i : in std_logic_vector(31 downto 0);
iram_d_sel_o : out std_logic_vector(3 downto 0);
iram_d_we_o : out std_logic;
iram_d_en_o : out std_logic;
D_DAT_O : out std_logic_vector(31 downto 0);
D_ADR_O : out std_logic_vector(31 downto 0);
D_CTI_O : out std_logic_vector(2 downto 0);
D_BTE_O : out std_logic_vector(1 downto 0);
D_lock_o: out std_logic;
D_CYC_O : out std_logic;
D_SEL_O : out std_logic_vector(3 downto 0);
D_STB_O : out std_logic;
D_WE_O : out std_logic;
D_DAT_I : in std_logic_vector(31 downto 0);
D_ACK_I : in std_logic;
D_ERR_I : in std_logic := '0';
D_RTY_I : in std_logic := '0'
);
end component;
function f_x_to_zero (x : std_logic_vector) return std_logic_vector is
variable tmp : std_logic_vector(x'length-1 downto 0);
begin
-- synthesis translate_off
for i in 0 to x'length-1 loop
if(x(i) = 'X' or x(i) = 'U') then
tmp(i) := '0';
else
tmp(i) := x(i);
end if;
end loop;
return tmp;
-- synthesis translate_on
return x;
end function;
constant c_cnx_slave_ports : integer := 1;
constant c_cnx_master_ports : integer := 2;
constant c_master_host : integer := 0;
constant c_slave_csr : integer := 0;
constant c_slave_vuart : integer := 1;
signal cnx_slave_in : t_wishbone_slave_in_array(c_cnx_slave_ports-1 downto 0);
signal cnx_slave_out : t_wishbone_slave_out_array(c_cnx_slave_ports-1 downto 0);
signal cnx_master_in : t_wishbone_master_in_array(c_cnx_master_ports-1 downto 0);
signal cnx_master_out : t_wishbone_master_out_array(c_cnx_master_ports-1 downto 0);
constant c_cfg_base_addr : t_wishbone_address_array(c_cnx_master_ports-1 downto 0) :=
(c_slave_csr => x"00000000",
c_slave_vuart => x"00000040"
);
constant c_cfg_base_mask : t_wishbone_address_array(c_cnx_master_ports-1 downto 0) :=
(c_slave_csr => x"00000040",
c_slave_vuart => x"00000040"
);
signal cpu_reset, cpu_enable, cpu_enable_init, cpu_reset_n : std_logic;
signal d_adr : std_logic_vector(31 downto 0);
signal core_sel_match : std_logic;
signal iram_i_wr, iram_d_wr : std_logic;
signal iram_i_en, iram_i_en_cpu, iram_d_en : std_logic;
signal iram_i_adr_cpu, iram_d_adr : std_logic_vector(31 downto 0);
signal udata_addr, iram_i_adr, iram_i_adr_host : std_logic_vector(f_log2_size(g_iram_size)-3 downto 0);
signal iram_i_dat_q, iram_i_dat_d, iram_d_dat_d, iram_d_dat_q : std_logic_vector(31 downto 0);
signal iram_d_sel : std_logic_vector(3 downto 0);
signal cpu_dwb_out, cpu_dwb_out_sys : t_wishbone_master_out;
signal cpu_dwb_in, cpu_dwb_in_sys : t_wishbone_master_in;
signal dwb_out : t_wishbone_master_out;
signal bus_timeout : unsigned(7 downto 0);
signal bus_timeout_hit : std_logic;
signal host_slave_in : t_wishbone_slave_in;
signal host_slave_out : t_wishbone_slave_out;
signal cpu_csr_udata_out, cpu_csr_uaddr_addr, cpu_csr_udata_in : std_logic_vector(31 downto 0);
signal cpu_csr_udata_load : std_logic;
attribute keep : string;
attribute keep of dwb_i : signal is "true";
attribute keep of cpu_dwb_in_sys : signal is "true";
begin
U_CPU : lm32_cpu_wr_node
generic map (
eba_reset => x"00000000")
port map (
clk_i => clk_sys_i,
rst_i => cpu_reset,
interrupt => irq_i,
-- instruction bus
iram_i_adr_o => iram_i_adr_cpu,
iram_i_dat_i => iram_i_dat_q,
iram_i_en_o => iram_i_en_cpu,
-- data bus (IRAM)
iram_d_adr_o => iram_d_adr,
iram_d_dat_o => iram_d_dat_d,
iram_d_dat_i => iram_d_dat_q,
iram_d_sel_o => iram_d_sel,
iram_d_we_o => iram_d_wr,
iram_d_en_o => iram_d_en,
D_DAT_O => cpu_dwb_out.dat,
D_ADR_O => cpu_dwb_out.adr,
D_CYC_O => cpu_dwb_out.cyc,
D_SEL_O => cpu_dwb_out.sel,
D_STB_O => cpu_dwb_out.stb,
D_WE_O => cpu_dwb_out.we,
D_DAT_I => cpu_dwb_in.dat,
D_ACK_I => cpu_dwb_in.ack,
D_ERR_I => cpu_dwb_in.err,
D_RTY_I => cpu_dwb_in.rty);
cpu_dwb_in.dat <= f_x_to_zero(cpu_dwb_in_sys.dat);
cpu_dwb_in.ack <= cpu_dwb_in_sys.ack;
cpu_dwb_in.stall <= cpu_dwb_in_sys.stall;
cpu_dwb_in.rty <= '0';
cpu_dwb_in.err <= bus_timeout_hit or cpu_dwb_in_sys.err;
cpu_dwb_out_sys <= cpu_dwb_out;
p_timeout_counter : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if cpu_reset = '1' or cpu_dwb_out.cyc = '0' or (cpu_dwb_in.ack = '1' and cpu_dwb_out.cyc = '1') then
bus_timeout <= (others => '0');
bus_timeout_hit <= '0';
elsif (bus_timeout /= g_bus_timeout) then
bus_timeout <= bus_timeout + 1;
bus_timeout_hit <= '0';
else
bus_timeout_hit <= '1';
end if;
end if;
end process;
inst_iram : generic_dpram_split
generic map (
g_size => g_iram_size/4,
g_addr_conflict_resolution => "dont_care",
g_init_file => g_preload_firmware,
g_fail_if_file_not_found => true )
port map (
rst_n_i => rst_n_i,
clk_i => clk_sys_i,
bwea_i => "1111",
wea_i => iram_i_wr,
aa_i => iram_i_adr,
da_i => iram_i_dat_d,
qa_o => iram_i_dat_q,
bweb_i => iram_d_sel,
web_i => iram_d_wr,
ab_i => iram_d_adr(f_log2_size(g_iram_size)-1 downto 2),
db_i => iram_d_dat_d,
qb_o => iram_d_dat_q);
iram_i_dat_d <= cpu_csr_udata_out;
iram_i_wr <= cpu_csr_udata_load;
iram_i_adr <= cpu_csr_uaddr_addr(f_log2_size(g_iram_size)-3 downto 0) when cpu_enable = '0' else
iram_i_adr_cpu(f_log2_size(g_iram_size)-1 downto 2);
iram_i_en <= '1' when cpu_enable = '0' else iram_i_en_cpu;
cpu_csr_udata_in <= iram_i_dat_q;
U_Classic2Pipe : wb_slave_adapter
generic map (
g_master_use_struct => true,
g_master_mode => PIPELINED,
g_master_granularity => BYTE,
g_slave_use_struct => true,
g_slave_mode => CLASSIC,
g_slave_granularity => BYTE)
port map (
clk_sys_i => clk_sys_i,
rst_n_i => rst_n_i,
slave_i => cpu_dwb_out_sys,
slave_o => cpu_dwb_in_sys,
master_i => dwb_i,
master_o => dwb_out);
dwb_o <= dwb_out;
cpu_reset <= not rst_n_i or (not cpu_enable);
cpu_reset_n <= not cpu_reset;
cnx_slave_in(c_master_host) <= host_wb_i;
host_wb_o <= cnx_slave_out(c_master_host);
U_Intercon : xwb_crossbar
generic map (
g_num_masters => c_cnx_slave_ports,
g_num_slaves => c_cnx_master_ports,
g_registered => true,
g_address => c_cfg_base_addr,
g_mask => c_cfg_base_mask)
port map (
clk_sys_i => clk_sys_i,
rst_n_i => rst_n_i,
slave_i => cnx_slave_in,
slave_o => cnx_slave_out,
master_i => cnx_master_in,
master_o => cnx_master_out);
U_UART : xwb_simple_uart
generic map (
g_with_virtual_uart => true,
g_with_physical_uart => true,
g_interface_mode => PIPELINED,
g_address_granularity => BYTE,
g_vuart_fifo_size => 1024)
port map (
clk_sys_i => clk_sys_i,
rst_n_i => rst_n_i,
slave_i => cnx_master_out(c_slave_vuart),
slave_o => cnx_master_in(c_slave_vuart),
uart_rxd_i => dbg_rxd_i,
uart_txd_o => dbg_txd_o);
iram_i_dat_d <= cpu_csr_udata_out;
iram_i_wr <= cpu_csr_udata_load;
iram_i_adr <= cpu_csr_uaddr_addr(f_log2_size(g_iram_size)-3 downto 0) when cpu_enable = '0' else
iram_i_adr_cpu(f_log2_size(g_iram_size)-1 downto 2);
iram_i_en <= '1' when cpu_enable = '0' else iram_i_en_cpu;
cpu_csr_udata_in <= iram_i_dat_q;
host_slave_in <= cnx_master_out(c_slave_csr);
cnx_master_in(c_slave_csr) <= host_slave_out;
p_local_regs : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
cpu_csr_udata_load <= '0';
cpu_enable <= '0';
cpu_csr_uaddr_addr <= (others => '0');
host_slave_out.ack <= '0';
host_slave_out.err <= '0';
host_slave_out.rty <= '0';
host_slave_out.stall <= '0';
cpu_enable_init <= '0';
else
cpu_csr_udata_load <= '0';
host_slave_out.ack <= '0';
if g_preload_firmware /= "" and cpu_enable_init = '0' then
cpu_enable <= '1';
cpu_enable_init <= '1';
end if;
if host_slave_in.cyc = '1' and host_slave_in.stb = '1' then
host_slave_out.ack <= '1';
if host_slave_in.we = '1' then
case host_slave_in.adr(3 downto 0) is
when "0000" => -- csr
cpu_enable <= host_slave_in.dat(0);
when "0100" => -- data
cpu_csr_udata_out <= host_slave_in.dat;
cpu_csr_udata_load <= '1';
when "1000" => -- addr
cpu_csr_uaddr_addr <= host_slave_in.dat;
when others => null;
end case;
else
case host_slave_in.adr(3 downto 0) is
when "0000" =>
host_slave_out.dat(0) <= cpu_enable;
host_slave_out.dat(31 downto 1) <= std_logic_vector(to_unsigned(g_iram_size, 31));
when "0100" =>
host_slave_out.dat <= cpu_csr_udata_in;
when others => null;
end case;
end if;
end if;
end if;
end if;
end process;
-- chipscope_icon_1 : chipscope_icon
-- port map (
-- CONTROL0 => CONTROL0);
-- chipscope_ila_1 : chipscope_ila
-- port map (
-- CONTROL => CONTROL0,
-- CLK => clk_sys_i,
-- TRIG0 => TRIG0,
-- TRIG1 => TRIG1,
-- TRIG2 => TRIG2,
-- TRIG3 => TRIG3);
trig0(31 downto 0) <= cnx_master_in(c_slave_vuart).dat;
trig1(31 downto 0) <= cnx_master_out(c_slave_vuart).dat;
trig2(16) <= cnx_master_out(c_slave_vuart).cyc;
trig2(17) <= cnx_master_out(c_slave_vuart).stb;
trig2(18) <= cnx_master_out(c_slave_vuart).we;
trig2(19) <= cnx_master_in(c_slave_vuart).stall;
trig2(20) <= cnx_master_in(c_slave_vuart).ack;
trig3 <= cnx_master_out(c_slave_vuart).adr;
end wrapper;
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
# This Makefile can be called by the Continuous Integration (CI) tool to execute all
# testbenches added for CI
# AXI4 cores
TB_DIRS+=axi/axi4lite_wb_bridge
TB_DIRS+=axi/z7_axi_gpio_expander
TB_DIRS+=axi/axi4lite32_axi4full64_bridge
TB_DIRS+=axi/axi4lite_axi4full_bridge
.PHONY: $(TB_DIRS)
all: $(TB_DIRS) summary
$(TB_DIRS):
@echo "Run HDLMAKE"
@cd "$@"; \
hdlmake 2>&1
@echo "Run make"
@$(MAKE) -C $@ $(TARGET)
@echo "Run ghdl"
@cd "$@" ;\
./run.sh
@echo "ghdl returned $$?"
summary: $(TB_DIRS)
@echo "-------------------------------------------------------------------"
@echo "Summary:"
@for d in $(TB_DIRS); do \
if [ -f $$d/transcript ]; then \
echo "Warnings for $$d:"; \
cat $$d/transcript | grep Warning; \
if [ $$? -eq 1 ]; then echo "None"; fi ;\
echo "Errors for $$d:"; \
cat $$d/transcript | grep Error; \
if [ $$? -eq 1 ]; then echo "None"; fi ;\
else \
echo "No transcript file for $$d"; \
fi \
done
clean:
@for d in $(TB_DIRS); do \
if [ -f $$d/Makefile ]; then \
$(MAKE) -C $$d $@; \
rm -f $$d/Makefile; \
fi \
done
# Description
The majority of the general cores have their own testbench written in VHDL and as a verification methodology, OSVVM is used. There are also some testbenches which are written in SystemVerilog.
The common features of each test are:
- Randomization of the input signals
- FSM coverage (when there are FSM in the RTL design), results are shown at the end of the simulation
- Assertions are used to verify aspects of the core's functionality, cumply with the specifications
There are two options for the users, in order to run these tests. First is to run them all by using the Makefile in the current directory. This Makefile contains all the VHDL tests. Second option, is to run each test individually.
## Requirements
- [hdlmake](https://hdlmake.readthedocs.io/en/master/#install-hdlmake-package)
- [ghdl](https://ghdl.github.io/ghdl/development/building/index.html#build)
## Set up environment
- OSVVM is a dependency for most of these testbenches. It is already included as a git submodule. Therefore, it is necessary to run at least once `git submodule update --init` before running these testbenches.
## How to test
```console
hdlmake makefile
make
./run.sh
```
Waveform option:
```console
./run.sh --wave=waveform.ghw
```
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
*
!.gitignore
!Manifest.py
!*.vhd
!*.cheby
!run.sh
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
action="simulation"
sim_tool="ghdl"
target="generic"
ghdl_opt="--std=08 -frelaxed-rules -Wno-hide"
sim_top="tb_axi4lite32_axi4full64_bridge"
files="tb_axi4lite32_axi4full64_bridge.vhd"
modules={"local" : ["../../../",
"../../osvvm/",
"../../../modules/wishbone",
"../../../modules/axi"]}
## Description
Testbench for [axi4lite32_axi4full64_bridge](../../modules/axi/axi4lite32_axi4full64_bridge/axi4lite32_axi4full64_bridge.vhd) which is a bridge from AXI4Lite32 to AXI4Full64. Master is the axi4lite and the slave is axi4full.
NOTE: By default, the simulation time is 4ms. For any change in this, run the test and pass the simulation time as an argument to this script:
```console
./run.sh <simulation time>
```
#!/bin/bash -e
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
#This is a simple script to run simulations in GHDL
TB=tb_axi4lite32_axi4full64_bridge
if [ -z "$1" ]; then
TIME="4"
else
TIME="$1"
fi;
echo "Running simulation for $TB"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_sim_time=$TIME
-------------------------------------------------------------------------------
-- SPDX-FileCopyrightText: 2023 CERN (home.cern)
--
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
-------------------------------------------------------------------------------
-- Title : Testbench for AXI4Full64 to AXI4Lite32 bridge
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : tb_axi4lite32_axi4full64_bridge.vhd
-- Author : Konstantinos Blantos
-- Company : CERN (BE-CEM-EDL)
-- Platform : FPGA-generics
-- Standard : VHDL '08
-------------------------------------------------------------------------------
--=============================================================================
-- Libraries & Packages --
--=============================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
--=============================================================================
-- Entity declaration for tb_axi4lite32_axi4full64_bridge --
--=============================================================================
entity tb_axi4lite32_axi4full64_bridge is
generic (
g_seed : natural;
g_sim_time : natural);
end entity;
--==============================================================================
-- Architecture declaration --
--==============================================================================
architecture tb of tb_axi4lite32_axi4full64_bridge is
--==========================================================
-- constants
--==========================================================
constant C_CLK_PERIOD : time := 10 ns;
constant C_SIM_TIME : time := (g_sim_time*1.0 ms);
constant RSP_OKAY : std_logic_vector(1 downto 0) := b"00";
constant RSP_EXOKAY : std_logic_vector(1 downto 0) := b"01";
constant RSP_SLVERR : std_logic_vector(1 downto 0) := b"10";
constant RSP_DECERR : std_logic_vector(1 downto 0) := b"11";
--==========================================================
-- Signals
--==========================================================
signal tb_clk_i : std_logic;
signal tb_rst_n_i : std_logic;
-- AXI4-Full slave
signal tb_s_awaddr : std_logic_vector (31 downto 0);
signal tb_s_awlen : std_logic_vector (7 downto 0);
signal tb_s_awsize : std_logic_vector (2 downto 0);
signal tb_s_awburst : std_logic_vector (1 downto 0);
signal tb_s_awvalid : std_logic;
signal tb_s_awready : std_logic;
signal tb_s_wdata : std_logic_vector (63 downto 0);
signal tb_s_wstrb : std_logic_vector (7 downto 0);
signal tb_s_wlast : std_logic;
signal tb_s_wvalid : std_logic;
signal tb_s_wready : std_logic;
signal tb_s_bresp : std_logic_vector (1 downto 0);
signal tb_s_bvalid : std_logic;
signal tb_s_bready : std_logic;
signal tb_s_araddr : std_logic_vector (31 downto 0);
signal tb_s_arlen : std_logic_vector (7 downto 0);
signal tb_s_arsize : std_logic_vector (2 downto 0);
signal tb_s_arburst : std_logic_vector (1 downto 0);
signal tb_s_arvalid : std_logic;
signal tb_s_arready : std_logic;
signal tb_s_rdata : std_logic_vector (63 downto 0);
signal tb_s_rresp : std_logic_vector (1 downto 0);
signal tb_s_rlast : std_logic;
signal tb_s_rvalid : std_logic;
signal tb_s_rready : std_logic;
-- AXI4-Lite master
signal tb_m_awaddr : std_logic_vector (31 downto 0);
signal tb_m_awvalid : std_logic;
signal tb_m_awready : std_logic;
signal tb_m_wdata : std_logic_vector (31 downto 0);
signal tb_m_wstrb : std_logic_vector (3 downto 0);
signal tb_m_wvalid : std_logic;
signal tb_m_wready : std_logic;
signal tb_m_bresp : std_logic_vector (1 downto 0);
signal tb_m_bvalid : std_logic;
signal tb_m_bready : std_logic;
signal tb_m_araddr : std_logic_vector (31 downto 0);
signal tb_m_arvalid : std_logic;
signal tb_m_arready : std_logic;
signal tb_m_rdata : std_logic_vector (31 downto 0);
signal tb_m_rresp : std_logic_vector (1 downto 0);
signal tb_m_rvalid : std_logic;
signal tb_m_rready : std_logic;
-- other TB signals
signal stop : boolean;
signal s_waddr : std_logic_vector(31 downto 0);
signal s_wlen : std_logic_vector(7 downto 0);
signal s_wsize : std_logic_vector(2 downto 0);
signal s_raddr : std_logic_vector(31 downto 0);
signal s_rlen : std_logic_vector(7 downto 0);
signal s_rsize : std_logic_vector(2 downto 0);
signal s_rdata : std_logic_vector(63 downto 0);
signal s_awvalid : std_logic;
signal s_wvalid : std_logic;
signal s_arvalid : std_logic;
signal s_rready : std_logic;
signal s_m_awready : std_logic;
signal s_m_wready : std_logic;
signal s_bready : std_logic;
signal s_m_bvalid : std_logic;
signal rdata : std_logic_vector(63 downto 0);
signal s_rd_cnt : natural;
signal s_wr_cnt : natural;
signal wdata : std_logic_vector(31 downto 0);
signal s_tmp_wdata : std_logic_vector(63 downto 0);
type t_wr_state is (WR_IDLE,
WR_MASTER, WR_SLAVE, WR_SLAVE2, WR_WAIT, WR_DONE);
type t_rd_state is (RD_IDLE, RD_READ, RD_SLAVE);
signal s_wstate : t_wr_state;
signal s_rstate : t_rd_state;
shared variable sv_cover_wr : covPType;
shared variable sv_cover_rd : covPType;
--=============================================================================
-- Procedures used for fsm coverage
--=============================================================================
-- legal states for Write FSM
procedure fsm_covadd_states_wr (
name : in string;
prev : in t_wr_state;
curr : in t_wr_state;
covdb : inout covPType) is
begin
covdb.AddCross ( name,
GenBin(t_wr_state'pos(prev)),
GenBin(t_wr_state'pos(curr)));
end procedure;
-- legal states for Read FSM
procedure fsm_covadd_states_rd (
name : in string;
prev : in t_rd_state;
curr : in t_rd_state;
covdb : inout covPType) is
begin
covdb.AddCross ( name,
GenBin(t_rd_state'pos(prev)),
GenBin(t_rd_state'pos(curr)));
end procedure;
-- illegal states
procedure fsm_covadd_illegal (
name : in string;
covdb : inout covPType ) is
begin
covdb.AddCross(ALL_ILLEGAL,ALL_ILLEGAL);
end procedure;
-- bin collection for Write FSM
procedure fsm_covcollect_wr (
signal reset : in std_logic;
signal clk : in std_logic;
signal state : in t_wr_state;
covdb : inout covPType) is
variable v_state : t_wr_state := t_wr_state'left;
begin
wait until reset='1';
loop
v_state := state;
wait until rising_edge(clk);
covdb.ICover((t_wr_state'pos(v_state), t_wr_state'pos(state)));
end loop;
end procedure;
-- bin collection for Read FSM
procedure fsm_covcollect_rd (
signal reset : in std_logic;
signal clk : in std_logic;
signal state : in t_rd_state;
covdb : inout covPType) is
variable v_state : t_rd_state := t_rd_state'left;
begin
wait until reset='1';
loop
v_state := state;
wait until rising_edge(clk);
covdb.ICover((t_rd_state'pos(v_state), t_rd_state'pos(state)));
end loop;
end procedure;
begin
-- Unit Under Test
UUT : entity work.axi4lite32_axi4full64_bridge
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
s_awaddr => tb_s_awaddr,
s_awlen => tb_s_awlen,
s_awsize => tb_s_awsize,
s_awburst => tb_s_awburst,
s_awvalid => tb_s_awvalid,
s_awready => tb_s_awready,
s_wdata => tb_s_wdata,
s_wstrb => tb_s_wstrb,
s_wlast => tb_s_wlast,
s_wvalid => tb_s_wvalid,
s_wready => tb_s_wready,
s_bresp => tb_s_bresp,
s_bvalid => tb_s_bvalid,
s_bready => tb_s_bready,
s_araddr => tb_s_araddr,
s_arlen => tb_s_arlen,
s_arsize => tb_s_arsize,
s_arburst => tb_s_arburst,
s_arvalid => tb_s_arvalid,
s_arready => tb_s_arready,
s_rdata => tb_s_rdata,
s_rresp => tb_s_rresp,
s_rlast => tb_s_rlast,
s_rvalid => tb_s_rvalid,
s_rready => tb_s_rready,
m_awaddr => tb_m_awaddr,
m_awvalid => tb_m_awvalid,
m_awready => tb_m_awready,
m_wdata => tb_m_wdata,
m_wstrb => tb_m_wstrb,
m_wvalid => tb_m_wvalid,
m_wready => tb_m_wready,
m_bresp => tb_m_bresp,
m_bvalid => tb_m_bvalid,
m_bready => tb_m_bready,
m_araddr => tb_m_araddr,
m_arvalid => tb_m_arvalid,
m_arready => tb_m_arready,
m_rdata => tb_m_rdata,
m_rresp => tb_m_rresp,
m_rvalid => tb_m_rvalid,
m_rready => tb_m_rready);
-- Clock generation
clk_proc : process
begin
while (not stop) loop
tb_clk_i <= '1';
wait for C_CLK_PERIOD/2;
tb_clk_i <= '0';
wait for C_CLK_PERIOD/2;
end loop;
wait;
end process clk_proc;
-- reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
-- Stimulus
stim : process
variable data : RandomPType;
variable ncycles : natural;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
wait until tb_rst_n_i = '1';
while (NOW < C_SIM_TIME) loop
wait until rising_edge(tb_clk_i);
-- AXI-4 Full inputs
tb_s_awaddr <= data.randSlv(32);
tb_s_awlen <= data.randSlv(0,4,8) when s_wstate=WR_IDLE else (others=>'0');
s_awvalid <= data.randSlv(1)(1);
tb_s_wdata <= data.randSlv(64);
s_wvalid <= data.randSlv(1)(1);
s_bready <= data.randSlv(1)(1);
tb_s_araddr <= data.randSlv(32);
tb_s_arlen <= data.randSlv(0,4,8) when s_rstate=RD_IDLE;
s_arvalid <= data.randSlv(1)(1);
s_rready <= data.randSlv(1)(1);
-- AXI-4 Lite inputs
s_m_awready <= data.randSlv(1)(1);
s_m_wready <= data.randSlv(1)(1);
tb_m_bresp <= data.randSlv(2);
s_m_bvalid <= data.randSlv(1)(1);
tb_m_rdata <= data.randSlv(32);
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= TRUE;
report "Test PASS!";
wait;
end process stim;
-- Based on AMBA AXI4 specification (A3.4)
-- since the size is 64-bit, aXsize="110"
tb_s_awsize <= "110";
tb_s_arsize <= "110";
-- Assign to strobe the default value which
-- means that all byte lanes hold valid data
tb_s_wstrb <= (others=>'1');
-- AXBurst logic not included in RTL core
-- The default value chosen for INCR
tb_s_awburst <= "01";
tb_s_arburst <= "01";
-- Valid/Ready signals generation
-- both for slave and master
tb_s_awvalid <= s_awvalid when s_wstate=WR_IDLE else '0';
tb_s_wvalid <= s_wvalid when s_wstate=WR_MASTER else '0';
tb_s_arvalid <= s_arvalid when s_rstate=RD_IDLE else '0';
tb_s_rready <= s_rready when s_rstate=RD_SLAVE else '0';
tb_s_bready <= s_bready when s_wstate=WR_DONE else '0';
tb_m_bvalid <= s_m_bvalid when s_wstate=WR_WAIT else '0';
-- wlast generation
tb_s_wlast <= '1' when (unsigned(s_wlen)=0 and tb_s_wvalid='1') else '0';
-- AWREADY generation
-- awready is asserted for one clock cycle when both
-- awvalid and wvalid are asserted. awready is
-- de-asserted when reset is low.
process (tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
tb_m_awready <= '0';
else
if tb_m_awready = '0' and tb_m_awvalid = '1' and tb_m_wvalid = '1' then
-- slave is ready to accept write address when
-- there is a valid write address and write data
-- on the write address and data bus.
tb_m_awready <= '1';
else
tb_m_awready <= '0';
end if;
end if;
end if;
end process;
-- WREADY generation
-- wready is asserted for one clock cycle when both
-- awvalid and wvalid are asserted. wready is
-- de-asserted when reset is low.
process (tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
tb_m_wready <= '0';
else
if tb_m_wready = '0' and tb_m_wvalid = '1' and tb_m_awvalid = '1' then
-- slave is ready to accept write data when
-- there is a valid write address and write data
-- on the write address and data bus.
tb_m_wready <= '1';
else
tb_m_wready <= '0';
end if;
end if;
end if;
end process;
-- RVALID generation
process (tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
tb_m_rvalid <= '0';
tb_m_rresp <= "00";
else
if tb_m_arready = '1' and tb_m_arvalid = '1' and tb_m_rvalid = '0' then
-- Valid read data is available at the read data bus
tb_m_rvalid <= '1';
tb_m_rresp <= "00"; -- 'OKAY' response
elsif tb_m_rvalid = '1' and tb_m_rready = '1' then
tb_m_rvalid <= '0';
tb_m_rresp <= (others=>'X');
end if;
end if;
end if;
end process;
-- ARREADY generation
process (tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
tb_m_arready <= '0';
else
if tb_m_arready = '0' and tb_m_arvalid = '1' then
-- indicates that the slave has acceped the valid read address
tb_m_arready <= '1';
else
tb_m_arready <= '0';
end if;
end if;
end if;
end process;
--==============================================================================
-- Coverage --
--==============================================================================
-- **********************
-- **FSM for Write Part**
-- **********************
p_wr_fsm : process (tb_clk_i)
begin
if rising_edge (tb_clk_i) then
if tb_rst_n_i = '0' then
s_wstate <= WR_IDLE;
else
case s_wstate is
when WR_IDLE =>
if tb_s_awvalid = '1' then
s_waddr <= tb_s_awaddr;
s_wlen <= tb_s_awlen;
s_wsize <= tb_s_awsize;
s_wstate <= WR_MASTER;
end if;
when WR_MASTER =>
if tb_s_wvalid = '1' then
s_wstate <= WR_SLAVE;
end if;
when WR_SLAVE =>
s_wstate <= WR_SLAVE2;
when WR_SLAVE2 =>
if tb_m_wready = '1' then
s_wstate <= WR_WAIT;
end if;
when WR_WAIT =>
-- End of transfer ?
if tb_m_bvalid = '1' then
if s_waddr (2) = '1'
or (s_wsize (1 downto 0) = "10" and s_waddr (1) /= '1') -- 4 bytes
or (s_wsize (1 downto 0) = "01" and s_waddr (1 downto 0) /= "11")
or s_wsize (1 downto 0) = "00" -- 1 byte
then
if s_wlen = x"00" then
s_wstate <= WR_DONE;
else
s_wlen <= std_logic_vector(unsigned(s_wlen) - 1);
s_wstate <= WR_MASTER;
end if;
else
s_waddr (2) <= '1';
s_wstate <= WR_SLAVE;
end if;
end if;
when WR_DONE =>
if tb_s_bready = '1' then
s_wstate <= WR_IDLE;
end if;
end case;
end if;
end if;
end process;
-- Legal, illegal states and coverage
-- report for write side FSM
process
begin
-- all possible legal state changes
fsm_covadd_states_wr("WR_IDLE -> WR_MASTER",WR_IDLE ,WR_MASTER,sv_cover_wr);
fsm_covadd_states_wr("WR_MASTER -> WR_SLAVE ",WR_MASTER,WR_SLAVE ,sv_cover_wr);
fsm_covadd_states_wr("WR_SLAVE -> WR_SLAVE2",WR_SLAVE ,WR_SLAVE2,sv_cover_wr);
fsm_covadd_states_wr("WR_SLAVE2 -> WR_WAIT ",WR_SLAVE2,WR_WAIT ,sv_cover_wr);
fsm_covadd_states_wr("WR_WAIT -> WR_DONE ",WR_WAIT ,WR_DONE ,sv_cover_wr);
fsm_covadd_states_wr("WR_WAIT -> WR_MASTER",WR_WAIT ,WR_MASTER,sv_cover_wr);
fsm_covadd_states_wr("WR_WAIT -> WR_SLAVE ",WR_WAIT ,WR_SLAVE ,sv_cover_wr);
fsm_covadd_states_wr("WR_DONE -> WR_IDLE ",WR_DONE ,WR_IDLE ,sv_cover_wr);
-- when current and next state is the same
fsm_covadd_states_wr("WR_IDLE -> WR_IDLE ",WR_IDLE ,WR_IDLE ,sv_cover_wr);
fsm_covadd_states_wr("WR_MASTER -> WR_MASTER",WR_MASTER,WR_MASTER,sv_cover_wr);
fsm_covadd_states_wr("WR_WAIT -> WR_WAIT ",WR_WAIT ,WR_WAIT ,sv_cover_wr);
fsm_covadd_states_wr("WR_SLAVE2 -> WR_SLAVE2",WR_SLAVE2,WR_SLAVE2,sv_cover_wr);
fsm_covadd_states_wr("WR_DONE -> WR_DONE ",WR_DONE ,WR_DONE ,sv_cover_wr);
-- illegal states
fsm_covadd_illegal("ILLEGAL",sv_cover_wr);
wait;
end process;
-- collect the cov bins
fsm_covcollect_wr(tb_rst_n_i, tb_clk_i, s_wstate, sv_cover_wr);
-- coverage report
cov_report_wr : process
begin
wait until stop;
sv_cover_wr.writebin;
report "Test PASS!";
end process;
-- **********************
-- **FSM for Read part**
-- **********************
p_rd_fsm : process (tb_clk_i)
begin
if rising_edge (tb_clk_i) then
if tb_rst_n_i = '0' then
s_rstate <= RD_IDLE;
s_raddr <= (others => 'X');
s_rdata <= (others => '0');
else
case s_rstate is
when RD_IDLE =>
if tb_s_arvalid = '1' then
s_raddr <= tb_s_araddr;
s_rlen <= tb_s_arlen;
s_rsize <= tb_s_arsize;
-- Provide a clean result.
s_rdata <= (others => '0');
s_rstate <= RD_READ;
end if;
when RD_READ =>
if tb_m_rvalid = '1' then
if s_raddr (2) = '1' then
s_rdata (63 downto 32) <= tb_m_rdata;
else
s_rdata (31 downto 0) <= tb_m_rdata;
end if;
-- End of transfer on the master ?
if s_raddr (2) = '1'
or (s_rsize (1 downto 0) = "10" and s_raddr (1) /= '1') -- 4 bytes
or (s_rsize (1 downto 0) = "01" and s_raddr (1 downto 0) /= "11")
or s_rsize (1 downto 0) = "00" -- 1 byte
then
-- To master.
s_rstate <= RD_SLAVE;
else
-- Next transfer.
s_raddr (2) <= '1';
end if;
end if;
when RD_SLAVE =>
if tb_s_rready = '1' then
if s_rlen = x"00" then
s_rstate <= RD_IDLE;
else
s_rlen <= std_logic_vector(unsigned(s_rlen) - 1);
s_rstate <= RD_READ;
end if;
end if;
end case;
end if;
end if;
end process p_rd_fsm;
-- Legal, illegal states and coverage
-- report for read side FSM
process
begin
-- all possible legal state changes
fsm_covadd_states_rd("RD_IDLE -> RD_READ ",RD_IDLE ,RD_READ ,sv_cover_rd);
fsm_covadd_states_rd("RD_READ -> RD_SLAVE ",RD_READ ,RD_SLAVE ,sv_cover_rd);
fsm_covadd_states_rd("RD_SLAVE -> RD_READ ",RD_SLAVE ,RD_READ ,sv_cover_rd);
fsm_covadd_states_rd("RD_SLAVE -> RD_IDLE ",RD_SLAVE ,RD_IDLE ,sv_cover_rd);
-- when current and next state is the same
fsm_covadd_states_rd("RD_IDLE -> RD_IDLE ",RD_IDLE ,RD_IDLE ,sv_cover_rd);
fsm_covadd_states_rd("RD_READ -> RD_READ ",RD_READ ,RD_READ ,sv_cover_rd);
fsm_covadd_states_rd("RD_SLAVE -> RD_SLAVE ",RD_SLAVE ,RD_SLAVE ,sv_cover_rd);
-- illegal states
fsm_covadd_illegal("ILLEGAL",sv_cover_rd);
wait;
end process;
-- collect the cov bins
fsm_covcollect_rd(tb_rst_n_i, tb_clk_i, s_rstate, sv_cover_rd);
-- coverage report
cov_report_rd : process
begin
wait until stop;
sv_cover_rd.writebin;
report "Test PASS!";
end process;
--==============================================================================
-- Assertions --
--==============================================================================
-- Check AXI-4 FULL Slave signals
p_s_check : process(tb_s_awvalid, tb_s_wvalid,tb_s_bready,tb_s_arvalid,tb_s_rready)
begin
if falling_edge(tb_s_awvalid) then
assert (tb_s_awready = '0')
report "SLAVE: Wrong AWREADY for AWVALID LOW" severity error;
end if;
if falling_edge(tb_s_wvalid) then
assert (tb_s_wready = '0')
report "SLAVE: Wrong WREADY for WVALID LOW" severity error;
end if;
if falling_edge(tb_s_bready) then
assert (tb_s_bvalid = '0')
report "SLAVE: Wrong BVALID for BREADY LOW" severity error;
end if;
if falling_edge(tb_s_arvalid) then
assert (tb_s_arready = '0')
report "SLAVE: Wrong ARREADY for ARVALID LOW" severity error;
end if;
if falling_edge(tb_s_rready) then
assert (tb_s_rvalid = '0')
report "SLAVE: Wrong RVALID for RREADY LOW" severity error;
end if;
end process;
-- Check AXI-4 LITE Master signals
p_m_check : process(tb_m_awready,tb_m_wready,tb_m_bvalid,tb_m_arready,tb_m_rready)
begin
if falling_edge(tb_m_awready) then
assert (tb_m_awvalid = '0')
report "MASTER: Wrong AWVALID for AWREADY LOW" severity error;
end if;
if falling_edge(tb_m_wready) then
assert (tb_m_wvalid = '0')
report "MASTER: Wrong WVALID for WREADY LOW" severity error;
end if;
if falling_edge(tb_m_bvalid) then
assert (tb_m_bready = '0')
report "MASTER: Wrong BREADY for BVALID LOW" severity error;
end if;
if falling_edge(tb_m_arready) then
assert (tb_m_arvalid = '0')
report "MASTER: Wrong ARVALID for ARREADY LOW" severity error;
end if;
if falling_edge(tb_m_rready) then
assert (tb_m_rvalid = '0')
report "MASTER: Wrong RREADY for RVALID LOW" severity error;
end if;
end process;
--Slave RDATA (64-bit) include master's rdata (2x32-bits)
process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
rdata <= (others=>'0');
s_rd_cnt <= 0;
else
if tb_m_rready = '1' and tb_m_rvalid = '1' then
if s_rd_cnt = 0 then
if tb_m_araddr(2) = '1' then
rdata(63 downto 32) <= tb_m_rdata;
else
rdata(31 downto 0) <= tb_m_rdata;
end if;
s_rd_cnt <= s_rd_cnt + 1;
elsif s_rd_cnt = 1 then
if tb_m_araddr(2) = '1' then
rdata(63 downto 32) <= tb_m_rdata;
else
rdata(31 downto 0) <= tb_m_rdata;
end if;
s_rd_cnt <= 0;
end if;
elsif s_rstate=RD_IDLE and tb_s_arvalid = '1' then
rdata <= (others=>'0');
end if;
end if;
end if;
end process;
check_s_rdata : process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_s_rvalid = '1' AND tb_s_rready = '1' then
assert (rdata = tb_s_rdata)
report "RDATA mismatch" severity error;
end if;
end if;
end process;
-- Slave WDATA (32-bit) has a part of Master's WDATA (64-bits)
s_tmp_wdata <= tb_s_wdata when (tb_s_wready = '1');
process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if s_wstate=WR_SLAVE OR (tb_s_wready = '1' and tb_s_wvalid = '1') then
if s_waddr(2) = '1' then
wdata <= s_tmp_wdata(63 downto 32);
else
wdata <= s_tmp_wdata(31 downto 0);
end if;
end if;
end if;
end process;
check_m_wdata : process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_m_wvalid = '1' AND tb_m_wready = '1' then
assert (wdata = tb_m_wdata)
report "WDATA mismatch" severity error;
end if;
end if;
end process;
end tb;
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
*
!.gitignore
!Manifest.py
!*.vhd
!*.cheby
!run.sh
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
action ="simulation"
sim_tool="ghdl"
target ="generic"
ghdl_opt="--std=08 -frelaxed-rules -Wno-hide"
sim_top ="tb_axi4lite_axi4full_bridge"
files ="tb_axi4lite_axi4full_bridge.vhd"
modules = {"local" : ["../../../",
"../../osvvm/",
]}
## Description
Testbench for [axi4lite_axi4full_bridge](../../modules/axi/axi4lite_axi4full_bridge/axi4lite_axi4full_bridge.vhd) which is a bridge from AXI4Lite to AXI4Full. Master is the axi4lite and the slave is axi4full.
NOTE: By default, the simulation time is 4ms. For any change in this, run the test and pass the simulation time as an argument (integer) to this script:
```console
./run.sh <simulation time>
```
#!/bin/bash -e
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
#This is a simple script to run simulations in GHDL
TB=tb_axi4lite_axi4full_bridge
if [ -z "$1" ]; then
TIME="4"
else
TIME="$1"
fi;
echo "Running simulation for $TB"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_sim_time=$TIME
-------------------------------------------------------------------------------
-- SPDX-FileCopyrightText: 2023 CERN (home.cern)
--
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
-------------------------------------------------------------------------------
-- Title : Testbench for AXI4Lite to AXI4Full bridge
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : tb_axi4lite_axi4full_bridge.vhd
-- Company : CERN (BE-CEM-EDL)
-- Author : Konstantinos Blantos <konstantinos.blantos@cern.ch>
-- Platform : FPGA-generics
-- Standard : VHDL '08
-------------------------------------------------------------------------------
--=============================================================================
-- Libraries & Packages --
--=============================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
--=============================================================================
-- Entity declaration for tb_axi4lite_axi4full_bridge --
--=============================================================================
entity tb_axi4lite_axi4full_bridge is
generic (
g_seed : natural;
g_sim_time : natural;
g_ADDR_WIDTH : natural := 32;
g_DATA_WIDTH : natural := 32;
g_ID_WIDTH : natural := 4;
g_LEN_WIDTH : natural := 8
);
end entity tb_axi4lite_axi4full_bridge;
--==============================================================================
-- Architecture declaration --
--==============================================================================
architecture tb of tb_axi4lite_axi4full_bridge is
--==========================================================
-- Constants
--==========================================================
constant C_CLK_PERIOD : time := 10 ns;
constant C_SIM_TIME : time := (g_sim_time*1.0 ms);
-- Used for FSM coverage
constant RSP_OKAY : std_logic_vector(1 downto 0) := b"00";
constant RSP_EXOKAY : std_logic_vector(1 downto 0) := b"01";
constant RSP_SLVERR : std_logic_vector(1 downto 0) := b"10";
constant RSP_DECERR : std_logic_vector(1 downto 0) := b"11";
--==========================================================
-- Signals
--==========================================================
signal tb_clk_i : std_logic;
signal tb_rst_n_i : std_logic;
-- AXI4-Full slave
signal tb_s_awaddr : std_logic_vector (g_ADDR_WIDTH-1 downto 0);
signal tb_s_awlen : std_logic_vector (g_LEN_WIDTH-1 downto 0);
signal tb_s_awsize : std_logic_vector (2 downto 0);
signal tb_s_awburst : std_logic_vector (1 downto 0);
signal tb_s_awid : std_logic_vector (g_ID_WIDTH-1 downto 0);
signal tb_s_awvalid : std_logic;
signal tb_s_awready : std_logic;
signal tb_s_wdata : std_logic_vector (g_DATA_WIDTH-1 downto 0);
signal tb_s_wstrb : std_logic_vector ((g_DATA_WIDTH/8)-1 downto 0);
signal tb_s_wid : std_logic_vector (g_ID_WIDTH-1 downto 0);
signal tb_s_wlast : std_logic;
signal tb_s_wvalid : std_logic;
signal tb_s_wready : std_logic;
signal tb_s_bid : std_logic_vector (g_ID_WIDTH-1 downto 0);
signal tb_s_bresp : std_logic_vector (1 downto 0);
signal tb_s_bvalid : std_logic;
signal tb_s_bready : std_logic;
signal tb_s_araddr : std_logic_vector (g_ADDR_WIDTH-1 downto 0);
signal tb_s_arlen : std_logic_vector (g_LEN_WIDTH-1 downto 0);
signal tb_s_arsize : std_logic_vector (2 downto 0);
signal tb_s_arburst : std_logic_vector (1 downto 0);
signal tb_s_arid : std_logic_vector (g_ID_WIDTH-1 downto 0);
signal tb_s_arvalid : std_logic;
signal tb_s_arready : std_logic;
signal tb_s_rdata : std_logic_vector (g_DATA_WIDTH-1 downto 0);
signal tb_s_rid : std_logic_vector (g_ID_WIDTH-1 downto 0);
signal tb_s_rresp : std_logic_vector (1 downto 0);
signal tb_s_rlast : std_logic;
signal tb_s_rvalid : std_logic;
signal tb_s_rready : std_logic;
-- AXI4-Lite master
signal tb_m_awaddr : std_logic_vector (g_ADDR_WIDTH-1 downto 0);
signal tb_m_awvalid : std_logic;
signal tb_m_awready : std_logic;
signal tb_m_wdata : std_logic_vector (g_DATA_WIDTH-1 downto 0);
signal tb_m_wstrb : std_logic_vector ((g_DATA_WIDTH/8)-1 downto 0);
signal tb_m_wvalid : std_logic;
signal tb_m_wready : std_logic;
signal tb_m_bresp : std_logic_vector (1 downto 0);
signal tb_m_bvalid : std_logic;
signal tb_m_bready : std_logic;
signal tb_m_araddr : std_logic_vector (g_ADDR_WIDTH-1 downto 0);
signal tb_m_arvalid : std_logic;
signal tb_m_arready : std_logic;
signal tb_m_rdata : std_logic_vector (g_DATA_WIDTH-1 downto 0);
signal tb_m_rresp : std_logic_vector (1 downto 0);
signal tb_m_rvalid : std_logic;
signal tb_m_rready : std_logic;
signal stop : boolean;
signal waddr : std_logic_vector(g_ADDR_WIDTH-1 downto 0) := (others=>'0');
signal s_wlen : std_logic_vector(g_LEN_WIDTH-1 downto 0) := (others=>'0');
signal s_wsize : std_logic_vector(2 downto 0) ;
signal s_raddr : std_logic_vector(g_ADDR_WIDTH-1 downto 0) := (others=>'0');
signal s_rlen : std_logic_vector(g_LEN_WIDTH-1 downto 0) := (others=>'0');
signal s_rsize : std_logic_vector(2 downto 0);
signal s_rdata : std_logic_vector(g_DATA_WIDTH-1 downto 0) := (others=>'0');
signal s_awvalid : std_logic;
signal s_wvalid : std_logic;
signal s_wstrb : std_logic_vector((g_DATA_WIDTH/8)-1 downto 0);
signal s_arvalid : std_logic;
signal s_rready : std_logic;
signal s_bready : std_logic;
signal m_bvalid : std_logic;
signal s_wid : std_logic_vector(g_ID_WIDTH-1 downto 0);
signal wdata : std_logic_vector(g_ADDR_WIDTH-1 downto 0);
signal tmp_awaddr : std_logic_vector(g_ADDR_WIDTH-1 downto 0) := (others=>'0');
signal tmp_araddr : std_logic_vector(g_ADDR_WIDTH-1 downto 0) := (others=>'0');
signal tmp_wdata : std_logic_vector(g_DATA_WIDTH-1 downto 0) := (others=>'0');
signal tmp_rdata : std_logic_vector(g_DATA_WIDTH-1 downto 0) := (others=>'0');
type t_wr_state is (WR_IDLE,
WR_MASTER, WR_SLAVE, WR_SLAVE2, WR_WAIT, WR_DONE);
type t_rd_state is (RD_IDLE, RD_READ, RD_SLAVE);
signal s_wstate : t_wr_state;
signal s_rstate : t_rd_state;
shared variable sv_cover_wr : covPType;
shared variable sv_cover_rd : covPType;
--==========================================================
-- Procedures used for FSM coverage
--==========================================================
-- legal states for Write FSM
procedure fsm_covadd_states_wr (
name : in string;
prev : in t_wr_state;
curr : in t_wr_state;
covdb : inout covPType) is
begin
covdb.AddCross ( name,
GenBin(t_wr_state'pos(prev)),
GenBin(t_wr_state'pos(curr)));
end procedure;
-- legal states for Read FSM
procedure fsm_covadd_states_rd (
name : in string;
prev : in t_rd_state;
curr : in t_rd_state;
covdb : inout covPType) is
begin
covdb.AddCross ( name,
GenBin(t_rd_state'pos(prev)),
GenBin(t_rd_state'pos(curr)));
end procedure;
-- illegal states
procedure fsm_covadd_illegal (
name : in string;
covdb : inout covPType ) is
begin
covdb.AddCross(ALL_ILLEGAL,ALL_ILLEGAL);
end procedure;
-- bin collection for Write FSM
procedure fsm_covcollect_wr (
signal reset : in std_logic;
signal clk : in std_logic;
signal state : in t_wr_state;
covdb : inout covPType) is
variable v_state : t_wr_state := t_wr_state'left;
begin
wait until reset='1';
loop
v_state := state;
wait until rising_edge(clk);
covdb.ICover((t_wr_state'pos(v_state), t_wr_state'pos(state)));
end loop;
end procedure;
-- bin collection for Read FSM
procedure fsm_covcollect_rd (
signal reset : in std_logic;
signal clk : in std_logic;
signal state : in t_rd_state;
covdb : inout covPType) is
variable v_state : t_rd_state := t_rd_state'left;
begin
wait until reset='1';
loop
v_state := state;
wait until rising_edge(clk);
covdb.ICover((t_rd_state'pos(v_state), t_rd_state'pos(state)));
end loop;
end procedure;
begin
-- Unit Under Test
UUT : entity work.axi4lite_axi4full_bridge
port map (
clk_i => tb_clk_i,
rst_n_i => tb_rst_n_i,
s_awaddr => tb_s_awaddr,
s_awlen => tb_s_awlen,
s_awsize => tb_s_awsize,
s_awburst => tb_s_awburst,
s_awid => tb_s_awid,
s_awvalid => tb_s_awvalid,
s_awready => tb_s_awready,
s_wdata => tb_s_wdata,
s_wstrb => tb_s_wstrb,
s_wid => tb_s_wid,
s_wlast => tb_s_wlast,
s_wvalid => tb_s_wvalid,
s_wready => tb_s_wready,
s_bid => tb_s_bid,
s_bresp => tb_s_bresp,
s_bvalid => tb_s_bvalid,
s_bready => tb_s_bready,
s_araddr => tb_s_araddr,
s_arlen => tb_s_arlen,
s_arsize => tb_s_arsize,
s_arburst => tb_s_arburst,
s_arid => tb_s_arid,
s_arvalid => tb_s_arvalid,
s_arready => tb_s_arready,
s_rdata => tb_s_rdata,
s_rid => tb_s_rid,
s_rresp => tb_s_rresp,
s_rlast => tb_s_rlast,
s_rvalid => tb_s_rvalid,
s_rready => tb_s_rready,
m_awaddr => tb_m_awaddr,
m_awvalid => tb_m_awvalid,
m_awready => tb_m_awready,
m_wdata => tb_m_wdata,
m_wstrb => tb_m_wstrb,
m_wvalid => tb_m_wvalid,
m_wready => tb_m_wready,
m_bresp => tb_m_bresp,
m_bvalid => tb_m_bvalid,
m_bready => tb_m_bready,
m_araddr => tb_m_araddr,
m_arvalid => tb_m_arvalid,
m_arready => tb_m_arready,
m_rdata => tb_m_rdata,
m_rresp => tb_m_rresp,
m_rvalid => tb_m_rvalid,
m_rready => tb_m_rready);
-- Clock generation
p_clk_gen : process
begin
while not stop loop
tb_clk_i <= '1';
wait for C_CLK_PERIOD/2;
tb_clk_i <= '0';
wait for C_CLK_PERIOD/2;
end loop;
wait;
end process p_clk_gen;
-- Reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
-- Stimulus
stim : process
variable data : RandomPType;
variable ncycles : natural;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
wait until tb_rst_n_i = '1';
while (NOW < C_SIM_TIME) loop
wait until rising_edge(tb_clk_i);
-- AXI-4 Full inputs
tb_s_awaddr <= data.randSlv(g_ADDR_WIDTH);
tb_s_awlen <= data.randSlv(0,4,8) when s_wstate=WR_IDLE else (others=>'0');
s_awvalid <= data.randSlv(1)(1);
tb_s_wdata <= data.randSlv(g_DATA_WIDTH);
s_wvalid <= data.randSlv(1)(1);
s_bready <= data.randSlv(1)(1);
tb_s_araddr <= data.randSlv(g_ADDR_WIDTH);
tb_s_arlen <= data.randSlv(0,4,8) when s_rstate=RD_IDLE;
s_arvalid <= data.randSlv(1)(1);
s_rready <= data.randSlv(1)(1);
-- AXI-4 Lite inputs
m_bvalid <= data.randSlv(1)(1);
tb_m_rdata <= data.randSlv(g_ADDR_WIDTH);
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= TRUE;
report "Test PASS!";
wait;
end process stim;
-- Based on AMBA AXI4 specification (A3.4)
-- depending on the data width, axSize can differ
g_axSize_gen : if g_DATA_WIDTH > 0 generate
process
begin
case g_DATA_WIDTH is
when 1 =>
tb_s_awsize <= "000";
tb_s_arsize <= "000";
when 2 =>
tb_s_awsize <= "001";
tb_s_arsize <= "001";
when 4 =>
tb_s_awsize <= "010";
tb_s_arsize <= "010";
when 8 =>
tb_s_awsize <= "011";
tb_s_arsize <= "011";
when 16 =>
tb_s_awsize <= "100";
tb_s_arsize <= "100";
when 32 =>
tb_s_awsize <= "101";
tb_s_arsize <= "101";
when 64 =>
tb_s_awsize <= "110";
tb_s_arsize <= "110";
when 128 =>
tb_s_awsize <= "111";
tb_s_arsize <= "111";
when others =>
tb_s_awsize <= "000";
tb_s_arsize <= "000";
end case;
wait;
end process;
end generate g_axSize_gen;
-- Assign to strobe the default value which
-- means that all byte lanes hold valid data
tb_s_wstrb <= (others=>'1');
-- AXBurst logic not included in RTL
-- The default value chosen for INCR
tb_s_awburst <= "01";
tb_s_arburst <= "01";
-- Transactions ID. Set all to 0
-- for convenience
tb_s_awid <= (others=>'0');
tb_s_wid <= (others=>'0');
tb_s_arid <= (others=>'0');
-- BRESP for Master is always OKAY
-- just for convenience in testing
tb_m_bresp <= RSP_OKAY;
-- Valid/Ready signals generation
-- both for slave and master
tb_s_awvalid <= s_awvalid when s_wstate = WR_IDLE else '0';
tb_s_wvalid <= s_wvalid when s_wstate = WR_MASTER else '0';
tb_s_arvalid <= s_arvalid when s_rstate = RD_IDLE else '0';
tb_s_rready <= s_rready when s_rstate = RD_SLAVE else '0';
tb_s_bready <= s_bready when s_wstate = WR_DONE else '0';
tb_m_bvalid <= m_bvalid when s_wstate = WR_WAIT else '0';
-- Write side, signal assignments
tb_m_awaddr <= waddr;
tb_m_wdata <= wdata;
tb_m_wstrb <= s_wstrb;
tb_s_bid <= s_wid;
-- Read side, signal assignments
tb_m_araddr <= s_raddr;
tb_s_rdata <= s_rdata;
-- Wlast generation
tb_s_wlast <= '1' when (unsigned(s_wlen)=0 and tb_s_wvalid = '1') else '0';
-- AWREADY generation
-- awready is asserted for one clock cycle when both
-- awvalid and wvalid are asserted. awready is
-- de-asserted when reset is low.
process (tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
tb_m_awready <= '0';
else
if tb_m_awready = '0' and tb_m_awvalid = '1' and tb_m_wvalid = '1' then
-- slave is ready to accept write address when
-- there is a valid write address and write data
-- on the write address and data bus.
tb_m_awready <= '1';
else
tb_m_awready <= '0';
end if;
end if;
end if;
end process;
-- WREADY generation
-- wready is asserted for one clock cycle when both
-- awvalid and wvalid are asserted. wready is
-- de-asserted when reset is low.
process (tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
tb_m_wready <= '0';
else
if tb_m_wready = '0' and tb_m_wvalid = '1' and tb_m_awvalid = '1' then
-- slave is ready to accept write data when
-- there is a valid write address and write data
-- on the write address and data bus.
tb_m_wready <= '1';
else
tb_m_wready <= '0';
end if;
end if;
end if;
end process;
-- RVALID generation
process (tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
tb_m_rvalid <= '0';
tb_m_rresp <= "00";
else
if tb_m_arready = '1' and tb_m_arvalid = '1' and tb_m_rvalid = '0' then
-- Valid read data is available at the read data bus
tb_m_rvalid <= '1';
tb_m_rresp <= "00"; -- 'OKAY' response
elsif tb_m_rvalid = '1' and tb_m_rready = '1' then
tb_m_rvalid <= '0';
tb_m_rresp <= (others=>'X');
end if;
end if;
end if;
end process;
-- ARREADY generation
process (tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
tb_m_arready <= '0';
else
if tb_m_arready = '0' and tb_m_arvalid = '1' then
-- indicates that the slave has acceped the valid read address
tb_m_arready <= '1';
else
tb_m_arready <= '0';
end if;
end if;
end if;
end process;
--==============================================================================
-- Coverage --
--==============================================================================
-- **********************
-- **FSM for Write Part**
-- **********************
p_wr_fsm : process (tb_clk_i)
begin
if rising_edge (tb_clk_i) then
if tb_rst_n_i = '0' then
s_wstate <= WR_IDLE;
tb_s_awready <= '1';
tb_s_bvalid <= '0';
tb_m_awvalid <= '0';
tb_m_wvalid <= '0';
tb_m_bready <= '0';
else
case s_wstate is
when WR_IDLE =>
-- Wait until awvalid is ready.
if tb_s_awvalid = '1' then
-- Save transaction parameters
waddr <= tb_s_awaddr;
s_wlen <= tb_s_awlen;
s_wsize <= tb_s_awsize;
s_wid <= tb_s_awid;
-- Not anymore ready for addresses.
tb_s_awready <= '0';
-- But ready for data.
s_wstate <= WR_MASTER;
end if;
when WR_MASTER =>
-- Clear wvalid when coming from WR_SLAVE.
tb_m_wvalid <= '0';
if tb_s_wvalid = '1' then
-- Got data from master.
wdata <= tb_s_wdata;
s_wstrb <= tb_s_wstrb;
-- Address cycle.
tb_m_awvalid <= '1';
s_wstate <= WR_SLAVE;
end if;
when WR_SLAVE =>
if tb_m_awready = '1' then
-- Wait for address ack.
tb_m_awvalid <= '0';
end if;
-- Prepare data write cycle.
tb_m_wvalid <= '1';
s_wstate <= WR_SLAVE2;
when WR_SLAVE2 =>
if tb_m_awready = '1' then
-- Wait for address ack.
tb_m_awvalid <= '0';
end if;
if tb_m_wready = '1' then
-- Data ack.
tb_m_wvalid <= '0';
tb_m_bready <= '1';
s_wstate <= WR_WAIT;
end if;
when WR_WAIT =>
-- End of transfer ?
if tb_m_bvalid = '1' then
tb_m_bready <= '0';
if s_wlen = (g_LEN_WIDTH - 1 downto 0 => '0') then
-- End of the burst.
tb_s_bresp <= RSP_OKAY;
tb_s_bvalid <= '1';
s_wstate <= WR_DONE;
else
s_wlen <= std_logic_vector(unsigned(s_wlen) - 1);
s_wstate <= WR_MASTER;
end if;
end if;
when WR_DONE =>
if tb_s_bready = '1' then
tb_s_bvalid <= '0';
tb_s_awready <= '1';
s_wstate <= WR_IDLE;
end if;
end case;
end if;
end if;
end process p_wr_fsm;
-- Legal, illegal states and coverage
-- report for write side FSM
process
begin
-- all possible legal state changes
fsm_covadd_states_wr("WR_IDLE -> WR_MASTER",WR_IDLE ,WR_MASTER,sv_cover_wr);
fsm_covadd_states_wr("WR_MASTER -> WR_SLAVE ",WR_MASTER,WR_SLAVE ,sv_cover_wr);
fsm_covadd_states_wr("WR_SLAVE -> WR_SLAVE2",WR_SLAVE ,WR_SLAVE2,sv_cover_wr);
fsm_covadd_states_wr("WR_SLAVE2 -> WR_WAIT ",WR_SLAVE2,WR_WAIT ,sv_cover_wr);
fsm_covadd_states_wr("WR_WAIT -> WR_DONE ",WR_WAIT ,WR_DONE ,sv_cover_wr);
fsm_covadd_states_wr("WR_WAIT -> WR_MASTER",WR_WAIT ,WR_MASTER,sv_cover_wr);
fsm_covadd_states_wr("WR_DONE -> WR_IDLE ",WR_DONE ,WR_IDLE ,sv_cover_wr);
-- when current and next state is the same
fsm_covadd_states_wr("WR_IDLE -> WR_IDLE ",WR_IDLE ,WR_IDLE ,sv_cover_wr);
fsm_covadd_states_wr("WR_MASTER -> WR_MASTER",WR_MASTER,WR_MASTER,sv_cover_wr);
fsm_covadd_states_wr("WR_WAIT -> WR_WAIT ",WR_WAIT ,WR_WAIT ,sv_cover_wr);
fsm_covadd_states_wr("WR_SLAVE2 -> WR_SLAVE2",WR_SLAVE2,WR_SLAVE2,sv_cover_wr);
fsm_covadd_states_wr("WR_DONE -> WR_DONE ",WR_DONE ,WR_DONE ,sv_cover_wr);
-- illegal states
fsm_covadd_illegal("ILLEGAL",sv_cover_wr);
wait;
end process;
-- collect the cov bins
fsm_covcollect_wr(tb_rst_n_i, tb_clk_i, s_wstate, sv_cover_wr);
-- coverage report
cov_report_wr : process
begin
wait until stop;
sv_cover_wr.writebin;
report "Test PASS!";
end process;
-- **********************
-- **FSM for Read part**
-- **********************
p_read_fsm : process (tb_clk_i)
begin
if rising_edge (tb_clk_i) then
if tb_rst_n_i = '0' then
s_rstate <= RD_IDLE;
tb_s_arready <= '1';
tb_s_rvalid <= '0';
tb_m_arvalid <= '0';
s_raddr <= (others => 'X');
s_rdata <= (others => '0');
else
case s_rstate is
when RD_IDLE =>
-- Wait until awvalid is ready.
if tb_s_arvalid = '1' then
-- Save transaction parameters
s_raddr <= tb_s_araddr;
s_rlen <= tb_s_arlen;
s_rsize <= tb_s_arsize;
tb_s_rid <= tb_s_arid;
-- Provide a clean result.
s_rdata <= (others => '0');
-- Not anymore ready for addresses.
tb_s_arready <= '0';
-- Start transfer on the slave part.
tb_m_arvalid <= '1';
s_rstate <= RD_READ;
end if;
when RD_READ =>
if tb_m_arready = '1' then
-- Address has been accepted.
tb_m_arvalid <= '0';
end if;
if tb_m_rvalid = '1' then
-- Read data. Address must have been acked.
-- According to A3.4.3 of AXI4 spec, the AXI4 bus is little
-- endian.
s_rdata <= tb_m_rdata;
s_rstate <= RD_SLAVE;
tb_s_rresp <= RSP_OKAY;
tb_s_rvalid <= '1';
end if;
when RD_SLAVE =>
if tb_s_rready = '1' then
tb_s_rvalid <= '0';
if s_rlen = (g_LEN_WIDTH - 1 downto 0 => '0') then
-- End of the burst.
tb_s_arready <= '1';
s_rstate <= RD_IDLE;
else
s_rlen <= std_logic_vector(unsigned(s_rlen) - 1);
-- New beat.
tb_m_arvalid <= '1';
s_rstate <= RD_READ;
end if;
end if;
end case;
end if;
end if;
end process;
-- Legal, illegal states and coverage
-- report for read side FSM
process
begin
-- all possible legal state changes
fsm_covadd_states_rd("RD_IDLE -> RD_READ ",RD_IDLE ,RD_READ ,sv_cover_rd);
fsm_covadd_states_rd("RD_READ -> RD_SLAVE ",RD_READ ,RD_SLAVE ,sv_cover_rd);
fsm_covadd_states_rd("RD_SLAVE -> RD_READ ",RD_SLAVE ,RD_READ ,sv_cover_rd);
fsm_covadd_states_rd("RD_SLAVE -> RD_IDLE ",RD_SLAVE ,RD_IDLE ,sv_cover_rd);
-- when current and next state is the same
fsm_covadd_states_rd("RD_IDLE -> RD_IDLE ",RD_IDLE ,RD_IDLE ,sv_cover_rd);
fsm_covadd_states_rd("RD_READ -> RD_READ ",RD_READ ,RD_READ ,sv_cover_rd);
fsm_covadd_states_rd("RD_SLAVE -> RD_SLAVE ",RD_SLAVE ,RD_SLAVE ,sv_cover_rd);
-- illegal states
fsm_covadd_illegal("ILLEGAL",sv_cover_rd);
wait;
end process;
-- collect the cov bins
fsm_covcollect_rd(tb_rst_n_i, tb_clk_i, s_rstate, sv_cover_rd);
-- coverage report
cov_report_rd : process
begin
wait until stop;
sv_cover_rd.writebin;
report "Test PASS!";
end process;
--==============================================================================
-- Assertions --
--==============================================================================
-- Check AXI-4 FULL Slave signals
p_s_check : process(tb_s_awvalid, tb_s_wvalid,tb_s_bready,tb_s_arvalid,tb_s_rready)
begin
if falling_edge(tb_s_awvalid) then
assert (tb_s_awready = '0')
report "SLAVE: Wrong AWREADY for AWVALID LOW" severity failure;
end if;
if falling_edge(tb_s_wvalid) then
assert (tb_s_wready = '0')
report "SLAVE: Wrong WREADY for WVALID LOW" severity failure;
end if;
if falling_edge(tb_s_bready) then
assert (tb_s_bvalid = '0')
report "SLAVE: Wrong BVALID for BREADY LOW" severity failure;
end if;
if falling_edge(tb_s_arvalid) then
assert (tb_s_arready = '0')
report "SLAVE: Wrong ARREADY for ARVALID LOW" severity failure;
end if;
if falling_edge(tb_s_rready) then
assert (tb_s_rvalid = '0')
report "SLAVE: Wrong RVALID for RREADY LOW" severity failure;
end if;
end process;
-- Check AXI-4 LITE Master signals
p_m_check : process(tb_m_awready,tb_m_wready,tb_m_bvalid,tb_m_arready,tb_m_rvalid)
begin
if falling_edge(tb_m_awready) then
assert (tb_m_awvalid = '0')
report "MASTER: Wrong AWVALID for AWREADY LOW" severity failure;
end if;
if falling_edge(tb_m_wready) then
assert (tb_m_wvalid = '0')
report "MASTER: Wrong WVALID for WREADY LOW" severity failure;
end if;
if falling_edge(tb_m_bvalid) then
assert (tb_m_bready = '0')
report "MASTER: Wrong BREADY for BVALID LOW" severity failure;
end if;
if falling_edge(tb_m_arready) then
assert (tb_m_arvalid = '0')
report "MASTER: Wrong ARVALID for ARREADY LOW" severity failure;
end if;
if falling_edge(tb_m_rvalid) then
assert (tb_m_rready = '0')
report "MASTER: Wrong RREADY for RVALID LOW" severity failure;
end if;
end process;
-- Check that master and slave awaddr is the same
p_awaddr_check : process
begin
while not stop loop
wait until (tb_s_awready = '1' and tb_s_awvalid = '1');
tmp_awaddr <= tb_s_awaddr;
wait until (tb_m_awready = '1' and tb_m_awvalid = '1');
assert (tb_m_awaddr = tmp_awaddr);
end loop;
wait;
end process;
-- Check that master and slave araddr is the same
p_araddr_check : process
begin
while not stop loop
wait until (tb_s_arready = '1' and tb_s_arvalid = '1');
tmp_araddr <= tb_s_araddr;
wait until (tb_m_arready = '1' and tb_m_arvalid = '1');
assert (tb_m_araddr = tmp_araddr);
end loop;
wait;
end process;
-- Check that master and slave wdata is the same
p_wdata_check : process
begin
while not stop loop
wait until (tb_s_wready = '1' and tb_s_wvalid = '1');
tmp_wdata <= tb_s_wdata;
wait until (tb_m_wready = '1' and tb_m_wvalid = '1');
assert (tb_m_wdata = tmp_wdata);
end loop;
wait;
end process;
-- Check that master and slave rdata is the same
p_rdata_check : process
begin
while not stop loop
wait until (tb_m_rready = '1' and tb_m_rvalid = '1');
tmp_rdata <= tb_m_rdata;
wait until (tb_s_rready = '1' and tb_s_rvalid = '1');
assert (tb_s_rdata = tmp_rdata);
end loop;
wait;
end process;
end tb;
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
*
!.gitignore
!Manifest.py
!*.vhd
!*.cheby
!run.sh
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
action="simulation"
sim_tool="ghdl"
target="generic"
ghdl_opt="--std=08 -frelaxed-rules -Wno-hide"
sim_top="tb_xaxi4lite_wb_bridge"
files="tb_xaxi4lite_wb_bridge.vhd"
modules={"local" : ["../../../",
"../../osvvm/",
"../../../modules/wishbone",
"../../../modules/axi"]}
## Description
Testbench for [axi4lite_wb_bridge](../../modules/axi/axi4lite_wb_bridge/xaxi4lite_wb_bridge.vhd) which is a bridge from AXI4 Lite to Wishbone. In this core, the Master is AXI4 Lite and Slave is Wishbone.
NOTE: By default, the simulation time is 4ms. To change this, run the test and pass the simulation time as an argument (integer) to this script:
```console
./run.sh <simulation time>
```
#!/bin/bash -e
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
#This is a simple script to run simulations in GHDL
TB=tb_xaxi4lite_wb_bridge
if [ -z "$1" ]; then
TIME="4"
else
TIME="$1"
fi;
echo "Running simulation for $TB"
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_sim_time=$TIME
-------------------------------------------------------------------------------
-- SPDX-FileCopyrightText: 2023 CERN (home.cern)
--
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
-------------------------------------------------------------------------------
-- Title : Testbench for WB-to-AXI4Lite bridge
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : tb_xaxi4lite_wb_bridge.vhd
-- Author : Konstantinos Blantos <Konstantinos.blantos@cern.ch>
-- Company : CERN (BE-CEM-EDL)
-- Platform : FPGA-generics
-- Standard : VHDL '08
-------------------------------------------------------------------------------
-- Description:
--
-- Testbench for a WB Slave Classic to AXI4-Lite Master bridge.
-------------------------------------------------------------------------------
--=============================================================================
-- Libraries & Packages --
--=============================================================================
library ieee;
use ieee.std_logic_1164.all;
use work.axi4_pkg.all;
use work.wishbone_pkg.all;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
--=============================================================================
-- Entity declaration for tb_axi4lite_wb_bridge --
--=============================================================================
entity tb_xaxi4lite_wb_bridge is
generic (
g_seed : natural;
g_sim_time : natural);
end entity;
--==============================================================================
-- Architecture declaration --
--==============================================================================
architecture tb of tb_xaxi4lite_wb_bridge is
-- Constants
constant C_CLK_PERIOD : time := 10 ns;
constant C_SIM_TIME : time := (g_sim_time*1.0 ms);
-- Signals
signal tb_clk_i : std_logic;
signal tb_rst_n_i : std_logic;
signal tb_wb_slave_i : t_wishbone_slave_in;
signal tb_wb_slave_o : t_wishbone_slave_out;
signal tb_axi4_master_o : t_axi4_lite_master_out_32;
signal tb_axi4_master_i : t_axi4_lite_master_in_32;
signal stop : boolean;
signal s_araddr : std_logic_vector(31 downto 0);
signal s_wb_data : std_logic_vector(31 downto 0);
type t_state is (IDLE, READ, WRITE, WB_END);
signal s_state : t_state;
shared variable sv_cover : covPType;
--------------------------------------------------------------------------------
-- Procedures used for fsm coverage
--------------------------------------------------------------------------------
-- legal states
procedure fsm_covadd_states (
name : in string;
prev : in t_state;
curr : in t_state;
covdb : inout covPType) is
begin
covdb.AddCross ( name,
GenBin(t_state'pos(prev)),
GenBin(t_state'pos(curr)));
end procedure;
-- illegal states
procedure fsm_covadd_illegal (
name : in string;
covdb : inout covPType ) is
begin
covdb.AddCross(ALL_ILLEGAL,ALL_ILLEGAL);
end procedure;
-- bin collection
procedure fsm_covcollect (
signal reset : in std_logic;
signal clk : in std_logic;
signal state : in t_state;
covdb : inout covPType) is
variable v_state : t_state := t_state'left;
begin
wait until reset='1';
loop
v_state := state;
wait until rising_edge(clk);
covdb.ICover((t_state'pos(v_state), t_state'pos(state)));
end loop;
end procedure;
begin
-- Unit Under Test
UUT : entity work.xaxi4lite_wb_bridge
port map (
rst_n_i => tb_rst_n_i,
clk_i => tb_clk_i,
wb_slave_i => tb_wb_slave_i,
wb_slave_o => tb_wb_slave_o,
axi4_master_i => tb_axi4_master_i,
axi4_master_o => tb_axi4_master_o);
-- Clock generation
clk_proc : process
begin
while (not stop) loop
tb_clk_i <= '1';
wait for C_CLK_PERIOD/2;
tb_clk_i <= '0';
wait for C_CLK_PERIOD/2;
end loop;
wait;
end process clk_proc;
-- reset generation
tb_rst_n_i <= '0', '1' after 2*C_CLK_PERIOD;
-- Stimulus
stim : process
variable data : RandomPType;
variable ncycles : natural;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
wait until tb_rst_n_i = '1';
while (NOW < C_SIM_TIME) loop
wait until rising_edge(tb_clk_i);
-- Slave inputs
tb_wb_slave_i.cyc <= data.randSlv(1)(1);
tb_wb_slave_i.stb <= data.randSlv(1)(1);
tb_wb_slave_i.we <= data.randSlv(1)(1);
tb_wb_slave_i.adr <= data.randSlv(32);
tb_wb_slave_i.sel <= data.randSlv(4);
tb_wb_slave_i.dat <= data.randSlv(32);
-- Master inputs
tb_axi4_master_i.ARREADY <= data.randSlv(1)(1);
tb_axi4_master_i.RVALID <= data.randSlv(1)(1);
tb_axi4_master_i.RRESP <= data.randSlv(2);
tb_axi4_master_i.RDATA <= data.randSlv(32);
tb_axi4_master_i.AWREADY <= data.randSlv(1)(1);
tb_axi4_master_i.WREADY <= data.randSlv(1)(1);
tb_axi4_master_i.BVALID <= data.randSlv(1)(1);
tb_axi4_master_i.BRESP <= data.randSlv(2);
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= TRUE;
report "Test PASS!";
wait;
end process stim;
--==============================================================================
-- Coverage --
--==============================================================================
-- FSM
fsm_proc : process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if tb_rst_n_i = '0' then
s_state <= IDLE;
else
case s_state is
-------------------------------------------
-- IDLE STATE --
------------------------------------------
when IDLE =>
if tb_wb_slave_i.stb = '1' and tb_wb_slave_i.we = '0' then
s_state <= READ;
elsif tb_wb_slave_i.stb = '1' and tb_wb_slave_i.we = '1' then
s_state <= WRITE;
else
s_state <= IDLE;
end if;
-------------------------------------------
-- READ CYCLE --
-------------------------------------------
when READ =>
if (tb_axi4_master_i.RVALID = '1') then
s_state <= WB_END;
else
s_state <= READ;
end if;
-------------------------------------------
-- WRITE CYCLE --
-------------------------------------------
when WRITE =>
if (tb_axi4_master_i.BVALID = '1') then
s_state <= WB_END;
else
s_state <= WRITE;
end if;
------------------------------------------
-- WB_END --
------------------------------------------
when WB_END =>
if (tb_wb_slave_i.stb = '0') then
s_state <= IDLE;
else
s_state <= WB_END;
end if;
end case;
end if;
end if;
end process;
process
begin
-- all possible legal state changes
fsm_covadd_states("IDLE -> READ ",IDLE, READ, sv_cover);
fsm_covadd_states("IDLE -> WRITE ",IDLE, WRITE, sv_cover);
fsm_covadd_states("READ -> WB_END",READ, WB_END,sv_cover);
fsm_covadd_states("WRITE -> WB_END",WRITE, WB_END,sv_cover);
fsm_covadd_states("WB_END -> IDLE ",WB_END,IDLE, sv_cover);
-- when current and next state is the same
fsm_covadd_states("IDLE -> IDLE ",IDLE, IDLE, sv_cover);
fsm_covadd_states("READ -> READ ",READ, READ, sv_cover);
fsm_covadd_states("WRITE -> READ ",WRITE, WRITE, sv_cover);
fsm_covadd_states("WB_END -> WB_END",WB_END,WB_END,sv_cover);
-- illegal states
fsm_covadd_illegal("ILLEGAL",sv_cover);
wait;
end process;
-- collect the cov bins
fsm_covcollect(tb_rst_n_i, tb_clk_i, s_state, sv_cover);
-- coverage report
cov_report : process
begin
wait until stop;
sv_cover.writebin;
report "Test PASS!";
end process;
--==============================================================================
-- Assertions --
--==============================================================================
-- Check wb and axi4lite signals when IDLE
process
begin
while (not stop) loop
wait until rising_edge(tb_clk_i) and tb_rst_n_i /= '0';
if s_state = IDLE then
if tb_wb_slave_i.stb = '1' and tb_wb_slave_i.we = '0' then
s_araddr <= tb_wb_slave_i.adr;
wait for C_CLK_PERIOD;
assert (tb_axi4_master_o.ARADDR = s_araddr)
report "Read Address mismatch" severity failure;
assert (tb_axi4_master_o.ARVALID = '1')
report "ARVALID mismatch" severity failure;
assert (tb_axi4_master_o.RREADY = '1')
report "RREADY mismatch" severity failure;
else
s_araddr <= (others=>'0');
end if;
end if;
end loop;
wait;
end process;
-- Check wb and axi4lite signals when READ
process
begin
while (not stop) loop
wait until rising_edge(tb_clk_i) and tb_rst_n_i /= '0';
if s_state = READ then
assert (tb_wb_slave_o.ack = '0' and tb_wb_slave_o.err = '0')
report "ACK and ERR not zero when READ" severity failure;
assert (tb_axi4_master_o.RREADY = '1')
report "RREADY not HIGH when READ" severity failure;
if falling_edge(tb_axi4_master_i.ARREADY) then
assert (tb_axi4_master_o.ARVALID = '0')
report "WRONG ARVALID" severity failure;
end if;
if tb_axi4_master_i.RVALID = '1' AND tb_axi4_master_i.RRESP = c_AXI4_RESP_OKAY then
s_wb_data <= tb_axi4_master_i.RDATA;
wait for 1 ns;
assert (tb_wb_slave_o.dat = s_wb_data)
report "WB slave output data mismatch" severity failure;
assert (tb_wb_slave_o.ack = '1' AND tb_wb_slave_o.err = '0')
report "Wrong ACK and ERR for specific RRESP" severity failure;
elsif tb_axi4_master_i.RVALID = '1' then
wait for 1 ns;
assert (tb_wb_slave_o.ack = '0' AND tb_Wb_slave_o.err = '1')
report "Wrong ACK and ERR" severity failure;
else
s_wb_data <= (others=>'0');
assert (tb_wb_slave_o.ack = '0' AND tb_Wb_slave_o.err = '0')
report "ACK and ERR are not zero" severity failure;
end if;
end if;
end loop;
wait;
end process;
-- Check wb and axi4lite signals when WRITE
process
begin
while (not stop) loop
wait until rising_edge(tb_clk_i) and tb_rst_n_i = '1';
if s_state = WRITE then
assert (tb_wb_slave_o.ack = '0' AND tb_wb_slave_o.err = '0')
report "ACK and ERR not zero when WRITE" severity failure;
if falling_edge(tb_axi4_master_i.AWREADY) then
assert (tb_axi4_master_o.AWVALID = '0')
report "Wrong AWVALID for AWREADY HIGH" severity failure;
end if;
if falling_edge(tb_axi4_master_i.WREADY) then
assert (tb_axi4_master_o.WVALID = '0')
report "Wrong WVALID for WREADY HIGH" severity failure;
end if;
if rising_edge(tb_axi4_master_i.BVALID) then
assert (tb_axi4_master_o.BREADY = '0')
report "Wrong BREADY for BVALID HIGH" severity failure;
elsif falling_edge(tb_axi4_master_i.BVALID) then
assert (tb_axi4_master_o.BREADY = '1')
report "Wrong BREADY for BVALID LOW" severity failure;
end if;
end if;
end loop;
wait;
end process;
-- Check wb signals when WB_END state
process
begin
while (not stop) loop
wait until rising_edge(tb_clk_i) and tb_rst_n_i = '1';
if s_state = WB_END then
wait for C_CLK_PERIOD;
assert (tb_wb_slave_o.ack = '0' AND tb_wb_slave_o.err = '0')
report "ACK and ERR are not zero when WB_END" severity failure;
end if;
end loop;
wait;
end process;
end tb;
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
*
!.gitignore
!Manifest.py
!*.vhd
!*.cheby
!run.sh
target = "xilinx"
action = "simulation"
sim_tool = "modelsim"
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
target = "xilinx"
action = "simulation"
sim_tool = "ghdl"
top_module = "sim_top_ps_gpio"
syn_device = "XC7Z010"
ghdl_opt = "--std=08 -frelaxed-rules -Wno-hide"
files = [ "gpio_axi.vhd", "sim_top_ps_gpio.vhd" ]
modules = { "local" : ["../../../"] }
modules = { "local" : ["../../../",
"../../osvvm/"] }
-- SPDX-FileCopyrightText: 2023 CERN (home.cern)
--
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
memory-map:
bus: axi4-lite-32
name: axi_gpio
......
-- SPDX-FileCopyrightText: 2023 CERN (home.cern)
--
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
......@@ -78,7 +82,7 @@ begin
wready <= axi_wip and wr_ack_int;
bvalid <= axi_wdone;
process (aclk, areset_n) begin
if areset_n = '0' then
if areset_n = '0' then
axi_wip <= '0';
axi_wdone <= '0';
elsif rising_edge(aclk) then
......@@ -93,7 +97,7 @@ begin
arready <= axi_rip and rd_ack_int;
rvalid <= axi_rdone;
process (aclk, areset_n) begin
if areset_n = '0' then
if areset_n = '0' then
axi_rip <= '0';
axi_rdone <= '0';
rdata <= (others => '0');
......@@ -117,7 +121,7 @@ begin
-- Process for write requests.
process (aclk, areset_n) begin
if areset_n = '0' then
if areset_n = '0' then
wr_ack_int <= '0';
out_b0_reg <= "00000000000000000000000000000000";
out_b1_reg <= "00000000000000000000000000000000";
......@@ -128,41 +132,41 @@ begin
elsif rising_edge(aclk) then
wr_ack_int <= '0';
case awaddr(15 downto 2) is
when "10100000010000" =>
when "10100000010000" =>
-- Register out_b0
if wr_int = '1' then
out_b0_reg <= wdata;
end if;
wr_ack_int <= wr_int;
when "10100000010001" =>
when "10100000010001" =>
-- Register out_b1
if wr_int = '1' then
out_b1_reg <= wdata;
end if;
wr_ack_int <= wr_int;
when "10100000011000" =>
when "10100000011000" =>
-- Register in_b0
when "10100000011001" =>
when "10100000011001" =>
-- Register in_b1
when "10100010000001" =>
when "10100010000001" =>
-- Register dir_b0
if wr_int = '1' then
dir_b0_reg <= wdata;
end if;
wr_ack_int <= wr_int;
when "10100010000010" =>
when "10100010000010" =>
-- Register oen_b0
if wr_int = '1' then
oen_b0_reg <= wdata;
end if;
wr_ack_int <= wr_int;
when "10100010010001" =>
when "10100010010001" =>
-- Register dir_b1
if wr_int = '1' then
dir_b1_reg <= wdata;
end if;
wr_ack_int <= wr_int;
when "10100010010010" =>
when "10100010010010" =>
-- Register oen_b1
if wr_int = '1' then
oen_b1_reg <= wdata;
......@@ -176,36 +180,36 @@ begin
-- Process for registers read.
process (aclk, areset_n) begin
if areset_n = '0' then
if areset_n = '0' then
rd_ack1_int <= '0';
reg_rdat_int <= (others => 'X');
elsif rising_edge(aclk) then
reg_rdat_int <= (others => '0');
case araddr(15 downto 2) is
when "10100000010000" =>
when "10100000010000" =>
-- out_b0
rd_ack1_int <= rd_int;
when "10100000010001" =>
when "10100000010001" =>
-- out_b1
rd_ack1_int <= rd_int;
when "10100000011000" =>
when "10100000011000" =>
-- in_b0
reg_rdat_int <= in_b0_i;
rd_ack1_int <= rd_int;
when "10100000011001" =>
when "10100000011001" =>
-- in_b1
reg_rdat_int <= in_b1_i;
rd_ack1_int <= rd_int;
when "10100010000001" =>
when "10100010000001" =>
-- dir_b0
rd_ack1_int <= rd_int;
when "10100010000010" =>
when "10100010000010" =>
-- oen_b0
rd_ack1_int <= rd_int;
when "10100010010001" =>
when "10100010010001" =>
-- dir_b1
rd_ack1_int <= rd_int;
when "10100010010010" =>
when "10100010010010" =>
-- oen_b1
rd_ack1_int <= rd_int;
when others =>
......@@ -219,35 +223,35 @@ begin
-- By default ack read requests
dato <= (others => '0');
case araddr(15 downto 2) is
when "10100000010000" =>
when "10100000010000" =>
-- out_b0
dato <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "10100000010001" =>
when "10100000010001" =>
-- out_b1
dato <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "10100000011000" =>
when "10100000011000" =>
-- in_b0
dato <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "10100000011001" =>
when "10100000011001" =>
-- in_b1
dato <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "10100010000001" =>
when "10100010000001" =>
-- dir_b0
dato <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "10100010000010" =>
when "10100010000010" =>
-- oen_b0
dato <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "10100010010001" =>
when "10100010010001" =>
-- dir_b1
dato <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "10100010010010" =>
when "10100010010010" =>
-- oen_b1
dato <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
......
vsim -t 10fs work.sim_top_ps_gpio -voptargs="+acc"
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
do wave.do
radix -hexadecimal
run 200ms
wave zoomfull
radix -hexadecimal
#!/bin/bash -e
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: CERN-OHL-W-2.0+
#This is a simple script to run simulations in GHDL
TB=sim_top_ps_gpio
echo "Running simulation for $TB"
ghdl -r --std=08 -frelaxed-rules $TB --stop-time=2ms
echo "********************************************"
-------------------------------------------------------------------------------
-- SPDX-FileCopyrightText: 2023 CERN (home.cern)
--
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
-------------------------------------------------------------------------------
-- Title : AXI PS_GPIO Expander for Zynq-7 Testbench
-- Project : General Cores
-------------------------------------------------------------------------------
......@@ -16,33 +20,35 @@
-- using xsim or GHDL.
--
-------------------------------------------------------------------------------
-- Copyright (c) 2019 CERN
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
--=============================================================================
-- Libraries & Packages --
--=============================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
--=============================================================================
-- Entity declaration for sim_top_ps_gpio --
--=============================================================================
entity sim_top_ps_gpio is
end sim_top_ps_gpio;
--==============================================================================
-- Architecture declaration --
--==============================================================================
architecture behav of sim_top_ps_gpio is
-- Constants
constant c_PERIOD : time := 10 ns;
constant c_NUM : integer := 54;
-- Signals
signal clk, rst_n : std_logic;
signal ARVALID : std_logic;
signal AWVALID : std_logic;
signal BREADY : std_logic;
......@@ -105,7 +111,7 @@ begin
ARADDR => ARADDR,
AWADDR => AWADDR,
WDATA => WDATA,
WSTRB => WSTRB,
WSTRB => WSTRB,
ARREADY => ARREADY,
AWREADY => AWREADY,
BVALID => BVALID,
......@@ -128,7 +134,7 @@ begin
araddr => ARADDR(15 downto 2),
awaddr => AWADDR(15 downto 2),
wdata => WDATA,
wstrb => WSTRB,
wstrb => WSTRB,
arready => ARREADY,
awready => AWREADY,
bvalid => BVALID,
......@@ -194,4 +200,34 @@ begin
wait;
end process;
--==============================================================================
-- Assertions --
--==============================================================================
-- Check AXI-4 LITE signals
p_axi_check : process(AWREADY,WREADY,BVALID,ARREADY,RVALID)
begin
if falling_edge(AWREADY) then
assert (AWVALID = '0')
report "Wrong AWVALID for AWREADY LOW" severity failure;
end if;
if falling_edge(WREADY) then
assert (WVALID = '0')
report "Wrong WVALID for WREADY LOW" severity failure;
end if;
if falling_edge(BVALID) then
assert (BREADY = '0')
report "Wrong BREADY for BVALID LOW" severity failure;
end if;
if falling_edge(ARREADY) then
assert (ARVALID = '0')
report "Wrong ARVALID for ARREADY LOW" severity failure;
end if;
if falling_edge(RVALID) then
assert (RREADY = '0')
report "Wrong RREADY for RVALID LOW" severity failure;
end if;
end process;
end behav;
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /sim_top_ps_gpio/clk
add wave -noupdate /sim_top_ps_gpio/rst_n
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/ARVALID
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/AWVALID
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/BREADY
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/RREADY
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/WVALID
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/ARADDR
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/AWADDR
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/WDATA
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/WSTRB
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/ARREADY
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/AWREADY
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/BVALID
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/RVALID
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/WREADY
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/BRESP
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/RRESP
add wave -noupdate -expand -group AXI /sim_top_ps_gpio/RDATA
add wave -noupdate /sim_top_ps_gpio/error_b1
add wave -noupdate /sim_top_ps_gpio/out_b0
add wave -noupdate /sim_top_ps_gpio/out_b1
add wave -noupdate /sim_top_ps_gpio/dir_b0
add wave -noupdate /sim_top_ps_gpio/dir_b1
add wave -noupdate /sim_top_ps_gpio/oen_b0
add wave -noupdate /sim_top_ps_gpio/oen_b1
add wave -noupdate /sim_top_ps_gpio/gpio_out
add wave -noupdate /sim_top_ps_gpio/gpio_oe
add wave -noupdate /sim_top_ps_gpio/gpio_dir
add wave -noupdate /sim_top_ps_gpio/gpio_in
add wave -noupdate /sim_top_ps_gpio/U_EXP/state
add wave -noupdate /sim_top_ps_gpio/U_EXP/gpio_oe_prev
add wave -noupdate /sim_top_ps_gpio/U_EXP/gpio_dir_prev
add wave -noupdate /sim_top_ps_gpio/U_EXP/gpio_out_prev
add wave -noupdate /sim_top_ps_gpio/U_EXP/gpio_oe_changed
add wave -noupdate /sim_top_ps_gpio/U_EXP/gpio_dir_changed
add wave -noupdate /sim_top_ps_gpio/U_EXP/gpio_out_changed
add wave -noupdate /sim_top_ps_gpio/U_EXP/refresh_all
add wave -noupdate /sim_top_ps_gpio/U_EXP/current_bank
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {0 fs} 0}
quietly wave cursor active 0
configure wave -namecolwidth 150
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits fs
update
WaveRestoreZoom {0 fs} {5780 fs}
library="osvvm"
files = [
"upstream/AlertLogPkg.vhd",
"upstream/CoveragePkg.vhd",
"upstream/MemoryGenericPkg.vhd",
"upstream/MemoryPkg.vhd",
"upstream/MemorySupportPkg.vhd",
"upstream/MessageListPkg.vhd",
"upstream/MessagePkg.vhd",
"upstream/NamePkg.vhd",
"upstream/NameStorePkg.vhd",
"upstream/OsvvmContext.vhd",
"upstream/OsvvmGlobalPkg.vhd",
"upstream/OsvvmTypesPkg.vhd",
"upstream/RandomBasePkg.vhd",
"upstream/RandomPkg.vhd",
"upstream/RandomProcedurePkg.vhd",
"upstream/ReportPkg.vhd",
"upstream/ResizePkg.vhd",
"upstream/ResolutionPkg.vhd",
"upstream/ScoreboardGenericPkg.vhd",
"upstream/ScoreboardPkg_int.vhd",
"upstream/ScoreboardPkg_slv.vhd",
"upstream/SortListPkg_int.vhd",
"upstream/TbUtilPkg.vhd",
"upstream/TextUtilPkg.vhd",
"upstream/TranscriptPkg.vhd",
"upstream/VendorCovApiPkg.vhd",
]
Subproject commit 0bced0107438a612b8656d5ae80a6d1a32f22b81
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment