Commit 0a83591a authored by Francis Fuentes's avatar Francis Fuentes Committed by Guillem
Browse files

Test to support Questa-sim testbench

parent 57efe64e
injector_ahb.vhd # Project files to test with SpyGlass
injector.vhd /home/ffuentes/GitHub/bsc_safeti/hdl/injector_ahb.vhd
injector_apb.vhd /home/ffuentes/GitHub/bsc_safeti/hdl/injector.vhd
injector_ctrl.vhd /home/ffuentes/GitHub/bsc_safeti/hdl/injector_apb.vhd
fifo.vhd /home/ffuentes/GitHub/bsc_safeti/hdl/injector_ctrl.vhd
injector_delay_if.vhd /home/ffuentes/GitHub/bsc_safeti/hdl/fifo.vhd
injector_read_if.vhd /home/ffuentes/GitHub/bsc_safeti/hdl/injector_delay_if.vhd
injector_write_if.vhd /home/ffuentes/GitHub/bsc_safeti/hdl/injector_read_if.vhd
/home/ffuentes/GitHub/bsc_safeti/hdl/injector_write_if.vhd
# BSC library files
bsc bsc
bsc/injector_pkg.vhd /home/ffuentes/GitHub/bsc_safeti/hdl/injector_pkg.vhd
This diff is collapsed.
------------------------------------------------------------------------------
-- Package: injector_pkg_selene
-- File: injector_pkg_selene.vhd
-- Author: Francis Fuentes
-- Description: Internal package for AHB interface of the injector.
-- Only to be loaded by the platform.
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library grlib;
use grlib.amba.all;
library techmap;
use techmap.gencomp.all;
package injector_pkg_selene is
-- AHB interface wrapper for SELENE platform
component injector_ahb_SELENE is
generic (
tech : integer range 0 to NTECH := inferred;
-- APB configuration
pindex : integer := 0;
paddr : integer := 0;
pmask : integer := 16#FF8#;
pirq : integer range 0 to NAHBIRQ-1 := 0;
-- Bus master configuration
dbits : integer range 32 to 128 := 32;
hindex : integer := 0;
max_burst_length : integer range 2 to 256 := 128;
MAX_SIZE_BEAT : integer range 32 to 1024 := 1024
);
port (
rstn : in std_ulogic;
clk : in std_ulogic;
-- APB interface signals
apbi : in apb_slv_in_type;
apbo : out apb_slv_out_type;
-- AHB interface signals
ahbmi : in ahb_mst_in_type;
ahbmo : out ahb_mst_out_type
);
end component injector_ahb_SELENE;
end package injector_pkg_selene;
package body injector_pkg_selene is
end package body injector_pkg_selene;
#$1
TOP=../../..
vlib bsc
vmap work $PWD/bsc
vlog +acc=rn +incdir+$TOP/hdl/injector_pkg $TOP/tb/tb_injector_pkg
vlib tb_injector
vmap work $PWD/tb_injector
vlog +acc=rn +incdir+$TOP/hdl/ $TOP/hdl/injector $TOP/hdl/injector_apb $TOP/hdl/injector_ctrl $TOP/hdl/injector_delay_if $TOP/hdl/injector_read_if $TOP/hdl/injector_write_if tb_injector.sv ./colors.vh
vmake tb_injector/ > Makefile
if [ -z "$1" ]
then
vsim work.tb_injector # -do "view wave -new" -do "do wave.do" -do "run -all"
else
vsim work.tb_injector $1 # -do "do save_wave.do"
fi
-----------------------------------------------------------------------------
-- Entity: tb_injector
-- File: tb_injector.vhd
-- Author: Francis Fuentes
-- Description: Testbench injector top level entity.
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library bsc;
use bsc.injector_pkg.all;
use bsc.tb_injector_pkg.all;
-----------------------------------------------------------------------------
-- Top level testbench entity for injector.
--
-- This testbench tests, previous to the AHB/AXI interface (on BM bus), the following:
-- Load of the descriptors (tests 1 and 2),
-- Transaction repetition (test 1),
-- Queue mode (test 1),
-- Injector reset (end of test 1 and to change between read and write vectors on test 2),
-- Transaction size on fixed/unfixed address (test 2) on both read and writes.
--
-----------------------------------------------------------------------------
entity tb_injector is
generic (
tech : integer range 0 to numTech := 65; -- Target technology
-- APB configuration
pindex : integer := 6; -- APB configuartion slave index
paddr : integer := 16#850#; -- APB configuartion slave address
pmask : integer := 16#FFF#; -- APB configuartion slave mask
pirq : integer range 0 to APB_IRQ_NMAX-1 := 6; -- APB configuartion slave irq
-- Bus master configuration
dbits : integer range 32 to 128 := 32; -- Data width of BM and FIFO
hindex : integer := 5; -- AHB master index
MAX_SIZE_BEAT : integer range 32 to 1024 := 1024; -- Maximum size of a beat at a burst transaction.
-- Injector configuration
ASYNC_RST : boolean := FALSE -- Allow asynchronous reset flag
);
end entity tb_injector;
architecture rtl of tb_injector is
-----------------------------------------------------------------------------
-- Constant declaration
-----------------------------------------------------------------------------
-- Pointers
constant apb_injector : std_logic_vector(31 downto 0) := 16#000# & paddr & 16#00#; -- Location of the injector at APB memory
constant descr_addr1 : std_logic_vector(31 downto 0) := X"0100_0000"; -- First descriptor MSB address for test 1
constant descr_addr2w : std_logic_vector(31 downto 0) := X"0110_0000"; -- First descriptor MSB address for test 2 writes
constant descr_addr2r : std_logic_vector(31 downto 0) := X"0120_0000"; -- First descriptor MSB address for test 2 reads
constant action_addr : std_logic_vector(31 downto 0) := X"0200_0000"; -- Write/read address
-- Injector configurations
-- Test 1 configuration: Queue mode enabled, enable interrupt on error, (interrupt disabled), (kick disabled), nreset, start injector.
constant inj_config1 : std_logic_vector(31 downto 0) := X"0000_00" & "00" & "110011";
-- Test 2 configuration: (Queue mode disabled), enable interrupt on error, (interrupt disabled), (kick disabled), nreset, start injector.
constant inj_config2 : std_logic_vector(31 downto 0) := X"0000_00" & "00" & "010011";
-- Descriptors to load into injector's fifo for test 1 (size, count, action, addr, addrfix, nextraddr, last)
constant descriptors1 : descriptor_bank(0 to 7) := (
write_descriptor( 4, 63, WRT, action_addr, '1', descr_addr1 + 0, '0' ) & -- 64 write transactions of 4 bytes
write_descriptor( 8, 31, WRT, action_addr, '1', descr_addr1 + 20, '0' ) & -- 32 write transactions of 8 bytes
write_descriptor( 16, 15, RD, action_addr, '1', descr_addr1 + 40, '0' ) & -- 16 read transactions of 16 bytes
write_descriptor( 32, 7, RD, action_addr, '1', descr_addr1 + 60, '0' ) & -- 8 read transactions of 32 bytes
write_descriptor( 64, 3, WRT, action_addr, '1', descr_addr1 + 80, '0' ) & -- 4 write transactions of 64 bytes
write_descriptor( 128, 1, WRT, action_addr, '1', descr_addr1 + 100, '0' ) & -- 2 write transactions of 128 bytes
write_descriptor( 256, 0, RD, action_addr, '1', descr_addr1 + 120, '1' ) -- 1 read transaction of 256 bytes
);
-- Descriptors to load into injector's fifo for test 2 write (size, count, action, addr, addrfix, nextraddr, last)
constant descriptors2w : descriptor_bank(0 to 5) := (
write_descriptor( MAX_SIZE_BEAT-3, 0, WRT, action_addr, '0', descr_addr2w + 0, '0' ), -- Check if writes the correct ammount below size beat
write_descriptor( MAX_SIZE_BEAT, 0, WRT, action_addr, '0', descr_addr2w + 20, '0' ), -- Check if writes the correct ammount equal size beat
write_descriptor( MAX_SIZE_BEAT+3, 0, WRT, action_addr, '0', descr_addr2w + 40, '0' ), -- Check if writes the correct ammount above size beat
write_descriptor( 3, 0, WRT, action_addr, '1', descr_addr2w + 60, '0' ), -- With fix addr, check if reads lower of a word
write_descriptor( 4, 0, WRT, action_addr, '1', descr_addr2w + 80, '0' ), -- With fix addr, check if reads a word
write_descriptor( 15, 0, WRT, action_addr, '1', descr_addr2w + 100, '1' ) -- With fix addr, check if it really fixes the addr
);
-- Descriptors to load into injector's fifo for test 2 read (size, count, action, addr, addrfix, nextraddr, last)
constant descriptors2r : descriptor_bank(0 to 5) := (
write_descriptor( MAX_SIZE_BEAT-3, 0, RD, action_addr, '0', descr_addr2r + 0, '0' ), -- Check if writes the correct ammount below size beat
write_descriptor( MAX_SIZE_BEAT, 0, RD, action_addr, '0', descr_addr2r + 20, '0' ), -- Check if writes the correct ammount equal size beat
write_descriptor( MAX_SIZE_BEAT+3, 0, RD, action_addr, '0', descr_addr2r + 40, '0' ), -- Check if writes the correct ammount above size beat
write_descriptor( 3, 0, RD, action_addr, '1', descr_addr2r + 60, '0' ), -- With fix addr, check if reads lower of a word
write_descriptor( 4, 0, RD, action_addr, '1', descr_addr2r + 80, '0' ), -- With fix addr, check if reads a word
write_descriptor( 15, 0, RD, action_addr, '1', descr_addr2r + 100, '1' ) -- With fix addr, check if it really fixes the addr
);
-----------------------------------------------------------------------------
-- Records and types
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Signal declaration
-----------------------------------------------------------------------------
-- Injector I/O + Initial input values
signal clk : std_ulogic := '0';
signal rstn : std_ulogic := '0';
signal apbo : apb_slave_out_type;
signal bm_in : bm_in_type;
signal apbi : apb_slave_in_type := DEF_INJ_APB;
signal bm_out : bm_out_type := DEF_INJ_BM;
-----------------------------------------------------------------------------
-- Function/procedure declaration
-----------------------------------------------------------------------------
begin -- rtl
-----------------
-- Assignments --
-----------------
-- Clock generation
clk <= not clk after T/2;
-----------------------------------------------------------------------------
-- Sequential process
-----------------------------------------------------------------------------
test : process
begin
-- Configure injector for test 1
apbi.sel <= std_logic_vector(shift_left(16#0000_0001#, pindex), 32);
apbi.addr <= apb_injector + 8; -- Write 1st descriptor pointer
apbi.wdata <= descr_addr1; -- Test 1 descriptors pointer
wait for T + 3 ns;
rstn <= '1';
wait for rising_edge(clk);
apbi.write <= '1';
wait for T;
apbi.write <= '0';
apbi.addr <= apb_injector; -- Configure injector
apbi.wdata <= inj_config1; -- Test 1 configuration
wait for T;
apbi.write <= '1';
wait for 3*T;
if(FALSE) then
assert TRUE report "Test 1: load configuration FAILED!" severity error;
else report "Test 1: load configuration passed!\n Starting to load descriptors.\n\n";
end if;
wait for rising_edge(bm_in.rd_req);
if(bm_in.rd_addr = descr_addr1) then
read_descr(descriptors1, bm_out.rd_data, bm_out.rd_valid, bm_out.rd_done, bm_in.rd_req, bm_out.rd_req_grant);
else assert TRUE report "Test 1: load descriptors FAILED!" severity error;
end if; report "Test 1: load descriptors passed!\n Executing Test 1.\n\n";
end process test;
-----------------------------------------------------------------------------
-- Component instantiation
-----------------------------------------------------------------------------
-- injector core
core : injector
generic map (
tech => tech,
pindex => pindex,
paddr => paddr,
pmask => pmask,
pirq => pirq,
dbits => dbits,
MAX_SIZE_BEAT => MAX_SIZE_BEAT
)
port map (
rstn => rstn,
clk => clk,
apbi => apbi,
apbo => apbo,
bm0_in => bm_in,
bm0_out => bm_out
);
end architecture rtl;
-----------------------------------------------------------------------------
-- Entity: tb_injector_pkg
-- File: tb_injector_pkg.vhd
-- Author: Francis Fuentes
-- Description: Package for injector testbenches.
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library bsc;
use bsc.injector_pkg.all;
-----------------------------------------------------------------------------
-- Top level entity for injector.
-- This is a wrapper which integrates injector core to the
-- AHB master - generic bus master bridge
-----------------------------------------------------------------------------
package tb_injector_pkg is
-----------------------------------------------------------------------------
-- Constant declaration
-----------------------------------------------------------------------------
constant T : time := 5 ns; -- Clock cycle period
-- Injector actions
constant RD : std_logic_vector(2 downto 0) := "000"; -- Read
constant WRT : std_logic_vector(2 downto 0) := "001"; -- Write
constant DELY : std_logic_vector(2 downto 0) := "010"; -- Delay (wait)
-- APB input stimulus to start injector
constant DEF_INJ_APB : apb_slave_in_type := (
sel => (others => '0'),
en => '0',
addr => (others => '0'),
write => '0',
wdata => (others => '0'),
irq => (others => '0'),
ten => '0',
trst => '1',
scnen => '0',
touten => '1',
tinen => (others => '0')
);
-- BM output (injector input) default state
constant DEF_INJ_BM : bm_out_type := (
rd_data => (others => '0'),
rd_req_grant => '1',
rd_valid => '0',
rd_done => '0',
rd_err => '0',
wr_req_grant => '1',
wr_full => '1',
wr_done => '0',
wr_err => '0'
);
-----------------------------------------------------------------------------
-- Records and types
-----------------------------------------------------------------------------
-- Since we are working with many descriptors, it's better to use both types
type descriptor_words is array (0 to 4) of std_logic_vector(31 downto 0); -- 5 word descriptor
type descriptor_bank is array (natural range <>) of descriptor_words; -- X number of descriptors
-----------------------------------------------------------------------------
-- Function/procedure declaration
-----------------------------------------------------------------------------
-- Function used to generate descriptors to be loaded into the injector
function write_descriptor(size : integer range 0 to 524287; -- Total size of a transfer
count : integer range 0 to 63; -- Number of repeats of the transfer
action : std_logic_vector(2 downto 0); -- Transaction type (read, write, delay)
addr : std_logic_vector(31 downto 0); -- Initial address to apply transaction
addrfix : std_ulogic; -- Address to write/read is fixed when asserted
nextaddr : std_logic_vector(31 downto 0); -- Address to load from the next descriptor
last : std_ulogic -- Last descriptor flag
) return descriptor_words;
-- Procedure used to simulate a memory fetch to load descriptors for a test
procedure read_descr(
variable descriptor_bank : in descriptor_bank;
signal rdata : out std_logic_vector(31 downto 0);
signal valid : out std_logic := '0';
signal done : out std_logic := '0';
signal req : in std_logic;
signal req_grant : out std_logic := '1'
);
end package tb_injector_pkg;
package body tb_injector_pkg is
-----------------------------------------------------------------------------
-- Sequential process
-----------------------------------------------------------------------------
function write_descriptor(size : integer range 0 to 524287; -- Total size of a transfer
count : integer range 0 to 63; -- Number of repeats of the transfer
action : std_logic_vector(2 downto 0); -- Transaction type (read, write, delay)
addr : std_logic_vector(31 downto 0); -- Initial address to apply transaction
addrfix : std_ulogic; -- Address to write/read is fixed when asserted
nextaddr : std_logic_vector(31 downto 0); -- Address to load from the next descriptor
last : std_ulogic -- Last descriptor flag
) return descriptor_words is
variable descr_words : descriptor_words := (others => (others => '0'));
variable src_addr, dest_addr : std_ulogic := '0';
variable src_fix_addr, dest_fix_addr, size_std, count_std : std_logic_vector(31 downto 0) := (others => '0');
begin
size_std := std_logic_vector( unsigned(size, size_std'length ) );
count_std := std_logic_vector( unsigned(count, count_std'length) );
case action is
when READ =>
src_addr := addr;
src_fix_addr := addrfix;
when WRITE =>
dest_addr := addr;
dest_fix_addr := addrfix;
when others =>
null;
end case;
descr_words := (
size_std & --0x00 Injector control word
count_std &
dest_fix_addr &
src_fix_addr &
'1' & -- enable interrupt on descriptor completion
action &
'1' , -- enable descriptor
nextaddr(31 downto 1) & --0x04 Injector First descriptor pointer
last ,
dest_addr , --0x08 Write address
src_addr , --0x0C Read address
16#0000_0000# --0x10 Descriptor status word (for future implementation)
);
return descr_words;
end write_descriptor;
procedure read_descr(
variable descriptor_bank : in descriptor_bank;
signal rdata : out std_logic_vector(31 downto 0);
signal valid : out std_logic := '0';
signal done : out std_logic := '0';
signal req : in std_logic;
signal req_grant : out std_logic := '1'
) is
variable descriptor : descriptor_words;
begin
for j in descriptor_bank'range loop -- Loop between descriptors
descriptor := descriptor_bank(j);
wait for falling_edge(req);
req_grant <= '0';
for i in descriptor'range loop -- Loop for a single descriptor
valid <= '0';
rdata <= descriptor(i);
wait for T;
done <= (i = (descriptor'length - 1));
valid <= '1';
wait for T;
end loop;
rdata <= (others => '0');
done <= '0';
valid <= '0';
end loop;
end read_descr;
-----------------------------------------------------------------------------
-- Component instantiation
-----------------------------------------------------------------------------
end package body tb_injector_pkg;
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