Skip to content
Snippets Groups Projects
Commit 9a4906aa authored by Pieter Donker's avatar Pieter Donker
Browse files

Merge branch 'L2SDP-78' of git.astron.nl:desp/hdl into L2SDP-78

parents 75ee6be2 81bac2b6
No related branches found
No related tags found
2 merge requests!28Master,!26Resolve L2SDP-78
...@@ -372,6 +372,9 @@ PACKAGE common_pkg IS ...@@ -372,6 +372,9 @@ PACKAGE common_pkg IS
FUNCTION RESIZE_UVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- = RESIZE_UVEC() with w=32 for t_slv_32_arr slv elements FUNCTION RESIZE_UVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- = RESIZE_UVEC() with w=32 for t_slv_32_arr slv elements
FUNCTION RESIZE_SVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- = RESIZE_SVEC() with w=32 for t_slv_32_arr slv elements FUNCTION RESIZE_SVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- = RESIZE_SVEC() with w=32 for t_slv_32_arr slv elements
-- Negate vec, but avoid overflow by forcing -min to +max. Use w <= vec'LENGTH.
FUNCTION NEGATE_SVEC(vec : STD_LOGIC_VECTOR; w : INTEGER) RETURN STD_LOGIC_VECTOR;
FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR; FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR;
FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : UNSIGNED) RETURN STD_LOGIC_VECTOR; FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : UNSIGNED) RETURN STD_LOGIC_VECTOR;
...@@ -1754,6 +1757,22 @@ PACKAGE BODY common_pkg IS ...@@ -1754,6 +1757,22 @@ PACKAGE BODY common_pkg IS
RETURN RESIZE_SVEC(vec, 32); RETURN RESIZE_SVEC(vec, 32);
END; END;
-- Negate vec, but avoid overflow by forcing -min to +max. Use w <= vec'LENGTH.
FUNCTION NEGATE_SVEC(vec : STD_LOGIC_VECTOR; w : INTEGER) RETURN STD_LOGIC_VECTOR IS
CONSTANT c_max : INTEGER := 2**(w-1)-1;
CONSTANT c_min : INTEGER := -2**(w-1);
CONSTANT c_vec_w : NATURAL := vec'LENGTH;
VARIABLE v_vec : STD_LOGIC_VECTOR(c_vec_w-1 DOWNTO 0) := vec; -- independent of vec'RANGE
VARIABLE v_val : STD_LOGIC_VECTOR(w-1 DOWNTO 0);
BEGIN
v_val := v_vec(w-1 DOWNTO 0); -- operate on width w and resize to c_vec_w for return
IF SIGNED(v_val) = c_min THEN
RETURN STD_LOGIC_VECTOR(TO_SIGNED(c_max, c_vec_w)); -- most negative becomes most positive
ELSE
RETURN STD_LOGIC_VECTOR(RESIZE_NUM(-SIGNED(v_val), c_vec_w)); -- negate by multiplying by -1
END IF;
END;
FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR IS FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR IS
VARIABLE v_dec : INTEGER; VARIABLE v_dec : INTEGER;
BEGIN BEGIN
......
hdl_lib_name = si
hdl_library_clause_name = si_lib
hdl_lib_uses_synth = common dp
hdl_lib_uses_sim =
hdl_lib_technology =
synth_files =
src/vhdl/si.vhd
test_bench_files =
tb/vhdl/tb_si.vhd
regression_test_vhdl =
tb/vhdl/tb_si.vhd
[modelsim_project_file]
[quartus_project_file]
-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--
-- Author: E. Kooistra
-- Purpose: Spectral inversion.
-- Description:
-- In the even Nyquist zones the sampled spectrum gets flipped in frequency.
-- This flip can be compensated for by a spectral inversion (SI). When
-- enabled the SI multiplies the input samples by (-1)**n = +1, -1, ...,
-- 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. Then rewrote code to use t_dp_sosi.
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, dp_lib;
USE IEEE.STD_LOGIC_1164.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_sosi : IN t_dp_sosi;
out_sosi : OUT t_dp_sosi;
si_en : IN STD_LOGIC;
clk : IN STD_LOGIC;
rst : IN STD_LOGIC
);
END si;
ARCHITECTURE rtl OF si IS
SIGNAL plus : STD_LOGIC;
SIGNAL plus_reg : STD_LOGIC;
SIGNAL si_plus : STD_LOGIC;
SIGNAL si_sosi : t_dp_sosi;
BEGIN
p_reg : PROCESS(rst, clk)
BEGIN
IF rst='1' THEN
plus_reg <= '1';
ELSIF rising_edge(clk) THEN
plus_reg <= plus;
END IF;
END PROCESS;
-- Control -1**n to start with +1 at sop and then toggle at every valid
p_si_control : PROCESS (plus_reg, in_sosi)
BEGIN
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_sosi)
BEGIN
si_sosi <= in_sosi;
IF si_plus = '0' THEN
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;
-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--
-- Author: E. Kooistra
-- Purpose: Spectral inversion.
-- Description:
-- Test bench for si.vhd.
-- Remark:
-- . Ported from LOFAR1 rsp. Made the tb self-stopping and self-checking.
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;
ARCHITECTURE tb OF tb_si IS
CONSTANT c_clk_period : TIME := 10 ns;
CONSTANT c_dat_w : NATURAL := 5;
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_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;
SIGNAL out_dat : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0);
SIGNAL out_val : STD_LOGIC;
SIGNAL out_sop : STD_LOGIC;
SIGNAL out_sync : STD_LOGIC;
SIGNAL si_en : STD_LOGIC;
SIGNAL clk : STD_LOGIC := '1';
SIGNAL rst : STD_LOGIC;
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL toggle : STD_LOGIC;
SIGNAL clip_even : STD_LOGIC;
SIGNAL clip_odd : STD_LOGIC;
BEGIN
rst <= '1', '0' AFTER c_clk_period;
clk <= NOT(clk) OR tb_end AFTER c_clk_period/2;
u_si : ENTITY work.si
GENERIC MAP (
g_pipeline => 0,
g_dat_w => c_dat_w
)
PORT MAP(
in_sosi => in_sosi,
out_sosi => out_sosi,
si_en => si_en,
clk => clk,
rst => rst
);
-- 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
IF in_val='1' THEN
IF toggle='1' THEN
in_dat <= INCR_UVEC(in_dat, 1);
END IF;
toggle <= NOT toggle;
END IF;
END IF;
END PROCESS;
p_stimuli : PROCESS
BEGIN
si_en <= '1';
in_sop <= '0';
in_sync <= '0';
in_val <= '0';
WAIT FOR 10*c_clk_period;
-- pulse in_sync, to check that it is passed on
-- pulse sop and continue with valid data
in_sync <= '1';
in_sop <= '1';
in_val <= '1';
WAIT FOR c_clk_period;
in_sync <= '0';
in_sop <= '0';
WAIT FOR c_block_size*c_clk_period;
-- insert some valid low cycles
in_val <= '0';
WAIT FOR 3*c_clk_period;
in_val <= '1';
-- some more blocks
FOR I IN 0 TO 15 LOOP
in_sop <= '1';
WAIT FOR c_clk_period;
in_sop <= '0';
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