From c1e25456ca1fa6e1295e24a037007ccc2212a81c Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Tue, 22 Feb 2022 17:40:40 +0100 Subject: [PATCH] Use generic g_switch_en, instead of signal, to support zero input to output latency when g_switch_en = FALSE. --- libraries/dsp/fft/src/vhdl/fft_switch.vhd | 130 ++++++++++++-------- libraries/dsp/fft/src/vhdl/fft_unswitch.vhd | 130 ++++++++++++-------- libraries/dsp/fft/tb/vhdl/tb_fft_switch.vhd | 15 ++- 3 files changed, 162 insertions(+), 113 deletions(-) diff --git a/libraries/dsp/fft/src/vhdl/fft_switch.vhd b/libraries/dsp/fft/src/vhdl/fft_switch.vhd index 3825d52de8..6f10f0c712 100644 --- a/libraries/dsp/fft/src/vhdl/fft_switch.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_switch.vhd @@ -31,13 +31,13 @@ -- blocks of c_nof_clk_per_block samples to the FFT. -- Remark: Copy from applications/lofar1/RSP/pft2/src/vhdl/pft_switch.vhd -LIBRARY IEEE, common_lib, dp_lib; +LIBRARY IEEE, common_lib; USE IEEE.std_logic_1164.ALL; USE common_lib.common_pkg.ALL; -USE dp_lib.dp_stream_pkg.ALL; ENTITY fft_switch IS GENERIC ( + g_switch_en : BOOLEAN := FALSE; g_fft_sz_w : NATURAL; g_dat_w : NATURAL ); @@ -45,7 +45,6 @@ ENTITY fft_switch IS in_re : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); -- real input A in_im : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); -- real input B in_val : IN STD_LOGIC; - switch_en : IN STD_LOGIC := '1'; out_re : OUT STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); out_im : OUT STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); out_val : OUT STD_LOGIC; @@ -59,6 +58,9 @@ ARCHITECTURE rtl OF fft_switch IS CONSTANT c_nof_clk_per_block : NATURAL := 2**g_fft_sz_w; + SIGNAL in_sop : STD_LOGIC; + SIGNAL in_eop : STD_LOGIC; + SIGNAL cnt : STD_LOGIC_VECTOR(g_fft_sz_w DOWNTO 0) := (OTHERS => '0'); SIGNAL nxt_cnt : STD_LOGIC_VECTOR(cnt'RANGE); @@ -71,60 +73,84 @@ ARCHITECTURE rtl OF fft_switch IS BEGIN - p_reg : PROCESS (rst, clk) - BEGIN - IF rst = '1' THEN - cnt <= (OTHERS => '0'); - out_val <= '0'; - out_re <= (OTHERS => '0'); - out_im <= (OTHERS => '0'); - ELSIF rising_edge(clk) THEN - cnt <= nxt_cnt; - out_val <= in_val; - out_re <= nxt_out_re; - out_im <= nxt_out_im; - END IF; - END PROCESS; - - p_counter: PROCESS(cnt, in_val) - BEGIN - nxt_cnt <= cnt; - IF in_val = '1' THEN - nxt_cnt <= INCR_UVEC(cnt, 1); - END IF; - END PROCESS; - - p_lfsr_ctrl: PROCESS(cnt, in_val) - BEGIN - if TO_SINT(cnt) = -1 AND in_val = '1' THEN - lfsr_en <= '1'; - ELSE - lfsr_en <= '0'; - END IF; - END PROCESS; - - p_out: PROCESS(in_re, in_im, switch_en, cnt, lfsr_bit1, lfsr_bit2) - BEGIN - nxt_out_re <= in_re; - nxt_out_im <= in_im; - - IF switch_en = '1' THEN + -- Create input strobes to view data blocks for debugging + u_in_strobes : ENTITY common_lib.common_create_strobes_from_valid + GENERIC MAP ( + g_pipeline => FALSE, + g_nof_clk_per_sync => c_nof_clk_per_block * 16, -- void value, sync is not used + g_nof_clk_per_block => c_nof_clk_per_block + ) + PORT MAP ( + rst => rst, + clk => clk, + in_val => in_val, + out_val => OPEN, -- out_val = in_val, because g_pipeline = FALSE + out_sop => in_sop, + out_eop => in_eop, + out_sync => OPEN + ); + + no_switch : IF g_switch_en = FALSE GENERATE + -- wire inputs to outputs + out_re <= in_re; + out_im <= in_im; + out_val <= in_val; + END GENERATE; + + gen_switch : IF g_switch_en = TRUE GENERATE + p_reg : PROCESS (rst, clk) + BEGIN + IF rst = '1' THEN + cnt <= (OTHERS => '0'); + out_val <= '0'; + out_re <= (OTHERS => '0'); + out_im <= (OTHERS => '0'); + ELSIF rising_edge(clk) THEN + cnt <= nxt_cnt; + out_val <= in_val; + out_re <= nxt_out_re; + out_im <= nxt_out_im; + END IF; + END PROCESS; + + p_counter: PROCESS(cnt, in_val) + BEGIN + nxt_cnt <= cnt; + IF in_val = '1' THEN + nxt_cnt <= INCR_UVEC(cnt, 1); + END IF; + END PROCESS; + + p_lfsr_ctrl: PROCESS(cnt, in_val) + BEGIN + if TO_SINT(cnt) = -1 AND in_val = '1' THEN + lfsr_en <= '1'; + ELSE + lfsr_en <= '0'; + END IF; + END PROCESS; + + p_out: PROCESS(in_re, in_im, cnt, lfsr_bit1, lfsr_bit2) + BEGIN + nxt_out_re <= in_re; + nxt_out_im <= in_im; + IF lfsr_bit1 = cnt(cnt'HIGH) THEN nxt_out_re <= NEGATE_SVEC(in_re, g_dat_w); -- negate block of input A samples END IF; IF lfsr_bit2 = cnt(cnt'HIGH) THEN nxt_out_im <= NEGATE_SVEC(in_im, g_dat_w); -- negate block of input B samples END IF; - END IF; - END PROCESS; - - u_fft_lfsr: ENTITY work.fft_lfsr - PORT MAP ( - clk => clk, - rst => rst, - in_en => lfsr_en, - out_bit1 => lfsr_bit1, - out_bit2 => lfsr_bit2 - ); + END PROCESS; + + u_fft_lfsr: ENTITY work.fft_lfsr + PORT MAP ( + clk => clk, + rst => rst, + in_en => lfsr_en, + out_bit1 => lfsr_bit1, + out_bit2 => lfsr_bit2 + ); + END GENERATE; END rtl; diff --git a/libraries/dsp/fft/src/vhdl/fft_unswitch.vhd b/libraries/dsp/fft/src/vhdl/fft_unswitch.vhd index 9f32850800..b8a7de8c7b 100644 --- a/libraries/dsp/fft/src/vhdl/fft_unswitch.vhd +++ b/libraries/dsp/fft/src/vhdl/fft_unswitch.vhd @@ -26,13 +26,13 @@ -- c_nof_clk_per_block samples, forever after rst release. -- Remark: Copy from applications/lofar1/RSP/pft2/src/vhdl/pft_unswitch.vhd -LIBRARY IEEE, common_lib, dp_lib; +LIBRARY IEEE, common_lib; USE IEEE.std_logic_1164.ALL; USE common_lib.common_pkg.ALL; -USE dp_lib.dp_stream_pkg.ALL; ENTITY fft_unswitch IS GENERIC ( + g_switch_en : BOOLEAN := FALSE; g_fft_sz_w : NATURAL; g_dat_w : NATURAL ); @@ -40,7 +40,6 @@ ENTITY fft_unswitch IS in_re : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); in_im : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); in_val : IN STD_LOGIC; - switch_en : IN STD_LOGIC := '1'; out_re : OUT STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); out_im : OUT STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); out_val : OUT STD_LOGIC; @@ -53,7 +52,8 @@ ARCHITECTURE rtl OF fft_unswitch IS CONSTANT c_nof_clk_per_block : NATURAL := 2**g_fft_sz_w; - SIGNAL in_sosi : t_dp_sosi; + SIGNAL in_sop : STD_LOGIC; + SIGNAL in_eop : STD_LOGIC; SIGNAL cnt : STD_LOGIC_VECTOR(g_fft_sz_w DOWNTO 0) := (OTHERS => '0'); SIGNAL nxt_cnt : STD_LOGIC_VECTOR(cnt'RANGE); @@ -68,44 +68,68 @@ ARCHITECTURE rtl OF fft_unswitch IS BEGIN - p_reg : PROCESS (rst, clk) - BEGIN - IF rst = '1' THEN - cnt <= (OTHERS => '0'); - out_val <= '0'; - out_re <= (OTHERS => '0'); - out_im <= (OTHERS => '0'); - ELSIF rising_edge(clk) THEN - cnt <= nxt_cnt; - out_val <= in_val; - out_re <= nxt_out_re; - out_im <= nxt_out_im; - END IF; - END PROCESS; - - p_counter: PROCESS(cnt, in_val) - BEGIN - nxt_cnt <= cnt; - IF in_val = '1' THEN - nxt_cnt <= INCR_UVEC(cnt, 1); - END IF; - END PROCESS; - - p_lfsr_ctrl: PROCESS(cnt, in_val) - BEGIN - if TO_SINT(cnt) = -1 AND in_val = '1' THEN - lfsr_en <= '1'; - ELSE - lfsr_en <= '0'; - END IF; - END PROCESS; - - p_out: PROCESS(in_re, in_im, switch_en, cnt, lfsr_bit1, lfsr_bit2) - BEGIN - nxt_out_re <= in_re; - nxt_out_im <= in_im; - - IF switch_en = '1' THEN + -- Create input strobes to view data blocks for debugging + u_in_strobes : ENTITY common_lib.common_create_strobes_from_valid + GENERIC MAP ( + g_pipeline => FALSE, + g_nof_clk_per_sync => c_nof_clk_per_block * 16, -- void value, sync is not used + g_nof_clk_per_block => c_nof_clk_per_block + ) + PORT MAP ( + rst => rst, + clk => clk, + in_val => in_val, + out_val => OPEN, -- out_val = in_val, because g_pipeline = FALSE + out_sop => in_sop, + out_eop => in_eop, + out_sync => OPEN + ); + + no_switch : IF g_switch_en = FALSE GENERATE + -- wire inputs to outputs + out_re <= in_re; + out_im <= in_im; + out_val <= in_val; + END GENERATE; + + gen_switch : IF g_switch_en = TRUE GENERATE + p_reg : PROCESS (rst, clk) + BEGIN + IF rst = '1' THEN + cnt <= (OTHERS => '0'); + out_val <= '0'; + out_re <= (OTHERS => '0'); + out_im <= (OTHERS => '0'); + ELSIF rising_edge(clk) THEN + cnt <= nxt_cnt; + out_val <= in_val; + out_re <= nxt_out_re; + out_im <= nxt_out_im; + END IF; + END PROCESS; + + p_counter: PROCESS(cnt, in_val) + BEGIN + nxt_cnt <= cnt; + IF in_val = '1' THEN + nxt_cnt <= INCR_UVEC(cnt, 1); + END IF; + END PROCESS; + + p_lfsr_ctrl: PROCESS(cnt, in_val) + BEGIN + if TO_SINT(cnt) = -1 AND in_val = '1' THEN + lfsr_en <= '1'; + ELSE + lfsr_en <= '0'; + END IF; + END PROCESS; + + p_out: PROCESS(in_re, in_im, cnt, lfsr_bit1, lfsr_bit2) + BEGIN + nxt_out_re <= in_re; + nxt_out_im <= in_im; + -- multiplexed spectrum for input A at index 0, B at index 1 IF cnt(0) = '0' THEN IF cnt(cnt'HIGH) = lfsr_bit1 THEN -- negate spectrum to undo negate of block of real input A @@ -118,16 +142,16 @@ BEGIN nxt_out_im <= NEGATE_SVEC(in_im, g_dat_w); END IF; END IF; - END IF; - END PROCESS; - - u_fft_lfsr: ENTITY work.fft_lfsr - PORT MAP ( - clk => clk, - rst => rst, - in_en => lfsr_en, - out_bit1 => lfsr_bit1, - out_bit2 => lfsr_bit2 - ); + END PROCESS; + + u_fft_lfsr: ENTITY work.fft_lfsr + PORT MAP ( + clk => clk, + rst => rst, + in_en => lfsr_en, + out_bit1 => lfsr_bit1, + out_bit2 => lfsr_bit2 + ); + END GENERATE; END rtl; diff --git a/libraries/dsp/fft/tb/vhdl/tb_fft_switch.vhd b/libraries/dsp/fft/tb/vhdl/tb_fft_switch.vhd index 9d41bcb2dd..08d04ee3e9 100644 --- a/libraries/dsp/fft/tb/vhdl/tb_fft_switch.vhd +++ b/libraries/dsp/fft/tb/vhdl/tb_fft_switch.vhd @@ -55,6 +55,7 @@ USE common_lib.tb_common_pkg.ALL; ENTITY tb_fft_switch IS GENERIC ( + g_switch_en : BOOLEAN := TRUE; g_in_val_gaps : BOOLEAN := TRUE; g_increment_at_val : BOOLEAN := TRUE; g_fft_size_w : NATURAL := 3; @@ -87,7 +88,6 @@ ARCHITECTURE tb OF tb_fft_switch IS SIGNAL in_eop : STD_LOGIC := '0'; SIGNAL in_sync : STD_LOGIC := '0'; - SIGNAL switch_en : STD_LOGIC := '1'; SIGNAL switch_a : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); SIGNAL switch_b : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); SIGNAL switch_val : STD_LOGIC; @@ -101,7 +101,6 @@ ARCHITECTURE tb OF tb_fft_switch IS SIGNAL mux_im : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL mux_val : STD_LOGIC := '0'; - SIGNAL unswitch_en : STD_LOGIC := '1'; SIGNAL unswitch_re : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); SIGNAL unswitch_im : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); SIGNAL unswitch_val : STD_LOGIC := '0'; @@ -185,14 +184,14 @@ BEGIN u_fft_switch : ENTITY work.fft_switch GENERIC MAP ( - g_fft_sz_w => g_fft_size_w, - g_dat_w => c_dat_w + g_switch_en => g_switch_en, + g_fft_sz_w => g_fft_size_w, + g_dat_w => c_dat_w ) PORT MAP ( in_re => in_a, in_im => in_b, in_val => in_val, - switch_en => switch_en, out_re => switch_a, out_im => switch_b, out_val => switch_val, @@ -227,14 +226,14 @@ BEGIN u_fft_unswitch : ENTITY work.fft_unswitch GENERIC MAP ( - g_fft_sz_w => g_fft_size_w, - g_dat_w => c_dat_w + g_switch_en => g_switch_en, + g_fft_sz_w => g_fft_size_w, + g_dat_w => c_dat_w ) PORT MAP ( in_re => mux_re, in_im => mux_im, in_val => mux_val, - switch_en => unswitch_en, out_re => unswitch_re, out_im => unswitch_im, out_val => unswitch_val, -- GitLab