----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date: 03/08/2021 07:09:54 PM
-- Design Name: 
-- Module Name: FFT_ADR_GEN - Behavioral
-- Project Name: 
-- Target Devices: 
-- Tool Versions: 
-- Description: 
--  This componenect selec the correct sram aaddress and it adjust it in the case that the 
--  an ifft is performed.
-- Dependencies: 
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
----------------------------------------------------------------------------------
library IEEE;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


library work;
use work.Common.all;

entity ADR_GEN is
generic (constant DEPTH: integer);
Port 
( 
    Clk:        in std_logic;
    Rst_n:      in std_logic;
    
    sel:         in adr_sel;
    sram_we:     in std_logic;
    ifft_idx:   in std_logic_vector(DEPTH-1 downto 0);
    cnt_value:   in std_logic_vector(DEPTH-1 downto 0);
     
    
    ifft_mode: in std_logic := '0';
    out_addr: out std_logic_vector(DEPTH-1 downto 0)
);
end ADR_GEN;

architecture Behavioral of ADR_GEN is
    signal mux_addr: std_logic_vector(DEPTH-1 downto 0);
    signal out_addr_tmp: std_logic_vector(DEPTH-1 downto 0);
    signal cnt_value_rev: std_logic_vector(DEPTH-1 downto 0);
    
begin

-- f_cnt_rst_rev <= 
-- Reverse the order of bits, aka
-- 001 -> 100
-- 100 -> 001
-- This is need because the fft output are in bit reverse order. 
-- NOTE There are hardware nsolution to reaorder bit-reverse samples
-- that would allow to remove the IFFT input SRAM. I will look at them
-- when I have finish this big refectoring and breaking up in file thing.
BIT_REVERSE: for i in 0 to DEPTH-1 generate
    cnt_value_rev(i) <= cnt_value(DEPTH-1-i);
end generate;

AdrSelProc: process(Rst_n, sel, cnt_value, cnt_value_rev, ifft_idx)
begin
    if (Rst_n='0') then 
        mux_addr <= (others => '0');
    else
        case sel is
            when SRAM_ADR_SEL_NONE => mux_addr <= (others => '0');
            when SRAM_ADR_SEL_CNT_VAL => mux_addr <= std_logic_vector(cnt_value);
            when SRAM_ADR_SEL_CNT_VAL_REV => mux_addr <= std_logic_vector(cnt_value_rev);
            when SRAM_ADR_SEL_IFFT_TUSER => mux_addr <= ifft_idx; -- Why here we enter with this? timing issue?
            when others => mux_addr <= (others => '0');
        end case;
    end if;
end process; 

-- We don't need this anymore, there was an error regarding how
-- the IFFT IP was configured so that the FFT was performed. 
-- An interessting property of the DFT is that F^-1(x) = F(x_{N-n})
-- so basically the element are shifted, by applying two FFT on the same data
-- we get the same result. 
-- So now that we perform a real IFFT this is not need anymore.
 
--MUX_Proc: process (Rst_n, mux_addr, ifft_mode)
--begin
--    if Rst_n='0' then
--        out_addr_tmp <= (others => '0');
--    else 
--        if ifft_mode='1' and unsigned(mux_addr)/=0 then
--           out_addr_tmp <= std_logic_vector(to_unsigned(2**DEPTH, DEPTH) - unsigned(mux_addr));
--        else
--            out_addr_tmp <= mux_addr;
--        end if;
--    end if;
--end process;

-- We only have to reverse the index when we are writing to the memory
-- and we are doing an IFFT. It is easier to handle this case here 
-- as this arleady is not a  convential RAM block by introducing 
-- yet another MUX here. So the memory is always read depending 
-- on the passed index!!!!
--out_addr <= out_addr_tmp when sram_we='1' else
--            mux_addr;
out_addr <= mux_addr;

end Behavioral;







