------------------------------------------------------------------------------- -- -- fft.vhd: Fast Fourier Transform finite state machine -- Dan R. K. Ports -- 6.111 final project, 2003/12/04 -- ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_signed.all; entity fft is port ( start, reset, clk : in std_logic; addrbus : out std_logic_vector(13 downto 0); testaddrbus : out std_logic_vector(6 downto 0); -- databus : inout std_logic_vector(7 downto 0); databusout : out std_logic_vector(7 downto 0); databusin : in std_logic_vector(7 downto 0); busy : out std_logic; inbufsel, outbufsel : in std_logic_vector(2 downto 0); inverse : in std_logic; treout,timout,breout,bimout, wbreout, wbimout : out std_logic_vector(7 downto 0); databusinout : out std_logic_vector(7 downto 0); nextiout : out std_logic_vector(9 downto 0); copyimout : out std_logic; ramreq : out std_logic; ramdone : in std_logic; ramwe : out std_logic); end fft; architecture behavioral of fft is component twiddler512 port ( twiddlesel : in std_logic_vector(8 downto 0); twiddlere, twiddleim : out std_logic_vector(7 downto 0)); end component; component twiddler8 port ( twiddlesel : in std_logic_vector(8 downto 0); twiddlere, twiddleim : out std_logic_vector(7 downto 0)); end component; component complexmult port ( are, aim, bre, bim : in std_logic_vector(7 downto 0); prodre, prodim : out std_logic_vector(15 downto 0)); end component; type StateType is (s_Idle, s_CopySel, s_CopyWr, s_FFTStart, s_PassStart, s_BlockStart, s_BflyLoad, s_BflyWrite, s_BflyEnd, s_BlockEnd, s_PassEnd); signal curState, nextState : StateType; signal i, nexti : std_logic_vector(9 downto 0); signal copyim : std_logic := '0'; signal p : std_logic_vector(4 downto 0); signal BP, b, NP, NPp, BaseB, BaseT, k : std_logic_vector(9 downto 0); signal tre, tim, bre, bim, cbuf : std_logic_vector(7 downto 0); signal wbre, wbim : std_logic_vector(15 downto 0); signal twiddlesel : std_logic_vector(8 downto 0); signal twiddlere, twiddleim, twiddleimi : std_logic_vector(7 downto 0); signal addrbusint : std_logic_vector(13 downto 0); signal dataoutbuf : std_logic_vector(7 downto 0); begin -- behavioral treout <= tre; timout <= tim; bimout <= bim; breout <= bre; wbreout <= wbre(15 downto 8); wbimout <= wbim(15 downto 8); copyimout <= copyim; nextiout <= nexti; databusinout <= databusin; twiddler : twiddler512 port map ( twiddlesel => twiddlesel, twiddlere => twiddlere, twiddleim => twiddleim); cmult : complexmult port map ( are => bre, aim => bim, bre => twiddlere, bim => twiddleimi, prodre => wbre, prodim => wbim); twiddleimi <= twiddleim when inverse = '0' else ((not twiddleim) + 1); -- purpose: select next state -- type : combinational -- inputs : curState -- outputs: nextState, nexti newstate: process (curState, i, start, reset) begin -- process newstate if reset = '1' then nextState <= s_Idle; else case curState is when s_Idle => if start = '1' then nextState <= s_CopySel; nexti <= (others => '0'); else nextState <= s_Idle; nexti <= i; end if; when s_CopySel => if ramdone = '1' then nextState <= s_CopyWr; nexti <= i; else nextState <= s_CopySel; nexti <= i; end if; when s_CopyWr => if ramdone = '1' then if i = 1023 then --* -- if i = 15 then nextState <= s_FFTStart; else nextState <= s_CopySel; end if; if copyim = '1' then nexti <= i + 1; end if; else nextState <= s_CopyWr; nexti <= i; end if; when s_FFTStart => nextState <= s_PassStart; when s_PassStart => nextState <= s_BlockStart; when s_BlockStart => nextState <= s_BflyLoad; nexti <= (others => '0'); when s_BflyLoad => if ramdone = '1' then if i = 3 then nextState <= s_BflyWrite; nexti <= (others => '0'); else nextState <= s_BflyLoad; nexti <= i + 1; end if; else nextState <= s_BflyLoad; nexti <= i; end if; when s_BflyWrite => if ramdone = '1' then if i = 3 then nextState <= s_BflyEnd; nexti <= (others => '0'); else nextState <= s_BflyWrite; nexti <= i + 1; end if; else nextState <= s_BflyWrite; nexti <= i; end if; when s_BflyEnd => nexti <= (others => '0'); if k = npp then nextState <= s_BlockEnd; else nextState <= s_BflyLoad; end if; when s_BlockEnd => if b = bp then nextState <= s_PassEnd; else nextState <= s_BlockStart; end if; when s_PassEnd => if p = 10 then --* -- if p = 4 then nextState <= s_Idle; else nextState <= s_PassStart; end if; when others => nextState <= s_Idle; end case; end if; end process newstate; -- purpose: update state and i on clock -- type : combinational -- inputs : clk -- outputs: curState, i state_clocked: process (clk) begin -- process state_clocked if rising_edge(clk) then curState <= nextState; i <= nexti; if nextState = s_CopySel then if curState = s_CopyWr then copyim <= not copyim; elsif curState = s_CopySel then copyim <= copyim; else copyim <= '0'; end if; elsif nextState = s_FFTStart then Bp <= "1000000000"; --* -- BP <= "0000001000"; Np <= "0000000010"; p <= (others => '0'); elsif nextState = s_PassStart then BaseT <= (others => '0'); b <= (others => '0'); elsif nextState = s_BlockStart then k <= (others => '0'); twiddlesel <= (others => '0'); BaseB <= BaseT + npp; elsif nextState = s_BflyEnd then k <= k + 1; twiddlesel <= twiddlesel + ('0' & Bp(9 downto 1)); elsif nextState = s_BlockEnd then b <= b + 1; BaseT <= BaseT + np; elsif nextState = s_PassEnd then p <= p + 1; Np <= Np(8 downto 0) & '0'; Bp <= '0' & Bp(9 downto 1); end if; if curState = s_BflyLoad and i = 0 then tre <= databusin; elsif curState = s_BflyLoad and i = 1 then tim <= databusin; elsif curState = s_BflyLoad and i = 2 then bre <= databusin; elsif curState = s_BflyLoad and i = 3 then bim <= databusin; end if; end if; end process state_clocked; -- purpose: read input values from RAM at appropriate times -- type : combinational -- inputs : curState, databus -- outputs: tre, tim, bre, bim -- grab_inputs: process (curState, databusin) -- begin -- process grab_inputs -- if curState = s_BflyLoad then -- if i = 0 then -- tre <= databusin; -- tim <= tim; -- bre <= bre; -- bim <= bim; -- elsif i = 1 then -- tre <= tre; -- tim <= databusin; -- bre <= bre; -- bim <= bim; -- elsif i = 2 then -- tre <= tre; -- tim <= tim; -- bre <= databusin; -- bim <= bim; -- elsif i = 3 then -- tre <= tre; -- tim <= tim; -- bre <= bre; -- bim <= databusin; -- end if; -- elsif curState = s_BflyWrite then -- tre <= tre; -- tim <= tim; -- bre <= bre; -- bim <= bim; -- elsif curState = s_CopySel then -- tre <= databusin; -- elsif curState = s_CopyWr then -- tre <= tre; -- else -- tre <= tre; -- tim <= tim; -- bre <= bre; -- bim <= bim; -- end if; -- end process grab_inputs; -- temp_grab_inputs: process (curState, databus) -- begin -- process temp_grab_inputs -- if curState = s_CopySel then -- tre <= databus; -- tim <= databus; -- bre <= databus; -- bim <= databus; -- end if; -- end process temp_grab_inputs; -- process (curState, i, databusin) -- begin -- if curState = s_BflyLoad and i=0 then -- tre <= databusin; -- else -- tre <= tre; -- end if; -- end process; -- -- -- process (curState, i, databusin) -- begin -- if curState = s_BflyLoad and i=1 then -- tim <= databusin; -- else -- tim <= tim; -- end if; -- end process; -- -- process (curState, i, databusin) -- begin -- if curState = s_BflyLoad and i=2 then -- bre <= databusin; -- else -- bre <= bre; -- end if; -- end process; -- -- process (curState, i, databusin) -- begin -- if curState = s_BflyLoad and i=3 then -- bim <= databusin; -- else -- bim <= bim; -- end if; -- end process; process (curState, i, databusin) begin if curState = s_CopySel then cbuf <= databusin; else cbuf <= cbuf; end if; end process; busy <= '0' when curState = s_Idle else '1'; ramwe <= '1' when curState = s_CopyWr or curState = s_BflyWrite else '0'; ramreq <= '1' when curState = s_CopySel or curState = s_CopyWr or curState = s_BflyLoad or curState = s_BflyWrite else '0'; -- purpose: generate data bus outputs -- type : combinational -- inputs : curState, tre, tim, bre, bim -- outputs: databus gen_bus_outputs: process (curState, tre, tim, wbre, wbim) begin -- process gen_bus_outputs if curState = s_BflyWrite then if i = 0 then dataoutbuf <= tre + (wbre(15) & wbre(13 downto 7)); elsif i = 1 then dataoutbuf <= tim + (wbim(15) & wbim(13 downto 7)); elsif i = 2 then dataoutbuf <= tre - (wbre(15) & wbre(13 downto 7)); else dataoutbuf <= tim - (wbim(15) & wbim(13 downto 7)); end if; elsif curState = s_CopyWr then dataoutbuf <= cbuf; else -- databusout <= (others => 'Z'); dataoutbuf <= (others => '0'); end if; end process gen_bus_outputs; -- purpose: chop off low-order bit on alternate pass -- type : combinational -- inputs : curState, p, dataoutbuf -- outputs: databusout gen_real_bus_out: process (curState, p, dataoutbuf) begin -- process gen_real_bus_out if (curState = s_BflyWrite and p(0) = '1' and not (p = 9)) or curState = s_CopyWr then databusout <= dataoutbuf(7) & dataoutbuf(7 downto 1); else databusout <= dataoutbuf; end if; end process gen_real_bus_out; gen_addr_out: process (clk) begin -- process gen_addr_out if curState = s_BflyLoad or curState = s_BflyWrite then if i = 0 or i = 1 then addrbusint(10 downto 1) <= BaseT + k; else addrbusint(10 downto 1) <= BaseB + k; end if; addrbusint(0) <= i(0); addrbusint(13 downto 11) <= outbufsel; elsif curState = s_CopySel then addrbusint <= inbufsel & i & copyim; elsif curState = s_CopyWr then --addrbusint <= outbufsel & i(0) & i(1) & i(2) & i(3) & i(4) & i(5) & i(6) -- & i(7) & i(8) & i(9) & i(10); addrbusint <= outbufsel & "000000" & i(0) & i(1) & i(2) & i(3) & copyim; else addrbusint <= (others => '0'); end if; end process gen_addr_out; npp <= '0' & np(9 downto 1); testaddrbus <= addrbusint(12 downto 11) & addrbusint(4 downto 0); addrbus <= addrbusint; end behavioral;