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 =
tb/vhdl/tb_si.vhd
regression_test_vhdl =
#tb/vhdl/tb_si.vhd -- tb is not self checking yet
tb/vhdl/tb_si.vhd
[modelsim_project_file]
......
......@@ -29,26 +29,22 @@
-- 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.
-- 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.NUMERIC_STD.ALL;
USE common_lib.common_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
ENTITY si IS
GENERIC (
g_pipeline : NATURAL := 1; -- 0 for wires, 1 for output pipeline
g_dat_w : NATURAL := 18
);
PORT (
in_dat : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0);
in_val : IN STD_LOGIC;
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;
in_sosi : IN t_dp_sosi;
out_sosi : OUT t_dp_sosi;
si_en : IN STD_LOGIC;
clk : IN STD_LOGIC;
rst : IN STD_LOGIC
......@@ -57,54 +53,56 @@ END si;
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 nxt_plus : STD_LOGIC;
SIGNAL plus_reg : STD_LOGIC;
SIGNAL si_plus : STD_LOGIC;
SIGNAL si_sosi : t_dp_sosi;
BEGIN
reg_si : PROCESS(rst, clk)
p_reg : PROCESS(rst, clk)
BEGIN
IF rst='1' THEN
out_val <= '0';
out_sop <= '0';
out_sync <= '0';
plus <= '1';
plus_reg <= '1';
ELSIF rising_edge(clk) THEN
out_dat <= nxt_out_dat;
out_val <= in_val;
out_sop <= in_sop;
out_sync <= in_sync;
plus <= nxt_plus;
plus_reg <= plus;
END IF;
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
nxt_plus <= plus;
IF in_sop = '1' THEN
nxt_plus <= '1';
ELSIF in_val = '1' THEN
nxt_plus <= NOT plus;
plus <= plus_reg;
IF in_sosi.sop = '1' THEN
plus <= '1';
ELSIF in_sosi.valid = '1' THEN
plus <= NOT plus_reg;
END IF;
END PROCESS;
-- Use SI when enabled, else pass on input
si_plus <= plus WHEN si_en = '1' ELSE '1';
si_data : PROCESS (si_plus, in_dat)
si_data : PROCESS (si_plus, in_sosi)
BEGIN
nxt_out_dat <= in_dat;
si_sosi <= in_sosi;
IF si_plus = '0' THEN
nxt_out_dat <= STD_LOGIC_VECTOR(-SIGNED(in_dat));
-- Clip -c_dat_min to c_dat_max instead of wrapping to c_dat_min
IF SIGNED(in_dat) = c_dat_min THEN
nxt_out_dat <= STD_LOGIC_VECTOR(TO_SIGNED(c_dat_max, g_dat_w));
END IF;
si_sosi.data <= NEGATE_SVEC(in_sosi.data, g_dat_w);
si_sosi.re <= NEGATE_SVEC(in_sosi.re, g_dat_w);
si_sosi.im <= NEGATE_SVEC(in_sosi.im, g_dat_w);
END IF;
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;
......@@ -25,12 +25,13 @@
-- Description:
-- Test bench for si.vhd.
-- Remark:
-- . Ported from LOFAR1 rsp
-- . The tb is self-stopping, but not self checking.
-- . Ported from LOFAR1 rsp. Made the tb self-stopping and self-checking.
LIBRARY IEEE, common_lib;
LIBRARY IEEE, common_lib, dp_lib;
USE IEEE.STD_LOGIC_1164.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
END tb_si;
......@@ -40,10 +41,14 @@ ARCHITECTURE tb OF tb_si IS
CONSTANT c_clk_period : TIME := 10 ns;
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 nxt_in_dat : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0);
SIGNAL in_sosi : t_dp_sosi;
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_sop : STD_LOGIC;
SIGNAL in_sync : STD_LOGIC;
......@@ -57,7 +62,8 @@ ARCHITECTURE tb OF tb_si IS
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL toggle : STD_LOGIC;
SIGNAL nxt_toggle : STD_LOGIC;
SIGNAL clip_even : STD_LOGIC;
SIGNAL clip_odd : STD_LOGIC;
BEGIN
......@@ -66,44 +72,47 @@ BEGIN
u_si : ENTITY work.si
GENERIC MAP (
g_pipeline => 0,
g_dat_w => c_dat_w
)
PORT MAP(
in_dat => in_dat,
in_val => in_val,
in_sop => in_sop,
in_sync => in_sync,
out_dat => out_dat,
out_val => out_val,
out_sop => out_sop,
out_sync => out_sync,
in_sosi => in_sosi,
out_sosi => out_sosi,
si_en => si_en,
clk => clk,
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
IF rst='1' THEN
in_dat <= (OTHERS => '0');
toggle <= '0';
ELSIF rising_edge(clk) THEN
in_dat <= nxt_in_dat;
toggle <= nxt_toggle;
END IF;
END PROCESS;
nxt_toggle <= NOT toggle;
data_counter : PROCESS (toggle, in_dat)
BEGIN
nxt_in_dat <= in_dat;
IF in_val='1' THEN
IF toggle='1' THEN
nxt_in_dat <= INCR_UVEC(in_dat, 1);
in_dat <= INCR_UVEC(in_dat, 1);
END IF;
toggle <= NOT toggle;
END IF;
END IF;
END PROCESS;
PROCESS
p_stimuli : PROCESS
BEGIN
si_en <= '1';
in_sop <= '0';
......@@ -112,41 +121,62 @@ BEGIN
WAIT FOR 10*c_clk_period;
-- 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_sop <= '1';
in_val <= '0';
in_val <= '1';
WAIT FOR c_clk_period;
in_sync <= '0';
in_sop <= '0';
in_val <= '1';
WAIT FOR c_block_size*c_clk_period;
-- insert a single valid low cycle
-- insert some valid low cycles
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
-- some more blocks
FOR I IN 0 TO 15 LOOP
in_sop <= '1';
in_val <= '1';
WAIT FOR c_clk_period;
in_sop <= '0';
in_val <= '1';
WAIT FOR c_block_size*c_clk_period;
-- insert an in phase resync sop cycle
in_sop <= '1';
in_val <= '1';
WAIT FOR c_clk_period;
in_sop <= '0';
in_val <= '1';
WAIT FOR c_block_size*c_clk_period;
END LOOP;
tb_end <= '1';
WAIT;
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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment