------------------------------------------------------------------------ -- fft_magnitude_calc -- -- calculation of FFT magnitude sqrt(real_part²+im_part²) -- Inputs: -- input_re in: +-1 signed Fixpoint (0.5=0x40000000, -0.5=0xC0000000 (negative numbers in 2K) -- input_im in: +-1 signed Fixpoint (0.5=0x40000000, -0.5=0xC0000000 (negative numbers in 2K) -- input_valid: high = inputs are valid for data processing -- Outputs -- output_magnitude: Fixpoint 0.5=0x40000000 (always positive) -- output_valid: high = magnitude data is valid ----------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library work; use work.task.all; use work.float.all; entity fft_magnitude_calc is port ( clk : in std_logic; reset : in std_logic; input_valid: in std_logic; input_re : in std_logic_vector( 31 downto 0 ); -- in Fixpoint input_im : in std_logic_vector( 31 downto 0 ); -- in Fixpoint output_valid : out std_logic; output_magnitude : out std_logic_vector( 31 downto 0 ) ); end entity fft_magnitude_calc; architecture rtl of fft_magnitude_calc is subtype Word_64 is std_logic_vector( 63 downto 0 ); type Array_64 is array ( natural range <> ) of Word_64; subtype Word_32 is std_logic_vector( 31 downto 0 ); type Array_32 is array ( natural range <> ) of Word_32; subtype Word_16 is std_logic_vector( 15 downto 0 ); type Array_16 is array ( natural range <> ) of Word_16; signal input_valid_stage1 : std_logic; signal re_multiply_re_stage1 : signed(63 downto 0); signal im_multiply_re_stage1 : signed(63 downto 0); signal input_valid_stage2 : std_logic; signal re2_add_im2 : signed(63 downto 0); signal input_valid_stage3 : std_logic; signal input_sqrt : Array_32( 0 to 16 ); signal output_sqrt: Array_16( 0 to 16 ); signal output_delay_sqrt: std_logic_vector(15 downto 0); signal data_memory : work.reg32.RegArray( 0 to 1023 ); signal index_sqrt : integer range 0 to 16; begin -- calculation of real_part² and im_part² p_pow2_stage1: process ( clk, reset ) is begin if ( reset = '1' ) then input_valid_stage1 <= '0'; re_multiply_re_stage1 <= (others => '0'); im_multiply_re_stage1 <= (others => '0'); elsif ( rising_edge( clk ) ) then input_valid_stage1 <= input_valid; if input_valid = '1' then re_multiply_re_stage1 <= signed(input_re) * signed(input_re); im_multiply_re_stage1 <= signed(input_im) * signed(input_im); end if; end if; end process p_pow2_stage1; -- calculation of real_part²*+im_part² p_add_stage2: process ( clk, reset ) is begin if ( reset = '1' ) then input_valid_stage2 <= '0'; re2_add_im2 <= (others => '0'); elsif ( rising_edge( clk ) ) then input_valid_stage2 <= input_valid_stage1; re2_add_im2 <= re_multiply_re_stage1 + im_multiply_re_stage1; end if; end process p_add_stage2; -- calculation of sqrt (one sqrt caluation needs 16 clks with G_DATA_W => 32 -- for continous stream 17 sqrt instances are needed p_sqrt_stage3: process ( clk, reset ) is begin if ( reset = '1' ) then input_valid_stage3 <= '0'; index_sqrt <= 0; input_sqrt(0) <= (others => '0'); input_sqrt(1) <= (others => '0'); input_sqrt(2) <= (others => '0'); input_sqrt(3) <= (others => '0'); input_sqrt(4) <= (others => '0'); input_sqrt(5) <= (others => '0'); input_sqrt(6) <= (others => '0'); input_sqrt(7) <= (others => '0'); input_sqrt(8) <= (others => '0'); input_sqrt(9) <= (others => '0'); input_sqrt(10) <= (others => '0'); input_sqrt(11) <= (others => '0'); input_sqrt(12) <= (others => '0'); input_sqrt(13) <= (others => '0'); input_sqrt(14) <= (others => '0'); input_sqrt(15) <= (others => '0'); input_sqrt(16) <= (others => '0'); elsif ( rising_edge( clk ) ) then input_valid_stage3 <= input_valid_stage2; if input_valid_stage2 = '1' then if index_sqrt = 16 then index_sqrt <= 0; else index_sqrt <= index_sqrt +1; end if; end if; case index_sqrt is when 16 => input_sqrt(16) <= std_logic_vector(re2_add_im2(63 downto 32)); when 15 => input_sqrt(15) <= std_logic_vector(re2_add_im2(63 downto 32)); when 14 => input_sqrt(14) <= std_logic_vector(re2_add_im2(63 downto 32)); when 13 => input_sqrt(13) <= std_logic_vector(re2_add_im2(63 downto 32)); when 12 => input_sqrt(12) <= std_logic_vector(re2_add_im2(63 downto 32)); when 11 => input_sqrt(11) <= std_logic_vector(re2_add_im2(63 downto 32)); when 10 => input_sqrt(10) <= std_logic_vector(re2_add_im2(63 downto 32)); when 9 => input_sqrt(9) <= std_logic_vector(re2_add_im2(63 downto 32)); when 8 => input_sqrt(8) <= std_logic_vector(re2_add_im2(63 downto 32)); when 7 => input_sqrt(7) <= std_logic_vector(re2_add_im2(63 downto 32)); when 6 => input_sqrt(6) <= std_logic_vector(re2_add_im2(63 downto 32)); when 5 => input_sqrt(5) <= std_logic_vector(re2_add_im2(63 downto 32)); when 4 => input_sqrt(4) <= std_logic_vector(re2_add_im2(63 downto 32)); when 3 => input_sqrt(3) <= std_logic_vector(re2_add_im2(63 downto 32)); when 2 => input_sqrt(2) <= std_logic_vector(re2_add_im2(63 downto 32)); when 1 => input_sqrt(1) <= std_logic_vector(re2_add_im2(63 downto 32)); when 0 => input_sqrt(0) <= std_logic_vector(re2_add_im2(63 downto 32)); when others => null; end case; end if; end process p_sqrt_stage3; -- generate sqrt instances for continous data stream gen_sqrt_array: for i in 0 to 16 generate sqrt_module : entity work.squareRoot_pipe generic map ( G_DATA_W => 32 ) port map ( clk => clk, rst => reset, iv_data => input_sqrt(i), ov_res => output_sqrt(i) ); end generate gen_sqrt_array; -- output assignment p_output_stage4: process ( clk, reset ) is begin if ( reset = '1' ) then output_valid <= '0'; output_magnitude <= (others => '0'); output_delay_sqrt <= (others => '0'); elsif ( rising_edge( clk ) ) then output_delay_sqrt <= output_delay_sqrt(14 downto 0) & input_valid_stage3; output_valid <= output_delay_sqrt(15); output_magnitude <= std_logic_vector(output_sqrt(index_sqrt)) & x"0000"; end if; end process p_output_stage4; end architecture rtl;