From 0c3414642cf9668e1ecdf309718ad83866416122 Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Mon, 22 Jun 2020 13:53:54 +0200 Subject: [PATCH] Ported si.vhd + tb from RSP in LOFAR1. --- libraries/dsp/si/hdllib.cfg | 21 ++++ libraries/dsp/si/src/vhdl/si.vhd | 127 +++++++++++++++++++++++ libraries/dsp/si/tb/vhdl/tb_si.vhd | 160 +++++++++++++++++++++++++++++ 3 files changed, 308 insertions(+) create mode 100755 libraries/dsp/si/hdllib.cfg create mode 100755 libraries/dsp/si/src/vhdl/si.vhd create mode 100755 libraries/dsp/si/tb/vhdl/tb_si.vhd diff --git a/libraries/dsp/si/hdllib.cfg b/libraries/dsp/si/hdllib.cfg new file mode 100755 index 0000000000..218fb87f7a --- /dev/null +++ b/libraries/dsp/si/hdllib.cfg @@ -0,0 +1,21 @@ +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 -- tb is not self checking yet + + +[modelsim_project_file] + + +[quartus_project_file] + diff --git a/libraries/dsp/si/src/vhdl/si.vhd b/libraries/dsp/si/src/vhdl/si.vhd new file mode 100755 index 0000000000..e0350848a3 --- /dev/null +++ b/libraries/dsp/si/src/vhdl/si.vhd @@ -0,0 +1,127 @@ +------------------------------------------------------------------------------- +-- +-- 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 +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; + +ENTITY si IS + GENERIC ( + g_dat_w : NATURAL := 18; + g_si_dat_w : NATURAL := 12 + ); + PORT ( + in_dat_x : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); + in_dat_y : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); + in_val : IN STD_LOGIC; + in_sync : IN STD_LOGIC; + out_dat_x : OUT STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); + out_dat_y : OUT STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); + out_val : OUT STD_LOGIC; + out_sync : OUT STD_LOGIC; + si_en_x : IN STD_LOGIC; + si_en_y : IN STD_LOGIC; + clk : IN STD_LOGIC; + rst : IN STD_LOGIC + ); +END si; + +ARCHITECTURE rtl OF si IS + + CONSTANT c_dat_max : INTEGER := 2**(g_si_dat_w-1)-1; + CONSTANT c_dat_min : INTEGER := -2**(g_si_dat_w-1); + + SIGNAL nxt_out_dat_x : STD_LOGIC_VECTOR(out_dat_x'RANGE); + SIGNAL nxt_out_dat_y : STD_LOGIC_VECTOR(out_dat_y'RANGE); + SIGNAL plus : STD_LOGIC; + SIGNAL nxt_plus : STD_LOGIC; + SIGNAL plus_x : STD_LOGIC; + SIGNAL plus_y : STD_LOGIC; + +BEGIN + + reg_si : PROCESS(rst,clk) + BEGIN + IF rst='1' THEN + out_dat_x <= (OTHERS => '0'); + out_dat_y <= (OTHERS => '0'); + out_val <= '0'; + out_sync <= '0'; + plus <= '1'; + ELSIF rising_edge(clk) THEN + out_dat_x <= nxt_out_dat_x; + out_dat_y <= nxt_out_dat_y; + out_val <= in_val; + out_sync <= in_sync; + plus <= nxt_plus; + END IF; + END PROCESS; + + si_control : PROCESS (plus, in_sync, in_val) + BEGIN + nxt_plus <= plus; + IF in_sync = '1' THEN + nxt_plus <= '1'; + ELSIF in_val = '1' THEN + nxt_plus <= NOT plus; + END IF; + END PROCESS; + + plus_x <= plus WHEN si_en_x = '1' ELSE '1'; + plus_y <= plus WHEN si_en_y = '1' ELSE '1'; + + si_data_x : PROCESS (plus_x, in_dat_x) + BEGIN + nxt_out_dat_x <= in_dat_x; + IF plus_x = '0' THEN + nxt_out_dat_x <= STD_LOGIC_VECTOR(-SIGNED(in_dat_x)); + -- Clip -c_dat_min to c_dat_max instead of wrapping to c_dat_min + IF SIGNED(in_dat_x) = c_dat_min THEN + nxt_out_dat_x <= STD_LOGIC_VECTOR(TO_SIGNED(c_dat_max, g_dat_w)); + END IF; + END IF; + END PROCESS; + + si_data_y : PROCESS (plus_y, in_dat_y) + BEGIN + nxt_out_dat_y <= in_dat_y; + IF plus_y = '0' THEN + nxt_out_dat_y <= STD_LOGIC_VECTOR(-SIGNED(in_dat_y)); + -- Clip -c_dat_min to c_dat_max instead of wrapping to c_dat_min + IF SIGNED(in_dat_y) = c_dat_min THEN + nxt_out_dat_y <= STD_LOGIC_VECTOR(TO_SIGNED(c_dat_max, g_dat_w)); + END IF; + END IF; + END PROCESS; +END rtl; diff --git a/libraries/dsp/si/tb/vhdl/tb_si.vhd b/libraries/dsp/si/tb/vhdl/tb_si.vhd new file mode 100755 index 0000000000..273e124c70 --- /dev/null +++ b/libraries/dsp/si/tb/vhdl/tb_si.vhd @@ -0,0 +1,160 @@ +------------------------------------------------------------------------------- +-- +-- 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 +-- . The tb is self-stopping, but not self checking. + +LIBRARY IEEE, si_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.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_si_dat_w : NATURAL := 5; + + SIGNAL in_dat_x : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); + SIGNAL in_dat_y : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); + SIGNAL nxt_in_dat_x : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); + SIGNAL nxt_in_dat_y : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); + SIGNAL in_val : STD_LOGIC; + SIGNAL in_sync : STD_LOGIC; + SIGNAL out_dat_x : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); + SIGNAL out_dat_y : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); + SIGNAL out_val : STD_LOGIC; + SIGNAL out_sync : STD_LOGIC; + SIGNAL si_en_x : STD_LOGIC; + SIGNAL si_en_y : STD_LOGIC; + SIGNAL clk : STD_LOGIC := '1'; + SIGNAL rst : STD_LOGIC; + SIGNAL tb_end : STD_LOGIC := '0'; + + SIGNAL toggle : STD_LOGIC; + SIGNAL nxt_toggle : STD_LOGIC; + +BEGIN + + rst <= '1', '0' AFTER c_clk_period; + clk <= NOT(clk) OR tb_end AFTER c_clk_period/2; -- test bench clock + + u_si : ENTITY si_lib.si + GENERIC MAP( + g_dat_w => c_dat_w, + g_si_dat_w => c_si_dat_w + ) + PORT MAP( + in_dat_x => in_dat_x, + in_dat_y => in_dat_y, + in_val => in_val, + in_sync => in_sync, + out_dat_x => out_dat_x, + out_dat_y => out_dat_y, + out_val => out_val, + out_sync => out_sync, + si_en_x => si_en_x, + si_en_y => si_en_y, + clk => clk, + rst => rst + ); + + reg_stimuli : PROCESS(rst, clk) + BEGIN + IF rst='1' THEN + in_dat_x <= (OTHERS => '0'); + in_dat_y <= (OTHERS => '0'); + toggle <= '0'; + ELSIF rising_edge(clk) THEN + in_dat_x <= nxt_in_dat_x; + in_dat_y <= nxt_in_dat_y; + toggle <= nxt_toggle; + END IF; + END PROCESS; + + nxt_toggle <= NOT toggle; + + data_counter : PROCESS (toggle, in_dat_x, in_dat_y) + BEGIN + nxt_in_dat_x <= in_dat_x; + nxt_in_dat_y <= in_dat_y; + IF toggle = '1' THEN + nxt_in_dat_x <= STD_LOGIC_VECTOR(SIGNED(in_dat_x)+3); + nxt_in_dat_y <= STD_LOGIC_VECTOR(SIGNED(in_dat_y)+3); + END IF; + END PROCESS; + + PROCESS + BEGIN + si_en_x <= '1'; + si_en_y <= '1'; + in_sync <= '0'; + in_val <= '0'; + WAIT FOR 10*c_clk_period; + + -- sync followed by valid data + in_sync <= '1'; + in_val <= '0'; + WAIT FOR c_clk_period; + in_sync <= '0'; + in_val <= '1'; + WAIT FOR 99*c_clk_period; + + -- insert a single valid low cycle + in_sync <= '0'; + in_val <= '0'; + WAIT FOR c_clk_period; + in_sync <= '0'; + in_val <= '1'; + WAIT FOR 99*c_clk_period; + + -- insert an out of phase resync cycle + in_sync <= '1'; + in_val <= '1'; + WAIT FOR c_clk_period; + in_sync <= '0'; + in_val <= '1'; + WAIT FOR 99*c_clk_period; + + -- insert an in phase resync cycle + in_sync <= '1'; + in_val <= '1'; + WAIT FOR c_clk_period; + in_sync <= '0'; + in_val <= '1'; + WAIT FOR 99*c_clk_period; + + tb_end <= '1'; + WAIT; + + END PROCESS; + +END tb; + -- GitLab