Commit cf1946c6 authored by CI's avatar CI

Simple cleanup and README added

parent 1a4f47bb
Pipeline #3604 passed with stage
in 28 minutes and 2 seconds
This is a testbench to verify the gc_dual_pi_controler core. It uses GHDL simulator and OSVVM as verification methodology. All input signals in the testbench are random, with random seed also. There are two generics in the core:
- g_div_ratio_log2 : Clock division ratio
- g_num_data_bits : Number of data bits per transfer
Regarding the assigned values in these generic, there can be various combinations (testcases), some of them are presented here (1,1), (2,2), (2,4), (3,4).
The testbench, receives random input data (with random seeds). A clock divider counter generates s_tick which is used to control the FSM. One assertion exist in the testbench to bring self-checking capabilities in it and checks, if the incoming data is equal with the outcoming data, in the end of the FSM process.
FSM coverage is covered through the use of OSVVM methodology, where the transition of the states is being checked in every clock and the reports are shown in the end.
......@@ -6,20 +6,25 @@
TB=tb_gc_simple_spi_master
echo "Running simulation for $TB"
echo ""
echo "TEST CASE 1 "
echo "Clock division ratio = 1, Number of data bits per transfer = 1"
ghdl -r --std=08 -frelaxed-rules $TB -gg_div_ratio_log2=1 -gg_num_data_bits=1
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_div_ratio_log2=1 -gg_num_data_bits=1
echo "************************************************************************"
echo "TEST CASE 2 "
echo "Clock division ratio = 2, Number of data bits per transfer = 2"
ghdl -r --std=08 -frelaxed-rules $TB -gg_div_ratio_log2=2 -gg_num_data_bits=2
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_div_ratio_log2=2 -gg_num_data_bits=2
echo "************************************************************************"
echo "TEST CASE 3 "
echo "Clock division ratio = 2, Number of data bits per transfer = 4"
ghdl -r --std=08 -frelaxed-rules $TB -gg_div_ratio_log2=2 -gg_num_data_bits=4
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_div_ratio_log2=2 -gg_num_data_bits=4
echo "************************************************************************"
echo "TEST CASE 4 "
echo "Clock division ratio = 3, Number of data bits per transfer = 4"
ghdl -r --std=08 -frelaxed-rules $TB -gg_div_ratio_log2=3 -gg_num_data_bits=4
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_div_ratio_log2=3 -gg_num_data_bits=4
echo "************************************************************************"
......@@ -37,121 +37,113 @@ library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use std.env.finish;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
use osvvm.NamePkg.all;
use osvvm.AlertLogPkg.all;
entity tb_gc_simple_spi_master is
generic (
g_div_ratio_log2 : integer := 2;
g_num_data_bits : integer := 2);
generic (
g_seed : natural;
g_div_ratio_log2 : integer := 2;
g_num_data_bits : integer := 2);
end entity;
architecture tb of tb_gc_simple_spi_master is
-- constants
constant C_CLK_SYS_PERIOD : time := 10 ns;
-- signals
signal tb_clk_sys_i : std_logic;
signal tb_rst_n_i : std_logic;
signal tb_cs_i : std_logic := '0';
signal tb_start_i : std_logic := '0';
signal tb_cpol_i : std_logic := '0';
signal tb_data_i : std_logic_vector(g_num_data_bits - 1 downto 0) := (others=>'0');
signal tb_ready_o : std_logic;
signal tb_data_o : std_logic_vector(g_num_data_bits - 1 downto 0);
signal tb_spi_cs_n_o : std_logic;
signal tb_spi_sclk_o : std_logic;
signal tb_spi_mosi_o : std_logic;
signal tb_spi_miso_i : std_logic := '0';
-- constants
constant C_CLK_SYS_PERIOD : time := 10 ns;
signal stop : boolean;
signal s_tick : std_logic;
signal s_div : unsigned(11 downto 0);
signal s_mosi : std_logic;
-- signals
signal tb_clk_sys_i : std_logic;
signal tb_rst_n_i : std_logic;
signal tb_cs_i : std_logic := '0';
signal tb_start_i : std_logic := '0';
signal tb_cpol_i : std_logic := '0';
signal tb_data_i : std_logic_vector(g_num_data_bits - 1 downto 0) := (others=>'0');
signal tb_ready_o : std_logic;
signal tb_data_o : std_logic_vector(g_num_data_bits - 1 downto 0);
signal tb_spi_cs_n_o : std_logic;
signal tb_spi_sclk_o : std_logic;
signal tb_spi_mosi_o : std_logic;
signal tb_spi_miso_i : std_logic := '0';
signal stop : boolean;
signal s_tick : std_logic;
signal s_div : unsigned(11 downto 0);
signal s_mosi : std_logic;
type t_state is (IDLE, TX_CS, TX_DAT1, TX_DAT2, TX_SCK1, TX_SCK2, TX_CS2, TX_GAP);
signal s_state : t_state;
signal s_cnt : unsigned(4 downto 0) := (others=>'0');
shared variable sv_cover : covPType;
type t_state is (IDLE, TX_CS, TX_DAT1, TX_DAT2, TX_SCK1, TX_SCK2, TX_CS2, TX_GAP);
signal s_state : t_state;
signal s_cnt : unsigned(4 downto 0) := (others=>'0');
-- Shared variable used for FSM coverage
shared variable sv_cover : covPType;
--------------------------------------------------------------------------------
-- Procedures used for fsm coverage
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Procedures used for fsm coverage --
--------------------------------------------------------------------------------
-- 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)));
wait;
end procedure;
-- 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
procedure fsm_covadd_illegal (
name : in string;
covdb : inout covPType ) is
begin
covdb.AddCross(ALL_ILLEGAL,ALL_ILLEGAL);
wait;
end procedure;
-- 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 := IDLE; --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;
wait;
end procedure;
-- illegal
procedure fsm_covadd_illegal (
name : in string;
covdb : inout covPType ) is
begin
covdb.AddCross(ALL_ILLEGAL,ALL_ILLEGAL);
end procedure;
-- 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 := IDLE; --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.gc_simple_spi_master
generic map (
g_div_ratio_log2 => g_div_ratio_log2,
g_num_data_bits => g_num_data_bits)
port map (
clk_sys_i => tb_clk_sys_i,
rst_n_i => tb_rst_n_i,
cs_i => tb_cs_i,
start_i => tb_start_i,
cpol_i => tb_cpol_i,
data_i => tb_data_i,
ready_o => tb_ready_o,
data_o => tb_data_o,
spi_cs_n_o => tb_spi_cs_n_o,
spi_sclk_o => tb_spi_sclk_o,
spi_mosi_o => s_mosi,
spi_miso_i => s_mosi);
-- Unit Under Test
UUT : entity work.gc_simple_spi_master
generic map (
g_div_ratio_log2 => g_div_ratio_log2,
g_num_data_bits => g_num_data_bits)
port map (
clk_sys_i => tb_clk_sys_i,
rst_n_i => tb_rst_n_i,
cs_i => tb_cs_i,
start_i => tb_start_i,
cpol_i => tb_cpol_i,
data_i => tb_data_i,
ready_o => tb_ready_o,
data_o => tb_data_o,
spi_cs_n_o => tb_spi_cs_n_o,
spi_sclk_o => tb_spi_sclk_o,
spi_mosi_o => s_mosi,
spi_miso_i => s_mosi);
-- Clock generation
-- Clock generation
clk_sys_proc : process
begin
while STOP = FALSE loop
while not stop loop
tb_clk_sys_i <= '1';
wait for C_CLK_SYS_PERIOD/2;
tb_clk_sys_i <= '0';
......@@ -160,209 +152,176 @@ begin
wait;
end process clk_sys_proc;
tb_rst_n_i <= '0', '1' after 4*C_CLK_SYS_PERIOD;
-- Reset generation
tb_rst_n_i <= '0', '1' after 4*C_CLK_SYS_PERIOD;
tb_cpol_i <= '1'; --slave clocks in tha data on rising SCLK edge
-- Slave clocks in the data on risigin SCLK edge
tb_cpol_i <= '1';
-- Stimulus
stim : process
variable seed1, seed2 : integer := 2022;
variable ncycles : natural;
impure function rand_stdl(len:integer:=1) return std_logic is
variable r: real;
variable stdlog : std_logic;
begin
uniform(seed1,seed2,r);
stdlog := '1' when r>0.5 else '0';
return stdlog;
end function;
impure function rand_slv(len:integer) return std_logic_vector is
variable r : real;
variable slv : std_logic_vector(len - 1 downto 0);
begin
for i in slv'range loop
uniform(seed1, seed2, r);
slv(i) := '1' when r>0.5 else '0';
end loop;
return slv;
end function;
-- Stimulus
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING] with seed = " & to_string(g_seed);
while NOW < 4 ms loop
wait until (rising_edge(tb_clk_sys_i) and tb_rst_n_i = '1');
tb_start_i <= data.randSlv(1)(1);
tb_cs_i <= data.randSlv(1)(1);
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= TRUE;
wait;
end process stim;
-- Stimulus for data
stim_data : process
variable data : RandomPType;
variable ncycles : natural;
begin
data.InitSeed(g_seed);
while not stop loop
wait until rising_edge(tb_ready_o);
tb_data_i <= data.randSlv(g_num_data_bits);
wait until rising_edge(tb_ready_o);
ncycles := ncycles + 1;
end loop;
wait;
end process;
begin
while (NOW < 1 ms) loop
wait until (rising_edge(tb_clk_sys_i) and tb_rst_n_i = '1');
tb_start_i <= rand_stdl(1);
tb_cs_i <= rand_stdl(1);
ncycles := ncycles + 1;
end loop;
report "Number of simulation cycles = " & to_string(ncycles);
stop <= TRUE;
wait;
end process stim;
stim_data : process
variable seed1,seed2 : integer := 2021;
impure function rand_slv(len:integer) return std_logic_vector is
variable r : real;
variable slv : std_logic_vector(len - 1 downto 0);
begin
for i in slv'range loop
uniform(seed1, seed2, r);
slv(i) := '1' when r>0.5 else '0';
end loop;
return slv;
end function;
impure function rand_stdl(len:integer:=1) return std_logic is
variable r: real;
variable stdlog : std_logic;
begin
uniform(seed1,seed2,r);
stdlog := '1' when r>0.5 else '0';
return stdlog;
end function;
begin
while (NOW < 1 ms) loop
wait until rising_edge(tb_ready_o);
tb_data_i <= rand_slv(g_num_data_bits);
wait until rising_edge(tb_ready_o);
end loop;
wait;
end process;
-- processs to produce the tick needed for changing the states
-- Simple clock divider like in the RTL code
clk_divide : process(tb_clk_sys_i)
begin
if (rising_edge(tb_clk_sys_i)) then
if (tb_rst_n_i = '0') then
s_div <= (others=>'0');
else
if (tb_start_i = '1' or s_tick = '1') then
s_div <= (others=>'0');
else
s_div <= s_div + 1;
end if;
end if;
-- processs to produce the tick needed for changing the states
-- Simple clock divider like in the RTL code
clk_divide : process(tb_clk_sys_i)
begin
if rising_edge(tb_clk_sys_i) then
if tb_rst_n_i = '0' then
s_div <= (others=>'0');
else
if (tb_start_i = '1' or s_tick = '1') then
s_div <= (others=>'0');
else
s_div <= s_div + 1;
end if;
end process;
end if;
end if;
end process;
s_tick <= s_div(g_div_ratio_log2);
s_tick <= s_div(g_div_ratio_log2);
-- Describe the FSM
fsm_descr : process(tb_clk_sys_i)
begin
if (rising_edge(tb_clk_sys_i)) then
if (tb_rst_n_i='0') then
s_state <= IDLE;
s_cnt <= (others=>'0');
else
case s_state is
when IDLE =>
s_cnt <= (others=>'0');
if (tb_start_i = '1') then
s_state <= TX_CS;
end if;
-- Describe the FSM
fsm_descr : process(tb_clk_sys_i)
begin
if rising_edge(tb_clk_sys_i) then
if tb_rst_n_i='0' then
s_state <= IDLE;
s_cnt <= (others=>'0');
else
case s_state is
when IDLE =>
s_cnt <= (others=>'0');
if tb_start_i = '1' then
s_state <= TX_CS;
end if;
when TX_CS =>
if (s_tick='1') then
s_state <=TX_DAT1;
end if;
when TX_CS =>
if s_tick='1' then
s_state <=TX_DAT1;
end if;
when TX_DAT1 =>
if (s_tick='1') then
s_state <= TX_SCK1;
end if;
when TX_DAT1 =>
if s_tick='1' then
s_state <= TX_SCK1;
end if;
when TX_SCK1 =>
if (s_tick='1') then
s_state <= TX_DAT2;
s_cnt <= s_cnt + 1;
end if;
when TX_SCK1 =>
if s_tick='1' then
s_state <= TX_DAT2;
s_cnt <= s_cnt + 1;
end if;
when TX_DAT2 =>
if (s_tick='1') then
s_state <= TX_SCK2;
end if;
when TX_DAT2 =>
if s_tick='1' then
s_state <= TX_SCK2;
end if;
when TX_SCK2 =>
if (s_tick='1') then
if (s_cnt=g_num_data_bits) then
s_state <= TX_CS2;
else
s_state <= TX_DAT1;
end if;
end if;
when TX_SCK2 =>
if s_tick='1' then
if s_cnt=g_num_data_bits then
s_state <= TX_CS2;
else
s_state <= TX_DAT1;
end if;
end if;
when TX_CS2 =>
if (s_tick='1') then
s_state <= TX_GAP;
end if;
when TX_CS2 =>
if s_tick='1' then
s_state <= TX_GAP;
end if;
when TX_GAP =>
if (s_tick='1') then
s_state <= IDLE;
end if;
when TX_GAP =>
if s_tick='1' then
s_state <= IDLE;
end if;
when others =>
null;
end case;
end if;
end if;
end process;
--------------------------------------------------------------------------------
-- Assertions
--------------------------------------------------------------------------------
when others =>
null;
end case;
end if;
end if;
end process;
-- Assertion - Self checking
process
begin
while (stop = FALSE) loop
wait until s_state = TX_GAP;
assert (tb_data_o = tb_data_i)
report "Data mismatch"
severity error;
end loop;
end process;
--------------------------------------------------------------------------------
-- Assertions --
--------------------------------------------------------------------------------
process
begin
while not stop loop
wait until s_state = TX_GAP;
assert (tb_data_o = tb_data_i)
report "Data mismatch" severity failure;
end loop;
end process;
--------------------------------------------------------------------------------
-- Coverage
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Coverage --
--------------------------------------------------------------------------------
process
begin
-- All possible legal changes
fsm_covadd_states("IDLE->TX_CS ", IDLE, TX_CS, sv_cover);
fsm_covadd_states("TX_CS->TX_DAT1 ", TX_CS, TX_DAT1, sv_cover);
fsm_covadd_states("IDLE ->TX_CS ", IDLE, TX_CS, sv_cover);
fsm_covadd_states("TX_CS ->TX_DAT1", TX_CS, TX_DAT1, sv_cover);
fsm_covadd_states("TX_DAT1->TX_SCK1", TX_DAT1, TX_SCK1, sv_cover);
fsm_covadd_states("TX_SCK1->TX_DAT2", TX_SCK1, TX_DAT2, sv_cover);
fsm_covadd_states("TX_DAT2->TX_SCK2", TX_DAT2, TX_SCK2, sv_cover);
fsm_covadd_states("TX_SCK2->TX_DAT1", TX_SCK2, TX_DAT1, sv_cover);
fsm_covadd_states("TX_SCK2->TX_CS2 ", TX_SCK2, TX_CS2, sv_cover);
fsm_covadd_states("TX_CS2->TX_GAP ", TX_CS2, TX_GAP, sv_cover);
fsm_covadd_states("TX_GAP->IDLE ", TX_GAP, IDLE, sv_cover);
fsm_covadd_states("TX_CS2 ->TX_GAP ", TX_CS2, TX_GAP, sv_cover);
fsm_covadd_states("TX_GAP ->IDLE ", TX_GAP, IDLE, sv_cover);
-- we have also the case where we stay for many clocks in the same state
fsm_covadd_states("IDLE->IDLE ", IDLE, IDLE, sv_cover);
fsm_covadd_states("TX_CS->TX_CS ", TX_CS, TX_CS, sv_cover);
fsm_covadd_states("IDLE ->IDLE ", IDLE, IDLE, sv_cover);
fsm_covadd_states("TX_CS ->TX_CS ", TX_CS, TX_CS, sv_cover);
fsm_covadd_states("TX_DAT1->TX_DAT1", TX_DAT1, TX_DAT1, sv_cover);
fsm_covadd_states("TX_SCK1->TX_SCK1", TX_SCK1, TX_SCK1, sv_cover);
fsm_covadd_states("TX_DAT2->TX_DAT2", TX_DAT2, TX_DAT2, sv_cover);
fsm_covadd_states("TX_SCK2->TX_SCK2", TX_SCK2, TX_SCK2, sv_cover);
fsm_covadd_states("TX_CS2->TX_CS2 ", TX_CS2, TX_CS2, sv_cover);
fsm_covadd_states("TX_GAP->TX_GAP ", TX_GAP, TX_GAP, sv_cover);
fsm_covadd_states("TX_CS2 ->TX_CS2 ", TX_CS2, TX_CS2, sv_cover);
fsm_covadd_states("TX_GAP ->TX_GAP ", TX_GAP, TX_GAP, sv_cover);
fsm_covadd_illegal("ILLEGAL ", sv_cover);
fsm_covcollect(tb_rst_n_i, tb_clk_sys_i, s_state,sv_cover);
wait;
end process;
fsm_covcollect(tb_rst_n_i, tb_clk_sys_i, s_state,sv_cover);
-- coverage report
cov_report : process
begin
wait until stop ;
sv_cover.writebin;
report "Test PASS!";
end process;
-- coverage report
cov_report : process
begin
wait until stop ;
sv_cover.writebin;
end process;
end tb;
Testbench to verify the functionality of the gc_single_reset_gen general core. It uses GHDL simulator and OSVVM verification methodology. This core is having 2 generics in the entity:
- g_out_reg_depth : Number of Flip-Flos before the signal's output
- g_rst_in_num : Number of input async reset signals
The testcases of the testbench can arise from a combination of these generics. There can be many testcases, but in here there are tested the following: (1,1), (2,2), (4,5), (2,8).
The testing process is very simple. It receives random input data (with random seeds). It uses a similar logic to the one that RTL uses and generates a testbench output. Some assertions exist in the testbench to bring self-checking capabilities in it, which are:
- Check that the number of f/f before the final signals' output is valid
- Check that number of asynchronous reset signals is valid
- Compare the output reset of testbench to be the same as the one from RTL core
- Reset to not be asserted before the powerup
Simple coverage is being covered also:
- Powerup has done (at least 1 time per simulation)
......@@ -5,18 +5,25 @@
TB=tb_gc_single_reset_gen
echo "Running simulation for $TB"
echo ""
echo "TEST CASE 1 "
echo "Number of FF's before the final reset signal = 1, number of input async reset signals = 1"
ghdl -r --std=08 -frelaxed-rules $TB -gg_out_reg_depth=1 -gg_rst_in_num=1
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_out_reg_depth=1 -gg_rst_in_num=1
echo "*****************************************************************************************"
echo "TEST CASE 2 "
echo "Number of FF's before the final reset signal = 2, number of input async reset signals = 2"
ghdl -r --std=08 -frelaxed-rules $TB -gg_out_reg_depth=2 -gg_rst_in_num=2
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_out_reg_depth=2 -gg_rst_in_num=2
echo "*****************************************************************************************"
echo "TEST CASE 3 "
echo "Number of FF's before the final reset signal = 4, number of input async reset signals = 5"
ghdl -r --std=08 -frelaxed-rules $TB -gg_out_reg_depth=4 -gg_rst_in_num=5
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_out_reg_depth=4 -gg_rst_in_num=5
echo "*****************************************************************************************"
echo "TEST CASE 4 "
echo "Number of FF's before the final reset signal = 2, number of input async reset signals = 8"
ghdl -r --std=08 -frelaxed-rules $TB -gg_out_reg_depth=2 -gg_rst_in_num=8
ghdl -r --std=08 -frelaxed-rules $TB -gg_seed=$RANDOM -gg_out_reg_depth=2 -gg_rst_in_num=8
echo "*****************************************************************************************"
......@@ -43,196 +43,179 @@ use ieee.numeric_std.all;
use work.gencores_pkg.all;
use ieee.math_real.all;
use std.env.finish;
-- OSVVM library
library osvvm;
use osvvm.RandomPkg.all;
use osvvm.CoveragePkg.all;
entity tb_gc_single_reset_gen is
generic (
g_out_reg_depth : natural := 4;
g_rst_in_num : natural := 5);
generic (
g_seed : natural;
g_out_reg_depth : natural := 4;
g_rst_in_num : natural := 5);
end entity;
architecture tb of tb_gc_single_reset_gen is
-- Constants and signals
constant C_CLK_PERIOD : time := 10 ns;
constant ONES : std_logic_vector(g_rst_in_num-1 downto 0) := (others => '1');
signal tb_clk_i : std_logic;
signal tb_rst_signals_n_a_i : std_logic_vector(g_rst_in_num-1 downto 0) := (others=>'0');
signal tb_rst_n_o : std_logic;
signal stop : boolean;
type t_rst_signals_array is array (0 to 3) of std_logic_vector(g_rst_in_num-1 downto 0);
signal s_rst_signals_arr : t_rst_signals_array;
signal s_cnt_powerup : unsigned(7 downto 0) := (others=>'0');
signal s_powerup : std_logic;
signal s_rst_n : std_logic;
signal s_rst_n_o : std_logic_vector(g_out_reg_depth-1 downto 0):= (others => '0');
-- used for coverage
shared variable cp_powerup : covPType;
-- Constants
constant C_CLK_PERIOD : time := 10 ns;
constant ONES : std_logic_vector(g_rst_in_num-1 downto 0) := (others => '1');
-- Signals
signal tb_clk_i : std_logic;
signal tb_rst_signals_n_a_i : std_logic_vector(g_rst_in_num-1 downto 0) := (others=>'0');
signal tb_rst_n_o : std_logic;
signal stop : boolean;
type t_rst_signals_array is array (0 to 3) of std_logic_vector(g_rst_in_num-1 downto 0);
signal s_rst_signals_arr : t_rst_signals_array;
signal s_cnt_powerup : unsigned(7 downto 0) := (others=>'0');
signal s_powerup : std_logic;
signal s_rst_n : std_logic;
signal s_rst_n_o : std_logic_vector(g_out_reg_depth-1 downto 0):= (others => '0');
-- Shared variable, used for coverage
shared variable cp_powerup : covPType;
begin
-- Unit Under Test
UUT : entity work.gc_single_reset_gen
generic map (
g_out_reg_depth => g_out_reg_depth,
g_rst_in_num => g_rst_in_num)
port map (
clk_i => tb_clk_i,
rst_signals_n_a_i => tb_rst_signals_n_a_i,
rst_n_o => tb_rst_n_o);
-- Clock and reset generation
clk_i_process : process
begin
while (stop = FALSE) 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;
-- Stimulus
stim : process
variable ncycles : natural;
variable seed1,seed2 : integer := 1992;
impure function rand_slv(len:integer) return std_logic_vector is
variable r : real;
variable slv : std_logic_vector(len - 1 downto 0);
begin
for i in slv'range loop
uniform(seed1, seed2, r);
slv(i) := '1' when r>0.5 else '0';
end loop;
return slv;
end function;
begin
while (NOW < 1 ms) loop
wait until (rising_edge(tb_clk_i));
tb_rst_signals_n_a_i <= rand_slv(g_rst_in_num);
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles = " & to_string(ncycles);
report "Test PASS!";
stop <= TRUE;
wait;
end process stim;
--------------------------------------------------------------------------------
-- Stimulate the behavior of the RTL module
--------------------------------------------------------------------------------
-- Unit Under Test
UUT : entity work.gc_single_reset_gen
generic map (
g_out_reg_depth => g_out_reg_depth,
g_rst_in_num => g_rst_in_num)
port map (
clk_i => tb_clk_i,
rst_signals_n_a_i => tb_rst_signals_n_a_i,
rst_n_o => tb_rst_n_o);
-- Clock generation
clk_i_process : 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;
-- Stimulus
stim : process
variable ncycles : natural;
variable data : RandomPType;
begin
data.InitSeed(g_seed);
report "[STARTING Slave] with seed = " & to_string(g_seed);
while NOW < 2 ms loop
wait until rising_edge(tb_clk_i);
tb_rst_signals_n_a_i <= data.randSlv(g_rst_in_num);
ncycles := ncycles + 1;
end loop;
report "Number of Simulation cycles = " & to_string(ncycles);
report "Test PASS!";
stop <= TRUE;
wait;
end process stim;
--------------------------------------------------------------------------------
-- Stimulate the behavior of the RTL module --
--------------------------------------------------------------------------------
-- generate the synchronized input reset signals
-- 3 clock cycles delay due to gc_sync_ffs
process (tb_clk_i)
begin
if (rising_edge(tb_clk_i)) then
s_rst_signals_arr(0) <= tb_rst_signals_n_a_i;
for i in 0 to 2 loop
s_rst_signals_arr(i+1) <= s_rst_signals_arr(i);
end loop;
end if;
end process;
-- powerup reset
process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if (s_cnt_powerup /= X"FF") then
s_cnt_powerup <= s_cnt_powerup + 1;
s_powerup <= '0';
else
s_powerup <= '1';
end if;
end if;
end process;
s_rst_n <= '1' when (s_powerup='1' and s_rst_signals_arr(2)= ONES) else '0';
-- generate the synchronized input reset signals
-- 3 clock cycles delay due to gc_sync_ffs
process (tb_clk_i)
begin
if rising_edge(tb_clk_i) then
s_rst_signals_arr(0) <= tb_rst_signals_n_a_i;
for i in 0 to 2 loop
s_rst_signals_arr(i+1) <= s_rst_signals_arr(i);
end loop;
end if;
end process;
-- powerup reset
process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if s_cnt_powerup /= X"FF" then
s_cnt_powerup <= s_cnt_powerup + 1;
s_powerup <= '0';
else
s_powerup <= '1';
end if;
end if;
end process;
s_rst_n <= '1' when (s_powerup='1' and s_rst_signals_arr(2)= ONES) else '0';
-- reset after flip-flops
-- final reset is s_rst_n_o(0)
process(tb_clk_i)
begin
if (rising_edge(tb_clk_i)) then
s_rst_n_o <= s_rst_n & s_rst_n_o(g_out_reg_depth-1 downto 1);
end if;
end process;
--------------------------------------------------------------------------------
-- Assertions
--------------------------------------------------------------------------------
-- Check that the number of f/f before the final signals' output is valid
assert (g_out_reg_depth > 0)
report "Invalid output register depth"
severity failure;
-- Check that number of asynchronous reset signals is valid
assert (g_rst_in_num > 0)
report "Invalid number of async reset signals"
severity failure;
check_output : process(tb_clk_i)
begin
if (rising_edge(tb_clk_i)) then
assert (s_rst_n_o(0) = tb_rst_n_o)
report "Reset mismatch"
severity failure;
end if;
end process;
no_output_before_powerup : process(tb_clk_i)
begin
if (rising_edge(tb_clk_i)) then
if (s_powerup = '0') then
assert (tb_rst_n_o = '0')
report "Reset asserted before powerup"
severity failure;
end if;
end if;
end process;
--------------------------------------------------------------------------------
-- Coverage
--------------------------------------------------------------------------------
-- reset after flip-flops
-- final reset is s_rst_n_o(0)
process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
s_rst_n_o <= s_rst_n & s_rst_n_o(g_out_reg_depth-1 downto 1);
end if;
end process;
--------------------------------------------------------------------------------
-- Assertions --
--------------------------------------------------------------------------------
-- Check that the number of f/f before the final signals' output is valid
assert (g_out_reg_depth > 0)
report "Invalid output register depth" severity failure;
-- Check that number of asynchronous reset signals is valid
assert (g_rst_in_num > 0)
report "Invalid number of async reset signals" severity failure;
check_output : process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
assert (s_rst_n_o(0) = tb_rst_n_o)
report "Reset mismatch" severity failure;
end if;
end process;
no_output_before_powerup : process(tb_clk_i)
begin
if rising_edge(tb_clk_i) then
if s_powerup = '0' then
assert (tb_rst_n_o = '0')
report "Reset asserted before powerup" severity failure;
end if;
end if;
end process;
--------------------------------------------------------------------------------
-- Coverage --
--------------------------------------------------------------------------------
-- Set up coverpoint bins
init_coverage : process
begin
cp_powerup.AddBins("powerup has done", ONE_BIN);
wait;
end process;
-- Set up coverpoint bins
init_coverage : process
begin
cp_powerup.AddBins("powerup has done", ONE_BIN);
wait;
end process;
-- Sample the coverpoints
sample_powerup_cov : process
begin
loop
wait until (rising_edge(s_powerup));
cp_powerup.ICover(to_integer(s_powerup='1'));
end loop;
end process;
-- Coverage report
cover_report : process
begin
wait until stop;
cp_powerup.Writebin;
end process;
-- Sample the coverpoints
sample_powerup_cov : process
begin
loop
wait until (rising_edge(s_powerup));
cp_powerup.ICover(to_integer(s_powerup='1'));
end loop;
end process;
-- Coverage report
cover_report : process
begin
wait until stop;
cp_powerup.Writebin;
end process;
end tb;
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