Browse Source

Merge pull request 'testing' (#1) from testing into master

master
Lilian RM 3 years ago
parent
commit
10880ce636
28 changed files with 27133 additions and 0 deletions
  1. +73
    -0
      5ndft/5k_DFT_pkg.vhd
  2. +263
    -0
      5ndft/FFT_tree.vhd
  3. +64
    -0
      5ndft/mult_blk_5ndft.vhd
  4. +97
    -0
      5ndft/radix_2_cell.vhd
  5. +306
    -0
      5ndft/winograd5.vhd
  6. +97
    -0
      PFB_blk.vhd
  7. +52
    -0
      PFB_pkg.vhd
  8. +142
    -0
      PFB_tb.vhd
  9. +15
    -0
      matlab/gen_Wn_coeffs_5ndft.m
  10. +9
    -0
      matlab/radix2.m
  11. +250
    -0
      matlab/tb_generation_5ndft.m
  12. +18
    -0
      matlab/winograd5.m
  13. +11
    -0
      matlab/write_file.m
  14. +13
    -0
      matlab/write_polyfir_coeffs.m
  15. +34
    -0
      polyphase_filter/add_blk.vhd
  16. +45
    -0
      polyphase_filter/mult_blk.vhd
  17. +85
    -0
      polyphase_filter/partial_fir.vhd
  18. +70
    -0
      polyphase_filter/poly_fir_blk.vhd
  19. +37
    -0
      polyphase_filter/poly_fir_blk__wires.vhd
  20. +200
    -0
      polyphase_filter/poly_fir_pkg.vhd
  21. +79
    -0
      polyphase_filter/poly_shift_reg2.vhd
  22. +31
    -0
      polyphase_filter/tree_fir.vhd
  23. +8
    -0
      tb_txt_files/coeffs_dft.vhd
  24. +6
    -0
      tb_txt_files/coeffs_fir.vhd
  25. +24987
    -0
      tb_txt_files/output.txt
  26. +13
    -0
      utils/simu_pkg.vhd
  27. +95
    -0
      utils/used_functions_pkg.vhd
  28. +33
    -0
      utils/utils.vhd

+ 73
- 0
5ndft/5k_DFT_pkg.vhd View File

@@ -0,0 +1,73 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.std_logic_signed.ALL;
USE work.PFB_PKG.ALL;
-- NOTE:
-- The number of in/output samples must be a 2^n factor of 5, < 160
PACKAGE FIVEn_DFT_PKG IS
CONSTANT cst_w_in_5ndft : natural := cst_w_polyfir_out_dft_in_pfb; -- input_bitwidth
CONSTANT cst_w_out_5ndft : natural := cst_w_out_pfb; -- output bitwidth, must be < 30
CONSTANT cst_nb_samples_in_5ndft : natural := cst_nb_subfilters_pfb; -- must be 5*n
CONSTANT cst_w_precision_winograd5_coeffs_5ndft : natural := cst_w_precision_winograd5_coeffs_pfb; -- must be <= 32 and >= 3, sign bit included. Ideal is >= 8
CONSTANT cst_w_precision_radix2_coeffs_5ndft : natural := cst_w_precision_radix2_coeffs_pfb; -- must be <= 32 and >= 3, sign bit included. Ideal is >= 8
-- CALCULATIONS --
CONSTANT cst_nb_parallel_winograd5 : natural := cst_nb_samples_in_5ndft/5;
CONSTANT cst_log2_nb_parallel_winograd5 : natural := cst_log2_nb_parallel_winograd_pfb; -- = log2(cst_nb_parallel_winograd5)
CONSTANT cst_w_winograd_added : natural := cst_w_precision_winograd5_coeffs_5ndft+6; -- 6 is the number of addition stages in the winograd5 blk
CONSTANT cst_w_radix2_added : natural := cst_w_precision_radix2_coeffs_5ndft+2;
CONSTANT cst_dft_w_out_5ndft : natural := cst_w_in_5ndft+cst_w_winograd_added+(cst_log2_nb_parallel_winograd5*cst_w_radix2_added);
CONSTANT cst_winograd5_w_out_5ndft : natural := cst_w_in_5ndft+cst_w_winograd_added; -- 6 is the number of addition stages in the winograd5 blk
CONSTANT cst_nb_wn_coeffs : natural := cst_nb_samples_in_5ndft/2;
-- TYPES --
SUBTYPE smpl_in_5ndft IS smpl_real_imag_polyfir_out_dft_in_pfb;
SUBTYPE smpl_out_5ndft IS smpl_real_imag_dft_out_pfb; --std_logic_vector(cst_w_out_5ndft-1 DOWNTO 0);
TYPE vect_dft_input IS ARRAY (0 TO cst_nb_samples_in_5ndft-1) OF smpl_in_5ndft;
SUBTYPE vect_dft_output IS vect_dft_output_pfb; --ARRAY (0 TO cst_nb_samples_in_5ndft-1) OF smpl_out_5ndft;
-- winograd5
SUBTYPE smpl_out_winograd5_5ndft IS std_logic_vector(cst_winograd5_w_out_5ndft-1 DOWNTO 0);
SUBTYPE smpl_out_winograd5_signed_5ndft IS signed(cst_winograd5_w_out_5ndft-1 DOWNTO 0);
TYPE vect_input_winograd5_5ndft IS ARRAY (0 TO 4) OF smpl_in_5ndft;
TYPE vect_output_winograd5_5ndft IS ARRAY (0 TO 4) OF smpl_out_winograd5_5ndft;
TYPE vect_total_output_winograd5_cells IS ARRAY (0 TO cst_nb_samples_in_5ndft-1) OF smpl_out_winograd5_5ndft;
TYPE vect_winograd5_generic_stage IS ARRAY (0 TO 5) OF smpl_out_winograd5_5ndft;
TYPE matrix_winograd5_generic_stages IS ARRAY (0 TO 7) OF vect_winograd5_generic_stage;
SUBTYPE smpl_mult_factor_w_multipliers IS std_logic_vector(cst_w_precision_winograd5_coeffs_5ndft-1 DOWNTO 0);
SUBTYPE smpl_mult_factor_w_multipliers_signed IS signed(cst_w_precision_winograd5_coeffs_5ndft-1 DOWNTO 0);
TYPE vect_mult_factors_32b IS ARRAY (1 TO 5) OF std_logic_vector(31 DOWNTO 0);
TYPE vect_mult_factor_w_multipliers IS ARRAY (1 TO 5) OF smpl_mult_factor_w_multipliers;
--radix2
SUBTYPE smpl_cos_sin_wb IS std_logic_vector(cst_w_precision_radix2_coeffs_5ndft-1 DOWNTO 0);
SUBTYPE smpl_cos_sin_signed_wb IS signed(cst_w_precision_radix2_coeffs_5ndft-1 DOWNTO 0);
TYPE vect_cos_sin_k_pi_over_5_32b IS ARRAY(0 TO 4) OF std_logic_vector(31 DOWNTO 0);
TYPE vect_cos_sin_k_pi_over_5_wb IS ARRAY(0 TO 4) OF smpl_cos_sin_wb;
TYPE vect_cos_sin_k_pi_over_80_32b IS ARRAY (0 TO cst_nb_wn_coeffs-1) OF std_logic_vector(31 DOWNTO 0);
SUBTYPE smpl_out_radix2 IS std_logic_vector(cst_dft_w_out_5ndft-1 DOWNTO 0);
SUBTYPE smpl_out_signed_radix2 IS signed(cst_dft_w_out_5ndft-1 DOWNTO 0);
TYPE vect_radix2_fft_line IS ARRAY (0 TO cst_log2_nb_parallel_winograd5) OF smpl_out_radix2;
TYPE vect_radix2_line IS ARRAY (0 TO 3) OF smpl_out_radix2;
TYPE matrix_radix2_cell IS ARRAY (0 TO 1) OF vect_radix2_line;
-- whole fft
TYPE matrix_fft_stages IS ARRAY (0 TO cst_nb_samples_in_5ndft-1) OF vect_radix2_fft_line; -- inputs and outputs of radix2 cells
END;

+ 263
- 0
5ndft/FFT_tree.vhd View File

@@ -0,0 +1,263 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_signed.ALL;
USE ieee.numeric_std.ALL;
USE work.FIVEn_DFT_PKG.ALL;
USE work.coeff_5ndft.ALL;
ENTITY FFT_tree IS
GENERIC(
nb_bits_shift_round : IN natural);
PORT(
i_clk : IN std_logic;
i_data_re : IN vect_dft_input;
i_data_im : IN vect_dft_input;
o_data_re : OUT vect_dft_output := (OTHERS => (OTHERS => '0'));
o_data_im : OUT vect_dft_output := (OTHERS => (OTHERS => '0'))
);
END FFT_tree;
ARCHITECTURE instanciating_cells OF FFT_tree IS
SIGNAL zero : std_logic_vector(0 DOWNTO 0) := "0";
SIGNAL cos_k_pi_over_5 : vect_cos_sin_k_pi_over_5_32b := ("01000000000000000000000000000000", "00110011110001101110111100110111", "00010011110001101110111100110111", "11101100001110010001000011001001", "11001100001110010001000011001001"); -- coeffs multiplied by 2^30
SIGNAL sin_k_pi_over_5 : vect_cos_sin_k_pi_over_5_32b := ("00000000000000000000000000000000", "11011010011000011011100111110111", "11000011001000011110001111011001", "11000011001000011110001111011001", "11011010011000011011100111110111"); -- coeffs multiplied by 2^30
-- purpose: give the proper arrangement for the winograd5 blks
-- the right order: even numbers then odd numbers. The even numbers are the
-- result of others even_odd order multiplied by 2, the odd numbers are the
-- result of others even_odd order multiplied by 2+1.
-- input: the nth winograd5 instance when sort
-- output: the corresponding winograd5 instance number when sort
FUNCTION rearrange (
i : IN natural)
RETURN natural IS
TYPE vect_rearrange IS ARRAY (0 TO cst_nb_samples_in_5ndft) OF natural;
TYPE matrix_rearrange IS ARRAY (0 TO cst_log2_nb_parallel_winograd5) OF vect_rearrange;
VARIABLE matrix_affect_rearrange : matrix_rearrange := (OTHERS => (OTHERS => 0));
BEGIN -- FUNCTION rearrange
IF cst_log2_nb_parallel_winograd5 > 0 THEN
matrix_affect_rearrange(1)(1) := 1;
FOR stage IN 2 TO cst_log2_nb_parallel_winograd5 LOOP
FOR i IN 0 TO 2**(stage-1)-1 LOOP
matrix_affect_rearrange(stage)(i) := matrix_affect_rearrange(stage-1)(i)*2;
matrix_affect_rearrange(stage)(i+2**(stage-1)) := matrix_affect_rearrange(stage-1)(i)*2+1;
END LOOP; -- i
END LOOP; -- stage
RETURN matrix_affect_rearrange(cst_log2_nb_parallel_winograd5)(i);
ELSE
RETURN 0;
END IF;
END FUNCTION rearrange;
TYPE matrix_input_winograd5_5ndft IS ARRAY (0 TO cst_nb_parallel_winograd5-1) OF vect_input_winograd5_5ndft;
TYPE matrix_output_winograd5_5ndft IS ARRAY (0 TO cst_nb_parallel_winograd5-1) OF vect_output_winograd5_5ndft;
SIGNAL cos_k_pi_over_5_wb : vect_cos_sin_k_pi_over_5_wb := (OTHERS => (OTHERS => '0'));
SIGNAL sin_k_pi_over_5_wb : vect_cos_sin_k_pi_over_5_wb := (OTHERS => (OTHERS => '0'));
SIGNAL data_out_winograd5_re : vect_total_output_winograd5_cells := (OTHERS => (OTHERS => '0'));
SIGNAL data_out_winograd5_im : vect_total_output_winograd5_cells := (OTHERS => (OTHERS => '0'));
SIGNAL winograd_rearranged_input_re : vect_dft_input := (OTHERS => (OTHERS => '0'));
SIGNAL winograd_rearranged_input_im : vect_dft_input := (OTHERS => (OTHERS => '0'));
SIGNAL matrix_inputs_outputs_radix2_cells_re : matrix_fft_stages := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL matrix_inputs_outputs_radix2_cells_im : matrix_fft_stages := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL vect_input_1_cell_winograd5_re : matrix_input_winograd5_5ndft := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL vect_input_1_cell_winograd5_im : matrix_input_winograd5_5ndft := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL vect_output_1_cell_winograd5_re : matrix_output_winograd5_5ndft := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL vect_output_1_cell_winograd5_im : matrix_output_winograd5_5ndft := (OTHERS => (OTHERS => (OTHERS => '0')));
BEGIN -- ARCHITECTURE instanciating_cells
-- coeffs cut
-- purpose: Rounds the data in 32bits into cst_w_precision_radix2_coeffs_5ndft bits (round for
-- MSBs). Should run and cut before simulation and bitstream
-- inputs : the coeffs to be cut sin_k_pi_over_5, cos_k_pi_over_5, sin_k_pi_over_80, cos_k_pi_over_80
-- outputs: the cut coeffs cos_k_pi_over_5_wb, sin_k_pi_over_5_wb, sin_k_pi_over_80_wb, cos_k_pi_over_80_wb
mult_coeffs_cut : PROCESS(sin_k_pi_over_5, cos_k_pi_over_5)
BEGIN
FOR i IN 0 TO 4 LOOP
cos_k_pi_over_5_wb(i) <= cos_k_pi_over_5(i)(31 DOWNTO 32-cst_w_precision_radix2_coeffs_5ndft);
sin_k_pi_over_5_wb(i) <= sin_k_pi_over_5(i)(31 DOWNTO 32-cst_w_precision_radix2_coeffs_5ndft);
IF(cos_k_pi_over_5(i)(32-cst_w_precision_radix2_coeffs_5ndft-1) = '1') THEN
cos_k_pi_over_5_wb(i) <= std_logic_vector(unsigned(signed(cos_k_pi_over_5(i)(31 DOWNTO 32-cst_w_precision_radix2_coeffs_5ndft))+1));
END IF;
IF(sin_k_pi_over_5(i)(32-cst_w_precision_radix2_coeffs_5ndft-1) = '1') THEN
sin_k_pi_over_5_wb(i) <= std_logic_vector(unsigned(signed(sin_k_pi_over_5(i)(31 DOWNTO 32-cst_w_precision_radix2_coeffs_5ndft))+1));
END IF;
END LOOP; -- i
END PROCESS mult_coeffs_cut;
-- inputs rearranging
-- purpose: affects inputs on their right way (cf. schema and explanations)
-- using the rearrange(i) function, which creates the right winograd
-- instances numbers order. Rearranging inputs order is equivalent to rearranging
-- winograd5 order.
-- inputs: i_data_re, i_data_im
-- outputs: winograd_rearranged_input_re, winograd_rearranged_input_im
rearrange_winograd_input : FOR i IN 0 TO cst_nb_parallel_winograd5-1 GENERATE
five_inputs : FOR j IN 0 TO 4 GENERATE
winograd_rearranged_input_re(rearrange(i => i)*5+j) <= i_data_re(j*cst_nb_parallel_winograd5+i);
winograd_rearranged_input_im(rearrange(i => i)*5+j) <= i_data_im(j*cst_nb_parallel_winograd5+i);
END GENERATE five_inputs;
END GENERATE rearrange_winograd_input;
-- winograd instanciating
-- purpose: wiring; instanciates the parallel winograd stage with their correct inputs and outputs
-- inputs: winograd_rearranged_input_im, winograd_rearranged_input_re (length
-- cst_nb_samples_in_5ndft each, cut then into subvectors of 5 inputs)
-- instances: WINOGRAD5(Behavioral)
-- outputs: vect_output_1_cell_winograd5_im, vect_output_1_cell_winograd5_re
-- (length cst_nb_samples_in_5ndft each, cut then into subvectors of 5 inputs)
winograd5_instances : FOR i IN 0 TO cst_nb_parallel_winograd5-1 GENERATE
fill_for : FOR j IN 0 TO 4 GENERATE
vect_input_1_cell_winograd5_im(i)(j) <= winograd_rearranged_input_im(j+5*i);
vect_input_1_cell_winograd5_re(i)(j) <= winograd_rearranged_input_re(j+5*i);
data_out_winograd5_im(j+5*i) <= vect_output_1_cell_winograd5_im(i)(j);
data_out_winograd5_re(j+5*i) <= vect_output_1_cell_winograd5_re(i)(j);
END GENERATE fill_for;
winograd5_inst : ENTITY work.WINOGRAD5(Behavioral)
PORT MAP(
i_clk => i_clk,
i_data_im => vect_input_1_cell_winograd5_im(i),
i_data_re => vect_input_1_cell_winograd5_re(i),
o_data_im => vect_output_1_cell_winograd5_im(i),
o_data_re => vect_output_1_cell_winograd5_re(i)
);
END GENERATE winograd5_instances;
-- winograd results
-- purpose: fill the 0th stage (input stage) of the matrix instanciating the
-- butterfly (radix2) cells only.
-- inputs: data_out_winograd5_re, data_out_winograd5_im
-- outputs: matrix_inputs_outputs_radix2_cells_re(x)(0), matrix_inputs_outputs_radix2_cells_im(x)(0)
fill_radix2_cells_input_matrix : FOR i IN 0 TO cst_nb_samples_in_5ndft-1 GENERATE
matrix_inputs_outputs_radix2_cells_re(i)(0)(cst_winograd5_w_out_5ndft-1 DOWNTO 0) <= data_out_winograd5_re(i);
matrix_inputs_outputs_radix2_cells_im(i)(0)(cst_winograd5_w_out_5ndft-1 DOWNTO 0) <= data_out_winograd5_im(i);
END GENERATE fill_radix2_cells_input_matrix;
-- purpose: instanciates the first butterfly cells stage (after the winograd
-- results). If there is only 1 parallel winograd5 cell, couple_winograd5_nb
-- will not be use between 0 and -1, so the FOR loop will no execute
-- inputs: matrix_inputs_outputs_radix2_cells_re(x)(0), matrix_inputs_outputs_radix2_cells_im(x)(0)
-- instances: radix_2_cell_winograd(radix2)
-- outputs: matrix_inputs_outputs_radix2_cells_re(x)(1), matrix_inputs_outputs_radix2_cells_im(x)(1)
radix2_cells_stage1 : FOR couple_winograd5_nb IN 0 TO cst_nb_parallel_winograd5/2-1 GENERATE
radix2_winograd_out : FOR i IN 0 TO 4 GENERATE
radix_2_out_winograd_inst : ENTITY work.radix_2_cell_winograd(radix2)
GENERIC MAP(
w_in => cst_winograd5_w_out_5ndft
)
PORT MAP(
i_clk => i_clk,
i_cos => cos_k_pi_over_5_wb(i MOD 5),
i_sin => sin_k_pi_over_5_wb(i MOD 5),
i_data1_re => matrix_inputs_outputs_radix2_cells_re(couple_winograd5_nb*10+i)(0),
i_data1_im => matrix_inputs_outputs_radix2_cells_im(couple_winograd5_nb*10+i)(0),
i_data2_re => matrix_inputs_outputs_radix2_cells_re(couple_winograd5_nb*10+i+5)(0),
i_data2_im => matrix_inputs_outputs_radix2_cells_im(couple_winograd5_nb*10+i+5)(0),
o_data1_re => matrix_inputs_outputs_radix2_cells_re(couple_winograd5_nb*10+i)(1),
o_data1_im => matrix_inputs_outputs_radix2_cells_im(couple_winograd5_nb*10+i)(1),
o_data2_re => matrix_inputs_outputs_radix2_cells_re(couple_winograd5_nb*10+i+5)(1),
o_data2_im => matrix_inputs_outputs_radix2_cells_im(couple_winograd5_nb*10+i+5)(1)
);
END GENERATE radix2_winograd_out;
END GENERATE radix2_cells_stage1;
-- radix2 cells instanciation
-- purpose: instanciates all the butterfly stages (except stage 1). The
-- stages are filled decrementing the stage number
-- inputs: matrix_inputs_outputs_radix2_cells_re(x)(1), matrix_inputs_outputs_radix2_cells_im(x)(1)
-- instances: radix_2_cell_winograd(radix2)
-- outputs: matrix_inputs_outputs_radix2_cells_re(x)(cst_log2_nb_parallel_winograd5), matrix_inputs_outputs_radix2_cells_im(x)(cst_log2_nb_parallel_winograd5)
stages_generation : FOR stage IN 1 TO cst_log2_nb_parallel_winograd5-1 GENERATE
k10_blocks : FOR cell_10_nb IN 1 TO 2**(stage-1) GENERATE
parallel_cells : FOR cell_nb IN (cst_nb_samples_in_5ndft/(2**stage))*(cell_10_nb-1) TO (cst_nb_samples_in_5ndft/(2**stage))*(cell_10_nb)-1 GENERATE
radix_2_generic_inst : ENTITY work.radix_2_cell_winograd(radix2)
GENERIC MAP(
w_in => cst_winograd5_w_out_5ndft+(cst_log2_nb_parallel_winograd5-stage)*cst_w_radix2_added
)
PORT MAP(
i_clk => i_clk,
i_cos => cos_k_pi_over_n_wb((cst_nb_wn_coeffs/10/(2**(cst_log2_nb_parallel_winograd5-stage-1))*cell_nb) MOD cst_nb_wn_coeffs),
i_sin => sin_k_pi_over_n_wb((cst_nb_wn_coeffs/10/(2**(cst_log2_nb_parallel_winograd5-stage-1))*cell_nb) MOD cst_nb_wn_coeffs),
i_data1_re => matrix_inputs_outputs_radix2_cells_re(cell_nb)(cst_log2_nb_parallel_winograd5-stage),
i_data1_im => matrix_inputs_outputs_radix2_cells_im(cell_nb)(cst_log2_nb_parallel_winograd5-stage),
i_data2_re => matrix_inputs_outputs_radix2_cells_re(cell_nb+(cst_nb_samples_in_5ndft/(2**stage)))(cst_log2_nb_parallel_winograd5-stage),
i_data2_im => matrix_inputs_outputs_radix2_cells_im(cell_nb+(cst_nb_samples_in_5ndft/(2**stage)))(cst_log2_nb_parallel_winograd5-stage),
o_data1_re => matrix_inputs_outputs_radix2_cells_re(cell_nb)(cst_log2_nb_parallel_winograd5-stage+1),
o_data1_im => matrix_inputs_outputs_radix2_cells_im(cell_nb)(cst_log2_nb_parallel_winograd5-stage+1),
o_data2_re => matrix_inputs_outputs_radix2_cells_re(cell_nb+(cst_nb_samples_in_5ndft/(2**stage)))(cst_log2_nb_parallel_winograd5-stage+1),
o_data2_im => matrix_inputs_outputs_radix2_cells_im(cell_nb+(cst_nb_samples_in_5ndft/(2**stage)))(cst_log2_nb_parallel_winograd5-stage+1)
);
END GENERATE parallel_cells;
END GENERATE k10_blocks;
END GENERATE stages_generation;
-- output results
-- purpose: rounds the outputs to have cst_w_out_5ndft bits. Does not round
-- if cst_w_out_5ndft = cst_dft_w_out_5ndft
-- type : sequential
-- inputs : i_clk, matrix_inputs_outputs_radix2_cells_re, matrix_inputs_outputs_radix2_cells_im
-- outputs: o_data_re, i_data_im
--output_rounding : PROCESS (i_clk) IS
--BEGIN -- PROCESS output_rounding
--IF rising_edge(i_clk) THEN -- rising clock edge
rounding : FOR i IN 0 TO cst_nb_samples_in_5ndft-1 generate
--IF(matrix_inputs_outputs_radix2_cells_re(i)(cst_log2_nb_parallel_winograd5)(cst_dft_w_out_5ndft-nb_bits_shift_round-1-cst_w_out_5ndft) = '1' AND cst_w_out_5ndft < cst_dft_w_out_5ndft) THEN
o_data_re(i) <= matrix_inputs_outputs_radix2_cells_re(i)(cst_log2_nb_parallel_winograd5)(cst_dft_w_out_5ndft-nb_bits_shift_round-1 DOWNTO cst_dft_w_out_5ndft-nb_bits_shift_round-cst_w_out_5ndft);
--ELSE
--o_data_re(i) <= matrix_inputs_outputs_radix2_cells_re(i)(cst_log2_nb_parallel_winograd5)(cst_dft_w_out_5ndft-nb_bits_shift_round-1 DOWNTO cst_dft_w_out_5ndft-nb_bits_shift_round-cst_w_out_5ndft);
--END IF;
--IF(matrix_inputs_outputs_radix2_cells_im(i)(cst_log2_nb_parallel_winograd5)(cst_dft_w_out_5ndft-nb_bits_shift_round-1-cst_w_out_5ndft) = '1' AND cst_w_out_5ndft < cst_dft_w_out_5ndft) THEN
o_data_im(i) <= matrix_inputs_outputs_radix2_cells_im(i)(cst_log2_nb_parallel_winograd5)(cst_dft_w_out_5ndft-nb_bits_shift_round-1 DOWNTO cst_dft_w_out_5ndft-nb_bits_shift_round-cst_w_out_5ndft);
--ELSE
--o_data_im(i) <= matrix_inputs_outputs_radix2_cells_im(i)(cst_log2_nb_parallel_winograd5)(cst_dft_w_out_5ndft-nb_bits_shift_round-1 DOWNTO cst_dft_w_out_5ndft-nb_bits_shift_round-cst_w_out_5ndft);
--END IF;
END GENERATE rounding; -- i
--END IF;
--END PROCESS output_rounding;
-- if you prefer the whole result, uncomment this section and comment the
-- output_rounding process above. You should also change smpl_out_5ndft from
-- cst_w_out_5ndft to cst_dft_w_out_5ndft (line 32 in FIVEn_dft_pkg).
--fill_outputs : FOR i IN 0 TO cst_nb_samples_in_5ndft-1 GENERATE
-- o_data_re(i) <= matrix_inputs_outputs_radix2_cells_re(i)(cst_log2_nb_parallel_winograd5);
-- o_data_im(i) <= matrix_inputs_outputs_radix2_cells_im(i)(cst_log2_nb_parallel_winograd5);
--END GENERATE fill_outputs;
END ARCHITECTURE instanciating_cells;

+ 64
- 0
5ndft/mult_blk_5ndft.vhd View File

@@ -0,0 +1,64 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE work.FIVEn_DFT_PKG.ALL;
-- purpose : deledate the multiplication and the addition witn the complex
-- exponential Wn to this bloc
ENTITY MULT_BLK_5nDFT IS
GENERIC(
w_in : natural;
w_mult : natural
);
PORT(i_clk : IN std_logic;
i_data_re : IN smpl_out_radix2;
i_data_im : IN smpl_out_radix2;
i_cos : IN smpl_cos_sin_wb;
i_sin : IN smpl_cos_sin_wb;
o_data_re : OUT smpl_out_radix2 := (OTHERS => '0');
o_data_im : OUT smpl_out_radix2 := (OTHERS => '0')
);
END MULT_BLK_5nDFT;
ARCHITECTURE Mult_Path OF MULT_BLK_5nDFT IS
SIGNAL data_mult_re_cos_signed : smpl_out_signed_radix2 := (OTHERS => '0'); -- intermediate result re*cos
SIGNAL data_mult_im_cos_signed : smpl_out_signed_radix2 := (OTHERS => '0'); -- intermediate result im*cos
SIGNAL data_mult_re_sin_signed : smpl_out_signed_radix2 := (OTHERS => '0'); -- intermediate result im*sin,!i*i=-1!
SIGNAL data_mult_im_sin_signed : smpl_out_signed_radix2 := (OTHERS => '0'); -- intermediate result re*sin
SIGNAL sin_signed : smpl_cos_sin_signed_wb := (OTHERS => '0'); -- signed input sin
SIGNAL cos_signed : smpl_cos_sin_signed_wb := (OTHERS => '0'); -- signed input cos
SIGNAL data_re_signed : smpl_out_signed_radix2 := (OTHERS => '0'); -- signed input data im
SIGNAL data_im_signed : smpl_out_signed_radix2 := (OTHERS => '0'); -- signed input data re
BEGIN
-- assign the signed signals before doing any operation
data_re_signed(w_in-1 DOWNTO 0) <= signed(i_data_re(w_in-1 DOWNTO 0));
data_im_signed(w_in-1 DOWNTO 0) <= signed(i_data_im(w_in-1 DOWNTO 0));
cos_signed <= signed(i_cos);
sin_signed <= signed(i_sin);
-- purpose: multiply the real and imag part with the cos ans isin part of the
-- exponential, and add the results of real parts and imag ones together.
-- Needs 2 clock edges to process the whole mult result
-- inputs: signed data(im & re), signed exponential (cos & sin)
-- outputs: o_data_re, o_data_im
mult : PROCESS(i_clk)
BEGIN
IF rising_edge(i_clk) THEN
data_mult_re_cos_signed(w_in+w_mult-1 DOWNTO 0) <= data_re_signed(w_in-1 DOWNTO 0) * cos_signed;
data_mult_im_cos_signed(w_in+w_mult-1 DOWNTO 0) <= data_im_signed(w_in-1 DOWNTO 0) * cos_signed;
data_mult_im_sin_signed(w_in+w_mult-1 DOWNTO 0) <= data_re_signed(w_in-1 DOWNTO 0) * sin_signed;
data_mult_re_sin_signed(w_in+w_mult-1 DOWNTO 0) <= data_im_signed(w_in-1 DOWNTO 0) * sin_signed;
o_data_re(w_in+w_mult DOWNTO 0) <= std_logic_vector(unsigned(signed(data_mult_re_cos_signed(w_in+w_mult-1)&data_mult_re_cos_signed(w_in+w_mult-1 DOWNTO 0)) - signed(data_mult_re_sin_signed(w_in+w_mult-1)&data_mult_re_sin_signed(w_in+w_mult-1 DOWNTO 0))));-- i*i=-1
o_data_im(w_in+w_mult DOWNTO 0) <= std_logic_vector(unsigned(signed(data_mult_im_cos_signed(w_in+w_mult-1)&data_mult_im_cos_signed(w_in+w_mult-1 DOWNTO 0)) + signed(data_mult_im_sin_signed(w_in+w_mult-1)&data_mult_im_sin_signed(w_in+w_mult-1 DOWNTO 0))));
END IF;
END PROCESS;
END Mult_Path;

+ 97
- 0
5ndft/radix_2_cell.vhd View File

@@ -0,0 +1,97 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_signed.ALL;
USE ieee.numeric_std.ALL;
USE work.FIVEn_DFT_PKG.ALL;
ENTITY radix_2_cell_winograd IS
GENERIC(
w_in : natural
);
PORT(
i_clk : std_logic;
i_cos : smpl_cos_sin_wb;
i_sin : smpl_cos_sin_wb;
i_data1_re : IN smpl_out_radix2;
i_data1_im : IN smpl_out_radix2;
i_data2_re : IN smpl_out_radix2;
i_data2_im : IN smpl_out_radix2;
o_data1_re : OUT smpl_out_radix2 := (OTHERS => '0');
o_data1_im : OUT smpl_out_radix2 := (OTHERS => '0');
o_data2_re : OUT smpl_out_radix2 := (OTHERS => '0');
o_data2_im : OUT smpl_out_radix2 := (OTHERS => '0')
);
END radix_2_cell_winograd;
ARCHITECTURE radix2 OF radix_2_cell_winograd IS
TYPE vect_result_multiply IS ARRAY (0 TO 1) OF std_logic_vector(w_in + cst_w_precision_radix2_coeffs_5ndft-2 DOWNTO 0);
SIGNAL signed_data_im : smpl_out_winograd5_signed_5ndft := (OTHERS => '0');
SIGNAL signed_data_re : smpl_out_winograd5_signed_5ndft := (OTHERS => '0');
SIGNAL multiply_by_2_power_cst_w_precision : std_logic_vector(cst_w_precision_radix2_coeffs_5ndft-3 DOWNTO 0) := (OTHERS => '0');
SIGNAL data_matrix_im : matrix_radix2_cell := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL data_matrix_re : matrix_radix2_cell := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL data_vect_result_mult_re : vect_result_multiply := (OTHERS => (OTHERS => '0'));
SIGNAL data_vect_result_mult_im : vect_result_multiply := (OTHERS => (OTHERS => '0'));
BEGIN
-- assign block inputs and outputs their corresponding matrix columns
data_matrix_re(0)(0) <= i_data1_re;
data_matrix_re(1)(0) <= i_data2_re;
data_matrix_im(0)(0) <= i_data1_im;
data_matrix_im(1)(0) <= i_data2_im;
o_data1_re <= data_matrix_re(0)(3);
o_data2_re <= data_matrix_re(1)(3);
o_data1_im <= data_matrix_im(0)(3);
o_data2_im <= data_matrix_im(1)(3);
--instanciating the MULT_BLK_5nDFT(Mult_Path)
mult_inst1 : ENTITY work.MULT_BLK_5nDFT(Mult_Path)
GENERIC MAP(
w_in => w_in,
w_mult => cst_w_precision_radix2_coeffs_5ndft
)
PORT MAP(i_clk => i_clk,
i_data_re => data_matrix_re(1)(0),
i_data_im => data_matrix_im(1)(0),
i_cos => i_cos,
i_sin => i_sin,
o_data_re => data_matrix_re(1)(2),
o_data_im => data_matrix_im(1)(2)
);
-- purpose: calculating the multiplication and the 2 additions/substractions.
-- The multiplication per 1 in the top of the butterfly is replaced by a
-- shift with 0s towards the MSBs
-- inputs: data_matrix_im(x)(0), data_matrix_re(x)(0)
-- outputs: data_matrix_im(x)(3), data_matrix_re(x)(3)
radix2_structure : PROCESS(i_clk)
BEGIN
IF(rising_edge(i_clk)) THEN
-- mult per 1 (top)
data_matrix_im(0)(1)(w_in+cst_w_precision_radix2_coeffs_5ndft DOWNTO 0) <= data_matrix_im(0)(0)(w_in-1)&data_matrix_im(0)(0)(w_in-1)&data_matrix_im(0)(0)(w_in-1)&data_matrix_im(0)(0)(w_in-1 DOWNTO 0)&multiply_by_2_power_cst_w_precision;
data_matrix_re(0)(1)(w_in+cst_w_precision_radix2_coeffs_5ndft DOWNTO 0) <= data_matrix_re(0)(0)(w_in-1)&data_matrix_re(0)(0)(w_in-1)&data_matrix_re(0)(0)(w_in-1)&data_matrix_re(0)(0)(w_in-1 DOWNTO 0)&multiply_by_2_power_cst_w_precision;
data_matrix_im(0)(2) <= data_matrix_im(0)(1);
data_matrix_re(0)(2) <= data_matrix_re(0)(1);
-- mult (down) : see mult_blk instanciation
--add
data_matrix_re(0)(3)(w_in+cst_w_precision_radix2_coeffs_5ndft+1 DOWNTO 0) <= std_logic_vector(unsigned(signed(data_matrix_re(0)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft)&data_matrix_re(0)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft DOWNTO 0))+signed(data_matrix_re(1)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft)&data_matrix_re(1)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft DOWNTO 0))));
data_matrix_re(1)(3)(w_in+cst_w_precision_radix2_coeffs_5ndft+1 DOWNTO 0) <= std_logic_vector(unsigned(signed(data_matrix_re(0)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft)&data_matrix_re(0)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft DOWNTO 0))-signed(data_matrix_re(1)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft)&data_matrix_re(1)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft DOWNTO 0))));
data_matrix_im(0)(3)(w_in+cst_w_precision_radix2_coeffs_5ndft+1 DOWNTO 0) <= std_logic_vector(unsigned(signed(data_matrix_im(0)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft)&data_matrix_im(0)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft DOWNTO 0))+signed(data_matrix_im(1)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft)&data_matrix_im(1)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft DOWNTO 0))));
data_matrix_im(1)(3)(w_in+cst_w_precision_radix2_coeffs_5ndft+1 DOWNTO 0) <= std_logic_vector(unsigned(signed(data_matrix_im(0)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft)&data_matrix_im(0)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft DOWNTO 0))-signed(data_matrix_im(1)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft)&data_matrix_im(1)(2)(w_in+cst_w_precision_radix2_coeffs_5ndft DOWNTO 0))));
END IF;
END PROCESS;
END radix2;

