VHDL implementation of a polyphase filter bank with polyphase filter and 5ndft
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

264 lines
15KB

  1. LIBRARY ieee;
  2. USE ieee.std_logic_1164.ALL;
  3. USE ieee.std_logic_signed.ALL;
  4. USE ieee.numeric_std.ALL;
  5. USE work.FIVEn_DFT_PKG.ALL;
  6. USE work.coeff_5ndft.ALL;
  7. ENTITY FFT_tree IS
  8. GENERIC(
  9. nb_bits_shift_round : IN natural);
  10. PORT(
  11. i_clk : IN std_logic;
  12. i_data_re : IN vect_dft_input;
  13. i_data_im : IN vect_dft_input;
  14. o_data_re : OUT vect_dft_output := (OTHERS => (OTHERS => '0'));
  15. o_data_im : OUT vect_dft_output := (OTHERS => (OTHERS => '0'))
  16. );
  17. END FFT_tree;
  18. ARCHITECTURE instanciating_cells OF FFT_tree IS
  19. SIGNAL zero : std_logic_vector(0 DOWNTO 0) := "0";
  20. SIGNAL cos_k_pi_over_5 : vect_cos_sin_k_pi_over_5_32b := ("01000000000000000000000000000000", "00110011110001101110111100110111", "00010011110001101110111100110111", "11101100001110010001000011001001", "11001100001110010001000011001001"); -- coeffs multiplied by 2^30
  21. SIGNAL sin_k_pi_over_5 : vect_cos_sin_k_pi_over_5_32b := ("00000000000000000000000000000000", "11011010011000011011100111110111", "11000011001000011110001111011001", "11000011001000011110001111011001", "11011010011000011011100111110111"); -- coeffs multiplied by 2^30
  22. -- purpose: give the proper arrangement for the winograd5 blks
  23. -- the right order: even numbers then odd numbers. The even numbers are the
  24. -- result of others even_odd order multiplied by 2, the odd numbers are the
  25. -- result of others even_odd order multiplied by 2+1.
  26. -- input: the nth winograd5 instance when sort
  27. -- output: the corresponding winograd5 instance number when sort
  28. FUNCTION rearrange (
  29. i : IN natural)
  30. RETURN natural IS
  31. TYPE vect_rearrange IS ARRAY (0 TO cst_nb_samples_in_5ndft) OF natural;
  32. TYPE matrix_rearrange IS ARRAY (0 TO cst_log2_nb_parallel_winograd5) OF vect_rearrange;
  33. VARIABLE matrix_affect_rearrange : matrix_rearrange := (OTHERS => (OTHERS => 0));
  34. BEGIN -- FUNCTION rearrange
  35. IF cst_log2_nb_parallel_winograd5 > 0 THEN
  36. matrix_affect_rearrange(1)(1) := 1;
  37. FOR stage IN 2 TO cst_log2_nb_parallel_winograd5 LOOP
  38. FOR i IN 0 TO 2**(stage-1)-1 LOOP
  39. matrix_affect_rearrange(stage)(i) := matrix_affect_rearrange(stage-1)(i)*2;
  40. matrix_affect_rearrange(stage)(i+2**(stage-1)) := matrix_affect_rearrange(stage-1)(i)*2+1;
  41. END LOOP; -- i
  42. END LOOP; -- stage
  43. RETURN matrix_affect_rearrange(cst_log2_nb_parallel_winograd5)(i);
  44. ELSE
  45. RETURN 0;
  46. END IF;
  47. END FUNCTION rearrange;
  48. TYPE matrix_input_winograd5_5ndft IS ARRAY (0 TO cst_nb_parallel_winograd5-1) OF vect_input_winograd5_5ndft;
  49. TYPE matrix_output_winograd5_5ndft IS ARRAY (0 TO cst_nb_parallel_winograd5-1) OF vect_output_winograd5_5ndft;
  50. SIGNAL cos_k_pi_over_5_wb : vect_cos_sin_k_pi_over_5_wb := (OTHERS => (OTHERS => '0'));
  51. SIGNAL sin_k_pi_over_5_wb : vect_cos_sin_k_pi_over_5_wb := (OTHERS => (OTHERS => '0'));
  52. SIGNAL data_out_winograd5_re : vect_total_output_winograd5_cells := (OTHERS => (OTHERS => '0'));
  53. SIGNAL data_out_winograd5_im : vect_total_output_winograd5_cells := (OTHERS => (OTHERS => '0'));
  54. SIGNAL winograd_rearranged_input_re : vect_dft_input := (OTHERS => (OTHERS => '0'));
  55. SIGNAL winograd_rearranged_input_im : vect_dft_input := (OTHERS => (OTHERS => '0'));
  56. SIGNAL matrix_inputs_outputs_radix2_cells_re : matrix_fft_stages := (OTHERS => (OTHERS => (OTHERS => '0')));
  57. SIGNAL matrix_inputs_outputs_radix2_cells_im : matrix_fft_stages := (OTHERS => (OTHERS => (OTHERS => '0')));
  58. SIGNAL vect_input_1_cell_winograd5_re : matrix_input_winograd5_5ndft := (OTHERS => (OTHERS => (OTHERS => '0')));
  59. SIGNAL vect_input_1_cell_winograd5_im : matrix_input_winograd5_5ndft := (OTHERS => (OTHERS => (OTHERS => '0')));
  60. SIGNAL vect_output_1_cell_winograd5_re : matrix_output_winograd5_5ndft := (OTHERS => (OTHERS => (OTHERS => '0')));
  61. SIGNAL vect_output_1_cell_winograd5_im : matrix_output_winograd5_5ndft := (OTHERS => (OTHERS => (OTHERS => '0')));
  62. BEGIN -- ARCHITECTURE instanciating_cells
  63. -- coeffs cut
  64. -- purpose: Rounds the data in 32bits into cst_w_precision_radix2_coeffs_5ndft bits (round for
  65. -- MSBs). Should run and cut before simulation and bitstream
  66. -- 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
  67. -- 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
  68. mult_coeffs_cut : PROCESS(sin_k_pi_over_5, cos_k_pi_over_5)
  69. BEGIN
  70. FOR i IN 0 TO 4 LOOP
  71. cos_k_pi_over_5_wb(i) <= cos_k_pi_over_5(i)(31 DOWNTO 32-cst_w_precision_radix2_coeffs_5ndft);
  72. sin_k_pi_over_5_wb(i) <= sin_k_pi_over_5(i)(31 DOWNTO 32-cst_w_precision_radix2_coeffs_5ndft);
  73. IF(cos_k_pi_over_5(i)(32-cst_w_precision_radix2_coeffs_5ndft-1) = '1') THEN
  74. 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));
  75. END IF;
  76. IF(sin_k_pi_over_5(i)(32-cst_w_precision_radix2_coeffs_5ndft-1) = '1') THEN
  77. 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));
  78. END IF;
  79. END LOOP; -- i
  80. END PROCESS mult_coeffs_cut;
  81. -- inputs rearranging
  82. -- purpose: affects inputs on their right way (cf. schema and explanations)
  83. -- using the rearrange(i) function, which creates the right winograd
  84. -- instances numbers order. Rearranging inputs order is equivalent to rearranging
  85. -- winograd5 order.
  86. -- inputs: i_data_re, i_data_im
  87. -- outputs: winograd_rearranged_input_re, winograd_rearranged_input_im
  88. rearrange_winograd_input : FOR i IN 0 TO cst_nb_parallel_winograd5-1 GENERATE
  89. five_inputs : FOR j IN 0 TO 4 GENERATE
  90. winograd_rearranged_input_re(rearrange(i => i)*5+j) <= i_data_re(j*cst_nb_parallel_winograd5+i);
  91. winograd_rearranged_input_im(rearrange(i => i)*5+j) <= i_data_im(j*cst_nb_parallel_winograd5+i);
  92. END GENERATE five_inputs;
  93. END GENERATE rearrange_winograd_input;
  94. -- winograd instanciating
  95. -- purpose: wiring; instanciates the parallel winograd stage with their correct inputs and outputs
  96. -- inputs: winograd_rearranged_input_im, winograd_rearranged_input_re (length
  97. -- cst_nb_samples_in_5ndft each, cut then into subvectors of 5 inputs)
  98. -- instances: WINOGRAD5(Behavioral)
  99. -- outputs: vect_output_1_cell_winograd5_im, vect_output_1_cell_winograd5_re
  100. -- (length cst_nb_samples_in_5ndft each, cut then into subvectors of 5 inputs)
  101. winograd5_instances : FOR i IN 0 TO cst_nb_parallel_winograd5-1 GENERATE
  102. fill_for : FOR j IN 0 TO 4 GENERATE
  103. vect_input_1_cell_winograd5_im(i)(j) <= winograd_rearranged_input_im(j+5*i);
  104. vect_input_1_cell_winograd5_re(i)(j) <= winograd_rearranged_input_re(j+5*i);
  105. data_out_winograd5_im(j+5*i) <= vect_output_1_cell_winograd5_im(i)(j);
  106. data_out_winograd5_re(j+5*i) <= vect_output_1_cell_winograd5_re(i)(j);
  107. END GENERATE fill_for;
  108. winograd5_inst : ENTITY work.WINOGRAD5(Behavioral)
  109. PORT MAP(
  110. i_clk => i_clk,
  111. i_data_im => vect_input_1_cell_winograd5_im(i),
  112. i_data_re => vect_input_1_cell_winograd5_re(i),
  113. o_data_im => vect_output_1_cell_winograd5_im(i),
  114. o_data_re => vect_output_1_cell_winograd5_re(i)
  115. );
  116. END GENERATE winograd5_instances;
  117. -- winograd results
  118. -- purpose: fill the 0th stage (input stage) of the matrix instanciating the
  119. -- butterfly (radix2) cells only.
  120. -- inputs: data_out_winograd5_re, data_out_winograd5_im
  121. -- outputs: matrix_inputs_outputs_radix2_cells_re(x)(0), matrix_inputs_outputs_radix2_cells_im(x)(0)
  122. fill_radix2_cells_input_matrix : FOR i IN 0 TO cst_nb_samples_in_5ndft-1 GENERATE
  123. matrix_inputs_outputs_radix2_cells_re(i)(0)(cst_winograd5_w_out_5ndft-1 DOWNTO 0) <= data_out_winograd5_re(i);
  124. matrix_inputs_outputs_radix2_cells_im(i)(0)(cst_winograd5_w_out_5ndft-1 DOWNTO 0) <= data_out_winograd5_im(i);
  125. END GENERATE fill_radix2_cells_input_matrix;
  126. -- purpose: instanciates the first butterfly cells stage (after the winograd
  127. -- results). If there is only 1 parallel winograd5 cell, couple_winograd5_nb
  128. -- will not be use between 0 and -1, so the FOR loop will no execute
  129. -- inputs: matrix_inputs_outputs_radix2_cells_re(x)(0), matrix_inputs_outputs_radix2_cells_im(x)(0)
  130. -- instances: radix_2_cell_winograd(radix2)
  131. -- outputs: matrix_inputs_outputs_radix2_cells_re(x)(1), matrix_inputs_outputs_radix2_cells_im(x)(1)
  132. radix2_cells_stage1 : FOR couple_winograd5_nb IN 0 TO cst_nb_parallel_winograd5/2-1 GENERATE
  133. radix2_winograd_out : FOR i IN 0 TO 4 GENERATE
  134. radix_2_out_winograd_inst : ENTITY work.radix_2_cell_winograd(radix2)
  135. GENERIC MAP(
  136. w_in => cst_winograd5_w_out_5ndft
  137. )
  138. PORT MAP(
  139. i_clk => i_clk,
  140. i_cos => cos_k_pi_over_5_wb(i MOD 5),
  141. i_sin => sin_k_pi_over_5_wb(i MOD 5),
  142. i_data1_re => matrix_inputs_outputs_radix2_cells_re(couple_winograd5_nb*10+i)(0),
  143. i_data1_im => matrix_inputs_outputs_radix2_cells_im(couple_winograd5_nb*10+i)(0),
  144. i_data2_re => matrix_inputs_outputs_radix2_cells_re(couple_winograd5_nb*10+i+5)(0),
  145. i_data2_im => matrix_inputs_outputs_radix2_cells_im(couple_winograd5_nb*10+i+5)(0),
  146. o_data1_re => matrix_inputs_outputs_radix2_cells_re(couple_winograd5_nb*10+i)(1),
  147. o_data1_im => matrix_inputs_outputs_radix2_cells_im(couple_winograd5_nb*10+i)(1),
  148. o_data2_re => matrix_inputs_outputs_radix2_cells_re(couple_winograd5_nb*10+i+5)(1),
  149. o_data2_im => matrix_inputs_outputs_radix2_cells_im(couple_winograd5_nb*10+i+5)(1)
  150. );
  151. END GENERATE radix2_winograd_out;
  152. END GENERATE radix2_cells_stage1;
  153. -- radix2 cells instanciation
  154. -- purpose: instanciates all the butterfly stages (except stage 1). The
  155. -- stages are filled decrementing the stage number
  156. -- inputs: matrix_inputs_outputs_radix2_cells_re(x)(1), matrix_inputs_outputs_radix2_cells_im(x)(1)
  157. -- instances: radix_2_cell_winograd(radix2)
  158. -- 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)
  159. stages_generation : FOR stage IN 1 TO cst_log2_nb_parallel_winograd5-1 GENERATE
  160. k10_blocks : FOR cell_10_nb IN 1 TO 2**(stage-1) GENERATE
  161. 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
  162. radix_2_generic_inst : ENTITY work.radix_2_cell_winograd(radix2)
  163. GENERIC MAP(
  164. w_in => cst_winograd5_w_out_5ndft+(cst_log2_nb_parallel_winograd5-stage)*cst_w_radix2_added
  165. )
  166. PORT MAP(
  167. i_clk => i_clk,
  168. 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),
  169. 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),
  170. i_data1_re => matrix_inputs_outputs_radix2_cells_re(cell_nb)(cst_log2_nb_parallel_winograd5-stage),
  171. i_data1_im => matrix_inputs_outputs_radix2_cells_im(cell_nb)(cst_log2_nb_parallel_winograd5-stage),
  172. i_data2_re => matrix_inputs_outputs_radix2_cells_re(cell_nb+(cst_nb_samples_in_5ndft/(2**stage)))(cst_log2_nb_parallel_winograd5-stage),
  173. i_data2_im => matrix_inputs_outputs_radix2_cells_im(cell_nb+(cst_nb_samples_in_5ndft/(2**stage)))(cst_log2_nb_parallel_winograd5-stage),
  174. o_data1_re => matrix_inputs_outputs_radix2_cells_re(cell_nb)(cst_log2_nb_parallel_winograd5-stage+1),
  175. o_data1_im => matrix_inputs_outputs_radix2_cells_im(cell_nb)(cst_log2_nb_parallel_winograd5-stage+1),
  176. 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),
  177. 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)
  178. );
  179. END GENERATE parallel_cells;
  180. END GENERATE k10_blocks;
  181. END GENERATE stages_generation;
  182. -- output results
  183. -- purpose: rounds the outputs to have cst_w_out_5ndft bits. Does not round
  184. -- if cst_w_out_5ndft = cst_dft_w_out_5ndft
  185. -- type : sequential
  186. -- inputs : i_clk, matrix_inputs_outputs_radix2_cells_re, matrix_inputs_outputs_radix2_cells_im
  187. -- outputs: o_data_re, i_data_im
  188. --output_rounding : PROCESS (i_clk) IS
  189. --BEGIN -- PROCESS output_rounding
  190. --IF rising_edge(i_clk) THEN -- rising clock edge
  191. rounding : FOR i IN 0 TO cst_nb_samples_in_5ndft-1 generate
  192. --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
  193. 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);
  194. --ELSE
  195. --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);
  196. --END IF;
  197. --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
  198. 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);
  199. --ELSE
  200. --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);
  201. --END IF;
  202. END GENERATE rounding; -- i
  203. --END IF;
  204. --END PROCESS output_rounding;
  205. -- if you prefer the whole result, uncomment this section and comment the
  206. -- output_rounding process above. You should also change smpl_out_5ndft from
  207. -- cst_w_out_5ndft to cst_dft_w_out_5ndft (line 32 in FIVEn_dft_pkg).
  208. --fill_outputs : FOR i IN 0 TO cst_nb_samples_in_5ndft-1 GENERATE
  209. -- o_data_re(i) <= matrix_inputs_outputs_radix2_cells_re(i)(cst_log2_nb_parallel_winograd5);
  210. -- o_data_im(i) <= matrix_inputs_outputs_radix2_cells_im(i)(cst_log2_nb_parallel_winograd5);
  211. --END GENERATE fill_outputs;
  212. END ARCHITECTURE instanciating_cells;