Skip to content
Snippets Groups Projects
Commit 81bac2b6 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Use sosi signals and made tb somewhat self-checking.

parent 320d6c1b
No related branches found
No related tags found
1 merge request!28Master
...@@ -11,7 +11,7 @@ test_bench_files = ...@@ -11,7 +11,7 @@ test_bench_files =
tb/vhdl/tb_si.vhd tb/vhdl/tb_si.vhd
regression_test_vhdl = regression_test_vhdl =
#tb/vhdl/tb_si.vhd -- tb is not self checking yet tb/vhdl/tb_si.vhd
[modelsim_project_file] [modelsim_project_file]
......
...@@ -29,26 +29,22 @@ ...@@ -29,26 +29,22 @@
-- where n = 0 is the first sample in the FFT block. For more information -- where n = 0 is the first sample in the FFT block. For more information
-- see section 4.19 in LOFAR_ASTRON_SDD_018_RSP_Firmware_DD.pdf. -- see section 4.19 in LOFAR_ASTRON_SDD_018_RSP_Firmware_DD.pdf.
-- Remark: -- Remark:
-- . Ported from LOFAR1 rsp -- . Ported from LOFAR1 rsp. Then rewrote code to use t_dp_sosi.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
LIBRARY IEEE; LIBRARY IEEE, common_lib, dp_lib;
USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL; USE common_lib.common_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
ENTITY si IS ENTITY si IS
GENERIC ( GENERIC (
g_pipeline : NATURAL := 1; -- 0 for wires, 1 for output pipeline
g_dat_w : NATURAL := 18 g_dat_w : NATURAL := 18
); );
PORT ( PORT (
in_dat : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); in_sosi : IN t_dp_sosi;
in_val : IN STD_LOGIC; out_sosi : OUT t_dp_sosi;
in_sop : IN STD_LOGIC;
in_sync : IN STD_LOGIC;
out_dat : OUT STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0);
out_val : OUT STD_LOGIC;
out_sop : OUT STD_LOGIC;
out_sync : OUT STD_LOGIC;
si_en : IN STD_LOGIC; si_en : IN STD_LOGIC;
clk : IN STD_LOGIC; clk : IN STD_LOGIC;
rst : IN STD_LOGIC rst : IN STD_LOGIC
...@@ -57,54 +53,56 @@ END si; ...@@ -57,54 +53,56 @@ END si;
ARCHITECTURE rtl OF si IS ARCHITECTURE rtl OF si IS
CONSTANT c_dat_max : INTEGER := 2**(g_dat_w-1)-1;
CONSTANT c_dat_min : INTEGER := -2**(g_dat_w-1);
SIGNAL nxt_out_dat : STD_LOGIC_VECTOR(out_dat'RANGE);
SIGNAL plus : STD_LOGIC; SIGNAL plus : STD_LOGIC;
SIGNAL nxt_plus : STD_LOGIC; SIGNAL plus_reg : STD_LOGIC;
SIGNAL si_plus : STD_LOGIC; SIGNAL si_plus : STD_LOGIC;
SIGNAL si_sosi : t_dp_sosi;
BEGIN BEGIN
reg_si : PROCESS(rst, clk) p_reg : PROCESS(rst, clk)
BEGIN BEGIN
IF rst='1' THEN IF rst='1' THEN
out_val <= '0'; plus_reg <= '1';
out_sop <= '0';
out_sync <= '0';
plus <= '1';
ELSIF rising_edge(clk) THEN ELSIF rising_edge(clk) THEN
out_dat <= nxt_out_dat; plus_reg <= plus;
out_val <= in_val;
out_sop <= in_sop;
out_sync <= in_sync;
plus <= nxt_plus;
END IF; END IF;
END PROCESS; END PROCESS;
si_control : PROCESS (plus, in_sop, in_val) -- Control -1**n to start with +1 at sop and then toggle at every valid
p_si_control : PROCESS (plus_reg, in_sosi)
BEGIN BEGIN
nxt_plus <= plus; plus <= plus_reg;
IF in_sop = '1' THEN IF in_sosi.sop = '1' THEN
nxt_plus <= '1'; plus <= '1';
ELSIF in_val = '1' THEN ELSIF in_sosi.valid = '1' THEN
nxt_plus <= NOT plus; plus <= NOT plus_reg;
END IF; END IF;
END PROCESS; END PROCESS;
-- Use SI when enabled, else pass on input
si_plus <= plus WHEN si_en = '1' ELSE '1'; si_plus <= plus WHEN si_en = '1' ELSE '1';
si_data : PROCESS (si_plus, in_dat) si_data : PROCESS (si_plus, in_sosi)
BEGIN BEGIN
nxt_out_dat <= in_dat; si_sosi <= in_sosi;
IF si_plus = '0' THEN IF si_plus = '0' THEN
nxt_out_dat <= STD_LOGIC_VECTOR(-SIGNED(in_dat)); si_sosi.data <= NEGATE_SVEC(in_sosi.data, g_dat_w);
-- Clip -c_dat_min to c_dat_max instead of wrapping to c_dat_min si_sosi.re <= NEGATE_SVEC(in_sosi.re, g_dat_w);
IF SIGNED(in_dat) = c_dat_min THEN si_sosi.im <= NEGATE_SVEC(in_sosi.im, g_dat_w);
nxt_out_dat <= STD_LOGIC_VECTOR(TO_SIGNED(c_dat_max, g_dat_w));
END IF;
END IF; END IF;
END PROCESS; END PROCESS;
-- Output
u_pipeline : ENTITY dp_lib.dp_pipeline
GENERIC MAP (
g_pipeline => g_pipeline
)
PORT MAP (
rst => rst,
clk => clk,
snk_in => si_sosi,
src_out => out_sosi
);
END rtl; END rtl;
...@@ -25,12 +25,13 @@ ...@@ -25,12 +25,13 @@
-- Description: -- Description:
-- Test bench for si.vhd. -- Test bench for si.vhd.
-- Remark: -- Remark:
-- . Ported from LOFAR1 rsp -- . Ported from LOFAR1 rsp. Made the tb self-stopping and self-checking.
-- . The tb is self-stopping, but not self checking.
LIBRARY IEEE, common_lib; LIBRARY IEEE, common_lib, dp_lib;
USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_1164.ALL;
USE common_lib.common_pkg.ALL; USE common_lib.common_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
ENTITY tb_si IS ENTITY tb_si IS
END tb_si; END tb_si;
...@@ -40,10 +41,14 @@ ARCHITECTURE tb OF tb_si IS ...@@ -40,10 +41,14 @@ ARCHITECTURE tb OF tb_si IS
CONSTANT c_clk_period : TIME := 10 ns; CONSTANT c_clk_period : TIME := 10 ns;
CONSTANT c_dat_w : NATURAL := 5; CONSTANT c_dat_w : NATURAL := 5;
CONSTANT c_block_size : NATURAL := 19; CONSTANT c_max : INTEGER := 2**(c_dat_w-1)-1;
CONSTANT c_min : INTEGER := -2**(c_dat_w-1);
CONSTANT c_block_size : NATURAL := 9;
SIGNAL in_dat : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); SIGNAL in_sosi : t_dp_sosi;
SIGNAL nxt_in_dat : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); SIGNAL out_sosi : t_dp_sosi;
SIGNAL in_dat : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL in_val : STD_LOGIC; SIGNAL in_val : STD_LOGIC;
SIGNAL in_sop : STD_LOGIC; SIGNAL in_sop : STD_LOGIC;
SIGNAL in_sync : STD_LOGIC; SIGNAL in_sync : STD_LOGIC;
...@@ -57,7 +62,8 @@ ARCHITECTURE tb OF tb_si IS ...@@ -57,7 +62,8 @@ ARCHITECTURE tb OF tb_si IS
SIGNAL tb_end : STD_LOGIC := '0'; SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL toggle : STD_LOGIC; SIGNAL toggle : STD_LOGIC;
SIGNAL nxt_toggle : STD_LOGIC; SIGNAL clip_even : STD_LOGIC;
SIGNAL clip_odd : STD_LOGIC;
BEGIN BEGIN
...@@ -65,45 +71,48 @@ BEGIN ...@@ -65,45 +71,48 @@ BEGIN
clk <= NOT(clk) OR tb_end AFTER c_clk_period/2; clk <= NOT(clk) OR tb_end AFTER c_clk_period/2;
u_si : ENTITY work.si u_si : ENTITY work.si
GENERIC MAP( GENERIC MAP (
g_pipeline => 0,
g_dat_w => c_dat_w g_dat_w => c_dat_w
) )
PORT MAP( PORT MAP(
in_dat => in_dat, in_sosi => in_sosi,
in_val => in_val, out_sosi => out_sosi,
in_sop => in_sop,
in_sync => in_sync,
out_dat => out_dat,
out_val => out_val,
out_sop => out_sop,
out_sync => out_sync,
si_en => si_en, si_en => si_en,
clk => clk, clk => clk,
rst => rst rst => rst
); );
reg_stimuli : PROCESS(rst, clk) -- wires
in_sosi.sync <= in_sync;
in_sosi.sop <= in_sop;
in_sosi.valid <= in_val;
in_sosi.data <= RESIZE_DP_SDATA(in_dat);
in_sosi.re <= TO_DP_DSP_DATA(0);
in_sosi.im <= TO_DP_DSP_DATA(0);
out_sync <= out_sosi.sync;
out_sop <= out_sosi.sop;
out_val <= out_sosi.valid;
out_dat <= out_sosi.data(c_dat_w-1 DOWNTO 0);
-- Create in_dat with equal value per pair
p_clk : PROCESS(rst, clk)
BEGIN BEGIN
IF rst='1' THEN IF rst='1' THEN
in_dat <= (OTHERS => '0'); in_dat <= (OTHERS => '0');
toggle <= '0'; toggle <= '0';
ELSIF rising_edge(clk) THEN ELSIF rising_edge(clk) THEN
in_dat <= nxt_in_dat; IF in_val='1' THEN
toggle <= nxt_toggle; IF toggle='1' THEN
in_dat <= INCR_UVEC(in_dat, 1);
END IF;
toggle <= NOT toggle;
END IF;
END IF; END IF;
END PROCESS; END PROCESS;
nxt_toggle <= NOT toggle; p_stimuli : PROCESS
data_counter : PROCESS (toggle, in_dat)
BEGIN
nxt_in_dat <= in_dat;
IF toggle = '1' THEN
nxt_in_dat <= INCR_UVEC(in_dat, 1);
END IF;
END PROCESS;
PROCESS
BEGIN BEGIN
si_en <= '1'; si_en <= '1';
in_sop <= '0'; in_sop <= '0';
...@@ -112,42 +121,63 @@ BEGIN ...@@ -112,42 +121,63 @@ BEGIN
WAIT FOR 10*c_clk_period; WAIT FOR 10*c_clk_period;
-- pulse in_sync, to check that it is passed on -- pulse in_sync, to check that it is passed on
-- sop followed by valid data -- pulse sop and continue with valid data
in_sync <= '1'; in_sync <= '1';
in_sop <= '1'; in_sop <= '1';
in_val <= '0'; in_val <= '1';
WAIT FOR c_clk_period; WAIT FOR c_clk_period;
in_sync <= '0'; in_sync <= '0';
in_sop <= '0'; in_sop <= '0';
in_val <= '1';
WAIT FOR c_block_size*c_clk_period; WAIT FOR c_block_size*c_clk_period;
-- insert a single valid low cycle -- insert some valid low cycles
in_val <= '0'; in_val <= '0';
WAIT FOR c_clk_period; WAIT FOR 3*c_clk_period;
in_val <= '1';
WAIT FOR c_block_size*c_clk_period;
-- insert an out of phase resync sop cycle
in_sop <= '1';
in_val <= '1'; in_val <= '1';
WAIT FOR c_clk_period;
in_sop <= '0'; -- some more blocks
in_val <= '1'; FOR I IN 0 TO 15 LOOP
WAIT FOR c_block_size*c_clk_period; in_sop <= '1';
WAIT FOR c_clk_period;
-- insert an in phase resync sop cycle in_sop <= '0';
in_sop <= '1'; WAIT FOR c_block_size*c_clk_period;
in_val <= '1'; END LOOP;
WAIT FOR c_clk_period;
in_sop <= '0';
in_val <= '1';
WAIT FOR c_block_size*c_clk_period;
tb_end <= '1'; tb_end <= '1';
WAIT; WAIT;
END PROCESS; END PROCESS;
p_verify : PROCESS
VARIABLE v_even : INTEGER;
VARIABLE v_odd : INTEGER;
VARIABLE v_clip_even : STD_LOGIC;
VARIABLE v_clip_odd : STD_LOGIC;
BEGIN
-- verify per pair
WAIT FOR c_clk_period;
proc_common_wait_until_high(clk, out_val);
v_even := TO_SINT(out_dat);
WAIT FOR c_clk_period;
proc_common_wait_until_high(clk, out_val);
v_odd := TO_SINT(out_dat);
-- identify clip wrap of -c_min to +c_max
IF v_even = c_max AND v_odd = c_min THEN v_clip_even := '1'; ELSE v_clip_even := '0'; END IF;
IF v_even = c_min AND v_odd = c_max THEN v_clip_odd := '1'; ELSE v_clip_odd := '0'; END IF;
clip_even <= v_clip_even; -- show in wave window (only cycle late)
clip_odd <= v_clip_odd; -- show in wave window (only cycle late)
-- compare pair
IF tb_end = '0' THEN
IF v_even /= -v_odd THEN
IF NOT (v_clip_even = '1') THEN
IF NOT (v_clip_odd = '1') THEN
REPORT "Wrong negate value" SEVERITY ERROR;
END IF;
END IF;
END IF;
ELSE
WAIT;
END IF;
END PROCESS;
END tb; END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment