From 82828719901d7a610056ac69b308dc4c0264700b Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Wed, 20 Nov 2019 23:04:49 -0300 Subject: [PATCH 01/15] modules/hpf_adcinput: add new high pass filter module The primary use of this module is to filter out EMI (DC to 5 MHz) from pulsed magnets close to BPMs. The filter code was generated by MATLAB HDL Coder. --- hdl/modules/Manifest.py | 3 +- hdl/modules/dsp_cores_pkg.vhd | 12 + hdl/modules/hpf_adcinput/Manifest.py | 1 + hdl/modules/hpf_adcinput/hpf_adcinput.vhd | 392 ++++++++++++++++++++++ 4 files changed, 407 insertions(+), 1 deletion(-) create mode 100755 hdl/modules/hpf_adcinput/Manifest.py create mode 100644 hdl/modules/hpf_adcinput/hpf_adcinput.vhd diff --git a/hdl/modules/Manifest.py b/hdl/modules/Manifest.py index 5142aa58..10a24926 100644 --- a/hdl/modules/Manifest.py +++ b/hdl/modules/Manifest.py @@ -23,5 +23,6 @@ "clock_driver", "machine", "rp_math_pack", - "part_delta_sigma" + "part_delta_sigma", + "hpf_adcinput" ] }; diff --git a/hdl/modules/dsp_cores_pkg.vhd b/hdl/modules/dsp_cores_pkg.vhd index ac870221..273547eb 100755 --- a/hdl/modules/dsp_cores_pkg.vhd +++ b/hdl/modules/dsp_cores_pkg.vhd @@ -1602,6 +1602,18 @@ package dsp_cores_pkg is ); end component; + component hpf_adcinput + port + ( + clk_i : in std_logic; + rst_n_i : in std_logic; + ce_i : in std_logic; + + data_i : in std_logic_vector(15 downto 0); + data_o : out std_logic_vector(15 downto 0) + ); + end component hpf_adcinput; + end dsp_cores_pkg; package body dsp_cores_pkg is diff --git a/hdl/modules/hpf_adcinput/Manifest.py b/hdl/modules/hpf_adcinput/Manifest.py new file mode 100755 index 00000000..f926f6a3 --- /dev/null +++ b/hdl/modules/hpf_adcinput/Manifest.py @@ -0,0 +1 @@ +files = ["hpf_adcinput.vhd"] diff --git a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd new file mode 100644 index 00000000..161b35fe --- /dev/null +++ b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd @@ -0,0 +1,392 @@ +-- ------------------------------------------------------------- +-- +-- Module: hpf_adcinput +-- Generated by MATLAB(R) 8.3 and the Filter Design HDL Coder 2.9.5. +-- Generated on: 2019-11-20 23:00:25 +-- ------------------------------------------------------------- + +-- ------------------------------------------------------------- +-- HDL Code Generation Options: +-- +-- TargetLanguage: VHDL +-- ResetType: Synchronous +-- FoldingFactor: 12 +-- ClockEnableInputPort: ce_i +-- ClockInputPort: clk_i +-- ResetInputPort: rst_n_i +-- UseRisingEdge: on +-- TargetDirectory: /home/danielot/hdlsrc +-- EDAScriptGeneration: off +-- InputPort: data_i +-- OutputPort: data_o +-- Name: hpf_adcinput +-- TestBenchStimulus: step ramp chirp +-- GenerateHDLTestBench: off + +-- Filter Specifications: +-- +-- Sample Rate : N/A (normalized frequency) +-- Response : Highpass +-- Specification : Fst,Fp,Ast,Ap +-- Stopband Edge : 0.045266 +-- Passband Edge : 0.36213 +-- Stopband Atten. : 40 dB +-- Passband Ripple : 1 dB +-- ------------------------------------------------------------- + +-- ------------------------------------------------------------- +-- HDL Implementation : Fully Serial +-- Multipliers : 1 +-- Folding Factor : 12 +-- ------------------------------------------------------------- +-- Filter Settings: +-- +-- Discrete-Time IIR Filter (real) +-- ------------------------------- +-- Filter Structure : Direct-Form II, Second-Order Sections +-- Number of Sections : 2 +-- Stable : Yes +-- Linear Phase : No +-- Arithmetic : fixed +-- Numerator : s16,14 -> [-2 2) +-- Denominator : s16,14 -> [-2 2) +-- Scale Values : s16,15 -> [-1 1) +-- Input : s16,15 -> [-1 1) +-- Section Input : s16,10 -> [-32 32) +-- Section Output : s16,11 -> [-16 16) +-- Output : s16,11 -> [-16 16) +-- State : s16,15 -> [-1 1) +-- Numerator Prod : s32,29 -> [-4 4) +-- Denominator Prod : s32,29 -> [-4 4) +-- Numerator Accum : s34,29 -> [-16 16) +-- Denominator Accum : s34,29 -> [-16 16) +-- Round Mode : convergent +-- Overflow Mode : wrap +-- ------------------------------------------------------------- +LIBRARY IEEE; +USE IEEE.std_logic_1164.all; +USE IEEE.numeric_std.ALL; + +ENTITY hpf_adcinput IS + PORT( clk_i : IN std_logic; + ce_i : IN std_logic; + rst_n_i : IN std_logic; + data_i : IN std_logic_vector(15 DOWNTO 0); -- sfix16_En15 + data_o : OUT std_logic_vector(15 DOWNTO 0) -- sfix16_En11 + ); + +END hpf_adcinput; + + +---------------------------------------------------------------- +--Module Architecture: hpf_adcinput +---------------------------------------------------------------- +ARCHITECTURE rtl OF hpf_adcinput IS + -- Local Functions + -- Type Definitions + TYPE delay_pipeline_type IS ARRAY (NATURAL range <>) OF signed(15 DOWNTO 0); -- sfix16_En15 + -- Constants + CONSTANT scaleconst1 : signed(17 DOWNTO 0) := to_signed(18503, 18); -- sfix18_En15 + CONSTANT coeff_b1_section1 : signed(17 DOWNTO 0) := to_signed(32768, 18); -- sfix18_En15 + CONSTANT coeff_b2_section1 : signed(17 DOWNTO 0) := to_signed(-65536, 18); -- sfix18_En15 + CONSTANT coeff_b3_section1 : signed(17 DOWNTO 0) := to_signed(32768, 18); -- sfix18_En15 + CONSTANT coeff_a2_section1 : signed(17 DOWNTO 0) := to_signed(-27366, 18); -- sfix18_En15 + CONSTANT coeff_a3_section1 : signed(17 DOWNTO 0) := to_signed(13880, 18); -- sfix18_En15 + CONSTANT scaleconst2 : signed(17 DOWNTO 0) := to_signed(21695, 18); -- sfix18_En15 + CONSTANT coeff_b1_section2 : signed(17 DOWNTO 0) := to_signed(32768, 18); -- sfix18_En15 + CONSTANT coeff_b2_section2 : signed(17 DOWNTO 0) := to_signed(-32768, 18); -- sfix18_En15 + CONSTANT coeff_b3_section2 : signed(17 DOWNTO 0) := to_signed(0, 18); -- sfix18_En15 + CONSTANT coeff_a2_section2 : signed(17 DOWNTO 0) := to_signed(-10622, 18); -- sfix18_En15 + CONSTANT coeff_a3_section2 : signed(17 DOWNTO 0) := to_signed(0, 18); -- sfix18_En15 + -- Signals + SIGNAL input_register : signed(15 DOWNTO 0); -- sfix16_En15 + SIGNAL cur_count : unsigned(3 DOWNTO 0); -- ufix4 + SIGNAL phase_0 : std_logic; -- boolean + SIGNAL phase_2 : std_logic; -- boolean + SIGNAL phase_3 : std_logic; -- boolean + SIGNAL phase_5 : std_logic; -- boolean + SIGNAL phase_6 : std_logic; -- boolean + SIGNAL phase_8 : std_logic; -- boolean + SIGNAL phase_9 : std_logic; -- boolean + SIGNAL phase_11 : std_logic; -- boolean + SIGNAL sectionipconvert : signed(15 DOWNTO 0); -- sfix16_En10 + SIGNAL storagetypeconvert : signed(15 DOWNTO 0); -- sfix16_En15 + SIGNAL prev_stg_op1 : signed(15 DOWNTO 0); -- sfix16_En11 + SIGNAL storage_state_in1 : signed(15 DOWNTO 0); -- sfix16_En15 + SIGNAL delay_section1 : delay_pipeline_type(0 TO 1); -- sfix16_En15 + SIGNAL storage_state_in2 : signed(15 DOWNTO 0); -- sfix16_En15 + SIGNAL delay_section2 : delay_pipeline_type(0 TO 1); -- sfix16_En15 + SIGNAL input_section1_cast : signed(19 DOWNTO 0); -- sfix20_En15 + SIGNAL storage_in_section1_cast : signed(19 DOWNTO 0); -- sfix20_En15 + SIGNAL delay_section11_cast : signed(19 DOWNTO 0); -- sfix20_En15 + SIGNAL delay_section12_cast : signed(19 DOWNTO 0); -- sfix20_En15 + SIGNAL input_section2_cast : signed(19 DOWNTO 0); -- sfix20_En15 + SIGNAL storage_in_section2_cast : signed(19 DOWNTO 0); -- sfix20_En15 + SIGNAL delay_section21_cast : signed(19 DOWNTO 0); -- sfix20_En15 + SIGNAL delay_section22_cast : signed(19 DOWNTO 0); -- sfix20_En15 + SIGNAL inputmux_section_1 : signed(19 DOWNTO 0); -- sfix20_En15 + SIGNAL coeffmux_section_1 : signed(17 DOWNTO 0); -- sfix18_En15 + SIGNAL prod : signed(37 DOWNTO 0); -- sfix38_En30 + SIGNAL prod_den : signed(31 DOWNTO 0); -- sfix32_En29 + SIGNAL prod_den_cast_temp : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL prod_den_cast : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL prod_den_cast_neg : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL unaryminus_temp : signed(34 DOWNTO 0); -- sfix35_En29 + SIGNAL prod_num : signed(31 DOWNTO 0); -- sfix32_En29 + SIGNAL prod_num_cast_temp : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL prod_num_cast : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL accum_mux_in1 : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL accum_mux_in2 : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL accum_mux_out : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL accum_mux_in1_temp : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL sectionipconvert_cast : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL final_phase : std_logic; -- boolean + SIGNAL section_phase : std_logic; -- boolean + SIGNAL accum_reg : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL add_cast : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL add_cast_1 : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL add_temp : signed(34 DOWNTO 0); -- sfix35_En29 + SIGNAL acc_out_cast_numacc : signed(33 DOWNTO 0); -- sfix34_En29 + SIGNAL sectionopconvert : signed(15 DOWNTO 0); -- sfix16_En11 + SIGNAL output_typeconvert : signed(15 DOWNTO 0); -- sfix16_En11 + SIGNAL output_register : signed(15 DOWNTO 0); -- sfix16_En11 + + +BEGIN + + -- Block Statements + input_reg_process : PROCESS (clk_i) + BEGIN + IF rising_edge(clk_i) THEN + IF rst_n_i = '0' THEN + input_register <= (OTHERS => '0'); + ELSIF ce_i = '1' THEN + input_register <= signed(data_i); + END IF; + END IF; + END PROCESS input_reg_process; + + Counter_process : PROCESS (clk_i) + BEGIN + IF rising_edge(clk_i) THEN + IF rst_n_i = '0' THEN + cur_count <= to_unsigned(0, 4); + ELSIF ce_i = '1' THEN + IF cur_count = to_unsigned(11, 4) THEN + cur_count <= to_unsigned(0, 4); + ELSE + cur_count <= cur_count + 1; + END IF; + END IF; + END IF; + END PROCESS Counter_process; + + phase_0 <= '1' WHEN cur_count = to_unsigned(0, 4) AND ce_i = '1' ELSE '0'; + + phase_2 <= '1' WHEN cur_count = to_unsigned(2, 4) AND ce_i = '1' ELSE '0'; + + phase_3 <= '1' WHEN cur_count = to_unsigned(3, 4) AND ce_i = '1' ELSE '0'; + + phase_5 <= '1' WHEN cur_count = to_unsigned(5, 4) AND ce_i = '1' ELSE '0'; + + phase_6 <= '1' WHEN cur_count = to_unsigned(6, 4) AND ce_i = '1' ELSE '0'; + + phase_8 <= '1' WHEN cur_count = to_unsigned(8, 4) AND ce_i = '1' ELSE '0'; + + phase_9 <= '1' WHEN cur_count = to_unsigned(9, 4) AND ce_i = '1' ELSE '0'; + + phase_11 <= '1' WHEN cur_count = to_unsigned(11, 4) AND ce_i = '1' ELSE '0'; + + + -- Next stage input = Previous stage output. Storing Previous stage output + prev_stg_op1_process : PROCESS (clk_i) + BEGIN + IF rising_edge(clk_i) THEN + IF rst_n_i = '0' THEN + prev_stg_op1 <= (OTHERS => '0'); + ELSIF phase_5 = '1' THEN + prev_stg_op1 <= sectionopconvert; + END IF; + END IF; + END PROCESS prev_stg_op1_process; + + delay_process_section1 : PROCESS (clk_i) + BEGIN + IF rising_edge(clk_i) THEN + IF rst_n_i = '0' THEN + delay_section1 <= (OTHERS => (OTHERS => '0')); + ELSIF phase_0 = '1' THEN + delay_section1(1) <= delay_section1(0); + delay_section1(0) <= storage_state_in1; + END IF; + END IF; + END PROCESS delay_process_section1; + + delay_process_section2 : PROCESS (clk_i) + BEGIN + IF rising_edge(clk_i) THEN + IF rst_n_i = '0' THEN + delay_section2 <= (OTHERS => (OTHERS => '0')); + ELSIF phase_0 = '1' THEN + delay_section2(1) <= delay_section2(0); + delay_section2(0) <= storage_state_in2; + END IF; + END IF; + END PROCESS delay_process_section2; + + -- Making common precision for input and state + input_section1_cast <= resize(input_register, 20); + + delay_section11_cast <= resize(delay_section1(0), 20); + + delay_section12_cast <= resize(delay_section1(1), 20); + + storage_in_section1_cast <= resize(storage_state_in1, 20); + + delay_section11_cast <= resize(delay_section1(0), 20); + + delay_section12_cast <= resize(delay_section1(1), 20); + + input_section2_cast <= resize(prev_stg_op1(15 DOWNTO 0) & '0' & '0' & '0' & '0', 20); + + delay_section21_cast <= resize(delay_section2(0), 20); + + delay_section22_cast <= resize(delay_section2(1), 20); + + storage_in_section2_cast <= resize(storage_state_in2, 20); + + delay_section21_cast <= resize(delay_section2(0), 20); + + delay_section22_cast <= resize(delay_section2(1), 20); + + inputmux_section_1 <= input_section1_cast WHEN ( cur_count = to_unsigned(0, 4) ) ELSE + delay_section11_cast WHEN ( cur_count = to_unsigned(1, 4) ) ELSE + delay_section12_cast WHEN ( cur_count = to_unsigned(2, 4) ) ELSE + storage_in_section1_cast WHEN ( cur_count = to_unsigned(3, 4) ) ELSE + delay_section11_cast WHEN ( cur_count = to_unsigned(4, 4) ) ELSE + delay_section12_cast WHEN ( cur_count = to_unsigned(5, 4) ) ELSE + input_section2_cast WHEN ( cur_count = to_unsigned(6, 4) ) ELSE + delay_section21_cast WHEN ( cur_count = to_unsigned(7, 4) ) ELSE + delay_section22_cast WHEN ( cur_count = to_unsigned(8, 4) ) ELSE + storage_in_section2_cast WHEN ( cur_count = to_unsigned(9, 4) ) ELSE + delay_section21_cast WHEN ( cur_count = to_unsigned(10, 4) ) ELSE + delay_section22_cast; + + coeffmux_section_1 <= scaleconst1 WHEN ( cur_count = to_unsigned(0, 4) ) ELSE + coeff_a2_section1 WHEN ( cur_count = to_unsigned(1, 4) ) ELSE + coeff_a3_section1 WHEN ( cur_count = to_unsigned(2, 4) ) ELSE + coeff_b1_section1 WHEN ( cur_count = to_unsigned(3, 4) ) ELSE + coeff_b2_section1 WHEN ( cur_count = to_unsigned(4, 4) ) ELSE + coeff_b3_section1 WHEN ( cur_count = to_unsigned(5, 4) ) ELSE + scaleconst2 WHEN ( cur_count = to_unsigned(6, 4) ) ELSE + coeff_a2_section2 WHEN ( cur_count = to_unsigned(7, 4) ) ELSE + coeff_a3_section2 WHEN ( cur_count = to_unsigned(8, 4) ) ELSE + coeff_b1_section2 WHEN ( cur_count = to_unsigned(9, 4) ) ELSE + coeff_b2_section2 WHEN ( cur_count = to_unsigned(10, 4) ) ELSE + coeff_b3_section2; + + prod <= inputmux_section_1 * coeffmux_section_1; + + prod_den <= resize(shift_right(prod(32 DOWNTO 0) + ( "0" & (prod(1))), 1), 32); + + prod_den_cast_temp <= resize(prod_den, 34); + + prod_den_cast <= prod_den_cast_temp; + + unaryminus_temp <= ('0' & prod_den_cast) WHEN prod_den_cast = "1000000000000000000000000000000000" + ELSE -resize(prod_den_cast,35); + prod_den_cast_neg <= unaryminus_temp(33 DOWNTO 0); + + prod_num <= resize(shift_right(prod(32 DOWNTO 0) + ( "0" & (prod(1))), 1), 32); + + prod_num_cast_temp <= resize(prod_num, 34); + + prod_num_cast <= prod_num_cast_temp; + + accum_mux_in1 <= prod_num_cast WHEN ( cur_count = to_unsigned(0, 4) ) ELSE + prod_den_cast_neg WHEN ( cur_count = to_unsigned(1, 4) ) ELSE + prod_den_cast_neg WHEN ( cur_count = to_unsigned(2, 4) ) ELSE + prod_num_cast WHEN ( cur_count = to_unsigned(3, 4) ) ELSE + prod_num_cast WHEN ( cur_count = to_unsigned(4, 4) ) ELSE + prod_num_cast WHEN ( cur_count = to_unsigned(5, 4) ) ELSE + prod_num_cast WHEN ( cur_count = to_unsigned(6, 4) ) ELSE + prod_den_cast_neg WHEN ( cur_count = to_unsigned(7, 4) ) ELSE + prod_den_cast_neg WHEN ( cur_count = to_unsigned(8, 4) ) ELSE + prod_num_cast WHEN ( cur_count = to_unsigned(9, 4) ) ELSE + prod_num_cast WHEN ( cur_count = to_unsigned(10, 4) ) ELSE + prod_num_cast; + + final_phase <= phase_0 OR phase_3 OR phase_6 OR phase_9; + + section_phase <= phase_0 OR phase_6; + + accum_mux_in1_temp <= sectionipconvert_cast WHEN ( section_phase = '1' ) ELSE + accum_mux_in1; + + accum_mux_out <= accum_mux_in1_temp WHEN ( final_phase = '1' ) ELSE + accum_mux_in2; + + accumulator_reg_process : PROCESS (clk_i) + BEGIN + IF rising_edge(clk_i) THEN + IF rst_n_i = '0' THEN + accum_reg <= (OTHERS => '0'); + ELSIF ce_i = '1' THEN + accum_reg <= accum_mux_out; + END IF; + END IF; + END PROCESS accumulator_reg_process; + + add_cast <= accum_reg; + add_cast_1 <= accum_mux_in1; + add_temp <= resize(add_cast, 35) + resize(add_cast_1, 35); + accum_mux_in2 <= add_temp(33 DOWNTO 0); + + storagetypeconvert <= resize(shift_right(accum_mux_out(29 DOWNTO 0) + ( "0" & (accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14))), 14), 16); + + sectionipconvert <= resize(shift_right(prod(35 DOWNTO 0) + ( "0" & (prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20))), 20), 16); + + sectionipconvert_cast <= resize(sectionipconvert(14 DOWNTO 0) & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0', 34); + + acc_out_cast_numacc <= accum_mux_out; + + sectionopconvert <= resize(shift_right(acc_out_cast_numacc(33 DOWNTO 0) + ( "0" & (acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18))), 18), 16); + + output_typeconvert <= resize(shift_right(acc_out_cast_numacc(33 DOWNTO 0) + ( "0" & (acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18))), 18), 16); + + storage_reg1_process : PROCESS (clk_i) + BEGIN + IF rising_edge(clk_i) THEN + IF rst_n_i = '0' THEN + storage_state_in1 <= (OTHERS => '0'); + ELSIF phase_2 = '1' THEN + storage_state_in1 <= storagetypeconvert; + END IF; + END IF; + END PROCESS storage_reg1_process; + + storage_reg2_process : PROCESS (clk_i) + BEGIN + IF rising_edge(clk_i) THEN + IF rst_n_i = '0' THEN + storage_state_in2 <= (OTHERS => '0'); + ELSIF phase_8 = '1' THEN + storage_state_in2 <= storagetypeconvert; + END IF; + END IF; + END PROCESS storage_reg2_process; + + Output_Register_process : PROCESS (clk_i) + BEGIN + IF rising_edge(clk_i) THEN + IF rst_n_i = '0' THEN + output_register <= (OTHERS => '0'); + ELSIF phase_11 = '1' THEN + output_register <= output_typeconvert; + END IF; + END IF; + END PROCESS Output_Register_process; + + -- Assignment Statements + data_o <= std_logic_vector(output_register); +END rtl; From eb4abffbe143303c988cbb7c6cb8b2854e89a7c7 Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Thu, 21 Nov 2019 02:42:28 -0300 Subject: [PATCH 02/15] modules/wb_position_calc: insert high pass filters on all ADC inputs The HPFs were inserted between the "raw ADC" and "ADC swap" data streams. --- .../wb_position_calc_core.vhd | 62 +++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/hdl/modules/wb_position_calc/wb_position_calc_core.vhd b/hdl/modules/wb_position_calc/wb_position_calc_core.vhd index 56345fb2..426394a4 100755 --- a/hdl/modules/wb_position_calc/wb_position_calc_core.vhd +++ b/hdl/modules/wb_position_calc/wb_position_calc_core.vhd @@ -443,6 +443,12 @@ architecture rtl of wb_position_calc_core is signal dsp_ch_tag_en : std_logic := '0'; signal dsp_ch_valid : std_logic; + -- High pass filtering + signal adc_ch0_hpf : std_logic_vector(g_input_width-1 downto 0); + signal adc_ch1_hpf : std_logic_vector(g_input_width-1 downto 0); + signal adc_ch2_hpf : std_logic_vector(g_input_width-1 downto 0); + signal adc_ch3_hpf : std_logic_vector(g_input_width-1 downto 0); + -- BPM Swap signals signal sw_mode1 : std_logic_vector(1 downto 0); signal sw_mode2 : std_logic_vector(1 downto 0); @@ -987,6 +993,54 @@ begin -- Test data test_data <= regs_out.dds_cfg_test_data_o; + + ------------------------------------ + -- High pass filtering on ADC input + ------------------------------------ + cmp_hpf0 : hpf_adcinput + port map + ( + clk_i => clk_i, + rst_n_i => rst_n_i, + ce_i => '1', -- FIXME: create proper CE signal + data_i => adc_ch0_i, + data_o => adc_ch0_hpf + ); + end component hpf_adcinput; + + cmp_hpf1 : hpf_adcinput + port map + ( + clk_i => clk_i, + rst_n_i => rst_n_i, + ce_i => '1', -- FIXME: create proper CE signal + data_i => adc_ch1_i, + data_o => adc_ch1_hpf + ); + end component hpf_adcinput; + + cmp_hpf2 : hpf_adcinput + port map + ( + clk_i => clk_i, + rst_n_i => rst_n_i, + ce_i => '1', -- FIXME: create proper CE signal + data_i => adc_ch2_i, + data_o => adc_ch2_hpf + ); + end component hpf_adcinput; + + cmp_hpf3 : hpf_adcinput + port map + ( + clk_i => clk_i, + rst_n_i => rst_n_i, + ce_i => '1', -- FIXME: create proper CE signal + data_i => adc_ch3_i, + data_o => adc_ch3_hpf + ); + end component hpf_adcinput; + ----------------------------- -- BPM Swap Module. ----------------------------- @@ -1024,10 +1078,10 @@ begin -- External ports ----------------------------- -- Input from ADC FMC board - cha_i => adc_ch0_i, - chb_i => adc_ch1_i, - chc_i => adc_ch2_i, - chd_i => adc_ch3_i, + cha_i => adc_ch0_hpf, + chb_i => adc_ch1_hpf, + chc_i => adc_ch2_hpf, + chd_i => adc_ch3_hpf, ch_valid_i => adc_valid_i, cha_o => adc_ch0_sp, chb_o => adc_ch1_sp, From 2a9125a77dc49af68064cae51d6736f9d3d8ff2a Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Thu, 21 Nov 2019 14:24:44 -0200 Subject: [PATCH 03/15] modules/wb_position_calc: fix wrong syntax --- hdl/modules/wb_position_calc/wb_position_calc_core.vhd | 4 ---- 1 file changed, 4 deletions(-) diff --git a/hdl/modules/wb_position_calc/wb_position_calc_core.vhd b/hdl/modules/wb_position_calc/wb_position_calc_core.vhd index 426394a4..4461d83e 100755 --- a/hdl/modules/wb_position_calc/wb_position_calc_core.vhd +++ b/hdl/modules/wb_position_calc/wb_position_calc_core.vhd @@ -1006,7 +1006,6 @@ begin data_i => adc_ch0_i, data_o => adc_ch0_hpf ); - end component hpf_adcinput; cmp_hpf1 : hpf_adcinput port map @@ -1017,7 +1016,6 @@ begin data_i => adc_ch1_i, data_o => adc_ch1_hpf ); - end component hpf_adcinput; cmp_hpf2 : hpf_adcinput port map @@ -1028,7 +1026,6 @@ begin data_i => adc_ch2_i, data_o => adc_ch2_hpf ); - end component hpf_adcinput; cmp_hpf3 : hpf_adcinput port map @@ -1039,7 +1036,6 @@ begin data_i => adc_ch3_i, data_o => adc_ch3_hpf ); - end component hpf_adcinput; ----------------------------- -- BPM Swap Module. From 6f3d3be08d94abac8c10750a71ad4d8ab70ec325 Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Thu, 21 Nov 2019 14:26:16 -0200 Subject: [PATCH 04/15] modules/wb_position_calc: fix clock and reset inputs on HPF Use fs_clk_i/fs_rst_n_i instead of clk_i/rst_n_i --- .../wb_position_calc/wb_position_calc_core.vhd | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hdl/modules/wb_position_calc/wb_position_calc_core.vhd b/hdl/modules/wb_position_calc/wb_position_calc_core.vhd index 4461d83e..8a404a9f 100755 --- a/hdl/modules/wb_position_calc/wb_position_calc_core.vhd +++ b/hdl/modules/wb_position_calc/wb_position_calc_core.vhd @@ -1000,8 +1000,8 @@ begin cmp_hpf0 : hpf_adcinput port map ( - clk_i => clk_i, - rst_n_i => rst_n_i, + clk_i => fs_clk_i, + rst_n_i => fs_rst_n_i, ce_i => '1', -- FIXME: create proper CE signal data_i => adc_ch0_i, data_o => adc_ch0_hpf @@ -1010,8 +1010,8 @@ begin cmp_hpf1 : hpf_adcinput port map ( - clk_i => clk_i, - rst_n_i => rst_n_i, + clk_i => fs_clk_i, + rst_n_i => fs_rst_n_i, ce_i => '1', -- FIXME: create proper CE signal data_i => adc_ch1_i, data_o => adc_ch1_hpf @@ -1020,8 +1020,8 @@ begin cmp_hpf2 : hpf_adcinput port map ( - clk_i => clk_i, - rst_n_i => rst_n_i, + clk_i => fs_clk_i, + rst_n_i => fs_rst_n_i, ce_i => '1', -- FIXME: create proper CE signal data_i => adc_ch2_i, data_o => adc_ch2_hpf @@ -1030,8 +1030,8 @@ begin cmp_hpf3 : hpf_adcinput port map ( - clk_i => clk_i, - rst_n_i => rst_n_i, + clk_i => fs_clk_i, + rst_n_i => fs_rst_n_i, ce_i => '1', -- FIXME: create proper CE signal data_i => adc_ch3_i, data_o => adc_ch3_hpf From f393cb2fc11aadaa0f7f1bf7733c34266502d5d7 Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Thu, 21 Nov 2019 16:45:20 -0300 Subject: [PATCH 05/15] hpf_adcinput.vhd: move from IIR to FIR with similar specs Adopt Symmetric Direct-Form trying to achieve >221 MHz clock performance. --- hdl/modules/hpf_adcinput/hpf_adcinput.vhd | 427 ++++++++-------------- 1 file changed, 151 insertions(+), 276 deletions(-) diff --git a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd index 161b35fe..8650a651 100644 --- a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd +++ b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd @@ -2,7 +2,7 @@ -- -- Module: hpf_adcinput -- Generated by MATLAB(R) 8.3 and the Filter Design HDL Coder 2.9.5. --- Generated on: 2019-11-20 23:00:25 +-- Generated on: 2019-11-21 16:38:12 -- ------------------------------------------------------------- -- ------------------------------------------------------------- @@ -10,58 +10,45 @@ -- -- TargetLanguage: VHDL -- ResetType: Synchronous --- FoldingFactor: 12 +-- FIRAdderStyle: tree +-- OptimizeForHDL: on -- ClockEnableInputPort: ce_i -- ClockInputPort: clk_i -- ResetInputPort: rst_n_i -- UseRisingEdge: on --- TargetDirectory: /home/danielot/hdlsrc -- EDAScriptGeneration: off +-- AddPipelineRegisters: on -- InputPort: data_i -- OutputPort: data_o -- Name: hpf_adcinput --- TestBenchStimulus: step ramp chirp +-- ResetAssertedLevel: Active-low +-- TestBenchStimulus: impulse step ramp chirp noise -- GenerateHDLTestBench: off - --- Filter Specifications: --- --- Sample Rate : N/A (normalized frequency) --- Response : Highpass --- Specification : Fst,Fp,Ast,Ap --- Stopband Edge : 0.045266 --- Passband Edge : 0.36213 --- Stopband Atten. : 40 dB --- Passband Ripple : 1 dB --- ------------------------------------------------------------- +-- LoopUnrolling: on -- ------------------------------------------------------------- --- HDL Implementation : Fully Serial --- Multipliers : 1 --- Folding Factor : 12 +-- HDL Implementation : Fully parallel +-- Multipliers : 7 +-- Folding Factor : 1 -- ------------------------------------------------------------- -- Filter Settings: -- --- Discrete-Time IIR Filter (real) +-- Discrete-Time FIR Filter (real) -- ------------------------------- --- Filter Structure : Direct-Form II, Second-Order Sections --- Number of Sections : 2 --- Stable : Yes --- Linear Phase : No --- Arithmetic : fixed --- Numerator : s16,14 -> [-2 2) --- Denominator : s16,14 -> [-2 2) --- Scale Values : s16,15 -> [-1 1) --- Input : s16,15 -> [-1 1) --- Section Input : s16,10 -> [-32 32) --- Section Output : s16,11 -> [-16 16) --- Output : s16,11 -> [-16 16) --- State : s16,15 -> [-1 1) --- Numerator Prod : s32,29 -> [-4 4) --- Denominator Prod : s32,29 -> [-4 4) --- Numerator Accum : s34,29 -> [-16 16) --- Denominator Accum : s34,29 -> [-16 16) --- Round Mode : convergent --- Overflow Mode : wrap +-- Filter Structure : Direct-Form Symmetric FIR +-- Filter Length : 13 +-- Stable : Yes +-- Linear Phase : Yes (Type 1) +-- Arithmetic : fixed +-- Numerator : s16,14 -> [-2 2) +-- Input : s16,15 -> [-1 1) +-- Filter Internals : Specify Precision +-- Output : s16,15 -> [-1 1) +-- Tap Sum : s17,15 -> [-2 2) +-- Product : s32,30 -> [-2 2) +-- Accumulator : s32,30 -> [-2 2) +-- Round Mode : convergent +-- Overflow Mode : wrap -- ------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.all; @@ -70,9 +57,9 @@ USE IEEE.numeric_std.ALL; ENTITY hpf_adcinput IS PORT( clk_i : IN std_logic; ce_i : IN std_logic; - rst_n_i : IN std_logic; + rst_n_i : IN std_logic; data_i : IN std_logic_vector(15 DOWNTO 0); -- sfix16_En15 - data_o : OUT std_logic_vector(15 DOWNTO 0) -- sfix16_En11 + data_o : OUT std_logic_vector(15 DOWNTO 0) -- sfix16_En15 ); END hpf_adcinput; @@ -86,302 +73,190 @@ ARCHITECTURE rtl OF hpf_adcinput IS -- Type Definitions TYPE delay_pipeline_type IS ARRAY (NATURAL range <>) OF signed(15 DOWNTO 0); -- sfix16_En15 -- Constants - CONSTANT scaleconst1 : signed(17 DOWNTO 0) := to_signed(18503, 18); -- sfix18_En15 - CONSTANT coeff_b1_section1 : signed(17 DOWNTO 0) := to_signed(32768, 18); -- sfix18_En15 - CONSTANT coeff_b2_section1 : signed(17 DOWNTO 0) := to_signed(-65536, 18); -- sfix18_En15 - CONSTANT coeff_b3_section1 : signed(17 DOWNTO 0) := to_signed(32768, 18); -- sfix18_En15 - CONSTANT coeff_a2_section1 : signed(17 DOWNTO 0) := to_signed(-27366, 18); -- sfix18_En15 - CONSTANT coeff_a3_section1 : signed(17 DOWNTO 0) := to_signed(13880, 18); -- sfix18_En15 - CONSTANT scaleconst2 : signed(17 DOWNTO 0) := to_signed(21695, 18); -- sfix18_En15 - CONSTANT coeff_b1_section2 : signed(17 DOWNTO 0) := to_signed(32768, 18); -- sfix18_En15 - CONSTANT coeff_b2_section2 : signed(17 DOWNTO 0) := to_signed(-32768, 18); -- sfix18_En15 - CONSTANT coeff_b3_section2 : signed(17 DOWNTO 0) := to_signed(0, 18); -- sfix18_En15 - CONSTANT coeff_a2_section2 : signed(17 DOWNTO 0) := to_signed(-10622, 18); -- sfix18_En15 - CONSTANT coeff_a3_section2 : signed(17 DOWNTO 0) := to_signed(0, 18); -- sfix18_En15 + CONSTANT coeff1 : signed(15 DOWNTO 0) := to_signed(253, 16); -- sfix16_En14 + CONSTANT coeff2 : signed(15 DOWNTO 0) := to_signed(486, 16); -- sfix16_En14 + CONSTANT coeff3 : signed(15 DOWNTO 0) := to_signed(250, 16); -- sfix16_En14 + CONSTANT coeff4 : signed(15 DOWNTO 0) := to_signed(-966, 16); -- sfix16_En14 + CONSTANT coeff5 : signed(15 DOWNTO 0) := to_signed(-3070, 16); -- sfix16_En14 + CONSTANT coeff6 : signed(15 DOWNTO 0) := to_signed(-5154, 16); -- sfix16_En14 + CONSTANT coeff7 : signed(15 DOWNTO 0) := to_signed(16384, 16); -- sfix16_En14 + -- Signals - SIGNAL input_register : signed(15 DOWNTO 0); -- sfix16_En15 - SIGNAL cur_count : unsigned(3 DOWNTO 0); -- ufix4 - SIGNAL phase_0 : std_logic; -- boolean - SIGNAL phase_2 : std_logic; -- boolean - SIGNAL phase_3 : std_logic; -- boolean - SIGNAL phase_5 : std_logic; -- boolean - SIGNAL phase_6 : std_logic; -- boolean - SIGNAL phase_8 : std_logic; -- boolean - SIGNAL phase_9 : std_logic; -- boolean - SIGNAL phase_11 : std_logic; -- boolean - SIGNAL sectionipconvert : signed(15 DOWNTO 0); -- sfix16_En10 - SIGNAL storagetypeconvert : signed(15 DOWNTO 0); -- sfix16_En15 - SIGNAL prev_stg_op1 : signed(15 DOWNTO 0); -- sfix16_En11 - SIGNAL storage_state_in1 : signed(15 DOWNTO 0); -- sfix16_En15 - SIGNAL delay_section1 : delay_pipeline_type(0 TO 1); -- sfix16_En15 - SIGNAL storage_state_in2 : signed(15 DOWNTO 0); -- sfix16_En15 - SIGNAL delay_section2 : delay_pipeline_type(0 TO 1); -- sfix16_En15 - SIGNAL input_section1_cast : signed(19 DOWNTO 0); -- sfix20_En15 - SIGNAL storage_in_section1_cast : signed(19 DOWNTO 0); -- sfix20_En15 - SIGNAL delay_section11_cast : signed(19 DOWNTO 0); -- sfix20_En15 - SIGNAL delay_section12_cast : signed(19 DOWNTO 0); -- sfix20_En15 - SIGNAL input_section2_cast : signed(19 DOWNTO 0); -- sfix20_En15 - SIGNAL storage_in_section2_cast : signed(19 DOWNTO 0); -- sfix20_En15 - SIGNAL delay_section21_cast : signed(19 DOWNTO 0); -- sfix20_En15 - SIGNAL delay_section22_cast : signed(19 DOWNTO 0); -- sfix20_En15 - SIGNAL inputmux_section_1 : signed(19 DOWNTO 0); -- sfix20_En15 - SIGNAL coeffmux_section_1 : signed(17 DOWNTO 0); -- sfix18_En15 - SIGNAL prod : signed(37 DOWNTO 0); -- sfix38_En30 - SIGNAL prod_den : signed(31 DOWNTO 0); -- sfix32_En29 - SIGNAL prod_den_cast_temp : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL prod_den_cast : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL prod_den_cast_neg : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL unaryminus_temp : signed(34 DOWNTO 0); -- sfix35_En29 - SIGNAL prod_num : signed(31 DOWNTO 0); -- sfix32_En29 - SIGNAL prod_num_cast_temp : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL prod_num_cast : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL accum_mux_in1 : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL accum_mux_in2 : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL accum_mux_out : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL accum_mux_in1_temp : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL sectionipconvert_cast : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL final_phase : std_logic; -- boolean - SIGNAL section_phase : std_logic; -- boolean - SIGNAL accum_reg : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL add_cast : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL add_cast_1 : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL add_temp : signed(34 DOWNTO 0); -- sfix35_En29 - SIGNAL acc_out_cast_numacc : signed(33 DOWNTO 0); -- sfix34_En29 - SIGNAL sectionopconvert : signed(15 DOWNTO 0); -- sfix16_En11 - SIGNAL output_typeconvert : signed(15 DOWNTO 0); -- sfix16_En11 - SIGNAL output_register : signed(15 DOWNTO 0); -- sfix16_En11 + SIGNAL delay_pipeline : delay_pipeline_type(0 TO 12); -- sfix16_En15 + SIGNAL tapsum1 : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL tapsum_mcand : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL tapsum2 : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL tapsum_mcand_1 : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL tapsum3 : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL tapsum_mcand_2 : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL tapsum4 : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL tapsum_mcand_3 : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL tapsum5 : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL tapsum_mcand_4 : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL tapsum6 : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL tapsum_mcand_5 : signed(16 DOWNTO 0); -- sfix17_En15 + SIGNAL product6 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL mul_temp : signed(32 DOWNTO 0); -- sfix33_En29 + SIGNAL product5 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL mul_temp_1 : signed(32 DOWNTO 0); -- sfix33_En29 + SIGNAL product4 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL mul_temp_2 : signed(32 DOWNTO 0); -- sfix33_En29 + SIGNAL product3 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL mul_temp_3 : signed(32 DOWNTO 0); -- sfix33_En29 + SIGNAL product2 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL mul_temp_4 : signed(32 DOWNTO 0); -- sfix33_En29 + SIGNAL product1 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL mul_temp_5 : signed(32 DOWNTO 0); -- sfix33_En29 + SIGNAL sum_final : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL sum1_1 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL add_temp : signed(32 DOWNTO 0); -- sfix33_En30 + SIGNAL sumpipe1_1 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL sum1_2 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL add_temp_1 : signed(32 DOWNTO 0); -- sfix33_En30 + SIGNAL sumpipe1_2 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL sum1_3 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL add_temp_2 : signed(32 DOWNTO 0); -- sfix33_En30 + SIGNAL sumpipe1_3 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL sumpipe1_4 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL sum2_1 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL add_temp_3 : signed(32 DOWNTO 0); -- sfix33_En30 + SIGNAL sumpipe2_1 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL sum2_2 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL add_temp_4 : signed(32 DOWNTO 0); -- sfix33_En30 + SIGNAL sumpipe2_2 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL sum3_1 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL add_temp_5 : signed(32 DOWNTO 0); -- sfix33_En30 + SIGNAL sumpipe3_1 : signed(31 DOWNTO 0); -- sfix32_En30 + SIGNAL output_typeconvert : signed(15 DOWNTO 0); -- sfix16_En15 + SIGNAL output_register : signed(15 DOWNTO 0); -- sfix16_En15 BEGIN -- Block Statements - input_reg_process : PROCESS (clk_i) - BEGIN - IF rising_edge(clk_i) THEN - IF rst_n_i = '0' THEN - input_register <= (OTHERS => '0'); - ELSIF ce_i = '1' THEN - input_register <= signed(data_i); - END IF; - END IF; - END PROCESS input_reg_process; - - Counter_process : PROCESS (clk_i) + Delay_Pipeline_process : PROCESS (clk_i) BEGIN IF rising_edge(clk_i) THEN IF rst_n_i = '0' THEN - cur_count <= to_unsigned(0, 4); + delay_pipeline(0 TO 12) <= (OTHERS => (OTHERS => '0')); ELSIF ce_i = '1' THEN - IF cur_count = to_unsigned(11, 4) THEN - cur_count <= to_unsigned(0, 4); - ELSE - cur_count <= cur_count + 1; - END IF; + delay_pipeline(0) <= signed(data_i); + delay_pipeline(1 TO 12) <= delay_pipeline(0 TO 11); END IF; END IF; - END PROCESS Counter_process; + END PROCESS Delay_Pipeline_process; - phase_0 <= '1' WHEN cur_count = to_unsigned(0, 4) AND ce_i = '1' ELSE '0'; + tapsum1 <= resize(delay_pipeline(0), 17) + resize(delay_pipeline(12), 17); - phase_2 <= '1' WHEN cur_count = to_unsigned(2, 4) AND ce_i = '1' ELSE '0'; + tapsum_mcand <= tapsum1; - phase_3 <= '1' WHEN cur_count = to_unsigned(3, 4) AND ce_i = '1' ELSE '0'; + tapsum2 <= resize(delay_pipeline(1), 17) + resize(delay_pipeline(11), 17); - phase_5 <= '1' WHEN cur_count = to_unsigned(5, 4) AND ce_i = '1' ELSE '0'; + tapsum_mcand_1 <= tapsum2; - phase_6 <= '1' WHEN cur_count = to_unsigned(6, 4) AND ce_i = '1' ELSE '0'; + tapsum3 <= resize(delay_pipeline(2), 17) + resize(delay_pipeline(10), 17); - phase_8 <= '1' WHEN cur_count = to_unsigned(8, 4) AND ce_i = '1' ELSE '0'; + tapsum_mcand_2 <= tapsum3; - phase_9 <= '1' WHEN cur_count = to_unsigned(9, 4) AND ce_i = '1' ELSE '0'; + tapsum4 <= resize(delay_pipeline(3), 17) + resize(delay_pipeline(9), 17); - phase_11 <= '1' WHEN cur_count = to_unsigned(11, 4) AND ce_i = '1' ELSE '0'; + tapsum_mcand_3 <= tapsum4; + tapsum5 <= resize(delay_pipeline(4), 17) + resize(delay_pipeline(8), 17); - -- Next stage input = Previous stage output. Storing Previous stage output - prev_stg_op1_process : PROCESS (clk_i) - BEGIN - IF rising_edge(clk_i) THEN - IF rst_n_i = '0' THEN - prev_stg_op1 <= (OTHERS => '0'); - ELSIF phase_5 = '1' THEN - prev_stg_op1 <= sectionopconvert; - END IF; - END IF; - END PROCESS prev_stg_op1_process; - - delay_process_section1 : PROCESS (clk_i) - BEGIN - IF rising_edge(clk_i) THEN - IF rst_n_i = '0' THEN - delay_section1 <= (OTHERS => (OTHERS => '0')); - ELSIF phase_0 = '1' THEN - delay_section1(1) <= delay_section1(0); - delay_section1(0) <= storage_state_in1; - END IF; - END IF; - END PROCESS delay_process_section1; - - delay_process_section2 : PROCESS (clk_i) - BEGIN - IF rising_edge(clk_i) THEN - IF rst_n_i = '0' THEN - delay_section2 <= (OTHERS => (OTHERS => '0')); - ELSIF phase_0 = '1' THEN - delay_section2(1) <= delay_section2(0); - delay_section2(0) <= storage_state_in2; - END IF; - END IF; - END PROCESS delay_process_section2; - - -- Making common precision for input and state - input_section1_cast <= resize(input_register, 20); + tapsum_mcand_4 <= tapsum5; - delay_section11_cast <= resize(delay_section1(0), 20); + tapsum6 <= resize(delay_pipeline(5), 17) + resize(delay_pipeline(7), 17); - delay_section12_cast <= resize(delay_section1(1), 20); + tapsum_mcand_5 <= tapsum6; - storage_in_section1_cast <= resize(storage_state_in1, 20); + mul_temp <= tapsum_mcand_5 * coeff6; + product6 <= resize(mul_temp(30 DOWNTO 0) & '0', 32); - delay_section11_cast <= resize(delay_section1(0), 20); + mul_temp_1 <= tapsum_mcand_4 * coeff5; + product5 <= resize(mul_temp_1(30 DOWNTO 0) & '0', 32); - delay_section12_cast <= resize(delay_section1(1), 20); + mul_temp_2 <= tapsum_mcand_3 * coeff4; + product4 <= resize(mul_temp_2(30 DOWNTO 0) & '0', 32); - input_section2_cast <= resize(prev_stg_op1(15 DOWNTO 0) & '0' & '0' & '0' & '0', 20); + mul_temp_3 <= tapsum_mcand_2 * coeff3; + product3 <= resize(mul_temp_3(30 DOWNTO 0) & '0', 32); - delay_section21_cast <= resize(delay_section2(0), 20); + mul_temp_4 <= tapsum_mcand_1 * coeff2; + product2 <= resize(mul_temp_4(30 DOWNTO 0) & '0', 32); - delay_section22_cast <= resize(delay_section2(1), 20); + mul_temp_5 <= tapsum_mcand * coeff1; + product1 <= resize(mul_temp_5(30 DOWNTO 0) & '0', 32); - storage_in_section2_cast <= resize(storage_state_in2, 20); + add_temp <= resize(delay_pipeline(6) & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0', 33) + resize(product6, 33); + sum1_1 <= add_temp(31 DOWNTO 0); - delay_section21_cast <= resize(delay_section2(0), 20); + add_temp_1 <= resize(product5, 33) + resize(product4, 33); + sum1_2 <= add_temp_1(31 DOWNTO 0); - delay_section22_cast <= resize(delay_section2(1), 20); + add_temp_2 <= resize(product3, 33) + resize(product2, 33); + sum1_3 <= add_temp_2(31 DOWNTO 0); - inputmux_section_1 <= input_section1_cast WHEN ( cur_count = to_unsigned(0, 4) ) ELSE - delay_section11_cast WHEN ( cur_count = to_unsigned(1, 4) ) ELSE - delay_section12_cast WHEN ( cur_count = to_unsigned(2, 4) ) ELSE - storage_in_section1_cast WHEN ( cur_count = to_unsigned(3, 4) ) ELSE - delay_section11_cast WHEN ( cur_count = to_unsigned(4, 4) ) ELSE - delay_section12_cast WHEN ( cur_count = to_unsigned(5, 4) ) ELSE - input_section2_cast WHEN ( cur_count = to_unsigned(6, 4) ) ELSE - delay_section21_cast WHEN ( cur_count = to_unsigned(7, 4) ) ELSE - delay_section22_cast WHEN ( cur_count = to_unsigned(8, 4) ) ELSE - storage_in_section2_cast WHEN ( cur_count = to_unsigned(9, 4) ) ELSE - delay_section21_cast WHEN ( cur_count = to_unsigned(10, 4) ) ELSE - delay_section22_cast; - - coeffmux_section_1 <= scaleconst1 WHEN ( cur_count = to_unsigned(0, 4) ) ELSE - coeff_a2_section1 WHEN ( cur_count = to_unsigned(1, 4) ) ELSE - coeff_a3_section1 WHEN ( cur_count = to_unsigned(2, 4) ) ELSE - coeff_b1_section1 WHEN ( cur_count = to_unsigned(3, 4) ) ELSE - coeff_b2_section1 WHEN ( cur_count = to_unsigned(4, 4) ) ELSE - coeff_b3_section1 WHEN ( cur_count = to_unsigned(5, 4) ) ELSE - scaleconst2 WHEN ( cur_count = to_unsigned(6, 4) ) ELSE - coeff_a2_section2 WHEN ( cur_count = to_unsigned(7, 4) ) ELSE - coeff_a3_section2 WHEN ( cur_count = to_unsigned(8, 4) ) ELSE - coeff_b1_section2 WHEN ( cur_count = to_unsigned(9, 4) ) ELSE - coeff_b2_section2 WHEN ( cur_count = to_unsigned(10, 4) ) ELSE - coeff_b3_section2; - - prod <= inputmux_section_1 * coeffmux_section_1; - - prod_den <= resize(shift_right(prod(32 DOWNTO 0) + ( "0" & (prod(1))), 1), 32); - - prod_den_cast_temp <= resize(prod_den, 34); - - prod_den_cast <= prod_den_cast_temp; - - unaryminus_temp <= ('0' & prod_den_cast) WHEN prod_den_cast = "1000000000000000000000000000000000" - ELSE -resize(prod_den_cast,35); - prod_den_cast_neg <= unaryminus_temp(33 DOWNTO 0); - - prod_num <= resize(shift_right(prod(32 DOWNTO 0) + ( "0" & (prod(1))), 1), 32); - - prod_num_cast_temp <= resize(prod_num, 34); - - prod_num_cast <= prod_num_cast_temp; - - accum_mux_in1 <= prod_num_cast WHEN ( cur_count = to_unsigned(0, 4) ) ELSE - prod_den_cast_neg WHEN ( cur_count = to_unsigned(1, 4) ) ELSE - prod_den_cast_neg WHEN ( cur_count = to_unsigned(2, 4) ) ELSE - prod_num_cast WHEN ( cur_count = to_unsigned(3, 4) ) ELSE - prod_num_cast WHEN ( cur_count = to_unsigned(4, 4) ) ELSE - prod_num_cast WHEN ( cur_count = to_unsigned(5, 4) ) ELSE - prod_num_cast WHEN ( cur_count = to_unsigned(6, 4) ) ELSE - prod_den_cast_neg WHEN ( cur_count = to_unsigned(7, 4) ) ELSE - prod_den_cast_neg WHEN ( cur_count = to_unsigned(8, 4) ) ELSE - prod_num_cast WHEN ( cur_count = to_unsigned(9, 4) ) ELSE - prod_num_cast WHEN ( cur_count = to_unsigned(10, 4) ) ELSE - prod_num_cast; - - final_phase <= phase_0 OR phase_3 OR phase_6 OR phase_9; - - section_phase <= phase_0 OR phase_6; - - accum_mux_in1_temp <= sectionipconvert_cast WHEN ( section_phase = '1' ) ELSE - accum_mux_in1; - - accum_mux_out <= accum_mux_in1_temp WHEN ( final_phase = '1' ) ELSE - accum_mux_in2; - - accumulator_reg_process : PROCESS (clk_i) + temp_process1 : PROCESS (clk_i) BEGIN IF rising_edge(clk_i) THEN IF rst_n_i = '0' THEN - accum_reg <= (OTHERS => '0'); + sumpipe1_1 <= (OTHERS => '0'); + sumpipe1_2 <= (OTHERS => '0'); + sumpipe1_3 <= (OTHERS => '0'); + sumpipe1_4 <= (OTHERS => '0'); ELSIF ce_i = '1' THEN - accum_reg <= accum_mux_out; + sumpipe1_1 <= sum1_1; + sumpipe1_2 <= sum1_2; + sumpipe1_3 <= sum1_3; + sumpipe1_4 <= product1; END IF; END IF; - END PROCESS accumulator_reg_process; - - add_cast <= accum_reg; - add_cast_1 <= accum_mux_in1; - add_temp <= resize(add_cast, 35) + resize(add_cast_1, 35); - accum_mux_in2 <= add_temp(33 DOWNTO 0); - - storagetypeconvert <= resize(shift_right(accum_mux_out(29 DOWNTO 0) + ( "0" & (accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14) & NOT accum_mux_out(14))), 14), 16); - - sectionipconvert <= resize(shift_right(prod(35 DOWNTO 0) + ( "0" & (prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20) & NOT prod(20))), 20), 16); - - sectionipconvert_cast <= resize(sectionipconvert(14 DOWNTO 0) & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0', 34); - - acc_out_cast_numacc <= accum_mux_out; + END PROCESS temp_process1; - sectionopconvert <= resize(shift_right(acc_out_cast_numacc(33 DOWNTO 0) + ( "0" & (acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18))), 18), 16); + add_temp_3 <= resize(sumpipe1_1, 33) + resize(sumpipe1_2, 33); + sum2_1 <= add_temp_3(31 DOWNTO 0); - output_typeconvert <= resize(shift_right(acc_out_cast_numacc(33 DOWNTO 0) + ( "0" & (acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18) & NOT acc_out_cast_numacc(18))), 18), 16); + add_temp_4 <= resize(sumpipe1_3, 33) + resize(sumpipe1_4, 33); + sum2_2 <= add_temp_4(31 DOWNTO 0); - storage_reg1_process : PROCESS (clk_i) + temp_process2 : PROCESS (clk_i) BEGIN IF rising_edge(clk_i) THEN IF rst_n_i = '0' THEN - storage_state_in1 <= (OTHERS => '0'); - ELSIF phase_2 = '1' THEN - storage_state_in1 <= storagetypeconvert; + sumpipe2_1 <= (OTHERS => '0'); + sumpipe2_2 <= (OTHERS => '0'); + ELSIF ce_i = '1' THEN + sumpipe2_1 <= sum2_1; + sumpipe2_2 <= sum2_2; END IF; END IF; - END PROCESS storage_reg1_process; + END PROCESS temp_process2; + + add_temp_5 <= resize(sumpipe2_1, 33) + resize(sumpipe2_2, 33); + sum3_1 <= add_temp_5(31 DOWNTO 0); - storage_reg2_process : PROCESS (clk_i) + temp_process3 : PROCESS (clk_i) BEGIN IF rising_edge(clk_i) THEN IF rst_n_i = '0' THEN - storage_state_in2 <= (OTHERS => '0'); - ELSIF phase_8 = '1' THEN - storage_state_in2 <= storagetypeconvert; + sumpipe3_1 <= (OTHERS => '0'); + ELSIF ce_i = '1' THEN + sumpipe3_1 <= sum3_1; END IF; END IF; - END PROCESS storage_reg2_process; + END PROCESS temp_process3; + + sum_final <= sumpipe3_1; + + output_typeconvert <= resize(shift_right(sum_final(30 DOWNTO 0) + ( "0" & (sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15))), 15), 16); Output_Register_process : PROCESS (clk_i) BEGIN IF rising_edge(clk_i) THEN IF rst_n_i = '0' THEN output_register <= (OTHERS => '0'); - ELSIF phase_11 = '1' THEN + ELSIF ce_i = '1' THEN output_register <= output_typeconvert; END IF; END IF; From c2b6a0e63eb78be0a7d26be504c5639fa272339a Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Sun, 24 Nov 2019 07:26:40 -0300 Subject: [PATCH 06/15] modules/hpf_adcinput: replace HPF with systolic FIR filter To achieve high clock performance the design is entirely based on DSP48E1 slices. --- hdl/modules/hpf_adcinput/Manifest.py | 4 +- hdl/modules/hpf_adcinput/hpf_adcinput.vhd | 399 +++++++--------------- hdl/modules/hpf_adcinput/mac1reg.vhd | 131 +++++++ hdl/modules/hpf_adcinput/mac2reg.vhd | 132 +++++++ 4 files changed, 398 insertions(+), 268 deletions(-) create mode 100644 hdl/modules/hpf_adcinput/mac1reg.vhd create mode 100644 hdl/modules/hpf_adcinput/mac2reg.vhd diff --git a/hdl/modules/hpf_adcinput/Manifest.py b/hdl/modules/hpf_adcinput/Manifest.py index f926f6a3..f5d4ebad 100755 --- a/hdl/modules/hpf_adcinput/Manifest.py +++ b/hdl/modules/hpf_adcinput/Manifest.py @@ -1 +1,3 @@ -files = ["hpf_adcinput.vhd"] +files = ["hpf_adcinput.vhd", + "mac1reg", + "mac2reg"] diff --git a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd index 8650a651..e71cc372 100644 --- a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd +++ b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd @@ -1,267 +1,132 @@ --- ------------------------------------------------------------- --- --- Module: hpf_adcinput --- Generated by MATLAB(R) 8.3 and the Filter Design HDL Coder 2.9.5. --- Generated on: 2019-11-21 16:38:12 --- ------------------------------------------------------------- - --- ------------------------------------------------------------- --- HDL Code Generation Options: --- --- TargetLanguage: VHDL --- ResetType: Synchronous --- FIRAdderStyle: tree --- OptimizeForHDL: on --- ClockEnableInputPort: ce_i --- ClockInputPort: clk_i --- ResetInputPort: rst_n_i --- UseRisingEdge: on --- EDAScriptGeneration: off --- AddPipelineRegisters: on --- InputPort: data_i --- OutputPort: data_o --- Name: hpf_adcinput --- ResetAssertedLevel: Active-low --- TestBenchStimulus: impulse step ramp chirp noise --- GenerateHDLTestBench: off --- LoopUnrolling: on - --- ------------------------------------------------------------- --- HDL Implementation : Fully parallel --- Multipliers : 7 --- Folding Factor : 1 --- ------------------------------------------------------------- --- Filter Settings: --- --- Discrete-Time FIR Filter (real) --- ------------------------------- --- Filter Structure : Direct-Form Symmetric FIR --- Filter Length : 13 --- Stable : Yes --- Linear Phase : Yes (Type 1) --- Arithmetic : fixed --- Numerator : s16,14 -> [-2 2) --- Input : s16,15 -> [-1 1) --- Filter Internals : Specify Precision --- Output : s16,15 -> [-1 1) --- Tap Sum : s17,15 -> [-2 2) --- Product : s32,30 -> [-2 2) --- Accumulator : s32,30 -> [-2 2) --- Round Mode : convergent --- Overflow Mode : wrap --- ------------------------------------------------------------- -LIBRARY IEEE; -USE IEEE.std_logic_1164.all; -USE IEEE.numeric_std.ALL; - -ENTITY hpf_adcinput IS - PORT( clk_i : IN std_logic; - ce_i : IN std_logic; - rst_n_i : IN std_logic; - data_i : IN std_logic_vector(15 DOWNTO 0); -- sfix16_En15 - data_o : OUT std_logic_vector(15 DOWNTO 0) -- sfix16_En15 - ); - -END hpf_adcinput; - - ----------------------------------------------------------------- ---Module Architecture: hpf_adcinput ----------------------------------------------------------------- -ARCHITECTURE rtl OF hpf_adcinput IS - -- Local Functions - -- Type Definitions - TYPE delay_pipeline_type IS ARRAY (NATURAL range <>) OF signed(15 DOWNTO 0); -- sfix16_En15 - -- Constants - CONSTANT coeff1 : signed(15 DOWNTO 0) := to_signed(253, 16); -- sfix16_En14 - CONSTANT coeff2 : signed(15 DOWNTO 0) := to_signed(486, 16); -- sfix16_En14 - CONSTANT coeff3 : signed(15 DOWNTO 0) := to_signed(250, 16); -- sfix16_En14 - CONSTANT coeff4 : signed(15 DOWNTO 0) := to_signed(-966, 16); -- sfix16_En14 - CONSTANT coeff5 : signed(15 DOWNTO 0) := to_signed(-3070, 16); -- sfix16_En14 - CONSTANT coeff6 : signed(15 DOWNTO 0) := to_signed(-5154, 16); -- sfix16_En14 - CONSTANT coeff7 : signed(15 DOWNTO 0) := to_signed(16384, 16); -- sfix16_En14 - - -- Signals - SIGNAL delay_pipeline : delay_pipeline_type(0 TO 12); -- sfix16_En15 - SIGNAL tapsum1 : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL tapsum_mcand : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL tapsum2 : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL tapsum_mcand_1 : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL tapsum3 : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL tapsum_mcand_2 : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL tapsum4 : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL tapsum_mcand_3 : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL tapsum5 : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL tapsum_mcand_4 : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL tapsum6 : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL tapsum_mcand_5 : signed(16 DOWNTO 0); -- sfix17_En15 - SIGNAL product6 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL mul_temp : signed(32 DOWNTO 0); -- sfix33_En29 - SIGNAL product5 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL mul_temp_1 : signed(32 DOWNTO 0); -- sfix33_En29 - SIGNAL product4 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL mul_temp_2 : signed(32 DOWNTO 0); -- sfix33_En29 - SIGNAL product3 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL mul_temp_3 : signed(32 DOWNTO 0); -- sfix33_En29 - SIGNAL product2 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL mul_temp_4 : signed(32 DOWNTO 0); -- sfix33_En29 - SIGNAL product1 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL mul_temp_5 : signed(32 DOWNTO 0); -- sfix33_En29 - SIGNAL sum_final : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL sum1_1 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL add_temp : signed(32 DOWNTO 0); -- sfix33_En30 - SIGNAL sumpipe1_1 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL sum1_2 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL add_temp_1 : signed(32 DOWNTO 0); -- sfix33_En30 - SIGNAL sumpipe1_2 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL sum1_3 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL add_temp_2 : signed(32 DOWNTO 0); -- sfix33_En30 - SIGNAL sumpipe1_3 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL sumpipe1_4 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL sum2_1 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL add_temp_3 : signed(32 DOWNTO 0); -- sfix33_En30 - SIGNAL sumpipe2_1 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL sum2_2 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL add_temp_4 : signed(32 DOWNTO 0); -- sfix33_En30 - SIGNAL sumpipe2_2 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL sum3_1 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL add_temp_5 : signed(32 DOWNTO 0); -- sfix33_En30 - SIGNAL sumpipe3_1 : signed(31 DOWNTO 0); -- sfix32_En30 - SIGNAL output_typeconvert : signed(15 DOWNTO 0); -- sfix16_En15 - SIGNAL output_register : signed(15 DOWNTO 0); -- sfix16_En15 - - -BEGIN - - -- Block Statements - Delay_Pipeline_process : PROCESS (clk_i) - BEGIN - IF rising_edge(clk_i) THEN - IF rst_n_i = '0' THEN - delay_pipeline(0 TO 12) <= (OTHERS => (OTHERS => '0')); - ELSIF ce_i = '1' THEN - delay_pipeline(0) <= signed(data_i); - delay_pipeline(1 TO 12) <= delay_pipeline(0 TO 11); - END IF; - END IF; - END PROCESS Delay_Pipeline_process; - - tapsum1 <= resize(delay_pipeline(0), 17) + resize(delay_pipeline(12), 17); - - tapsum_mcand <= tapsum1; - - tapsum2 <= resize(delay_pipeline(1), 17) + resize(delay_pipeline(11), 17); - - tapsum_mcand_1 <= tapsum2; - - tapsum3 <= resize(delay_pipeline(2), 17) + resize(delay_pipeline(10), 17); - - tapsum_mcand_2 <= tapsum3; - - tapsum4 <= resize(delay_pipeline(3), 17) + resize(delay_pipeline(9), 17); - - tapsum_mcand_3 <= tapsum4; - - tapsum5 <= resize(delay_pipeline(4), 17) + resize(delay_pipeline(8), 17); - - tapsum_mcand_4 <= tapsum5; - - tapsum6 <= resize(delay_pipeline(5), 17) + resize(delay_pipeline(7), 17); - - tapsum_mcand_5 <= tapsum6; - - mul_temp <= tapsum_mcand_5 * coeff6; - product6 <= resize(mul_temp(30 DOWNTO 0) & '0', 32); - - mul_temp_1 <= tapsum_mcand_4 * coeff5; - product5 <= resize(mul_temp_1(30 DOWNTO 0) & '0', 32); - - mul_temp_2 <= tapsum_mcand_3 * coeff4; - product4 <= resize(mul_temp_2(30 DOWNTO 0) & '0', 32); - - mul_temp_3 <= tapsum_mcand_2 * coeff3; - product3 <= resize(mul_temp_3(30 DOWNTO 0) & '0', 32); - - mul_temp_4 <= tapsum_mcand_1 * coeff2; - product2 <= resize(mul_temp_4(30 DOWNTO 0) & '0', 32); - - mul_temp_5 <= tapsum_mcand * coeff1; - product1 <= resize(mul_temp_5(30 DOWNTO 0) & '0', 32); - - add_temp <= resize(delay_pipeline(6) & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0' & '0', 33) + resize(product6, 33); - sum1_1 <= add_temp(31 DOWNTO 0); - - add_temp_1 <= resize(product5, 33) + resize(product4, 33); - sum1_2 <= add_temp_1(31 DOWNTO 0); - - add_temp_2 <= resize(product3, 33) + resize(product2, 33); - sum1_3 <= add_temp_2(31 DOWNTO 0); - - temp_process1 : PROCESS (clk_i) - BEGIN - IF rising_edge(clk_i) THEN - IF rst_n_i = '0' THEN - sumpipe1_1 <= (OTHERS => '0'); - sumpipe1_2 <= (OTHERS => '0'); - sumpipe1_3 <= (OTHERS => '0'); - sumpipe1_4 <= (OTHERS => '0'); - ELSIF ce_i = '1' THEN - sumpipe1_1 <= sum1_1; - sumpipe1_2 <= sum1_2; - sumpipe1_3 <= sum1_3; - sumpipe1_4 <= product1; - END IF; - END IF; - END PROCESS temp_process1; - - add_temp_3 <= resize(sumpipe1_1, 33) + resize(sumpipe1_2, 33); - sum2_1 <= add_temp_3(31 DOWNTO 0); - - add_temp_4 <= resize(sumpipe1_3, 33) + resize(sumpipe1_4, 33); - sum2_2 <= add_temp_4(31 DOWNTO 0); - - temp_process2 : PROCESS (clk_i) - BEGIN - IF rising_edge(clk_i) THEN - IF rst_n_i = '0' THEN - sumpipe2_1 <= (OTHERS => '0'); - sumpipe2_2 <= (OTHERS => '0'); - ELSIF ce_i = '1' THEN - sumpipe2_1 <= sum2_1; - sumpipe2_2 <= sum2_2; - END IF; - END IF; - END PROCESS temp_process2; - - add_temp_5 <= resize(sumpipe2_1, 33) + resize(sumpipe2_2, 33); - sum3_1 <= add_temp_5(31 DOWNTO 0); - - temp_process3 : PROCESS (clk_i) - BEGIN - IF rising_edge(clk_i) THEN - IF rst_n_i = '0' THEN - sumpipe3_1 <= (OTHERS => '0'); - ELSIF ce_i = '1' THEN - sumpipe3_1 <= sum3_1; - END IF; - END IF; - END PROCESS temp_process3; - - sum_final <= sumpipe3_1; - - output_typeconvert <= resize(shift_right(sum_final(30 DOWNTO 0) + ( "0" & (sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15) & NOT sum_final(15))), 15), 16); - - Output_Register_process : PROCESS (clk_i) - BEGIN - IF rising_edge(clk_i) THEN - IF rst_n_i = '0' THEN - output_register <= (OTHERS => '0'); - ELSIF ce_i = '1' THEN - output_register <= output_typeconvert; - END IF; - END IF; - END PROCESS Output_Register_process; - - -- Assignment Statements - data_o <= std_logic_vector(output_register); -END rtl; +------------------------------------------------------------------------------ +-- Title : Systolic High Pass FIR Filter +------------------------------------------------------------------------------ +-- Author : Daniel Tavares +-- Company : CNPEM LNLS-DIG +-- Created : 2019-11-23 +-- Platform : FPGA-generic +------------------------------------------------------------------------------- +-- Description: Systolic FIR for high pass filter. +-- Coefficients are calculated to meet the specification: +-- - Stopband norm. frequency: 0.04545 +-- - Passband norm. frequency: 0.4545 +-- - Attenuation at stopband: 60 dB +-- - Attenuation ripple at passband: +/- 0.1 dB +------------------------------------------------------------------------------- +-- Copyright (c) 2019 CNPEM +-- Licensed under GNU Lesser General Public License (LGPL) v3.0 +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2019-11-23 1.0 daniel.tavares Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_signed.all; + +entity hpf_adcinput is +port +( + clk_i : in std_logic; + rst_n_i : in std_logic; + ce_i : in std_logic; + data_i : in std_logic_vector (17 downto 0); + data_o : out std_logic_vector (47 downto 0) +); +end hpf_adcinput; + +architecture rtl of hpf_adcinput is + + type t_coef is array(12 downto 0) of std_logic_vector(29 downto 0); + signal coef : t_coef; + + type t_cascade is array(12 downto 0) of std_logic_vector(47 downto 0); + signal cascade : t_cascade; + + type t_data_io is array(12 downto 0) of std_logic_vector(17 downto 0); + signal data : t_data_io; + + component mac1reg is + port + ( + clk_i : in std_logic; + data_i : in std_logic_vector (17 downto 0); + coef_i : in std_logic_vector (29 downto 0); + data_o : out std_logic_vector (17 downto 0); + mac_o : out std_logic_vector (47 downto 0); + casc_o : out std_logic_vector (47 downto 0) + ); + end component; + + component mac2reg is + port + ( + clk_i : in std_logic; + data_i : in std_logic_vector (17 downto 0); + coef_i : in std_logic_vector (29 downto 0); + casc_i : in std_logic_vector (47 downto 0); + data_o : out std_logic_vector (17 downto 0); + mac_o : out std_logic_vector (47 downto 0); + casc_o : out std_logic_vector (47 downto 0) + ); + end component; + + signal data_int : std_logic_vector(data_o'range); + +begin + + coef <= ( + 0 => conv_std_logic_vector( 5982972, 30), + 1 => conv_std_logic_vector( 11633010, 30), + 2 => conv_std_logic_vector( 6159007, 30), + 3 => conv_std_logic_vector( -22871568, 30), + 4 => conv_std_logic_vector( -73433591, 30), + 5 => conv_std_logic_vector(-123682115, 30), + 6 => conv_std_logic_vector( 392008402, 30), + 7 => conv_std_logic_vector(-123682115, 30), + 8 => conv_std_logic_vector( -73433591, 30), + 9 => conv_std_logic_vector( -22871568, 30), + 10 => conv_std_logic_vector( 6159007, 30), + 11 => conv_std_logic_vector( 11633010, 30), + 12 => conv_std_logic_vector( 5982972, 30) + ); + + cmp_mac_first : mac1reg + port map + ( + clk_i => clk_i, + data_i => data_i, + coef_i => coef(0), + data_o => data(0), + casc_o => cascade(0) + ); + + gen_mac_cascade : for i in 1 to 11 generate + cmp_mac : mac2reg + port map + ( + clk_i => clk_i, + data_i => data(i-1), + coef_i => coef(i), + casc_i => cascade(i-1), + data_o => data(i), + mac_o => open, + casc_o => cascade(i) + ); + end generate; + + cmp_mac_last : mac2reg + port map + ( + clk_i => clk_i, + data_i => data(11), + coef_i => coef(12), + casc_i => cascade(11), + data_o => open, + mac_o => data_o, + casc_o => open + ); + +end rtl; diff --git a/hdl/modules/hpf_adcinput/mac1reg.vhd b/hdl/modules/hpf_adcinput/mac1reg.vhd new file mode 100644 index 00000000..24dbd5c4 --- /dev/null +++ b/hdl/modules/hpf_adcinput/mac1reg.vhd @@ -0,0 +1,131 @@ +------------------------------------------------------------------------------ +-- Title : DSP48E1-based MAC and data registered data propagation (1 stage) +------------------------------------------------------------------------------ +-- Author : Daniel Tavares +-- Company : CNPEM LNLS-DIG +-- Created : 2019-11-23 +-- Platform : FPGA-generic +------------------------------------------------------------------------------- +-- Description: Elementary mulitply-accumulate block for systolic FIR filter +-- implementation. Use 1 pipeline stage at the input data. +-- Reference: "DSP: Designing for Optimal Results" +------------------------------------------------------------------------------- +-- Copyright (c) 2019 CNPEM +-- Licensed under GNU Lesser General Public License (LGPL) v3.0 +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2019-11-23 1.0 daniel.tavares Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_signed.all; + +library UNISIM; +use UNISIM.vcomponents.all; + +entity mac1reg is +port +( + clk_i : in std_logic; + data_i : in std_logic_vector (17 downto 0); + coef_i : in std_logic_vector (29 downto 0); + data_o : out std_logic_vector (17 downto 0); + mac_o : out std_logic_vector (47 downto 0); + casc_o : out std_logic_vector (47 downto 0) +); +end mac1reg; + +architecture wrap of mac1reg is +begin + + DSP48E1_inst : DSP48E1 + generic map ( + -- Feature Control Attributes: Data Path Selection + A_INPUT => "DIRECT", + B_INPUT => "CASCADE", + USE_DPORT => FALSE, + USE_MULT => "MULTIPLY", + USE_SIMD => "ONE48", + -- Pattern Detector Attributes: Pattern Detection Configuration + AUTORESET_PATDET => "NO_RESET", + MASK => X"3fffffffffff", + PATTERN => X"000000000000", + SEL_MASK => "MASK", + SEL_PATTERN => "PATTERN", + USE_PATTERN_DETECT => "NO_PATDET", + -- Register Control Attributes: Pipeline Register Configuration + ACASCREG => 1, + ADREG => 1, + ALUMODEREG => 1, + AREG => 1, + BCASCREG => 1, + BREG => 1, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 1, + DREG => 1, + INMODEREG => 0, + MREG => 1, + OPMODEREG => 0, + PREG => 1 + ) + port map ( + CLK => clk_i, + + A => coef_i, + B => data_i, + BCOUT => data_o, + PCOUT => casc_o, + P => mac_o, + BCIN => (others => '0'), + PCIN => (others => '0'), + INMODE => "10001", + OPMODE => "0000101", + ALUMODE => "0000", + + -- Reset/Clock Enable Inputs + CEA1 => '1', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '1', + CEB1 => '1', + CEB2 => '0', + CEC => '0', + CECARRYIN => '0', + CECTRL => '1', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '1', + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0', + + -- Unused port + ACOUT => open, + CARRYCASCOUT => open, + MULTSIGNOUT => open, + OVERFLOW => open, + PATTERNBDETECT => open, + PATTERNDETECT => open, + UNDERFLOW => open, + CARRYOUT => open, + ACIN => (others => '0'), + CARRYCASCIN => '0', + MULTSIGNIN => '0', + CARRYINSEL => "000", + C => (others => '0'), + CARRYIN => '0', + D => (others => '0') + ); +end wrap; diff --git a/hdl/modules/hpf_adcinput/mac2reg.vhd b/hdl/modules/hpf_adcinput/mac2reg.vhd new file mode 100644 index 00000000..74832bc7 --- /dev/null +++ b/hdl/modules/hpf_adcinput/mac2reg.vhd @@ -0,0 +1,132 @@ +------------------------------------------------------------------------------ +-- Title : DSP48E1-based MAC and data registered data propagation (2 stages) +------------------------------------------------------------------------------ +-- Author : Daniel Tavares +-- Company : CNPEM LNLS-DIG +-- Created : 2019-11-23 +-- Platform : FPGA-generic +------------------------------------------------------------------------------- +-- Description: Elementary mulitply-accumulate block for systolic FIR filter +-- implementation. Use 2 pipeline stages at the input data. +-- Reference: "DSP: Designing for Optimal Results" +------------------------------------------------------------------------------- +-- Copyright (c) 2019 CNPEM +-- Licensed under GNU Lesser General Public License (LGPL) v3.0 +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2019-11-23 1.0 daniel.tavares Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_signed.all; + +library UNISIM; +use UNISIM.vcomponents.all; + +entity mac2reg is +port +( + clk_i : in std_logic; + data_i : in std_logic_vector (17 downto 0); + coef_i : in std_logic_vector (29 downto 0); + casc_i : in std_logic_vector (47 downto 0); + data_o : out std_logic_vector (17 downto 0); + mac_o : out std_logic_vector (47 downto 0); + casc_o : out std_logic_vector (47 downto 0) +); +end mac2reg; + +architecture wrap of mac2reg is +begin + + DSP48E1_inst : DSP48E1 + generic map ( + -- Feature Control Attributes: Data Path Selection + A_INPUT => "DIRECT", + B_INPUT => "CASCADE", + USE_DPORT => FALSE, + USE_MULT => "MULTIPLY", + USE_SIMD => "ONE48", + -- Pattern Detector Attributes: Pattern Detection Configuration + AUTORESET_PATDET => "NO_RESET", + MASK => X"3fffffffffff", + PATTERN => X"000000000000", + SEL_MASK => "MASK", + SEL_PATTERN => "PATTERN", + USE_PATTERN_DETECT => "NO_PATDET", + -- Register Control Attributes: Pipeline Register Configuration + ACASCREG => 1, + ADREG => 1, + ALUMODEREG => 1, + AREG => 1, + BCASCREG => 2, + BREG => 2, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 1, + DREG => 1, + INMODEREG => 0, + MREG => 1, + OPMODEREG => 0, + PREG => 1 + ) + port map ( + CLK => clk_i, + + A => coef_i, + B => (others => '0'), + BCOUT => data_o, + PCOUT => casc_o, + P => mac_o, + BCIN => data_i, + PCIN => casc_i, + INMODE => "00001", + OPMODE => "0010101", + ALUMODE => "0000", + + -- Reset/Clock Enable Inputs + CEA1 => '1', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '1', + CEB1 => '1', + CEB2 => '1', + CEC => '0', + CECARRYIN => '0', + CECTRL => '1', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '1', + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0', + + -- Unused port + ACOUT => open, + CARRYCASCOUT => open, + MULTSIGNOUT => open, + OVERFLOW => open, + PATTERNBDETECT => open, + PATTERNDETECT => open, + UNDERFLOW => open, + CARRYOUT => open, + ACIN => (others => '0'), + CARRYCASCIN => '0', + MULTSIGNIN => '0', + CARRYINSEL => "000", + C => (others => '0'), + CARRYIN => '0', + D => (others => '0') + ); +end wrap; From e78e8d670a548fd714671b5e606f33c6482abf9e Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Sun, 24 Nov 2019 10:41:22 -0300 Subject: [PATCH 07/15] modules/hpf_adcinput: adjust width of data ports Match width requirements of wb_position_calc --- hdl/modules/hpf_adcinput/hpf_adcinput.vhd | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd index e71cc372..5a185ee5 100644 --- a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd +++ b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd @@ -32,8 +32,8 @@ port clk_i : in std_logic; rst_n_i : in std_logic; ce_i : in std_logic; - data_i : in std_logic_vector (17 downto 0); - data_o : out std_logic_vector (47 downto 0) + data_i : in std_logic_vector (15 downto 0); + data_o : out std_logic_vector (15 downto 0) ); end hpf_adcinput; @@ -48,6 +48,8 @@ architecture rtl of hpf_adcinput is type t_data_io is array(12 downto 0) of std_logic_vector(17 downto 0); signal data : t_data_io; + signal data_full : std_logic_vector(47 downto 0); + component mac1reg is port ( @@ -97,7 +99,7 @@ begin port map ( clk_i => clk_i, - data_i => data_i, + data_i => data_i & "00", coef_i => coef(0), data_o => data(0), casc_o => cascade(0) @@ -125,8 +127,10 @@ begin coef_i => coef(12), casc_i => cascade(11), data_o => open, - mac_o => data_o, + mac_o => data_full, casc_o => open ); + + data_o <= data_full(47 downto 32); end rtl; From ac20f59fcba637c7c9f29ee90874e8a8d4624830 Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Sun, 24 Nov 2019 10:54:25 -0300 Subject: [PATCH 08/15] modules/hpf_adcinput/mac*reg.vhd: cosmetic changes --- hdl/modules/hpf_adcinput/mac1reg.vhd | 4 ++-- hdl/modules/hpf_adcinput/mac2reg.vhd | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hdl/modules/hpf_adcinput/mac1reg.vhd b/hdl/modules/hpf_adcinput/mac1reg.vhd index 24dbd5c4..cb240bd8 100644 --- a/hdl/modules/hpf_adcinput/mac1reg.vhd +++ b/hdl/modules/hpf_adcinput/mac1reg.vhd @@ -38,7 +38,7 @@ port ); end mac1reg; -architecture wrap of mac1reg is +architecture rtl of mac1reg is begin DSP48E1_inst : DSP48E1 @@ -128,4 +128,4 @@ begin CARRYIN => '0', D => (others => '0') ); -end wrap; +end rtl; diff --git a/hdl/modules/hpf_adcinput/mac2reg.vhd b/hdl/modules/hpf_adcinput/mac2reg.vhd index 74832bc7..78afd4fd 100644 --- a/hdl/modules/hpf_adcinput/mac2reg.vhd +++ b/hdl/modules/hpf_adcinput/mac2reg.vhd @@ -39,7 +39,7 @@ port ); end mac2reg; -architecture wrap of mac2reg is +architecture rtl of mac2reg is begin DSP48E1_inst : DSP48E1 @@ -129,4 +129,4 @@ begin CARRYIN => '0', D => (others => '0') ); -end wrap; +end rtl; From 1edf34ee01d90268ac58535e6ad14f6113b2e571 Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Sun, 24 Nov 2019 10:55:48 -0300 Subject: [PATCH 09/15] hpf_adcinput/mac1reg.vhd: fix B port path (2 changes) 1) To implement a systolic FIR the first MAC must take B from port B, not BCIN. Thus B_INPUT = DIRECT 2) By simulation it has been verified the clock enable of the second B register must be active even when only the first B register is in use. Otherwise the B port it not propagated to BCOUT. Thus CEB2 = 1 --- hdl/modules/hpf_adcinput/mac1reg.vhd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hdl/modules/hpf_adcinput/mac1reg.vhd b/hdl/modules/hpf_adcinput/mac1reg.vhd index cb240bd8..c40dea1a 100644 --- a/hdl/modules/hpf_adcinput/mac1reg.vhd +++ b/hdl/modules/hpf_adcinput/mac1reg.vhd @@ -45,7 +45,7 @@ begin generic map ( -- Feature Control Attributes: Data Path Selection A_INPUT => "DIRECT", - B_INPUT => "CASCADE", + B_INPUT => "DIRECT", USE_DPORT => FALSE, USE_MULT => "MULTIPLY", USE_SIMD => "ONE48", @@ -92,7 +92,7 @@ begin CEAD => '0', CEALUMODE => '1', CEB1 => '1', - CEB2 => '0', + CEB2 => '1', CEC => '0', CECARRYIN => '0', CECTRL => '1', From 72df964b81b64f2253cab0ebd2d1d726630c98d4 Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Sun, 24 Nov 2019 11:45:22 -0300 Subject: [PATCH 10/15] modules/hpf_adcinput: remove unused cascade data The last stage of the FIR filter does not need to cascade its output. --- hdl/modules/hpf_adcinput/hpf_adcinput.vhd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd index 5a185ee5..4fc868ad 100644 --- a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd +++ b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd @@ -42,7 +42,7 @@ architecture rtl of hpf_adcinput is type t_coef is array(12 downto 0) of std_logic_vector(29 downto 0); signal coef : t_coef; - type t_cascade is array(12 downto 0) of std_logic_vector(47 downto 0); + type t_cascade is array(11 downto 0) of std_logic_vector(47 downto 0); signal cascade : t_cascade; type t_data_io is array(12 downto 0) of std_logic_vector(17 downto 0); From 6ee5c5c47b33c6e0811045d0c92c4cc78ed866a2 Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Sun, 24 Nov 2019 12:34:21 -0300 Subject: [PATCH 11/15] modules/hpf_adcinput: fix coefficients width to 25 bits The actual mulitplier inside the DSP48E1 slice is 25x18, hence only the 25 LSB out of 30 bits on A port are used. --- hdl/modules/hpf_adcinput/hpf_adcinput.vhd | 32 +++++++++++------------ hdl/modules/hpf_adcinput/mac1reg.vhd | 11 ++++++-- hdl/modules/hpf_adcinput/mac2reg.vhd | 11 ++++++-- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd index 4fc868ad..ca320aab 100644 --- a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd +++ b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd @@ -39,7 +39,7 @@ end hpf_adcinput; architecture rtl of hpf_adcinput is - type t_coef is array(12 downto 0) of std_logic_vector(29 downto 0); + type t_coef is array(12 downto 0) of std_logic_vector(24 downto 0); signal coef : t_coef; type t_cascade is array(11 downto 0) of std_logic_vector(47 downto 0); @@ -55,7 +55,7 @@ architecture rtl of hpf_adcinput is ( clk_i : in std_logic; data_i : in std_logic_vector (17 downto 0); - coef_i : in std_logic_vector (29 downto 0); + coef_i : in std_logic_vector (24 downto 0); data_o : out std_logic_vector (17 downto 0); mac_o : out std_logic_vector (47 downto 0); casc_o : out std_logic_vector (47 downto 0) @@ -67,7 +67,7 @@ architecture rtl of hpf_adcinput is ( clk_i : in std_logic; data_i : in std_logic_vector (17 downto 0); - coef_i : in std_logic_vector (29 downto 0); + coef_i : in std_logic_vector (24 downto 0); casc_i : in std_logic_vector (47 downto 0); data_o : out std_logic_vector (17 downto 0); mac_o : out std_logic_vector (47 downto 0); @@ -80,19 +80,19 @@ architecture rtl of hpf_adcinput is begin coef <= ( - 0 => conv_std_logic_vector( 5982972, 30), - 1 => conv_std_logic_vector( 11633010, 30), - 2 => conv_std_logic_vector( 6159007, 30), - 3 => conv_std_logic_vector( -22871568, 30), - 4 => conv_std_logic_vector( -73433591, 30), - 5 => conv_std_logic_vector(-123682115, 30), - 6 => conv_std_logic_vector( 392008402, 30), - 7 => conv_std_logic_vector(-123682115, 30), - 8 => conv_std_logic_vector( -73433591, 30), - 9 => conv_std_logic_vector( -22871568, 30), - 10 => conv_std_logic_vector( 6159007, 30), - 11 => conv_std_logic_vector( 11633010, 30), - 12 => conv_std_logic_vector( 5982972, 30) + 0 => conv_std_logic_vector( 186968, 25), + 1 => conv_std_logic_vector( 363532, 25), + 2 => conv_std_logic_vector( 192469, 25), + 3 => conv_std_logic_vector( -714736, 25), + 4 => conv_std_logic_vector( -2294800, 25), + 5 => conv_std_logic_vector( -3865066, 25), + 6 => conv_std_logic_vector( 12250263, 25), + 7 => conv_std_logic_vector( -3865066, 25), + 8 => conv_std_logic_vector( -2294800, 25), + 9 => conv_std_logic_vector( -714736, 25), + 10 => conv_std_logic_vector( 192469, 25), + 11 => conv_std_logic_vector( 363532, 25), + 12 => conv_std_logic_vector( 186968, 25) ); cmp_mac_first : mac1reg diff --git a/hdl/modules/hpf_adcinput/mac1reg.vhd b/hdl/modules/hpf_adcinput/mac1reg.vhd index c40dea1a..a9248431 100644 --- a/hdl/modules/hpf_adcinput/mac1reg.vhd +++ b/hdl/modules/hpf_adcinput/mac1reg.vhd @@ -31,7 +31,7 @@ port ( clk_i : in std_logic; data_i : in std_logic_vector (17 downto 0); - coef_i : in std_logic_vector (29 downto 0); + coef_i : in std_logic_vector (24 downto 0); data_o : out std_logic_vector (17 downto 0); mac_o : out std_logic_vector (47 downto 0); casc_o : out std_logic_vector (47 downto 0) @@ -39,6 +39,9 @@ port end mac1reg; architecture rtl of mac1reg is + + signal coef : std_logic_vector(29 downto 0); + begin DSP48E1_inst : DSP48E1 @@ -75,7 +78,7 @@ begin port map ( CLK => clk_i, - A => coef_i, + A => coef, B => data_i, BCOUT => data_o, PCOUT => casc_o, @@ -128,4 +131,8 @@ begin CARRYIN => '0', D => (others => '0') ); + + coef(24 downto 0) <= coef_i; + coef(29 downto 25) <= coef_i(24); + end rtl; diff --git a/hdl/modules/hpf_adcinput/mac2reg.vhd b/hdl/modules/hpf_adcinput/mac2reg.vhd index 78afd4fd..2e9b2b2f 100644 --- a/hdl/modules/hpf_adcinput/mac2reg.vhd +++ b/hdl/modules/hpf_adcinput/mac2reg.vhd @@ -31,7 +31,7 @@ port ( clk_i : in std_logic; data_i : in std_logic_vector (17 downto 0); - coef_i : in std_logic_vector (29 downto 0); + coef_i : in std_logic_vector (24 downto 0); casc_i : in std_logic_vector (47 downto 0); data_o : out std_logic_vector (17 downto 0); mac_o : out std_logic_vector (47 downto 0); @@ -40,6 +40,9 @@ port end mac2reg; architecture rtl of mac2reg is + + signal coef : std_logic_vector(29 downto 0); + begin DSP48E1_inst : DSP48E1 @@ -76,7 +79,7 @@ begin port map ( CLK => clk_i, - A => coef_i, + A => coef, B => (others => '0'), BCOUT => data_o, PCOUT => casc_o, @@ -129,4 +132,8 @@ begin CARRYIN => '0', D => (others => '0') ); + + coef(24 downto 0) <= coef_i; + coef(29 downto 25) <= coef_i(24); + end rtl; From c7d14ff35680314b037b93ea677f934c346a919d Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Sun, 24 Nov 2019 13:40:57 -0200 Subject: [PATCH 12/15] hpf_adcinput/Manifest.py: fix wrong listing of VHDL files --- hdl/modules/hpf_adcinput/Manifest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hdl/modules/hpf_adcinput/Manifest.py b/hdl/modules/hpf_adcinput/Manifest.py index f5d4ebad..f129042b 100755 --- a/hdl/modules/hpf_adcinput/Manifest.py +++ b/hdl/modules/hpf_adcinput/Manifest.py @@ -1,3 +1,3 @@ files = ["hpf_adcinput.vhd", - "mac1reg", - "mac2reg"] + "mac1reg.vhd", + "mac2reg.vhd"] From 1a1ca7719b61f1baa816074b476d2aa1e15f052f Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Sun, 24 Nov 2019 15:26:01 -0300 Subject: [PATCH 13/15] hpf_adcinput/mac*reg.vhd: fix syntax of sign extension --- hdl/modules/hpf_adcinput/mac1reg.vhd | 3 ++- hdl/modules/hpf_adcinput/mac2reg.vhd | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hdl/modules/hpf_adcinput/mac1reg.vhd b/hdl/modules/hpf_adcinput/mac1reg.vhd index a9248431..a3c4ed32 100644 --- a/hdl/modules/hpf_adcinput/mac1reg.vhd +++ b/hdl/modules/hpf_adcinput/mac1reg.vhd @@ -132,7 +132,8 @@ begin D => (others => '0') ); + -- Sign extension - DSP48E1 expects 30 bits on port A but multiplier uses only 25 bits coef(24 downto 0) <= coef_i; - coef(29 downto 25) <= coef_i(24); + coef(29 downto 25) <= (others => coef_i(24)); end rtl; diff --git a/hdl/modules/hpf_adcinput/mac2reg.vhd b/hdl/modules/hpf_adcinput/mac2reg.vhd index 2e9b2b2f..e67c5b95 100644 --- a/hdl/modules/hpf_adcinput/mac2reg.vhd +++ b/hdl/modules/hpf_adcinput/mac2reg.vhd @@ -133,7 +133,8 @@ begin D => (others => '0') ); + -- Sign extension - DSP48E1 expects 30 bits on port A but multiplier uses only 25 bits coef(24 downto 0) <= coef_i; - coef(29 downto 25) <= coef_i(24); + coef(29 downto 25) <= (others => coef_i(24)); end rtl; From 0301cc8acced7bf1658e60e14d860945bc7652d3 Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Sun, 24 Nov 2019 19:35:21 -0300 Subject: [PATCH 14/15] modules/hpf_adcinput: better truncation of filter output Truncate 7 MSB + 25 LSB instead of 0 MSB + 32 LSB. --- hdl/modules/hpf_adcinput/hpf_adcinput.vhd | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd index ca320aab..347f0c5a 100644 --- a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd +++ b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd @@ -130,7 +130,9 @@ begin mac_o => data_full, casc_o => open ); - - data_o <= data_full(47 downto 32); + + -- Truncate 7 MSB and 25 LSB to achieve better precision at the output + -- TODO: verify if this is the optimal solution + data_o <= data_full(40 downto 25); end rtl; From e2c871d117d955e5d6b4a752e88880f7a521c01b Mon Sep 17 00:00:00 2001 From: Daniel Tavares Date: Sun, 24 Nov 2019 22:04:30 -0300 Subject: [PATCH 15/15] hpf_adcinput: resize data input by 2 bits towards MSB, not LSB Although it would be possible to pad with zeros at the LSBs, the filter gain analysis has been made considering a 16-bit input data. To keep consistency, input data is now only sign extended by 2 bits. --- hdl/modules/hpf_adcinput/hpf_adcinput.vhd | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd index 347f0c5a..e8a92ab1 100644 --- a/hdl/modules/hpf_adcinput/hpf_adcinput.vhd +++ b/hdl/modules/hpf_adcinput/hpf_adcinput.vhd @@ -75,7 +75,8 @@ architecture rtl of hpf_adcinput is ); end component; - signal data_int : std_logic_vector(data_o'range); + signal data_se : std_logic_vector(17 downto 0); + signal data_int : std_logic_vector(data_o'range); begin @@ -99,7 +100,7 @@ begin port map ( clk_i => clk_i, - data_i => data_i & "00", + data_i => data_se, coef_i => coef(0), data_o => data(0), casc_o => cascade(0) @@ -131,6 +132,9 @@ begin casc_o => open ); + data_se(15 downto 0) <= data_i; + data_se(17 downto 16) <= (others => data_i(15)); + -- Truncate 7 MSB and 25 LSB to achieve better precision at the output -- TODO: verify if this is the optimal solution data_o <= data_full(40 downto 25);