+ 306
- 0
5ndft/winograd5.vhd View File

@@ -0,0 +1,306 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_signed.ALL;
USE ieee.numeric_std.ALL;
USE work.FIVEn_DFT_PKG.ALL;
ENTITY WINOGRAD5 IS
PORT(
i_clk : IN std_logic;
i_data_im : IN vect_input_winograd5_5ndft;
i_data_re : IN vect_input_winograd5_5ndft;
o_data_im : OUT vect_output_winograd5_5ndft := (OTHERS => (OTHERS => '0'));
o_data_re : OUT vect_output_winograd5_5ndft := (OTHERS => (OTHERS => '0'))
);
END WINOGRAD5;
ARCHITECTURE Behavioral OF WINOGRAD5 IS
SIGNAL mult_factors : vect_mult_factors_32b := ("10110000000000000000000000000000", "00100011110001101110111100110111", "00010111001111111101011000011110", "01100010011111000110001000101111", "00100101100111100100011000001001");
-- multipliers multiplied by 2^30
SIGNAL mult_factor_w_multipliers : vect_mult_factor_w_multipliers := (OTHERS => (OTHERS => '0'));
--SIGNAL matrix_stages_signed_im : matrix_winograd5_generic_signed_stages := (OTHERS => (OTHERS => (OTHERS => '0')));
--SIGNAL matrix_stages_signed_re : matrix_winograd5_generic_signed_stages := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL matrix_stages_im : matrix_winograd5_generic_stages := (OTHERS => (OTHERS => (OTHERS => '0'))); --matrix(x)(y) = matrix(stage)(layer) form
SIGNAL matrix_stages_re : matrix_winograd5_generic_stages := (OTHERS => (OTHERS => (OTHERS => '0'))); -- matrix(x)(y) = matrix(stage)(layer) form
SIGNAL multiply_by_2_power_cst_w_precision : std_logic_vector(cst_w_precision_winograd5_coeffs_5ndft-3 DOWNTO 0) := (OTHERS => '0');
--SIGNAL in1, in2 : smpl_out_winograd5_5ndft;
--SIGNAL isigned : smpl_out_winograd5_signed_5ndft;
FUNCTION add_sub (
w_smpl : IN natural;
sub : IN boolean;
in1, in2 : IN smpl_out_winograd5_5ndft)
RETURN smpl_out_winograd5_5ndft IS
VARIABLE smpl_stages_out : smpl_out_winograd5_5ndft := (OTHERS => '0');
BEGIN
IF sub THEN
smpl_stages_out(w_smpl DOWNTO 0) := std_logic_vector(unsigned(signed(in1(w_smpl-1)&in1(w_smpl-1 DOWNTO 0))-signed(in2(w_smpl-1)&in2(w_smpl-1 DOWNTO 0))));
ELSE
smpl_stages_out(w_smpl DOWNTO 0) := std_logic_vector(unsigned(signed(in1(w_smpl-1)&in1(w_smpl-1 DOWNTO 0))+signed(in2(w_smpl-1)&in2(w_smpl-1 DOWNTO 0))));
END IF;
RETURN smpl_stages_out;
END FUNCTION;
FUNCTION mult (
w_smpl : IN natural;
cmplx : IN boolean;
w_coeff : IN natural;
input : IN smpl_out_winograd5_5ndft;
coeff : IN smpl_mult_factor_w_multipliers
)
RETURN std_logic_vector IS
VARIABLE smpl_signed : smpl_out_winograd5_signed_5ndft := (OTHERS => '0');
VARIABLE smpl_out : smpl_out_winograd5_5ndft;
BEGIN -- FUNCTION mult
IF(cmplx) THEN
smpl_signed(w_smpl+w_coeff-1 DOWNTO 0) := signed(input(w_smpl-1 DOWNTO 0)) * (-signed(coeff));
ELSE
smpl_signed(w_smpl+w_coeff-1 DOWNTO 0) := signed(input(w_smpl-1 DOWNTO 0)) * signed(coeff);
END IF;
smpl_out := std_logic_vector(unsigned(smpl_signed));
RETURN smpl_out;
END FUNCTION mult;
FUNCTION smpl_copy (
w_smpl : natural;
smpl_in : smpl_out_winograd5_5ndft)
RETURN std_logic_vector IS
VARIABLE smpl_out : smpl_out_winograd5_5ndft := (OTHERS => '0');
BEGIN -- FUNCTION copy
smpl_out(w_smpl DOWNTO 0) := smpl_in(w_smpl-1)&smpl_in(w_smpl-1 DOWNTO 0);
RETURN smpl_out; --smpl_in(cst_winograd5_w_out_5ndft-1 DOWNTO w_smpl+1)&smpl_in(w_smpl-1)&smpl_in(w_smpl-1 DOWNTO 0);--smpl_out;
END FUNCTION smpl_copy;
BEGIN
fill_input_output_matrix_for : FOR i IN 0 TO 4 GENERATE
matrix_stages_im(0)(i)(cst_w_in_5ndft-1 DOWNTO 0) <= i_data_im(i)(cst_w_in_5ndft-1 DOWNTO 0);
matrix_stages_re(0)(i)(cst_w_in_5ndft-1 DOWNTO 0) <= i_data_re(i)(cst_w_in_5ndft-1 DOWNTO 0);
o_data_im(i) <= matrix_stages_im(7)(i);
o_data_re(i) <= matrix_stages_re(7)(i);
END GENERATE fill_input_output_matrix_for;
-- purpose: Rounds the data in 32bits into cst_w_precision_winograd5_coeffs_5ndft bits (round for
-- MSBs). Should run and cut before simulation and bitstream
-- inputs : the coeffs to be cut mult_factors
-- outputs: the cut coeffs mult_factor_w_multipliers
mult_coeffs_cut : PROCESS(mult_factors)
BEGIN
FOR i IN 1 TO 5 LOOP
mult_factor_w_multipliers(i) <= mult_factors(i)(31 DOWNTO 32-cst_w_precision_winograd5_coeffs_5ndft);
IF(mult_factors(i)(31-cst_w_precision_winograd5_coeffs_5ndft) = '1') THEN
mult_factor_w_multipliers(i) <= std_logic_vector(unsigned(signed(mult_factors(i)(31 DOWNTO 32-cst_w_precision_winograd5_coeffs_5ndft)) +1));
END IF;
END LOOP; -- i
END PROCESS mult_coeffs_cut;
-- purpose: calculates each stage following the winograd5 schema
-- inputs: matrix_stages_im(0)
-- outputs: matrix_stages_im(7)
calculations_process : PROCESS(i_clk)
VARIABLE w_smpl : natural;
BEGIN
IF(rising_edge(i_clk)) THEN
-- stage 1
-- w_smpl :=== cst_w_in_5ndft+1;
--data0
matrix_stages_im(1)(0) <= smpl_copy(w_smpl => cst_w_in_5ndft, smpl_in => matrix_stages_im(0)(0));
matrix_stages_re(1)(0) <= smpl_copy(w_smpl => cst_w_in_5ndft, smpl_in => matrix_stages_re(0)(0));
-- data1
matrix_stages_im(1)(1) <= add_sub (w_smpl => cst_w_in_5ndft, sub => false, in1 => matrix_stages_im(0)(3), in2 => matrix_stages_im(0)(2));
matrix_stages_re(1)(1) <= add_sub (w_smpl => cst_w_in_5ndft, sub => false, in1 => matrix_stages_re(0)(3), in2 => matrix_stages_re(0)(2));
--data2
matrix_stages_im(1)(2) <= add_sub (w_smpl => cst_w_in_5ndft, sub => false, in1 => matrix_stages_im(0)(4), in2 => matrix_stages_im(0)(1));
matrix_stages_re(1)(2) <= add_sub (w_smpl => cst_w_in_5ndft, sub => false, in1 => matrix_stages_re(0)(4), in2 => matrix_stages_re(0)(1));
--data3
matrix_stages_im(1)(3) <= add_sub (w_smpl => cst_w_in_5ndft, sub => true, in1 => matrix_stages_im(0)(3), in2 => matrix_stages_im(0)(2));
matrix_stages_re(1)(3) <= add_sub (w_smpl => cst_w_in_5ndft, sub => true, in1 => matrix_stages_re(0)(3), in2 => matrix_stages_re(0)(2));
--data4
matrix_stages_im(1)(4) <= add_sub (w_smpl => cst_w_in_5ndft, sub => true, in1 => matrix_stages_im(0)(1), in2 => matrix_stages_im(0)(4));
matrix_stages_re(1)(4) <= add_sub (w_smpl => cst_w_in_5ndft, sub => true, in1 => matrix_stages_re(0)(1), in2 => matrix_stages_re(0)(4));
-- stage 2
w_smpl := cst_w_in_5ndft+1;
-- data0,3,4
matrix_stages_im(2)(0) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(1)(0));
matrix_stages_re(2)(0) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(1)(0));
matrix_stages_im(2)(3) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(1)(3));
matrix_stages_re(2)(3) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(1)(3));
matrix_stages_im(2)(4) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(1)(4));
matrix_stages_re(2)(4) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(1)(4));
--data1
matrix_stages_im(2)(1) <= add_sub (w_smpl => w_smpl, sub => false, in1 => matrix_stages_im(1)(1), in2 => matrix_stages_im(1)(2));
matrix_stages_re(2)(1) <= add_sub (w_smpl => w_smpl, sub => false, in1 => matrix_stages_re(1)(1), in2 => matrix_stages_re(1)(2));
--data2
matrix_stages_re(2)(2) <= add_sub(w_smpl => w_smpl, sub => true, in1 => matrix_stages_re(1)(2), in2 => matrix_stages_re(1)(1));
matrix_stages_im(2)(2) <= add_sub(w_smpl => w_smpl, sub => true, in1 => matrix_stages_im(1)(2), in2 => matrix_stages_im(1)(1));
--data5
matrix_stages_re(2)(5) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_re(1)(3), in2 => matrix_stages_re(1)(4));
matrix_stages_im(2)(5) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_im(1)(3), in2 => matrix_stages_im(1)(4));
-- stage 3
w_smpl := cst_w_in_5ndft+2;
--data1,2,3,4,5
matrix_stages_im(3)(1) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(2)(1));
matrix_stages_re(3)(1) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(2)(1));
matrix_stages_im(3)(2) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(2)(2));
matrix_stages_re(3)(2) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(2)(2));
matrix_stages_im(3)(3) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(2)(3));
matrix_stages_re(3)(3) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(2)(3));
matrix_stages_im(3)(4) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(2)(4));
matrix_stages_re(3)(4) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(2)(4));
matrix_stages_im(3)(5) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(2)(5));
matrix_stages_re(3)(5) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(2)(5));
--data0
matrix_stages_im(3)(0) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_im(2)(1), in2 => matrix_stages_im(2)(0));
matrix_stages_re(3)(0) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_re(2)(1), in2 => matrix_stages_re(2)(0));
-- stage 4, multiply
w_smpl := cst_w_in_5ndft+3;
--data0, multiply by 1 = copy
matrix_stages_im(4)(0)(w_smpl+cst_w_precision_winograd5_coeffs_5ndft-1 DOWNTO 0) <= matrix_stages_im(3)(0)(w_smpl-1)&matrix_stages_im(3)(0)(w_smpl-1)&matrix_stages_im(3)(0)(w_smpl-1 DOWNTO 0)&multiply_by_2_power_cst_w_precision;
matrix_stages_re(4)(0)(w_smpl+cst_w_precision_winograd5_coeffs_5ndft-1 DOWNTO 0) <= matrix_stages_re(3)(0)(w_smpl-1)&matrix_stages_re(3)(0)(w_smpl-1)&matrix_stages_re(3)(0)(w_smpl-1 DOWNTO 0)&multiply_by_2_power_cst_w_precision;
--data1
matrix_stages_im(4)(1) <= mult (w_smpl => w_smpl, cmplx => false, w_coeff => cst_w_precision_winograd5_coeffs_5ndft, input => matrix_stages_im(3)(1), coeff => mult_factor_w_multipliers(1));
matrix_stages_re(4)(1) <= mult (w_smpl => w_smpl, cmplx => false, w_coeff => cst_w_precision_winograd5_coeffs_5ndft, input => matrix_stages_re(3)(1), coeff => mult_factor_w_multipliers(1));
--data2
matrix_stages_im(4)(2) <= mult (w_smpl => w_smpl, cmplx => false, w_coeff => cst_w_precision_winograd5_coeffs_5ndft, input => matrix_stages_im(3)(2), coeff => mult_factor_w_multipliers(2));
matrix_stages_re(4)(2) <= mult (w_smpl => w_smpl, cmplx => false, w_coeff => cst_w_precision_winograd5_coeffs_5ndft, input => matrix_stages_re(3)(2), coeff => mult_factor_w_multipliers(2));
--data3
matrix_stages_re(4)(3) <= mult (w_smpl => w_smpl, cmplx => true, w_coeff => cst_w_precision_winograd5_coeffs_5ndft, input => matrix_stages_im(3)(3), coeff => mult_factor_w_multipliers(3));
matrix_stages_im(4)(3) <= mult (w_smpl => w_smpl, cmplx => false, w_coeff => cst_w_precision_winograd5_coeffs_5ndft, input => matrix_stages_re(3)(3), coeff => mult_factor_w_multipliers(3));
--data4
matrix_stages_re(4)(4) <= mult (w_smpl => w_smpl, cmplx => true, w_coeff => cst_w_precision_winograd5_coeffs_5ndft, input => matrix_stages_im(3)(4), coeff => mult_factor_w_multipliers(4));
matrix_stages_im(4)(4) <= mult (w_smpl => w_smpl, cmplx => false, w_coeff => cst_w_precision_winograd5_coeffs_5ndft, input => matrix_stages_re(3)(4), coeff => mult_factor_w_multipliers(4));
--data5
matrix_stages_re(4)(5) <= mult (w_smpl => w_smpl, cmplx => true, w_coeff => cst_w_precision_winograd5_coeffs_5ndft, input => matrix_stages_im(3)(5), coeff => mult_factor_w_multipliers(5));
matrix_stages_im(4)(5) <= mult (w_smpl => w_smpl, cmplx => false, w_coeff => cst_w_precision_winograd5_coeffs_5ndft, input => matrix_stages_re(3)(5), coeff => mult_factor_w_multipliers(5));
-- stage 5
w_smpl := cst_w_in_5ndft+3+cst_w_precision_winograd5_coeffs_5ndft;
--data0, 2, 3, 4, 5
matrix_stages_im(5)(0) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(4)(0));
matrix_stages_re(5)(0) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(4)(0));
matrix_stages_im(5)(2) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(4)(2));
matrix_stages_re(5)(2) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(4)(2));
matrix_stages_im(5)(3) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(4)(3));
matrix_stages_re(5)(3) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(4)(3));
matrix_stages_im(5)(4) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(4)(4));
matrix_stages_re(5)(4) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(4)(4));
matrix_stages_im(5)(5) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(4)(5));
matrix_stages_re(5)(5) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(4)(5));
--data1
matrix_stages_re(5)(1) <= add_sub(w_smpl => w_smpl, sub => false, IN1 => matrix_stages_re(4)(1), in2 => matrix_stages_re(4)(0));
matrix_stages_im(5)(1) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_im(4)(1), in2 => matrix_stages_im(4)(0));
-- stage 6
w_smpl := cst_w_in_5ndft+3+cst_w_precision_winograd5_coeffs_5ndft+1;
--data0
matrix_stages_im(6)(0) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(5)(0));
matrix_stages_re(6)(0) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(5)(0));
--data1
matrix_stages_re(6)(1) <= add_sub(w_smpl => w_smpl, sub => true, in1 => matrix_stages_re(5)(1), in2 => matrix_stages_re(5)(2));
matrix_stages_im(6)(1) <= add_sub(w_smpl => w_smpl, sub => true, in1 => matrix_stages_im(5)(1), in2 => matrix_stages_im(5)(2));
--data2
matrix_stages_re(6)(2) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_re(5)(1), in2 => matrix_stages_re(5)(2));
matrix_stages_im(6)(2) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_im(5)(1), in2 => matrix_stages_im(5)(2));
--data3
matrix_stages_re(6)(3) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_re(5)(5), in2 => matrix_stages_re(5)(3));
matrix_stages_im(6)(3) <= add_sub(w_smpl => w_smpl, sub => false, IN1 => matrix_stages_im(5)(5), in2 => matrix_stages_im(5)(3));
--data4
matrix_stages_re(6)(4) <= add_sub(w_smpl => w_smpl, sub => true, in1 => matrix_stages_re(5)(5), in2 => matrix_stages_re(5)(4));
matrix_stages_im(6)(4) <= add_sub(w_smpl => w_smpl, sub => true, in1 => matrix_stages_im(5)(5), in2 => matrix_stages_im(5)(4));
-- stage 7
w_smpl := cst_w_in_5ndft+3+cst_w_precision_winograd5_coeffs_5ndft+2;
--data0
matrix_stages_im(7)(0) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_im(6)(0));
matrix_stages_re(7)(0) <= smpl_copy(w_smpl => w_smpl, smpl_in => matrix_stages_re(6)(0));
--data1
matrix_stages_re(7)(1) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_re(6)(2), in2 => matrix_stages_re(6)(4));
matrix_stages_im(7)(1) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_im(6)(2), in2 => matrix_stages_im(6)(4));
--data2
matrix_stages_re(7)(2) <= add_sub(w_smpl => w_smpl, sub => true, in1 => matrix_stages_re(6)(1), in2 => matrix_stages_re(6)(3));
matrix_stages_im(7)(2) <= add_sub(w_smpl => w_smpl, sub => true, in1 => matrix_stages_im(6)(1), in2 => matrix_stages_im(6)(3));
--data3
matrix_stages_re(7)(3) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_re(6)(1), in2 => matrix_stages_re(6)(3));
matrix_stages_im(7)(3) <= add_sub(w_smpl => w_smpl, sub => false, in1 => matrix_stages_im(6)(1), in2 => matrix_stages_im(6)(3));
--data4
matrix_stages_re(7)(4) <= add_sub(w_smpl => w_smpl, sub => true, in1 => matrix_stages_re(6)(2), in2 => matrix_stages_re(6)(4));
matrix_stages_im(7)(4) <= add_sub(w_smpl => w_smpl, sub => true, in1 => matrix_stages_im(6)(2), in2 => matrix_stages_im(6)(4));
END IF;
END PROCESS calculations_process;
END Behavioral;

