-- -------------------------------------------------------- -- Generic 8 point DIF FFT algorithm using a register -- array for data and coefficients PACKAGE n_bits_int IS -- User defined types SUBTYPE U9 IS INTEGER RANGE 0 TO 2**9-1; SUBTYPE S16 IS INTEGER RANGE -2**15 TO 2**15-1; SUBTYPE S32 IS INTEGER RANGE -2147483647 TO 2147483647; TYPE ARRAY0_7S16 IS ARRAY (0 TO 7) of S16; TYPE ARRAY0_255S16 IS ARRAY (0 TO 15) of S16; TYPE ARRAY0_127S16 IS ARRAY (0 TO 7) of S16; TYPE STATE_TYPE IS (start, load, calc, update, reverse, done); END n_bits_int; LIBRARY work; USE work.n_bits_int.ALL; LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.std_logic_arith.ALL; USE ieee.std_logic_signed.ALL; -- -------------------------------------------------------- ENTITY fft256 IS ------> Interface PORT (clk, reset : IN STD_LOGIC; -- Clock and reset xr_in, xi_in : IN S16; -- Real and imag. input fft_valid : OUT STD_LOGIC; -- FFT output is valid fftr, ffti : OUT S16; -- Real and imag. output rcount_o : OUT U9; -- Bitreverese index counter xr_out, xi_out : OUT ARRAY0_7S16; -- First 8 reg. files stage_o, gcount_o : OUT U9; --Stage and group count i1_o, i2_o : OUT U9; -- (Dual) data index k1_o, k2_o : OUT U9; -- Index offset w_o, dw_o : OUT U9; -- Cos/Sin (increment) angle wo : OUT U9); -- Decision tree location loop FSM END fft256; -- -------------------------------------------------------- ARCHITECTURE fpga OF fft256 IS SIGNAL s : STATE_TYPE; -- State machine variable CONSTANT N : U9 := 16; -- Number of points CONSTANT ldN : U9 := 4; -- Log_2 number of points -- Register array for 16 bit precision: SIGNAL xr, xi : ARRAY0_255S16:=(others=>0); SIGNAL w : U9 := 0; -- sine and cosine coefficient arrays -- -------------------------------------------------------- CONSTANT cos_rom : ARRAY0_127S16 := (16384,15136,11585,6270,0,-6270,-11585,-15136); -- CONSTANT cos_rom : ARRAY0_127S16 := (16384,16379,16364,16340 -- ,16305,16261,16207,16143,16069,15986,15893,15791,15679, -- 15557,15426,15286,15137,14978,14811,14635,14449,14256, -- 14053,13842,13623,13395,13160,12916,12665,12406,12140, -- 11866,11585,11297,11003,10702,10394,10080,9760,9434,9102, -- 8765,8423,8076,7723,7366,7005,6639,6270,5897,5520,5139, -- 4756,4370,3981,3590,3196,2801,2404,2006,1606,1205,804,402 -- ,0,-402,-804,-1205,-1606,-2006,-2404,-2801,-3196,-3590, -- -3981,-4370,-4756,-5139,-5520,-5897,-6270,-6639,-7005, -- -7366,-7723,-8076,-8423,-8765,-9102,-9434,-9760,-10080, -- -10394,-10702,-11003,-11297,-11585,-11866,-12140,-12406, -- -12665,-12916,-13160,-13395,-13623,-13842,-14053,-14256, -- -14449,-14635,-14811,-14978,-15137,-15286,-15426,-15557, -- -15679,-15791,-15893,-15986,-16069,-16143,-16207,-16261, -- -16305,-16340,-16364,-16379); -- -------------------------------------------------------- -- --CONSTANT sin_rom : ARRAY0_127S16 := (0,402,804,1205,1606, -- --2006,2404,2801,3196,3590,3981,4370,4756,5139,5520,5897, -- --6270,6639,7005,7366,7723,8076,8423,8765,9102,9434,9760, -- --10080,10394,10702,11003,11297,11585,11866,12140,12406, -- --12665,12916,13160,13395,13623,13842,14053,14256,14449, -- 14635,14811,14978,15137,15286,15426,15557,15679,15791, -- 15893,15986,16069,16143,16207,16261,16305,16340,16364, -- 16379,16384,16379,16364,16340,16305,16261,16207,16143, -- 16069,15986,15893,15791,15679,15557,15426,15286,15137, -- 14978,14811,14635,14449,14256,14053,13842,13623,13395, -- 13160,12916,12665,12406,12140,11866,11585,11297,11003, -- 10702,10394,10080,9760,9434,9102,8765,8423,8076,7723, -- 7366,7005,6639,6270,5897,5520,5139,4756,4370,3981,3590, -- 3196,2801,2404,2006,1606,1205,804,402); constant sin_rom : array0_127s16 := (0,6270,11585,15136,16384,15136,11585,6270); SIGNAL sin , cos : S16; BEGIN sin_read: PROCESS (clk) BEGIN IF falling_edge(clk) THEN sin <= sin_rom(w); -- Read from ROM END IF; END PROCESS; cos_read: PROCESS (clk) BEGIN IF falling_edge(clk) THEN cos <= cos_rom(w); -- Read from ROM END IF; END PROCESS; States: PROCESS(clk, reset, w)-----> FFT in behavioral style VARIABLE i1, i2, gcount, k1, k2 : U9 := 0; VARIABLE stage, dw, count, rcount : U9 := 0; VARIABLE tr, ti : S16 := 0; VARIABLE slv, rslv : STD_LOGIC_VECTOR(0 TO ldN-1); BEGIN IF reset = '1' THEN -- Asynchronous reset s <= start; ELSIF rising_edge(clk) THEN CASE s IS -- Next State assignments WHEN start => s <= load; count := 0; gcount := 0; stage:= 1; i1:=0; i2 := N/2; k1:=N; k2:=N/2; dw := 1; fft_valid <= '0'; WHEN load => -- Read in all data from I/O ports xr(count) <= xr_in; xi(count) <= xi_in; count := count + 1; IF count = N THEN s <= calc; ELSE s <= load; END IF; WHEN calc => -- Do the butterfly computation tr := xr(i1) - xr(i2); xr(i1) <= xr(i1) + xr(i2); ti := xi(i1) - xi(i2); xi(i1) <= xi(i1) + xi(i2); xr(i2) <= (cos * tr + sin * ti)/2**14; xi(i2) <= (cos * ti - sin * tr)/2**14; s <= update; WHEN update => -- All counters and pointers s <= calc; -- By default do next butterfly i1 := i1 + k1; -- Next butterfly in group i2 := i1 + k2; wo <= 1; IF i1 >= N-1 THEN -- All butterflies done in group? gcount := gcount + 1; i1 := gcount; i2 := i1 + k2; wo <= 2; IF gcount >= k2 THEN-- All groups done in stages? gcount := 0; i1 := 0; i2 := k2; dw := dw * 2; stage := stage + 1; wo <= 3; IF stage > ldN THEN -- All stages done s <= reverse; count := 0; wo <= 4; ELSE -- Start new stage k1 := k2; k2 := k2/2; i1 := 0; i2 := k2; w <= 0; wo <= 5; END IF; ELSE -- Start new group i1 := gcount; i2 := i1 + k2; w <= w + dw; wo <= 6; END IF; END IF; WHEN reverse => -- Apply bitreverse fft_valid <= '1'; slv := CONV_STD_LOGIC_VECTOR(count, ldn); FOR i IN 0 TO ldn-1 LOOP rslv(i) := slv(ldn-i-1); END LOOP; rcount := CONV_INTEGER('0' & rslv); fftr <= xr(rcount); ffti <= xi(rcount); count := count + 1; IF count >= N THEN s <= done; ELSE s <= reverse; END IF; WHEN done => -- Output of results s <= start; -- Start next cycle END CASE; END IF; i1_o<=i1; -- Provide some test signals as outputs i2_o<=i2; stage_o<=stage; gcount_o <= gcount; k1_o <= k1; k2_o<=k2; w_o<=w; dw_o<=dw; rcount_o <= rcount; END PROCESS States; Rk: FOR k IN 0 TO 7 GENERATE -- Show first 8 xr_out(k) <= xr(k); -- register values xi_out(k) <= xi(k); END GENERATE; END fpga;