Added test package and guide into documentation

This commit is contained in:
Thomas Fehmel
2017-06-28 07:42:58 -05:00
parent 8ee16f963b
commit 776cecb671
10 changed files with 483 additions and 134 deletions

View File

@@ -8,7 +8,18 @@ use ieee.std_logic_textio.all;
package can_tp is
type rx_check_result is (success, can_error, arbitration_lost, no_ack);
constant wbs_in_default : wb_slv_in_type := (
(others=>'-'), -- adr
(others=>'-'), -- dat
'-', -- we
(others => '-'), -- sel
'0', -- stb
'0', -- cyc
"000", -- cti
"00" -- bte
);
procedure can_wb_write_reg(
signal wbs_in : out wb_slv_in_type;
signal wbs_out : in wb_slv_out_type;
@@ -22,14 +33,28 @@ package can_tp is
constant addr : in integer;
signal clk : in std_logic);
procedure can_wb_read_reg(
signal wbs_in : out wb_slv_in_type;
signal wbs_out : in wb_slv_out_type;
constant addr : in integer;
signal data : out std_logic_vector(7 downto 0);
signal clk : in std_logic);
procedure write_regs_from_file(
constant filename : in string;
signal wbs_in : out wb_slv_in_type;
signal wbs_out : in wb_slv_out_type;
signal clk : in std_logic);
-- procedure read_regs_with_fileaddr(
-- constant filename : in string;
-- signal wbs_in : out wb_slv_in_type;
-- signal wbs_out : in wb_slv_out_type;
-- signal clk : in std_logic);
procedure read_regs_with_fileaddr(
constant filename : in string;
constant out_filename : in string;
signal wbs_in : out wb_slv_in_type;
signal wbs_out : in wb_slv_out_type;
signal clk : in std_logic);
@@ -46,6 +71,11 @@ package can_tp is
constant data : std_logic_vector(7 downto 0)
) return std_logic_vector;
function canwb2data(
constant data_in : std_logic_vector(63 downto 0);
constant sel : std_logic_vector(3 downto 0)
) return std_logic_vector;
function can_crc(
constant data: in std_logic_vector(0 to 63);
constant datasize: in integer)return std_logic_vector;
@@ -119,7 +149,23 @@ package body can_tp is
return wbcan_data;
end data2canwb;
--does a asynchronous wb-single-write-handshake and writes to an register of the can controller
function canwb2data(
constant data_in : std_logic_vector(31 downto 0);
constant sel : std_logic_vector(3 downto 0)
) return std_logic_vector is
variable data_out : std_logic_vector(7 downto 0);
begin
case sel is
when "1000" => data_out := data_in (31 downto 24);
when "0100" => data_out := data_in(23 downto 16);
when "0010" => data_out := data_in(15 downto 8);
when "0001" => data_out := data_in(7 downto 0);
when others => data_out := "0000"; -- should not occour
end case;
return data_out;
end canwb2data;
--does a synchronous wb-single-write-handshake with waitstates and writes to an register of the can controller
procedure can_wb_write_reg(
signal wbs_in : out wb_slv_in_type;
signal wbs_out : in wb_slv_out_type;
@@ -169,6 +215,18 @@ package body can_tp is
wbs_in.dat <= (others=>'-');
wbs_in.adr <= (others=>'-');
end can_wb_read_reg;
procedure can_wb_read_reg(
signal wbs_in : out wb_slv_in_type;
signal wbs_out : in wb_slv_out_type;
constant addr : integer;
signal data : out std_logic_vector(7 downto 0);
signal clk : in std_logic) is
begin
can_wb_read_reg(wbs_in, wbs_out, addr, clk);
data <= canwb2data(wbs_out.dat, canint2sel(addr));
end can_wb_read_reg;
@@ -190,25 +248,57 @@ package body can_tp is
can_wb_write_reg(wbs_in, wbs_out, addr, data, clk);
wait for 50 ns;
end loop;
file_close(sourcefile);
end procedure write_regs_from_file;
-- procedure read_regs_with_fileaddr(
-- constant filename : in string;
-- signal wbs_in : out wb_slv_in_type;
-- signal wbs_out : in wb_slv_out_type;
-- signal clk : in std_logic) is
--
-- file sourcefile : text open read_mode is filename;
-- variable input_line : line;
-- variable output_line : line;
-- variable addr : integer;
-- begin
-- while not endfile(sourcefile) loop
-- readline(sourcefile, input_line); --read line
-- read(input_line, addr); --read addr of register
-- can_wb_read_reg(wbs_in, wbs_out, addr, clk);
-- wait for 50 ns;
-- end loop;
-- file_close(sourcefile);
-- end procedure read_regs_with_fileaddr;
procedure read_regs_with_fileaddr(
constant filename : in string;
constant out_filename : in string;
signal wbs_in : out wb_slv_in_type;
signal wbs_out : in wb_slv_out_type;
signal clk : in std_logic) is
file sourcefile : text open read_mode is filename;
file targetfile : text open write_mode is out_filename;
variable input_line : line;
variable output_line : line;
variable addr : integer;
begin
while not endfile(sourcefile) loop
readline(sourcefile, input_line); --read line
read(input_line, addr); --read addr of register
can_wb_read_reg(wbs_in, wbs_out, addr, clk);
--wait for 1 ns;
write(output_line,addr);
write(output_line, ' ' );
write(output_line,canwb2data(wbs_out.dat, canint2sel(addr)));
writeline(targetfile,output_line);
wait for 50 ns;
end loop;
file_close(sourcefile);
file_close(targetfile);
end procedure read_regs_with_fileaddr;
function can_crc(

View File

@@ -1086,8 +1086,8 @@ package body wb_tp is
msto.dat <= enc_wb_dat(adr(1 downto 0),size,writedata);
wait until rising_edge(clk);
wait until slvo.ack = '1' for 1 ps;
assert slvo.ack = '1' report "Slave did not ACK the write properly";
wait until slvo.ack = '1' for 100 ns;
assert slvo.ack = '1' report "Slave did not ACK the write properly within 10 wait states";
wait until rising_edge(clk);
@@ -1180,8 +1180,8 @@ package body wb_tp is
msto.adr <= adr;
wait until rising_edge(clk);
wait until slvo.ack='1' for 1 ps;
assert slvo.ack='1' report "Slave did not ACK the read properly";
wait until slvo.ack='1' for 100 ns;
assert slvo.ack='1' report "Slave did not ACK the read properly within 10 wait states";
if slvo.ack='1' then
readdata <= dec_wb_dat(sel,slvo.dat);
else

View File

@@ -0,0 +1,195 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.wishbone.all;
use work.can_tp.all;
use work.config.all;
entity can_demo_tb is
end entity can_demo_tb;
architecture RTL of can_demo_tb is
component can_vhdl_top is
generic(
memaddr : generic_addr_type;
addrmask : generic_mask_type
);
port(
clk : in std_logic;
rstn : in std_logic;
wbs_i : in wb_slv_in_type;
wbs_o : out wb_slv_out_type;
rx_i : in std_logic;
tx_o : out std_logic;
irq_on : out std_logic
);
end component can_vhdl_top;
component phys_can_sim
generic(
peer_num : integer );
port(
rst : in std_logic;
rx_vector : out std_logic_vector(peer_num - 1 downto 0);
tx_vector : in std_logic_vector(peer_num - 1 downto 0) );
end component phys_can_sim;
-- management signal
signal clk : std_logic := '0';
signal rst : std_logic := '1';
signal test_result: rx_check_result;
--signal tx_frame: std_logic_vector(0 to 108);
-- signals to/from controller 1
signal wbs_i1 : wb_slv_in_type := wbs_in_default;
signal wbs_o1 : wb_slv_out_type;
signal irq_on1 : std_logic;
signal data_out : std_logic_vector(7 downto 0) := (others => '0');
-- signals to/from controller 2
signal wbs_i2 : wb_slv_in_type:= wbs_in_default;
signal wbs_o2 : wb_slv_out_type;
signal irq_on2 : std_logic;
--signals can interconnect
constant peer_num_inst : integer := 3;
signal rx_vector : std_logic_vector(peer_num_inst - 1 downto 0);
signal tx_vector : std_logic_vector(peer_num_inst - 1 downto 0);
begin
can_inst_1 : component can_vhdl_top
generic map(
memaddr=>CFG_BADR_MEM,
addrmask=>CFG_MADR_FULL
)
port map(
clk => clk,
rstn => rst,
wbs_i => wbs_i1,
wbs_o => wbs_o1,
rx_i => rx_vector(0),
tx_o => tx_vector(0),
irq_on => irq_on1);
can_inst_2 : component can_vhdl_top
generic map(
memaddr=>CFG_BADR_MEM,
addrmask=>CFG_MADR_FULL
)
port map(
clk => clk,
rstn => rst,
wbs_i => wbs_i2,
wbs_o => wbs_o2,
rx_i => rx_vector(1),
tx_o => tx_vector(1),
irq_on => irq_on2);
can_interconnect : component phys_can_sim
generic map( peer_num => peer_num_inst)
port map( rst => rst,
rx_vector => rx_vector,
tx_vector => tx_vector);
-- stimuli
stimuli: process is
begin
report "begin stimuli" severity warning;
--this tx line is used manually
tx_vector(2) <= '1';
wait for 40 ns;
rst <= '0';
--setup both can nodes
write_regs_from_file( "./testdata/default_setup.tdf", wbs_i1, wbs_o1, clk);
--wait for 1000 ns;
write_regs_from_file( "./testdata/default_setup.tdf", wbs_i2, wbs_o2, clk);
wait for 1000 ns;
--setup and execute a 2 byte transmission in controller 1
write_regs_from_file( "./testdata/data_send.tdf", wbs_i1, wbs_o1, clk);
tx_vector(2) <= tx_vector(1);
--manual ack by copying controler 2's ack
wait on tx_vector(1);
tx_vector(2) <= '0';
wait for 300 ns;
tx_vector(2) <= '1';
wait on irq_on2;
--read status register of controller 1
can_wb_read_reg(wbs_i1, wbs_o1, 2, data_out ,clk);
--read from controller 2's read buffer
--read_regs_with_fileaddr("./testdata/data_read.tdf", wbs_i2, wbs_o2, clk);
read_regs_with_fileaddr("./testdata/data_read.tdf", "./results/read_data0.tdf", wbs_i2, wbs_o2, clk);
wait for 1200 ns;
--release receive buffer of controller 2
can_wb_write_reg(wbs_i2, wbs_o2, 1, "00000100", clk);
wait for 1200 ns;
--manually transmit a 2 byte message on tx line 2 (tx_vector(2))
simulate_can_transmission("11100010111", x"770F000000000000", 2, 300 ns, rx_vector(2), tx_vector(2), test_result);
tx_vector(2) <= '1';
wait on irq_on2;
--read from both receive buffers
read_regs_with_fileaddr("./testdata/data_read.tdf", "./results/read_data1.tdf", wbs_i1, wbs_o1, clk);
read_regs_with_fileaddr("./testdata/data_read.tdf", "./results/read_data2.tdf", wbs_i2, wbs_o2, clk);
wait for 2400 ns;
--release both receive buffers
can_wb_write_reg(wbs_i1, wbs_o1, 1, "00000100", clk);
can_wb_write_reg(wbs_i2, wbs_o2, 1, "00000100", clk);
wait for 1200 ns;
report "end stimuli" severity failure;
wait;
end process stimuli;
-- clock generation
clock : process is
begin
clk <= not clk;
wait for 10 ns / 2;
end process clock;
-- input files used in this testbench:
--
-- default_setup.tdf:
-- 4 00000000
-- 5 11111111
-- 6 10000000
-- 7 01001000
-- 8 00000010
-- 0 11111110
--
-- data_send.tdf:
-- 10 10101010
-- 11 11000010
-- 12 10101010
-- 13 00001111
-- 1 00000001
--
-- data_read.tdf:
-- 20
-- 21
-- 22
-- 23
end architecture RTL;

View File

@@ -1,128 +0,0 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone.all;
use work.can_tp.all;
entity can_tx_sim_tb is
end entity can_tx_sim_tb;
architecture RTL of can_tx_sim_tb is
component can_vhdl_top is
generic(
memaddr : generic_addr_type;
addrmask : generic_mask_type;
);
port(
clk : in std_logic;
rstn : in std_logic;
wbs_i : in wb_slv_in_type;
wbs_o : out wb_slv_out_type;
rx_i : in std_logic;
tx_o : out std_logic;
irq_on : out std_logic
);
end component can_vhdl_top;
component phys_can_sim
generic(
peer_num : integer );
port(
rst : in std_logic;
rx_vector : out std_logic_vector(peer_num - 1 downto 0);
tx_vector : in std_logic_vector(peer_num - 1 downto 0) );
end component phys_can_sim;
-- management signal
signal clk : std_logic := '0';
signal rst : std_logic := '1';
signal test_result: rx_check_result;
signal tx_frame: std_logic_vector(0 to 108);
-- signals main controller
signal wbs_i : wb_slv_in_type;
signal wbs_o : wb_slv_out_type;
signal irq_on : std_logic;
--signals can interconnect
constant peer_num_inst : integer := 2;
signal rx_vector : std_logic_vector(peer_num_inst - 1 downto 0);
signal tx_vector : std_logic_vector(peer_num_inst - 1 downto 0);
begin
can_inst_main : component can_vhdl_top
generic map(
memaddr=>CFG_BADR_MEM,
addrmask=>CFG_MADR_FULL
)
port map(
clk => clk,
rstn => rst,
wbs_i => wbs_i,
wbs_o => wbs_o,
rx_i => rx_vector(0),
tx_o => tx_vector(0),
irq_on => irq_on);
can_interconnect : component phys_can_sim
generic map( peer_num => peer_num_inst)
port map( rst => rst,
rx_vector => rx_vector,
tx_vector => tx_vector);
-- stimuli
stimuli: process is
--variable data : std_logic_vector (7 downto 0);
--variable addr : integer;
begin
wait for 10 ns;
rst <= '1';
wait for 40 ns;
rst <= '0';
tx_vector(1) <= '1';
write_regs_from_file( "./testdata/default_setup.tdf", wbs_i, wbs_o, clk);
wait for 8400 ns;
simulate_can_transmission("10101010111", x"770F0F0F00000000", 1, 300 ns, rx_vector(1), tx_vector(1), test_result);
wait for 2400 ns;
simulate_can_transmission("11100010111", x"770F0F0F00000000", 3, 300 ns, rx_vector(1), tx_vector(1), test_result);
wait for 8400 ns;
simulate_can_transmission("00000000011", x"770F0F0F00000000", 5, 300 ns, rx_vector(1), tx_vector(1), test_result);
wait for 8400 ns;
simulate_can_transmission("10111110011", x"770F0F0F00000000", 8, 300 ns, rx_vector(1), tx_vector(1), test_result);
tx_vector(1) <= '1';
wait;
report "end stimuli" severity warning;
end process stimuli;
sub_programm_test: process is
begin
tx_frame <= buildframe("00000000000", x"770F0F0F00000000", 1);
wait;
end process;
-- clock generation
clock : process is
begin
clk <= not clk;
wait for 10 ns / 2;
end process clock;
end architecture RTL;

View File

@@ -0,0 +1,47 @@
library ieee;
use ieee.std_logic_1164.all;
entity phys_can_sim is
generic(
peer_num : integer --number of can participants connected to the bus
);
port(
rst : in std_logic;
rx_vector : out std_logic_vector(peer_num - 1 downto 0); --vector containing all rx_signals
tx_vector : in std_logic_vector(peer_num - 1 downto 0) --vector containing all tx_signals
);
end entity;
architecture behav of phys_can_sim is
begin
process(tx_vector, rst)
variable value : std_logic := '1';
variable i : integer;
begin
if rst = '1' then
rx_vector <= (others => '1');
else
value := '1';
for i in 0 to peer_num - 1 loop
value := value and tx_vector(i);
end loop;
if value = '1' then
rx_vector <= (others => '1');
else
rx_vector <= (others => '0');
end if;
end if;
end process;
end architecture;
--TODO: physical transmission delay simulation if needed (in a later simulation stage)