+ 97
- 0
PFB_blk.vhd View File

@@ -0,0 +1,97 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE work.PFB_PKG.ALL;
USE work.POLY_FIR_PKG.ALL;
USE work.FIVEn_DFT_PKG.ALL;
ENTITY PFB_blk IS
PORT (
i_clk : IN std_logic;
i_data : IN vect_adc_data_out_pfb;
i_coeffs : IN vect_polyfir_coeffs_in;
o_data : OUT vect_dft_output_pfb);
END ENTITY PFB_blk;
ARCHITECTURE polyfir_dft OF PFB_blk IS
TYPE matrix_polyfir_data_out_transpose IS ARRAY (0 TO cst_nb_parallel_firs_dfts_pfb-1) OF vect_dft_input;
TYPE matrix_dft_output_pfb IS ARRAY (0 TO cst_nb_parallel_firs_dfts_pfb-1) OF vect_dft_output;
SIGNAL input_polyfir_re : vect_adc_data_out := (OTHERS => (OTHERS => '0'));
SIGNAL input_polyfir_im : vect_adc_data_out := (OTHERS => (OTHERS => '0'));
SIGNAL matrix_out_polyfir_re : matrix_fir_data_out := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL matrix_out_polyfir_im : matrix_fir_data_out := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL matrix_out_dft_re : matrix_dft_output_pfb := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL matrix_out_dft_im : matrix_dft_output_pfb := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL matrix_polyfir_out_transpose_re : matrix_polyfir_data_out_transpose := (OTHERS => (OTHERS => ( OTHERS => '0')));
SIGNAL matrix_polyfir_out_transpose_im : matrix_polyfir_data_out_transpose := (OTHERS => (OTHERS => ( OTHERS => '0')));
BEGIN -- ARCHITECTURE polyfir_dft
-- purpose: wiring: placing imaginary and real part in different vectors.
inputs_discriminating_real_imag : FOR i IN 0 TO cst_nb_samples_adc_in_pfb-1 GENERATE
input_polyfir_re(i) <= i_data(2*i);
input_polyfir_im(i) <= i_data(2*i+1);
END GENERATE inputs_discriminating_real_imag;
-- instanciation of 2 polyphase filter (imaginary and real part)
polyfir_blk_re : ENTITY work.poly_fir_blk(polyphase)
PORT MAP(
i_clk => i_clk,
i_coeffs => i_coeffs,
i_data => input_polyfir_re,
o_data => matrix_out_polyfir_re);
polyfir_blk_im : ENTITY work.poly_fir_blk(polyphase)
PORT MAP(
i_clk => i_clk,
i_coeffs => i_coeffs,
i_data => input_polyfir_im,
o_data => matrix_out_polyfir_im);
-- purpose: wiring: transpose the polyfir matrixes
transpose_for: FOR i IN 0 TO cst_nb_parallel_firs_dfts_pfb-1 GENERATE
transpose_data: FOR j IN 0 TO cst_nb_subfilters_pfb-1 GENERATE
matrix_polyfir_out_transpose_re(i)(j) <= matrix_out_polyfir_re(j)(i);
matrix_polyfir_out_transpose_im(i)(j) <= matrix_out_polyfir_im(j)(i);
END GENERATE transpose_data;
END GENERATE transpose_for;
-- instanciation of cst_nb_parallel_firs_dfts_pfb dfts
instanciating_parallel_dfts : FOR i IN 0 TO cst_nb_parallel_firs_dfts_pfb-1 GENERATE
dft_inst : ENTITY work.FFT_tree(instanciating_cells)
GENERIC MAP (
nb_bits_shift_round => cst_nb_bits_shift_round_pfb)
PORT MAP(
i_clk => i_clk,
i_data_re => matrix_polyfir_out_transpose_re(i),
i_data_im => matrix_polyfir_out_transpose_im(i),
o_data_re => matrix_out_dft_re(i),
o_data_im => matrix_out_dft_im(i)
);
END GENERATE instanciating_parallel_dfts;
-- purpose: wiring: placing imaginary part and real part every other sample
fill_vect_output : FOR parallel_dft_nb IN 0 TO cst_nb_parallel_firs_dfts_pfb-1 GENERATE
fill_line_from_matrix : FOR dft_sample_nb IN 0 TO cst_nb_subfilters_pfb-1 GENERATE
o_data(2*dft_sample_nb+parallel_dft_nb*2*cst_nb_subfilters_pfb) <= matrix_out_dft_re(parallel_dft_nb)(dft_sample_nb);
o_data(2*dft_sample_nb+parallel_dft_nb*2*cst_nb_subfilters_pfb +1) <= matrix_out_dft_im(parallel_dft_nb)(dft_sample_nb);
END GENERATE fill_line_from_matrix;
END GENERATE fill_vect_output;
END ARCHITECTURE polyfir_dft;

