--
|
--
|
-- Test bench for spwstream.
|
-- Test bench for spwstream.
|
--
|
--
|
-- Tests:
|
-- Tests:
|
-- * one spwstream instance with SpaceWire signals looped back to itself
|
-- * one spwstream instance with SpaceWire signals looped back to itself
|
-- * sending of bytes, packets and time codes through the SpaceWire link
|
-- * sending of bytes, packets and time codes through the SpaceWire link
|
-- * handling of link disabling and link disconnection
|
-- * handling of link disabling and link disconnection
|
--
|
--
|
-- This test bench is intended to test the buffering logic in spwstream.
|
-- This test bench is intended to test the buffering logic in spwstream.
|
-- It does not thoroughly verify behaviour of the receiver, transmitter,
|
-- It does not thoroughly verify behaviour of the receiver, transmitter,
|
-- signal patterns etc. Please use spwlink_tb.vhd to test those aspects.
|
-- signal patterns etc. Please use spwlink_tb.vhd to test those aspects.
|
--
|
--
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
use std.textio.all;
|
use std.textio.all;
|
use work.spwpkg.all;
|
use work.spwpkg.all;
|
|
|
entity streamtest_tb is
|
entity streamtest_tb is
|
end entity;
|
end entity;
|
|
|
architecture tb_arch of streamtest_tb is
|
architecture tb_arch of streamtest_tb is
|
|
|
-- Parameters.
|
-- Parameters.
|
constant sys_clock_freq: real := 20.0e6;
|
constant sys_clock_freq: real := 20.0e6;
|
|
|
component streamtest is
|
component streamtest is
|
generic (
|
generic (
|
sysfreq: real;
|
sysfreq: real;
|
|
txclkfreq: real;
|
tickdiv: integer range 12 to 24 := 20;
|
tickdiv: integer range 12 to 24 := 20;
|
rximpl: spw_implementation_type := impl_generic;
|
rximpl: spw_implementation_type := impl_generic;
|
rxchunk: integer range 1 to 4 := 1;
|
rxchunk: integer range 1 to 4 := 1;
|
tximpl: spw_implementation_type := impl_generic;
|
tximpl: spw_implementation_type := impl_generic;
|
rxfifosize_bits: integer range 6 to 14 := 11;
|
rxfifosize_bits: integer range 6 to 14 := 11;
|
txfifosize_bits: integer range 2 to 14 := 11 );
|
txfifosize_bits: integer range 2 to 14 := 11 );
|
port (
|
port (
|
clk: in std_logic;
|
clk: in std_logic;
|
rxclk: in std_logic;
|
rxclk: in std_logic;
|
txclk: in std_logic;
|
txclk: in std_logic;
|
rst: in std_logic;
|
rst: in std_logic;
|
linkstart: in std_logic;
|
linkstart: in std_logic;
|
autostart: in std_logic;
|
autostart: in std_logic;
|
linkdisable: in std_logic;
|
linkdisable: in std_logic;
|
senddata: in std_logic;
|
senddata: in std_logic;
|
sendtick: in std_logic;
|
sendtick: in std_logic;
|
txdivcnt: in std_logic_vector(7 downto 0);
|
txdivcnt: in std_logic_vector(7 downto 0);
|
linkstarted: out std_logic;
|
linkstarted: out std_logic;
|
linkconnecting: out std_logic;
|
linkconnecting: out std_logic;
|
linkrun: out std_logic;
|
linkrun: out std_logic;
|
linkerror: out std_logic;
|
linkerror: out std_logic;
|
gotdata: out std_logic;
|
gotdata: out std_logic;
|
dataerror: out std_logic;
|
dataerror: out std_logic;
|
tickerror: out std_logic;
|
tickerror: out std_logic;
|
spw_di: in std_logic;
|
spw_di: in std_logic;
|
spw_si: in std_logic;
|
spw_si: in std_logic;
|
spw_do: out std_logic;
|
spw_do: out std_logic;
|
spw_so: out std_logic );
|
spw_so: out std_logic );
|
end component;
|
end component;
|
|
|
signal sys_clock_enable: std_logic := '0';
|
signal sys_clock_enable: std_logic := '0';
|
signal sysclk: std_logic := '0';
|
signal sysclk: std_logic := '0';
|
signal s_loopback: std_logic := '0';
|
signal s_loopback: std_logic := '0';
|
signal s_nreceived: integer := 0;
|
signal s_nreceived: integer := 0;
|
|
|
signal s_rst: std_logic := '1';
|
signal s_rst: std_logic := '1';
|
signal s_linkstart: std_logic;
|
signal s_linkstart: std_logic;
|
signal s_autostart: std_logic;
|
signal s_autostart: std_logic;
|
signal s_linkdisable: std_logic;
|
signal s_linkdisable: std_logic;
|
signal s_divcnt: std_logic_vector(7 downto 0);
|
signal s_divcnt: std_logic_vector(7 downto 0);
|
signal s_linkrun: std_logic;
|
signal s_linkrun: std_logic;
|
signal s_linkerror: std_logic;
|
signal s_linkerror: std_logic;
|
signal s_gotdata: std_logic;
|
signal s_gotdata: std_logic;
|
signal s_dataerror: std_logic;
|
signal s_dataerror: std_logic;
|
signal s_tickerror: std_logic;
|
signal s_tickerror: std_logic;
|
signal s_spwdi: std_logic;
|
signal s_spwdi: std_logic;
|
signal s_spwsi: std_logic;
|
signal s_spwsi: std_logic;
|
signal s_spwdo: std_logic;
|
signal s_spwdo: std_logic;
|
signal s_spwso: std_logic;
|
signal s_spwso: std_logic;
|
|
|
begin
|
begin
|
|
|
-- streamtest instance
|
-- streamtest instance
|
streamtest_inst: streamtest
|
streamtest_inst: streamtest
|
generic map (
|
generic map (
|
sysfreq => sys_clock_freq,
|
sysfreq => sys_clock_freq,
|
|
txclkfreq => sys_clock_freq,
|
tickdiv => 16,
|
tickdiv => 16,
|
rximpl => impl_generic,
|
rximpl => impl_generic,
|
rxchunk => 1,
|
rxchunk => 1,
|
tximpl => impl_generic,
|
tximpl => impl_generic,
|
rxfifosize_bits => 9,
|
rxfifosize_bits => 9,
|
txfifosize_bits => 8 )
|
txfifosize_bits => 8 )
|
port map (
|
port map (
|
clk => sysclk,
|
clk => sysclk,
|
rxclk => sysclk,
|
rxclk => sysclk,
|
txclk => sysclk,
|
txclk => sysclk,
|
rst => s_rst,
|
rst => s_rst,
|
linkstart => s_linkstart,
|
linkstart => s_linkstart,
|
autostart => s_autostart,
|
autostart => s_autostart,
|
linkdisable => s_linkdisable,
|
linkdisable => s_linkdisable,
|
senddata => '1',
|
senddata => '1',
|
sendtick => '1',
|
sendtick => '1',
|
txdivcnt => s_divcnt,
|
txdivcnt => s_divcnt,
|
linkstarted => open,
|
linkstarted => open,
|
linkconnecting => open,
|
linkconnecting => open,
|
linkrun => s_linkrun,
|
linkrun => s_linkrun,
|
linkerror => s_linkerror,
|
linkerror => s_linkerror,
|
gotdata => s_gotdata,
|
gotdata => s_gotdata,
|
dataerror => s_dataerror,
|
dataerror => s_dataerror,
|
tickerror => s_tickerror,
|
tickerror => s_tickerror,
|
spw_di => s_spwdi,
|
spw_di => s_spwdi,
|
spw_si => s_spwsi,
|
spw_si => s_spwsi,
|
spw_do => s_spwdo,
|
spw_do => s_spwdo,
|
spw_so => s_spwso );
|
spw_so => s_spwso );
|
|
|
-- Conditional loopback of SpaceWire signals.
|
-- Conditional loopback of SpaceWire signals.
|
s_spwdi <= s_spwdo when (s_loopback = '1') else '0';
|
s_spwdi <= s_spwdo when (s_loopback = '1') else '0';
|
s_spwsi <= s_spwso when (s_loopback = '1') else '0';
|
s_spwsi <= s_spwso when (s_loopback = '1') else '0';
|
|
|
-- Generate system clock.
|
-- Generate system clock.
|
process is
|
process is
|
begin
|
begin
|
if sys_clock_enable /= '1' then
|
if sys_clock_enable /= '1' then
|
wait until sys_clock_enable = '1';
|
wait until sys_clock_enable = '1';
|
end if;
|
end if;
|
sysclk <= '1';
|
sysclk <= '1';
|
wait for (0.5 sec) / sys_clock_freq;
|
wait for (0.5 sec) / sys_clock_freq;
|
sysclk <= '0';
|
sysclk <= '0';
|
wait for (0.5 sec) / sys_clock_freq;
|
wait for (0.5 sec) / sys_clock_freq;
|
end process;
|
end process;
|
|
|
-- Verify that error indications remain off.
|
-- Verify that error indications remain off.
|
process is
|
process is
|
begin
|
begin
|
wait on s_linkerror, s_dataerror, s_tickerror;
|
wait on s_linkerror, s_dataerror, s_tickerror;
|
assert s_dataerror = '0' report "Detected data error";
|
assert s_dataerror = '0' report "Detected data error";
|
assert s_tickerror = '0' report "Detected time code error";
|
assert s_tickerror = '0' report "Detected time code error";
|
if s_loopback = '1' then
|
if s_loopback = '1' then
|
assert s_linkerror /= '1' report "Unexpected link error";
|
assert s_linkerror /= '1' report "Unexpected link error";
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
-- Verify that data is received regularly when the link is up.
|
-- Verify that data is received regularly when the link is up.
|
process is
|
process is
|
begin
|
begin
|
if s_linkrun = '0' or s_gotdata = '1' then
|
if s_linkrun = '0' or s_gotdata = '1' then
|
wait until s_linkrun = '1' and s_gotdata = '0';
|
wait until s_linkrun = '1' and s_gotdata = '0';
|
end if;
|
end if;
|
wait until s_gotdata = '1' or s_linkrun = '0' for 3 ms;
|
wait until s_gotdata = '1' or s_linkrun = '0' for 3 ms;
|
if s_linkrun = '1' then
|
if s_linkrun = '1' then
|
assert s_gotdata = '1' report "Link running but no data received";
|
assert s_gotdata = '1' report "Link running but no data received";
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
-- Count number of received characters.
|
-- Count number of received characters.
|
process is
|
process is
|
begin
|
begin
|
wait until rising_edge(sysclk);
|
wait until rising_edge(sysclk);
|
if s_gotdata = '1' then
|
if s_gotdata = '1' then
|
s_nreceived <= s_nreceived + 1;
|
s_nreceived <= s_nreceived + 1;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
-- Main process.
|
-- Main process.
|
process is
|
process is
|
variable vline: LINE;
|
variable vline: LINE;
|
begin
|
begin
|
report "Starting streamtest test bench";
|
report "Starting streamtest test bench";
|
|
|
-- Initialize.
|
-- Initialize.
|
s_loopback <= '1';
|
s_loopback <= '1';
|
s_rst <= '1';
|
s_rst <= '1';
|
s_linkstart <= '0';
|
s_linkstart <= '0';
|
s_autostart <= '0';
|
s_autostart <= '0';
|
s_linkdisable <= '0';
|
s_linkdisable <= '0';
|
s_divcnt <= "00000001";
|
s_divcnt <= "00000001";
|
sys_clock_enable <= '1';
|
sys_clock_enable <= '1';
|
wait for 1 us;
|
wait for 1 us;
|
|
|
-- Test link and data transmission.
|
-- Test link and data transmission.
|
report "Testing txdivcnt = 1";
|
report "Testing txdivcnt = 1";
|
s_rst <= '0';
|
s_rst <= '0';
|
s_linkstart <= '1';
|
s_linkstart <= '1';
|
wait for 100 us;
|
wait for 100 us;
|
assert s_linkrun = '1' report "Link failed to start";
|
assert s_linkrun = '1' report "Link failed to start";
|
wait for 50 ms;
|
wait for 50 ms;
|
|
|
-- Check number of received characters.
|
-- Check number of received characters.
|
write(vline, string'("Received "));
|
write(vline, string'("Received "));
|
write(vline, s_nreceived);
|
write(vline, s_nreceived);
|
write(vline, string'(" characters in 50 ms."));
|
write(vline, string'(" characters in 50 ms."));
|
writeline(output, vline);
|
writeline(output, vline);
|
assert s_nreceived > 24000 report "Too few characters received";
|
assert s_nreceived > 24000 report "Too few characters received";
|
|
|
-- Test switching to different transmission rate.
|
-- Test switching to different transmission rate.
|
report "Testing txdivcnt = 2";
|
report "Testing txdivcnt = 2";
|
s_divcnt <= "00000010";
|
s_divcnt <= "00000010";
|
wait for 10 ms;
|
wait for 10 ms;
|
report "Testing txdivcnt = 3";
|
report "Testing txdivcnt = 3";
|
s_divcnt <= "00000011";
|
s_divcnt <= "00000011";
|
wait for 10 ms;
|
wait for 10 ms;
|
|
|
-- Disable and re-enable link.
|
-- Disable and re-enable link.
|
report "Testing link disable/re-enable";
|
report "Testing link disable/re-enable";
|
s_linkdisable <= '1';
|
s_linkdisable <= '1';
|
s_divcnt <= "00000001";
|
s_divcnt <= "00000001";
|
wait for 2 ms;
|
wait for 2 ms;
|
s_linkdisable <= '0';
|
s_linkdisable <= '0';
|
wait for 100 us;
|
wait for 100 us;
|
assert s_linkrun = '1' report "Link failed to start after re-enable";
|
assert s_linkrun = '1' report "Link failed to start after re-enable";
|
wait for 10 ms;
|
wait for 10 ms;
|
|
|
-- Cut and reconnect loopback wiring.
|
-- Cut and reconnect loopback wiring.
|
report "Testing physical disconnect/reconnect";
|
report "Testing physical disconnect/reconnect";
|
s_loopback <= '0';
|
s_loopback <= '0';
|
wait for 2 ms;
|
wait for 2 ms;
|
s_loopback <= '1';
|
s_loopback <= '1';
|
wait for 100 us;
|
wait for 100 us;
|
assert s_linkrun = '1' report "Link failed to start after reconnect";
|
assert s_linkrun = '1' report "Link failed to start after reconnect";
|
wait for 10 ms;
|
wait for 10 ms;
|
s_loopback <= '0';
|
s_loopback <= '0';
|
wait for 2 ms;
|
wait for 2 ms;
|
s_loopback <= '1';
|
s_loopback <= '1';
|
wait for 100 us;
|
wait for 100 us;
|
assert s_linkrun = '1' report "Link failed to start after reconnect (2)";
|
assert s_linkrun = '1' report "Link failed to start after reconnect (2)";
|
wait for 10 ms;
|
wait for 10 ms;
|
|
|
-- Shut down.
|
-- Shut down.
|
s_rst <= '1';
|
s_rst <= '1';
|
wait for 1 us;
|
wait for 1 us;
|
sys_clock_enable <= '0';
|
sys_clock_enable <= '0';
|
|
|
write(vline, string'("Received "));
|
write(vline, string'("Received "));
|
write(vline, s_nreceived);
|
write(vline, s_nreceived);
|
write(vline, string'(" characters."));
|
write(vline, string'(" characters."));
|
writeline(output, vline);
|
writeline(output, vline);
|
|
|
report "Done";
|
report "Done";
|
wait;
|
wait;
|
end process;
|
end process;
|
|
|
end architecture tb_arch;
|
end architecture tb_arch;
|
|
|