+ 52
- 0
PFB_pkg.vhd View File

@@ -0,0 +1,52 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_signed.ALL;
USE ieee.numeric_std.ALL;
USE work.used_functions_pkg.ALL;
PACKAGE PFB_PKG IS
-- NOTES and PACKAGES INSTRUCTIONS :
-- please cf. sub_packages instructions
--
-- this block takes real and imaginary part every other sample, for a total
-- of 2*cst_nb_samples_adc_in_pfb samples in input.
-- does not work yet for 20 subfilters (fir to be re-tested?)
-- input
CONSTANT cst_w_in_pfb : natural := 6;
CONSTANT cst_w_out_pfb : natural := 6;
CONSTANT cst_nb_samples_adc_in_pfb : natural := 80; -- a complete sample is a real AND an imag (both following)
-- polyphase filter
CONSTANT cst_w_coeffs_polyfir_pfb : natural := 8; -- polyfir coeffs bitwidth
CONSTANT cst_nb_coeffs_polyfir_pfb : natural := 200;
CONSTANT cst_polyfir_downsampling_factor_pfb : natural := 8;
-- dft
CONSTANT cst_nb_subfilters_pfb : natural := 10;
CONSTANT cst_w_precision_winograd5_coeffs_pfb : natural := 8; -- dft winograd coeffs bitwidth
CONSTANT cst_w_precision_radix2_coeffs_pfb : natural := 8; -- dft butterfly coeffs bitwidth
CONSTANT cst_nb_bits_shift_round_pfb : natural := 19; -- the number of MSBs to avoid (sign bits) before rounding. For cst_nb_subfilters_pfb=10, 19 works well; for cst_nb_subfilters_pfb=20, 23 should work well. See bellow for a potential correct formula, but please test for your application, don't trust this formula.
-- calculations --
CONSTANT cst_log2_sup_nb_coeffs_subfilter_pfb : natural := log2_sup_integer(number => cst_nb_coeffs_polyfir_pfb/cst_nb_subfilters_pfb);
CONSTANT cst_w_polyfir_out_dft_in_pfb : natural := cst_w_in_pfb + cst_w_coeffs_polyfir_pfb+cst_log2_sup_nb_coeffs_subfilter_pfb;
CONSTANT cst_log2_nb_parallel_winograd_pfb : natural := log2_sup_integer(number => cst_nb_subfilters_pfb/5);
CONSTANT cst_nb_parallel_firs_dfts_pfb : natural := cst_nb_samples_adc_in_pfb/cst_polyfir_downsampling_factor_pfb;
--CONSTANT cst_nb_bits_shift_round_pfb : natural := 15+4*cst_log2_nb_parallel_winograd_pfb; -- potential corect formula
-- TYPES
SUBTYPE smpl_real_imag_adc_data_in_pfb IS std_logic_vector(cst_w_in_pfb-1 DOWNTO 0);
SUBTYPE smpl_real_imag_polyfir_out_dft_in_pfb IS std_logic_vector(cst_w_polyfir_out_dft_in_pfb-1 DOWNTO 0);
SUBTYPE smpl_real_imag_dft_out_pfb IS std_logic_vector(cst_w_out_pfb-1 DOWNTO 0);
--TYPE vect_fir_out_dft_in_pfb IS ARRAY (0 TO cst_nb_subfilters_pfb-1) OF smpl_real_imag_polyfir_out_dft_in_pfb;
TYPE vect_adc_data_out_pfb IS ARRAY (0 TO 2*cst_nb_samples_adc_in_pfb-1) OF smpl_real_imag_adc_data_in_pfb;
TYPE vect_dft_output_pfb IS ARRAY (0 TO 2*cst_nb_parallel_firs_dfts_pfb*cst_nb_subfilters_pfb-1) OF smpl_real_imag_dft_out_pfb;
END PACKAGE PFB_PKG;

+ 142
- 0
PFB_tb.vhd View File

@@ -0,0 +1,142 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE work.PFB_PKG.ALL;
USE work.POLY_FIR_PKG.ALL;
USE work.FIVEn_DFT_PKG.ALL;
USE work.simu_pkg.ALL;
USE work.utils.ALL;
LIBRARY std;
USE std.textio.ALL;
USE work.coeff_fir.ALL;
ENTITY pfb_tb IS
GENERIC (
demi_periode : time := 5 ns;
-- duree de la demi periode des horloges
test_e : string := "D:\Stage\ALMA_OPFB\simu\v0.1 - PFB\tb_txts_files\input.txt";
-- fichier test contenant les echantillons d'entree
test_s : string := "D:\Stage\ALMA_OPFB\simu\v0.1 - PFB\tb_txts_files\output.txt"
-- fichier contenant les echantillons de sortie
);
END pfb_tb;
ARCHITECTURE beh OF pfb_tb IS
TYPE verif_vect IS ARRAY (0 TO 2*cst_nb_parallel_firs_dfts_pfb*cst_nb_subfilters_pfb-1) OF integer;
--TYPE partial_input_vect IS ARRAY (0 TO 9) OF smpl_in_5ndft;
--TYPE partial_output_vect IS ARRAY (0 TO 9) OF smpl_in_5ndft;
--TYPE vect_from_matrix_fir_data_out IS ARRAY (0 TO cst_nb_subfilters*cst_nb_parallel_firs-1) OF smpl_fir_data_out;
FILE fichier_e : text IS IN test_e;
FILE fichier_s : text IS IN test_s;
--FILE fichier_c : text IS IN test_c;
SIGNAL initialisation : std_logic;
SIGNAL h : std_logic;
SIGNAL entree_pfb : vect_adc_data_out_pfb := (OTHERS => (OTHERS => '0'));
SIGNAL sortie_pfb : vect_dft_output_pfb := (OTHERS => (OTHERS => '0'));
SIGNAL sortie_pfb_sim : vect_dft_output_pfb := (OTHERS => (OTHERS => '0'));
SIGNAL verif : verif_vect;
BEGIN -- ARCHITECTURE beh
module_simu : ENTITY work.pfb_blk(polyfir_dft)
PORT MAP(h, entree_pfb, fir_coeffs_generated, sortie_pfb_sim);
horloge_entree : horloge(h, demi_periode, demi_periode);
--sortie_dft_sim_process : PROCESS(sortie_dft_sim)
-- VARIABLE mots_lignes : natural := 20;
--BEGIN
----FOR k IN 0 TO mots_lignes-1 LOOP
---- FOR j IN 0 TO cst_nb_subfilters-1 LOOP
---- sortie_fir_sim_vect(k*mots_lignes+j) <= sortie_fir_sim(j)(k);
---- END LOOP;
----END LOOP;
--END PROCESS;
source : PROCESS
CONSTANT header : natural := 1; -- nombre de ligne d'en tête
CONSTANT nbr_ech : natural := 800000; -- nombre d'echantillons d'entree dans le fichier test
CONSTANT mots_ligne : natural := 2*cst_nb_samples_adc_in_pfb; -- nombre de mots par ligne dans le ficher
VARIABLE nbr_ligne : natural := 10000; -- nombre de lignes restant à lire dans le fichier
VARIABLE i : natural := 1;
VARIABLE donnee : integer;
VARIABLE tempo : natural := 0;
VARIABLE ligne : line;
VARIABLE head : boolean := false;
BEGIN -- PROCESS source
WAIT UNTIL falling_edge(h);
IF head = true THEN
head := false;
FOR i IN 0 TO header-1 LOOP
readline(fichier_e, ligne);
END LOOP;
END IF;
IF tempo > 0 THEN -- temps de synchro
tempo := tempo -1;
ELSIF nbr_ligne > 0 THEN
readline(fichier_e, ligne);
nbr_ligne := nbr_ligne-1;
FOR k IN 0 TO mots_ligne -1 LOOP
read(ligne, donnee);
entree_pfb(k) <= std_logic_vector(to_signed(donnee, cst_w_in_pfb));
END LOOP; -- k
END IF;
END PROCESS source;
test : PROCESS
CONSTANT header : natural := 1; -- nombre de ligne d'en tête
CONSTANT nbr_ech : natural := 1000000; --nombre d'echantillons d'entree dans le fichier test
CONSTANT mots_ligne : natural := 2*cst_nb_parallel_firs_dfts_pfb*cst_nb_subfilters_pfb; -- nombre de mots par ligne dans le ficher
VARIABLE nbr_ligne : natural := 10000; -- nombre de lignes restant à lire dans le fichier
VARIABLE i : natural;
VARIABLE donnee : donnee_sortie;
VARIABLE ligne : line;
VARIABLE tempo : natural := 17;
VARIABLE sortie : integer;
VARIABLE head : boolean := false;
BEGIN -- PROCESS test
WAIT UNTIL falling_edge(h);
IF tempo > 0 THEN -- temps de synchro
tempo := tempo -1;
ASSERT false REPORT "Attente_2 ... " SEVERITY note;
ELSIF nbr_ligne > 0 THEN
readline(fichier_s, ligne);
nbr_ligne := nbr_ligne-1;
FOR k IN 0 TO mots_ligne-1 LOOP
read(ligne, donnee(k));
sortie := to_integer(signed(sortie_pfb_sim(k)));
sortie_pfb(k) <= std_logic_vector(to_signed(donnee(k), cst_w_out_pfb));
verif(k) <= sortie-donnee(k);
ASSERT verif(k) = 0 REPORT "Valeur dft fausse"
SEVERITY error;
--ASSERT sortie /= donnee(k) REPORT "OK"
-- SEVERITY note;
END LOOP; -- k
END IF;
END PROCESS test;
END ARCHITECTURE beh;

+ 15
- 0
matlab/gen_Wn_coeffs_5ndft.m View File

@@ -0,0 +1,15 @@
function gen_Wn_coeffs_5ndft(nb_inputs_tot, bitwidth, file)
coeff_format = 'library ieee;\nUSE ieee.std_logic_1164.all;\nUSE work.FIVEn_DFT_PKG.all;\npackage coeff_5ndft is\n TYPE vect_cos_sin_k_pi_over_n_wb IS ARRAY (0 TO cst_nb_wn_coeffs-1) OF smpl_cos_sin_wb ;\n CONSTANT cos_k_pi_over_n_wb : vect_cos_sin_k_pi_over_n_wb := ("';
for i = 0:nb_inputs_tot/2-2
coeff_format = strcat(coeff_format, string(bin(fi(real(exp(-2*1i*pi*i/nb_inputs_tot)),1,bitwidth, bitwidth-2))), '","');
end
coeff_format = strcat(coeff_format, string(bin(fi(real(exp(-2*1i*pi*(nb_inputs_tot/2-1)/nb_inputs_tot)),1,bitwidth, bitwidth-2))), '");\n CONSTANT sin_k_pi_over_n_wb : vect_cos_sin_k_pi_over_n_wb := ("');
for i = 0:nb_inputs_tot/2-2
coeff_format = strcat(coeff_format, string(bin(fi(imag(exp(-2*1i*pi*i/nb_inputs_tot)),1,bitwidth, bitwidth-2))), '","');
end
coeff_format = strcat(coeff_format, string(bin(fi(imag(exp(-2*1i*pi*(nb_inputs_tot/2-1)/nb_inputs_tot)),1,bitwidth, bitwidth-2))), '");\nend package coeff_5ndft;');
fcoeff = fopen(file,'w');
fprintf(fcoeff,coeff_format);
fclose(fcoeff);
end

+ 9
- 0
matlab/radix2.m View File

@@ -0,0 +1,9 @@
function output = radix2(input, wn)
output = 0*input;
for i = 1:size(input,1)/2
s1 = [input(i,:); input(i+(size(input,1)/2),:)*wn(i)];
output(i,:) = s1(1,:)+s1(2,:);
output(i+(size(input,1)/2),:) = s1(1,:)-s1(2,:);
end

+ 250
- 0
matlab/tb_generation_5ndft.m View File

@@ -0,0 +1,250 @@
clear all;
clear;
close all;
rng(1); % random seed
global ns average quantization Q1 Q2 Q2_1 Q2_2 Q3 fs M D sb_nbr Apass Astop dens
%% Parameter
ns = 2e6; % Number of Sample
fs = 40e9; % Sampling Frequency
M = 20; % Polyphase factor
D = 8; % Decimator
sb_nbr = 3; % Sub-band Number in OPFB : 1 -> M
average = 0; % PSD smoothing : 0 = OFF ; 1 = ON
quantization = 1; % 0 = OFF ; 1 = ON
Q1 = 6; % DG Quantization
Q2 = 8; % PF coefficients Quantization
Q2_1 = 8; % TAP Winograd Quantizantion
Q2_2 = 8; % TAP radix2 Quantization
Q3 = 6; % PFB final Quantization
Apass = 0.25; % Passband Ripple (dB)
Astop = 50; % Stopband Attenuation (dB)
dens = 50; % Density Factor
%% Input Signal
bw = fs/M; % OPFB Output Bandwidth
f1 = bw*(sb_nbr);
f2 = bw*(sb_nbr-0.625+0.25*mod(sb_nbr,M/gcd(M,D)));
t = 0:1/fs:(ns-1)/fs;
sw1 = 1*sin(2*pi*f1*t);
sw2 = 1*sin(2*pi*f1*t);
noise = randn([1 ns]);
nsw = noise+sw1+sw2;
% win = hanning(ns);
% if average == 0
% [PSD, FREQ] = periodogram(nsw,win,ns,fs);
% else
% [PSD, FREQ] = pwelch(nsw,ns/100,[],ns,fs);
% end
% figure;
% MAX = max(10*log(PSD));
% plot(FREQ/1e9, 10*log(PSD)-MAX);
% title('Real Input signal');
% xlim([0,fs/1e9]);
% grid on;
%% Digitizer Anti-aliasing Filter
f = [0 0.1 0.9 1];
m = [0 1 1 0];
b = fir2(1000,f,m);
s_dg_real = conv(noise+sw1,b,'valid');
s_dg_imag = conv(noise+sw2,b,'valid');
s_dg_bb = 0*s_dg_real+1i*s_dg_imag;
ns_dg_bb = size(s_dg_bb,2);
if quantization == 1
s_dg_bb_fi = fi(s_dg_bb,1,Q1,0);
s_dg_bb = s_dg_bb_fi.data;
end
win = hanning(ns_dg_bb);
if average == 0
[PSD, FREQ] = periodogram(s_dg_bb,win,ns_dg_bb,fs);
else
[PSD, FREQ] = pwelch(s_dg_bb,ns_dg_bb/100,[],ns_dg_bb,fs);
end
figure;
MAX = max(10*log(PSD));
plot(FREQ/1e9, 10*log(PSD)-MAX);
title('Dual complex input signal');
xlim([0,fs/1e9]);
grid on;
%% Oversampled Polyphase Filter Bank
% All frequency values are in GHz.
Fs = fs/1e9; % Sampling Frequency
Fpass = (1-(1-D/M))*Fs/M; % Passband Frequency
Fstop = Fs/M; % Stopband Frequency
Dpass = 1-10^(-Apass/20); % Passband Ripple
Dstop = 10^(-Astop/20); % Stopband Attenuation
% Calculate the order from the parameters using FIRPMORD.
[N, Fo, Ao, W] = firpmord([Fpass, Fstop]/(Fs), [1 0], [Dpass, Dstop]);
Ndec0 = N;
if (mod(N,M) ~= M-1)
N = N + M-1 - mod(N,M);
end
% Calculate the coefficients using the FIRPM function.
Hdec0 = firpm(N, Fo, Ao, W, {dens});
% Calculate polyphase filter
Hdec0 = fliplr(Hdec0);
len = length(Hdec0);
nrows = len/M;
Hdec0_pol = zeros(M,nrows);
for m=1:M
for i=1:nrows
Hdec0_pol(m,i)=Hdec0(1,(i-1)*M+m);
end
end
if quantization == 1
Hdec0_pol_fi = fi(Hdec0_pol,1,Q2);
Hdec0_pol = Hdec0_pol_fi.data;
end
tb_coeff = reshape(Hdec0_pol*2^(Hdec0_pol_fi.FractionLength), 1, size(Hdec0_pol,1)*size(Hdec0_pol,2));
% Demux Input
ns_dg_rs1 = floor((ns_dg_bb-M)/D);
s_dg_rs1 = zeros(M,ns_dg_rs1);
for m=1:M
for i=1:ns_dg_rs1
s_dg_rs1(m,i) = s_dg_bb(1,(i-1)*D+m);
end
end
s_dg_rs1 = flipud(s_dg_rs1);
% Circular shifting
s_dg_rs2 = s_dg_rs1;
ns_dg_rs2 = ns_dg_rs1;
% for i = 1:ns_dg_rs2
% s_dg_rs2(:,i) = flip((s_dg_bb((i-1)*D+1:(i-1)*D+M))');
% end
for i=1:ns_dg_rs2
for m=1:M
s_dg_rs2(m,i) = s_dg_rs1(1+mod( (m-1) + mod((i-1)*D,M) ,M),i);
end
end
% Apply polyphase filter
ns_pol = ns_dg_rs2-(nrows-1);
s_pol = zeros(M,ns_pol);
for m=1:M
s_pol(m,:) = conv(s_dg_rs2(m,:),Hdec0_pol(m,:),'valid');
end
s_pol = s_pol(:,5:end); % to fit with the VHDL sim vector
ns_pol = ns_pol-4;
s_pol_fi = fi(s_pol,1,19,10+floor(M/20)); % attention, M=20 => 11, M=10 => 10
s_pol = s_pol_fi.data;
% DFT
s_pol_dft = zeros(M,ns_pol);
if M == 10
s_pol_rearranged = [s_pol(1,:); s_pol(3,:); s_pol(5,:); s_pol(7,:); s_pol(9,:); s_pol(2,:); s_pol(4,:); s_pol(6,:); s_pol(8,:); s_pol(10,:)];
elseif M == 20
s_pol_rearranged = [s_pol(1,:); s_pol(5,:); s_pol(9,:); s_pol(13,:); s_pol(17,:); s_pol(3,:); s_pol(7,:); s_pol(11,:); s_pol(15,:); s_pol(19,:); s_pol(2,:); s_pol(6,:); s_pol(10,:); s_pol(14,:); s_pol(18,:); s_pol(4,:); s_pol(8,:); s_pol(12,:); s_pol(16,:); s_pol(20,:)];
end
%%
for i = 1:M/5
s_pol_dft(1+5*(i-1):5*i,:) = winograd5(s_pol_rearranged(1+5*(i-1):5*i,:), 8);
end
wn5 = fi(exp(-2*1i*pi*[0:4]/10), 1, Q2_1, Q2_1-2);
wn5 = wn5.data;
wn10 = fi(exp(-2*1i*pi*[0:9]/20), 1, Q2_2, Q2_2-2);
wn10 = wn10.data;
for i = 1:M/10
s_pol_dft(1+10*(i-1):10*i, :) = radix2(s_pol_dft(1+10*(i-1):10*i, :), wn5);
end
if M == 20
s_pol_dft = radix2(s_pol_dft, wn10);
end
% for i=1:ns_pol
% s_pol_dft(:,i) = fft(s_pol(:,i));
% end
%s_pol_dft(2:end, :) = flip(s_pol_dft(2:end, :));
% for i=1:ns_pol
% for p=1:M
% for m=1:M
% s_pol_dft(p,i) = s_pol_dft(p,i) + s_pol(m,i)*exponential(mod((m-1)*(p-1), M)+1);
% end
% end
% end
tb_input_temp = s_dg_bb*2^s_dg_bb_fi.FractionLength;
tb_input_temp = imag(tb_input_temp(:,M+1:end));
tb_input = zeros(1, length(tb_input_temp));
for i = 1:length(tb_input_temp)
% tb_input(2*i-1) = real(tb_input_temp(i));
tb_input(i) = tb_input_temp(i);
end
tb_output_temp1 = fi(s_pol_dft,1,Q3,Q3-2, 'RoundingMethod', 'Floor');
tb_output_temp = tb_output_temp1.data*2^(tb_output_temp1.FractionLength);
tb_output_temp = reshape(tb_output_temp(6,:), 1, size(tb_output_temp(1,:),1)*size(tb_output_temp(1,:),2));
tb_output = zeros(1, 2*length(tb_output_temp));
for i = 1:length(tb_output_temp)
tb_output(2*i-1) = real(tb_output_temp(i));
tb_output(2*i) = imag(tb_output_temp(i));
end
%% Sub-band Selection
sb_nbr = 9;
%
% if sb_nbr < M/2
% s_pol_sel = s_pol_dft(sb_nbr+1,:)+conj(s_pol_dft(M-sb_nbr+1,:));
% elseif sb_nbr == M/2
% s_pol_sel = s_pol_dft(sb_nbr+1,:);
% if sb_nbr < M
% s_pol_sel = -1i*s_pol_dft(sb_nbr+1,:)+conj(-1i*s_pol_dft(M-sb_nbr+1,:));
% elseif sb_nbr == M
% s_pol_sel = s_pol_dft(1,:);
% end
s_pol_sel = s_pol_dft(sb_nbr,:);
% s_pol_sel = s_pol_dft(sb_nbr+1,:)+conj(s_pol_dft(M-sb_nbr+1,:));
% s_pol_sel = -1i*s_pol_dft(sb_nbr+1,:)+conj(-1i*s_pol_dft(M-sb_nbr+1,:));
s_pol_sel=s_pol_sel.*exp(-1i*pi*[1:ns_pol])/2;
win = hanning(ns_pol);
if average == 0
[PSD, FREQ] = periodogram(s_pol_sel,win,ns_pol,(fs)/D);
else
[PSD, FREQ] = pwelch(s_pol_sel,floor(ns_pol/100),[],ns_pol,(fs)/D);
end
figure;
MAX = max(10*log(PSD));
plot(FREQ/1e9, 10*log(PSD)-MAX);
title('Complex output signal');
xlim([0,(fs)/D/1e9]);
grid on;
%% Printf
demux = M;
file_folder = strcat(pwd, '/tb_txts_files');
write_file(tb_input, strcat(file_folder, '/input.txt'), 80, ' %3d');
write_file(tb_output, strcat(file_folder, '/output.txt'), 20, ' %3d');
gen_Wn_coeffs_5ndft(M, Q2_2, strcat(file_folder, '/coeffs_dft.vhd'));
write_polyfir_coeffs(strcat(file_folder, '/coeffs_fir.vhd'), tb_coeff);

+ 18
- 0
matlab/winograd5.m View File

@@ -0,0 +1,18 @@
function output = winograd55(input, w)
in = [input(1,:); input(4,:); input(5,:); input(3,:); input(2,:)];
s1 = [in(1,:); in(2,:)+in(4,:); in(3,:)+in(5,:); in(2,:)-in(4,:); in(5,:)-in(3,:)];
s2 = [s1(1,:); s1(2,:)+s1(3,:); s1(3,:)-s1(2,:); s1(4,:); s1(5,:); s1(4,:)+s1(5,:)];
mult = [1 (cos(2*pi/5)+cos(4*pi/5))/2-1 (cos(2*pi/5)-cos(4*pi/5))/2 sin(2*pi/5)-sin(4*pi/5) sin(2*pi/5)+sin(4*pi/5) sin(4*pi/5)];
mult = fi(mult, 1, w, w-2);
mult = mult.data;
s4 = [s2(1,:)+s2(2,:); s2(2,:)*mult(2); s2(3,:)*mult(3); s2(4,:)*1i*mult(4); s2(5,:)*1i*mult(5); s2(6,:)*1i*mult(6)];
s5 = [s4(1,:); s4(1,:)+s4(2,:); s4(3,:); s4(4,:); s4(5,:); s4(6,:)];
s6 = [s5(1,:); s5(2,:)-s5(3,:); s5(2,:)+s5(3,:); s5(4,:)+s5(6,:); s5(6,:)-s5(5,:)];
output = [s6(1,:); s6(3,:)+s6(5,:); s6(2,:)-s6(4,:); s6(2,:)+s6(4,:); s6(3,:)-s6(5,:)];
end
function output = radix2(input, w)
s1 = [input(1) input(2)*w];
output = [s1(1)+s1(2) s1(1)-s1(2)];
end

+ 11
- 0
matlab/write_file.m View File

@@ -0,0 +1,11 @@
function write_file(input, file, nb_words_per_line, words_format)
input_format = '';
for i=1:nb_words_per_line
input_format = strcat(input_format,words_format);
end
input_format = strcat(input_format,'\n');
fin = fopen(file,'w');
fprintf(fin,input_format,input);
fclose(fin);
end

+ 13
- 0
matlab/write_polyfir_coeffs.m View File

@@ -0,0 +1,13 @@
function write_polyfir_coeffs(file, coeffs)
coeff_format = 'library ieee;\nUSE ieee.std_logic_1164.all;\nUSE work.POLY_FIR_PKG.all;\npackage coeff_fir is\n CONSTANT fir_coeffs_generated : vect_polyfir_coeffs_in := (';
for i=1:(length(coeffs)-1)
coeff_format = strcat(coeff_format,'X"%02x", ');
end
coeff_format = strcat(coeff_format,'X"%02x");\nend package coeff_fir;');
fcoeff = fopen(file,'w');
fprintf(fcoeff,coeff_format,typecast(int8(coeffs),'uint8'));
fclose(fcoeff);
end

+ 34
- 0
polyphase_filter/add_blk.vhd View File

@@ -0,0 +1,34 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE work.POLY_FIR_PKG.ALL;
ENTITY add_blk IS
GENERIC(w_out : IN natural);
PORT(i_clk : IN std_logic;
i_data1 : IN smpl_adder_generic;
i_data2 : IN smpl_adder_generic;
o_data : OUT smpl_fir_adder_data_out := (OTHERS => '0')
);
END add_blk;
ARCHITECTURE add OF add_blk IS
SIGNAL smpl_stages_out : smpl_adder_generic := (OTHERS => '0');
BEGIN -- ARCHITECTURE add
-- purpose: creates the add process for the adding tree
-- type : sequential
-- inputs : i_clk, i_data1, i_data2
-- outputs: o_data
adding_process : PROCESS (i_clk) IS
BEGIN -- PROCESS adding_process
IF rising_edge(i_clk) THEN -- rising clock edge
smpl_stages_out(w_out DOWNTO 0) <= std_logic_vector(unsigned(signed(i_data1(w_out-1)&i_data1(w_out-1 DOWNTO 0))+signed(i_data2(w_out-1)&i_data2(w_out-1 DOWNTO 0))));
END IF;
END PROCESS adding_process;
o_data <= smpl_stages_out;
END ARCHITECTURE add;

+ 45
- 0
polyphase_filter/mult_blk.vhd View File

@@ -0,0 +1,45 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE work.POLY_FIR_PKG.ALL;
ENTITY MULT_BLK IS
PORT(i_clk : IN std_logic;
i_data : IN vect_fir_data_in;
i_coeffs : IN vect_fir_coeffs_in;
o_data : OUT vect_mult_data_out := (OTHERS => (OTHERS =>'0'))
);
END MULT_BLK;
ARCHITECTURE Mult_Path OF MULT_BLK IS
SIGNAL data_mult_signed : vect_mult_data_out_signed := (OTHERS => (OTHERS => '0'));
SIGNAL coeffs_signed : vect_mult_coeffs_signed := (OTHERS => (OTHERS => '0'));
SIGNAL data_signed : vect_data_mult_in_signed := (OTHERS => (OTHERS => '0'));
BEGIN
-- purpose: wiring: cast the i_data and i_coeffs into signed
cast : FOR i IN 0 TO cst_nb_coeffs_subfilter_in-1 GENERATE
data_signed(i) <= signed(i_data(i));
coeffs_signed(i) <= signed(i_coeffs(i));
END GENERATE cast;
-- purpose: calculate and send cast result to output
mult : PROCESS(i_clk)
BEGIN
IF rising_edge(i_clk) THEN
FOR i IN 0 TO cst_nb_coeffs_subfilter_in-1 LOOP
data_mult_signed(i) <= data_signed(i) * coeffs_signed(i);
END LOOP;
END IF;
END PROCESS;
o_data_wiring: FOR i IN 0 TO cst_nb_coeffs_subfilter_in-1 GENERATE
o_data(i) <= std_logic_vector(unsigned(data_mult_signed(i)));
END GENERATE o_data_wiring;
END Mult_Path;

+ 85
- 0
polyphase_filter/partial_fir.vhd View File

@@ -0,0 +1,85 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE work.POLY_FIR_PKG.ALL;
ENTITY PARTIAL_FIR IS
PORT(i_clk : IN std_logic;
i_coeffs : IN vect_fir_coeffs_in;
i_data : IN vect_fir_data_in;
o_data : OUT smpl_fir_adder_data_out := (OTHERS => '0')
);
END PARTIAL_FIR;
ARCHITECTURE Adder_Tree OF PARTIAL_FIR IS
SIGNAL matrix_adder_tree : matrix_adder_generic := (OTHERS => (OTHERS => (OTHERS => '0')));
--SIGNAL matrix_adder_tree_signed : matrix_adder_generic_signed := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL vect_i_coeffs : vect_fir_coeffs_in := (OTHERS => (OTHERS => '0'));
SIGNAL mult_out : vect_mult_data_out := (OTHERS => (OTHERS => '0'));
BEGIN
-- purpose: assign the filter in a decreasing order
in_assignment : FOR i IN 0 TO cst_nb_coeffs_subfilter_in-1 GENERATE
vect_i_coeffs(i) <= i_coeffs(cst_nb_coeffs_subfilter_in-1-i);
END GENERATE in_assignment;
-- instanciation of MULT_BLK(Mult_Path), multiplying each element from i_data
-- with the correct coefficient in vect_i_coeffs
mult_inst : ENTITY work.MULT_BLK(Mult_Path)
PORT MAP(i_clk => i_clk,
i_data => i_data,
i_coeffs => vect_i_coeffs,
o_data => mult_out
);
-- purpose: fill the input (which is the result of multiplication) of the addition tree matrix
-- inputs: mult_out
-- outputs: matrix_adder_tree(0)
mult_out_wire : FOR i IN 0 TO cst_nb_coeffs_subfilter_in-1 GENERATE
matrix_adder_tree(0)(i)(cst_w_mult_out-1 DOWNTO 0) <= mult_out(i)(cst_w_mult_out-1 DOWNTO 0);
END GENERATE mult_out_wire;
-- purpose: wiring: construct the adder tree. Construction:
--
-- 0-+--+----+->
-- 1/ / /
-- 2-+/ /
-- 3/ /
-- 4-+--+/
-- 5/ /
-- 6-+/
-- 7/
--
-- inputs: matrix_adder_tree(0)
-- outputs: matrix_adder_tree(cst_log2_adder_stages)
stages_loop : FOR stage IN 1 TO cst_log2_adder_stages GENERATE
cell_loops : FOR cell IN 0 TO 2**(cst_log2_adder_stages-stage)-1 GENERATE
add_inst : ENTITY work.add_blk(add)
GENERIC MAP(w_out => cst_w_mult_out+stage-1)
PORT MAP(i_clk => i_clk,
i_data1 => matrix_adder_tree(stage-1)((2**(stage-1))*2*cell),
i_data2 => matrix_adder_tree(stage-1)((2**(stage-1))*(2*cell+1)),
o_data => matrix_adder_tree(stage)((2**stage)*cell)
);
END GENERATE cell_loops;
END GENERATE stages_loop;
-- take the result when adder tree finished
o_data <= matrix_adder_tree(cst_log2_adder_stages)(0);
END Adder_Tree;

+ 70
- 0
polyphase_filter/poly_fir_blk.vhd View File

@@ -0,0 +1,70 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE work.POLY_FIR_PKG.ALL;
ENTITY poly_fir_blk IS
PORT (
i_clk : IN std_logic;
i_coeffs : IN vect_polyfir_coeffs_in;
i_data : IN vect_adc_data_out;
o_data : OUT matrix_fir_data_out := (OTHERS => (OTHERS => (OTHERS => '0')))
);
END ENTITY poly_fir_blk;
ARCHITECTURE polyphase OF poly_fir_blk IS
SIGNAL matrix3D_reg_out_simple_rif_in : matrix3D_reg_data_out := (OTHERS => (OTHERS => (OTHERS => (OTHERS => '0'))));
SIGNAL matrix_coeffs : matrix_fir_coeffs_in := (OTHERS => (OTHERS => (OTHERS => '0')));
SIGNAL matrix_fir_out : matrix_fir_data_out := (OTHERS => (OTHERS => (OTHERS => '0')));
BEGIN -- ARCHITECTURE polyphase
--purpose: fill the polyphase coefficients into a 2D matrix from the filter vector (1D)
fill_coeff : PROCESS(i_coeffs) -- rearrange coeffs into a matrix
VARIABLE coeff_nb : natural;
VARIABLE sf_coeff : natural;
VARIABLE subfilter_nb : natural;
BEGIN
coeff_nb := 0;
sf_coeff := 0;
subfilter_nb := 0;
coeff_for_matrix : FOR coeff_nb IN 0 TO cst_nb_coeffs_filter_in-1 LOOP
matrix_coeffs(subfilter_nb)(sf_coeff) <= i_coeffs(coeff_nb);
subfilter_nb := subfilter_nb+1;
IF (subfilter_nb = cst_nb_subfilters) THEN
sf_coeff := sf_coeff+1;
subfilter_nb := 0;
END IF;
END LOOP coeff_for_matrix;
END PROCESS fill_coeff;
-- instanciation of the shift-reg for polyphasd filter
shift_reg_inst : ENTITY work.POLY_SHIFT_REG(Fill_Matrix)
PORT MAP (i_clk => i_clk,
i_data => i_data,
o_data => matrix3D_reg_out_simple_rif_in
);
wires_inst : ENTITY work.tree_firs(wires)
PORT MAP(
i_clk => i_clk,
i_matrix3D_reg_out => matrix3D_reg_out_simple_rif_in,
i_coeffs => matrix_coeffs,
o_data => matrix_fir_out
);
o_data <= matrix_fir_out;
END ARCHITECTURE polyphase;

+ 37
- 0
polyphase_filter/poly_fir_blk__wires.vhd View File

@@ -0,0 +1,37 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE work.POLY_FIR_PKG.ALL;
ENTITY tree_firs IS
PORT (
i_clk : IN std_logic;
i_matrix3D_reg_out : IN matrix3D_reg_data_out;
i_coeffs : IN matrix_fir_coeffs_in;
o_data : OUT matrix_fir_data_out := (OTHERS => (OTHERS => (OTHERS => '0')))
);
END ENTITY tree_firs;
ARCHITECTURE wires OF tree_firs IS
BEGIN
-- instanciation of the cst_nb_subfilters subfilters
simple_fir_inst_loop : FOR i IN 0 TO cst_nb_subfilters-1 GENERATE
simple_fir_inst : ENTITY work.TREE_FIR(Simple_Fir)
PORT MAP(i_clk => i_clk,
i_coeffs => i_coeffs(i),
i_data => i_matrix3D_reg_out(i),
o_data => o_data(i)
);
END GENERATE simple_fir_inst_loop;
END ARCHITECTURE wires;

+ 200
- 0
polyphase_filter/poly_fir_pkg.vhd View File

@@ -0,0 +1,200 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.std_logic_signed.ALL;
PACKAGE POLY_FIR_PKG IS
-- NOTES and PACKAGE INSTRUCTIONS :
-- cst_downsampling_factor must be a multiplier OF cst_nb_samples_adc_in
-- and cst_nb_subfilters/cst_nb_samples_adc_in*cst_downsampling_factor must be an integer
-- with cst_downsampling_factor < or = cst_nb_subfilters.
--
-- INPUT : vector of samples (cst_nb_samples_adc_in samples);
-- OUTPUT : 2D matrix of samples (matrix_fir_data_out(y)(x), with y the
-- subfilter number, and x the xth parallel fir);
--
-- the lower parallel fir, the older result.
FUNCTION log2_sup_integer (number : natural) RETURN natural;
FUNCTION log2_inf_integer (number : natural) RETURN natural;
-- -- CONSTANTS -- --
-- ADC
CONSTANT cst_w_in : natural := 6; -- ADC in bitwidth
CONSTANT cst_nb_samples_adc_in : natural := 80; -- ADC in nb samples
-- FILTER
--coefficients
CONSTANT cst_w_coeff : natural := 8; -- coeffs bitwidth
CONSTANT cst_nb_coeffs_filter_in : natural := 7*20;
CONSTANT cst_log2_sup_nb_coeffs_subfilter_in : natural := 3;
-- FIR
CONSTANT cst_downsampling_factor : natural := 8;
-- POLYPHASE FILTER
CONSTANT cst_nb_subfilters : natural := 20;
-- -- CALCULATIONS -- --
CONSTANT cst_w_out : natural := cst_w_in + cst_w_coeff+cst_log2_sup_nb_coeffs_subfilter_in;
-- SHIFT REG
CONSTANT cst_nb_coeffs_subfilter_in : natural := cst_nb_coeffs_filter_in/cst_nb_subfilters;
CONSTANT cst_nb_samples_shiftreg_temp_in : natural := cst_nb_coeffs_subfilter_in + cst_nb_samples_adc_in/cst_downsampling_factor;
-- mult
CONSTANT cst_w_mult_out : natural := cst_w_coeff+cst_w_in;
-- adder
CONSTANT cst_log2_adder_stages : natural := cst_log2_sup_nb_coeffs_subfilter_in;
-- fir
CONSTANT cst_w_fir_adder_out : natural := cst_w_mult_out+cst_log2_adder_stages;
CONSTANT cst_nb_parallel_firs : natural := cst_nb_samples_adc_in/cst_downsampling_factor;
-- TYPES
-- ADC
SUBTYPE smpl_adc_data_in IS std_logic_vector(cst_w_in-1 DOWNTO 0);
SUBTYPE smpl_fir_data_out IS std_logic_vector(cst_w_out-1 DOWNTO 0);
-- SHIFT REG
TYPE vect_adc_data_out IS ARRAY (0 TO cst_nb_samples_adc_in-1) OF smpl_adc_data_in;
TYPE vect_fir_data_in IS ARRAY(0 TO cst_nb_coeffs_subfilter_in-1) OF smpl_adc_data_in;
TYPE vect_reg_data IS ARRAY(0 TO cst_nb_samples_shiftreg_temp_in-1) OF smpl_adc_data_in;
TYPE matrix_reg_data IS ARRAY(0 TO cst_nb_subfilters-1) OF vect_reg_data;
TYPE matrix_reg_data_out IS ARRAY(0 TO cst_nb_parallel_firs-1) OF vect_fir_data_in;
TYPE matrix3D_reg_data_out IS ARRAY (0 TO cst_nb_subfilters-1) OF matrix_reg_data_out;
-- FILTER
SUBTYPE smpl_coeff IS std_logic_vector(cst_w_coeff-1 DOWNTO 0);
-- mult
SUBTYPE smpl_mult_data_out IS std_logic_vector(cst_w_mult_out-1 DOWNTO 0);
SUBTYPE smpl_mult_data_out_signed IS signed(cst_w_mult_out-1 DOWNTO 0);
SUBTYPE smpl_coeffs_signed IS signed(cst_w_coeff-1 DOWNTO 0);
SUBTYPE smpl_mult_data_in_signed IS signed(cst_w_in-1 DOWNTO 0);
TYPE vect_polyfir_coeffs_in IS ARRAY (0 TO cst_nb_coeffs_filter_in-1) OF smpl_coeff;
TYPE vect_data_mult_in_signed IS ARRAY(0 TO cst_nb_coeffs_subfilter_in-1) OF smpl_mult_data_in_signed;
TYPE vect_fir_coeffs_in IS ARRAY(0 TO cst_nb_coeffs_subfilter_in-1) OF smpl_coeff;
TYPE vect_mult_coeffs_signed IS ARRAY(0 TO cst_nb_coeffs_subfilter_in-1) OF smpl_coeffs_signed;
TYPE vect_mult_data_out IS ARRAY(0 TO cst_nb_coeffs_subfilter_in-1) OF smpl_mult_data_out;
TYPE vect_mult_data_out_signed IS ARRAY(0 TO cst_nb_coeffs_subfilter_in-1) OF smpl_mult_data_out_signed;
TYPE matrix_fir_coeffs_in IS ARRAY (0 TO cst_nb_subfilters-1) OF vect_fir_coeffs_in;
-- adder
SUBTYPE smpl_adder_generic IS std_logic_vector(cst_w_fir_adder_out-1 DOWNTO 0);
SUBTYPE smpl_adder_generic_signed IS signed(cst_w_fir_adder_out-1 DOWNTO 0);
TYPE vect_adder_generic IS ARRAY(0 TO 2**(cst_log2_adder_stages)-1) OF smpl_adder_generic;
TYPE vect_adder_generic_signed IS ARRAY(0 TO 2**(cst_log2_adder_stages)-1) OF smpl_adder_generic_signed;
TYPE matrix_adder_generic IS ARRAY(0 TO cst_log2_adder_stages) OF vect_adder_generic;
TYPE matrix_adder_generic_signed IS ARRAY(0 TO cst_log2_adder_stages) OF vect_adder_generic_signed;
-- fir
SUBTYPE smpl_fir_adder_data_out IS std_logic_vector(cst_w_fir_adder_out-1 DOWNTO 0);
TYPE vect_fir_adder_data_out IS ARRAY (0 TO cst_nb_parallel_firs-1) OF smpl_fir_adder_data_out;
TYPE vect_fir_data_out IS ARRAY(0 TO cst_nb_parallel_firs-1) OF smpl_fir_data_out;
-- POLYPHASE FILTER
TYPE matrix_fir_data_out IS ARRAY (0 TO cst_nb_subfilters-1) OF vect_fir_data_out;
-- TYPE matrix_coeffs_polyphase_filter IS array(0 to cst_nb_subfilters) OF vect_mult_coeffs;
END;
PACKAGE BODY POLY_FIR_PKG IS
--functions
FUNCTION log2_sup_integer (number : natural) RETURN natural IS
VARIABLE result : natural;
BEGIN
IF(number <= 1) THEN
result := 0;
ELSIF(number = 2) THEN
result := 1;
ELSIF(number > 2 AND number <= 4) THEN
result := 2;
ELSIF(number > 4 AND number <= 8) THEN
result := 3;
ELSIF(number > 8 AND number <= 16) THEN
result := 4;
ELSIF(number > 16 AND number <= 32) THEN
result := 5;
ELSIF(number > 32 AND number <= 64) THEN
result := 6;
ELSIF(number > 64 AND number <= 128) THEN
result := 7;
ELSIF(number > 128 AND number <= 256) THEN
result := 8;
ELSIF(number > 256 AND number <= 512) THEN
result := 9;
ELSIF(number > 512 AND number <= 1024) THEN
result := 10;
ELSIF(number > 1024 AND number <= 2048) THEN
result := 11;
ELSIF(number > 2048 AND number <= 4096) THEN
result := 12;
ELSIF(number > 4096 AND number <= 8192) THEN
result := 13;
ELSIF(number > 8192 AND number <= 16384) THEN
result := 14;
ELSIF(number > 16384 AND number <= 32768) THEN
result := 15;
END IF;
RETURN result;
END FUNCTION;
FUNCTION log2_inf_integer (number : natural) RETURN natural IS
VARIABLE result : natural;
BEGIN
IF(number < 2) THEN
result := 0;
ELSIF(number >= 2 AND number < 4) THEN
result := 1;
ELSIF(number >= 4 AND number < 8) THEN
result := 2;
ELSIF(number >= 8 AND number < 16) THEN
result := 3;
ELSIF(number >= 16 AND number < 32) THEN
result := 4;
ELSIF(number >= 32 AND number < 64) THEN
result := 5;
ELSIF(number >= 64 AND number < 128) THEN
result := 6;
ELSIF(number >= 128 AND number < 256) THEN
result := 7;
ELSIF(number >= 256 AND number < 512) THEN
result := 8;
ELSIF(number >= 512 AND number < 1024) THEN
result := 9;
ELSIF(number >= 1024 AND number < 2048) THEN
result := 10;
ELSIF(number >= 2048 AND number < 4096) THEN
Result := 11;
ELSIF(Number >= 4096 AND number < 8192) THEN
result := 12;
ELSIF(number >= 8192 AND number < 16384) THEN
result := 13;
ELSIF(number >= 16384 AND number < 32768) THEN
result := 14;
END IF;
RETURN result;
END FUNCTION;
END PACKAGE BODY;

+ 79
- 0
polyphase_filter/poly_shift_reg2.vhd View File

@@ -0,0 +1,79 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE work.POLY_FIR_PKG.ALL;
ENTITY POLY_SHIFT_REG IS
PORT(i_clk : IN std_logic;
i_data : IN vect_adc_data_out;
o_data : OUT matrix3D_reg_data_out := (OTHERS => (OTHERS => (OTHERS => (OTHERS => '0'))))
);
END POLY_SHIFT_REG;
ARCHITECTURE Fill_Matrix OF POLY_SHIFT_REG IS
TYPE vect_i_data_temp IS ARRAY (0 TO cst_nb_subfilters-1) OF smpl_adc_data_in;
TYPE matrix_i_data_temp IS ARRAY (0 TO 1) OF vect_i_data_temp;
SIGNAL data_matrix : matrix3D_reg_data_out := (OTHERS => (OTHERS => (OTHERS => (OTHERS => '0'))));
--SIGNAL data_temp : vect_reg_data := (OTHERS =>(OTHERS => '0'));
SIGNAL data_temp : matrix_reg_data := (OTHERS => (OTHERS => (OTHERS => '0')));
--VARIABLE reg_i_data_temp : vect_i_data_temp := (OTHERS => (OTHERS => '0'));
BEGIN
-- purpose: fill a 3D matrix from a register. Each row is the input of the
-- input of a partial filter; each 2D matrix rows-columns is the input for a
-- subfilter
-- inputs: reg_i_data_temp, i_data
-- outputs: data_temp (3D matrix of std_logic_vectors)
PROCESS (i_clk) IS
VARIABLE subfilter_nb : natural := 0;
VARIABLE data_subfilter_nb : natural := 0;
VARIABLE reg_i_data_temp : matrix_i_data_temp;
BEGIN -- PROCESS
IF rising_edge(i_clk) THEN -- rising clock edge
-- shifting the old samples towards data_temp(0)
FOR i IN 0 TO cst_nb_subfilters-1 LOOP
data_temp(i)(0 TO cst_nb_samples_shiftreg_temp_in-cst_nb_parallel_firs-1) <= data_temp(i)(cst_nb_parallel_firs TO cst_nb_samples_shiftreg_temp_in-1);
END LOOP; -- i
-- fill a temp 2D matrix for each subfilter (equivalent to filling a temp
-- vector for 1 filter)
parallel_fir_for : FOR parallel_fir_nb IN 0 TO cst_nb_parallel_firs-1 LOOP
FOR i IN 0 TO cst_nb_subfilters-1 LOOP
reg_i_data_temp(1) := reg_i_data_temp(0);
END LOOP;
fill_previous_content : FOR data_nb IN cst_downsampling_factor TO cst_nb_subfilters-1 LOOP
data_temp(cst_nb_subfilters-1-((cst_downsampling_factor*parallel_fir_nb+data_nb) MOD cst_nb_subfilters))(cst_nb_samples_shiftreg_temp_in-cst_nb_parallel_firs+parallel_fir_nb) <= reg_i_data_temp(1)(cst_nb_subfilters-1-((cst_downsampling_factor*parallel_fir_nb+data_nb) MOD cst_nb_subfilters));
END LOOP fill_previous_content; -- data_nb
fill_data_temp : FOR data_nb IN 0 TO cst_downsampling_factor-1 LOOP -- fill data
data_temp(cst_nb_subfilters-1-((cst_downsampling_factor*parallel_fir_nb+data_nb) MOD cst_nb_subfilters))(cst_nb_samples_shiftreg_temp_in-cst_nb_parallel_firs+parallel_fir_nb) <= i_data(cst_downsampling_factor*parallel_fir_nb+data_nb);
reg_i_data_temp(0)(cst_nb_subfilters-1-((cst_downsampling_factor*parallel_fir_nb+data_nb) MOD cst_nb_subfilters)) := i_data(cst_downsampling_factor*parallel_fir_nb+data_nb);
END LOOP fill_data_temp;
END LOOP parallel_fir_for; -- parallel_fir_nb
o_data <= data_matrix;
END IF;
END PROCESS;
-- purpose: wiring (filling the 3D out matrix) for each line, for each subfilter
third_dimension : FOR subfilter_nb IN 0 TO cst_nb_subfilters-1 GENERATE
second_dimension : FOR parallel_fir IN 0 TO cst_nb_parallel_firs-1 GENERATE
first_dimension : FOR data_nb IN 0 TO cst_nb_coeffs_subfilter_in-1 GENERATE
data_matrix(subfilter_nb)(parallel_fir)(data_nb) <= data_temp(subfilter_nb)(data_nb+parallel_fir);
END GENERATE first_dimension; -- data_nb
END GENERATE second_dimension; -- parallel_fir
END GENERATE third_dimension; -- subfilter_nb
END Fill_Matrix;

+ 31
- 0
polyphase_filter/tree_fir.vhd View File

@@ -0,0 +1,31 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE work.POLY_FIR_PKG.ALL;
ENTITY TREE_FIR IS
PORT( i_clk : IN std_logic;
i_coeffs : IN vect_fir_coeffs_in;
i_data : IN matrix_reg_data_out;
o_data : OUT vect_fir_data_out := (OTHERS => (OTHERS => '0'))
);
END TREE_FIR;
ARCHITECTURE Simple_Fir OF TREE_FIR IS
SIGNAL partial_fir_out : vect_fir_adder_data_out := (OTHERS => (OTHERS => '0'));
BEGIN
-- purpose: wiring: instanciation of each partial FIR to make 1 FIR
partial_fir_for : FOR i IN 0 TO cst_nb_parallel_firs-1 GENERATE
partial_fir_inst : ENTITY work.PARTIAL_FIR(Adder_Tree)
PORT MAP( i_clk => i_clk,
i_coeffs => i_coeffs,
i_data => i_data(i),
o_data => partial_fir_out(i)
);
o_data(i)<= partial_fir_out(i)(cst_w_fir_adder_out-1 DOWNTO cst_w_fir_adder_out-cst_w_out);
END GENERATE partial_fir_for;
END Simple_Fir;

+ 8
- 0
tb_txt_files/coeffs_dft.vhd View File

@@ -0,0 +1,8 @@
library ieee;
USE ieee.std_logic_1164.all;
USE work.FIVEn_DFT_PKG.all;
package coeff_5ndft is
TYPE vect_cos_sin_k_pi_over_n_wb IS ARRAY (0 TO cst_nb_wn_coeffs-1) OF smpl_cos_sin_wb ;
CONSTANT cos_k_pi_over_n_wb : vect_cos_sin_k_pi_over_n_wb := ("01000000","00111101","00110100","00100110","00010100","00000000","11101100","11011010","11001100","11000011");
CONSTANT sin_k_pi_over_n_wb : vect_cos_sin_k_pi_over_n_wb := ("00000000","11101100","11011010","11001100","11000011","11000000","11000011","11001100","11011010","11101100");
end package coeff_5ndft;

+ 6
- 0
tb_txt_files/coeffs_fir.vhd View File

@@ -0,0 +1,6 @@
library ieee;
USE ieee.std_logic_1164.all;
USE work.POLY_FIR_PKG.all;
package coeff_fir is
CONSTANT fir_coeffs_generated : vect_polyfir_coeffs_in := (X"04",X"00",X"00",X"00",X"00",X"00",X"ff",X"ff",X"ff",X"fe",X"fe",X"fe",X"fd",X"fd",X"fc",X"fc",X"fb",X"fb",X"fa",X"fa",X"f9",X"f9",X"f9",X"f8",X"f8",X"f8",X"f7",X"f7",X"f7",X"f8",X"f8",X"f8",X"f9",X"f9",X"fa",X"fb",X"fc",X"fe",X"ff",X"01",X"02",X"04",X"07",X"09",X"0b",X"0e",X"10",X"13",X"16",X"19",X"1c",X"1f",X"22",X"25",X"27",X"2a",X"2d",X"30",X"32",X"35",X"37",X"39",X"3b",X"3d",X"3f",X"40",X"41",X"42",X"42",X"42",X"42",X"42",X"42",X"41",X"40",X"3f",X"3d",X"3b",X"39",X"37",X"35",X"32",X"30",X"2d",X"2a",X"27",X"25",X"22",X"1f",X"1c",X"19",X"16",X"13",X"10",X"0e",X"0b",X"09",X"07",X"04",X"02",X"01",X"ff",X"fe",X"fc",X"fb",X"fa",X"f9",X"f9",X"f8",X"f8",X"f8",X"f7",X"f7",X"f7",X"f8",X"f8",X"f8",X"f9",X"f9",X"f9",X"fa",X"fa",X"fb",X"fb",X"fc",X"fc",X"fd",X"fd",X"fe",X"fe",X"fe",X"ff",X"ff",X"ff",X"00",X"00",X"00",X"00",X"00",X"04");
end package coeff_fir;

+ 24987
- 0
tb_txt_files/output.txt
File diff suppressed because it is too large
View File


+ 13
- 0
utils/simu_pkg.vhd View File

@@ -0,0 +1,13 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE work.PFB_PKG.ALL;
PACKAGE simu_pkg IS
TYPE donnee_sortie IS ARRAY (0 TO 2*cst_nb_parallel_firs_dfts_pfb-1) OF integer;
CONSTANT w_x_simu : natural := 4;
END;

+ 95
- 0
utils/used_functions_pkg.vhd View File

@@ -0,0 +1,95 @@
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_signed.ALL;
USE ieee.numeric_std.ALL;
PACKAGE used_functions_pkg IS
FUNCTION log2_sup_integer (number : natural) RETURN natural;
FUNCTION log2_inf_integer (number : natural) RETURN natural;
END PACKAGE;
PACKAGE BODY used_functions_pkg IS
--functions
FUNCTION log2_sup_integer (number : natural) RETURN natural IS
VARIABLE result : natural;
BEGIN
IF(number <= 1) THEN
result := 0;
ELSIF(number = 2) THEN
result := 1;
ELSIF(number > 2 AND number <= 4) THEN
result := 2;
ELSIF(number > 4 AND number <= 8) THEN
result := 3;
ELSIF(number > 8 AND number <= 16) THEN
result := 4;
ELSIF(number > 16 AND number <= 32) THEN
result := 5;
ELSIF(number > 32 AND number <= 64) THEN
result := 6;
ELSIF(number > 64 AND number <= 128) THEN
result := 7;
ELSIF(number > 128 AND number <= 256) THEN
result := 8;
ELSIF(number > 256 AND number <= 512) THEN
result := 9;
ELSIF(number > 512 AND number <= 1024) THEN
result := 10;
ELSIF(number > 1024 AND number <= 2048) THEN
result := 11;
ELSIF(number > 2048 AND number <= 4096) THEN
result := 12;
ELSIF(number > 4096 AND number <= 8192) THEN
result := 13;
ELSIF(number > 8192 AND number <= 16384) THEN
result := 14;
ELSIF(number > 16384 AND number <= 32768) THEN
result := 15;
END IF;
RETURN result;
END FUNCTION;
FUNCTION log2_inf_integer (number : natural) RETURN natural IS
VARIABLE result : natural;
BEGIN
IF(number < 2) THEN
result := 0;
ELSIF(number >= 2 AND number < 4) THEN
result := 1;
ELSIF(number >= 4 AND number < 8) THEN
result := 2;
ELSIF(number >= 8 AND number < 16) THEN
result := 3;
ELSIF(number >= 16 AND number < 32) THEN
result := 4;
ELSIF(number >= 32 AND number < 64) THEN
result := 5;
ELSIF(number >= 64 AND number < 128) THEN
result := 6;
ELSIF(number >= 128 AND number < 256) THEN
result := 7;
ELSIF(number >= 256 AND number < 512) THEN
result := 8;
ELSIF(number >= 512 AND number < 1024) THEN
result := 9;
ELSIF(number >= 1024 AND number < 2048) THEN
result := 10;
ELSIF(number >= 2048 AND number < 4096) THEN
Result := 11;
ELSIF(Number >= 4096 AND number < 8192) THEN
result := 12;
ELSIF(number >= 8192 AND number < 16384) THEN
result := 13;
ELSIF(number >= 16384 AND number < 32768) THEN
result := 14;
END IF;
RETURN result;
END FUNCTION;
END PACKAGE BODY used_functions_pkg;

+ 33
- 0
utils/utils.vhd View File

@@ -0,0 +1,33 @@
-- *********************** Divers fonction utiles ***************************
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
PACKAGE utils IS
PROCEDURE horloge ( SIGNAL h: OUT std_logic; th, tb : time);
PROCEDURE horloge_retard ( SIGNAL h : OUT std_logic; periode : time ;
retard : time);
END utils;
---------------------------------------------------
PACKAGE BODY utils IS
PROCEDURE horloge ( SIGNAL h : OUT std_logic; th, tb : time) IS
BEGIN
LOOP
h <= '0', '1' AFTER tb;
WAIT FOR tb + th ;
END LOOP;
END;
PROCEDURE horloge_retard ( SIGNAL h : OUT std_logic; periode : time ;
retard : time) IS
BEGIN
h <= '0';
WAIT FOR retard;
LOOP
h <= '1' , '0' AFTER periode/2 ;
WAIT FOR periode;
END LOOP;
END;
END utils;

Loading…
Cancel
Save