# ----------------------------------------------------------------------------- # (C) Bibix # The content below includes confidential, proprietary information of # Bibix. All use, disclosure, and/or reproduction is prohibited # unless authorized in writing. All rights reserved. # ----------------------------------------------------------------------------- # File : fft_r8_64p.arx # Description : 64-point decimation-in-frequency FFT pipeline based on # two radix-2^3 butterfly stages # Author : Sabih Gerez, Bibix # based on work by Rene Moll (DSE) & # David van Kampen (UT, 2006) # Creation date: November 18, 2011 # ----------------------------------------------------------------------------- # $Rev: 182 $ # $Author: sabih $ # $Date: 2011-11-22 20:27:04 +0100 (Tue, 22 Nov 2011) $ # $Log$ # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # This file implements a 64 point R2^3 FFT consisting of # - Two R2^3 butterflies # - A complex multiplier for applying intermediate twiddle factors # - Control logic # # The structure is as follows: # # twiddle -----------------+ # | # +------+ +---+ +------+ # data_in -> | BF 1 | -> | * | -> | BF 2 | -> data_out # +------+ +---+ +------+ # # The control is created by two counters, one for each butterfly. # # The external twiddle factors need to be fed when the first butterfly # is outputting valid results. This is at cycle 59 (32 + 16 + 8 + 3) # due to the FIFO sizes and pipelining. # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # Radix-2 butterfly (Stage 1) # # The butterfly stage has two operation modes: # - Butterfly operation (select_s1 = 1) # - Bypass (select_s1 = 0) # Used to bypass the operation and route the FIFO to I/O # ----------------------------------------------------------------------------- component bf23_s1 T : generic type x_in_real : in T x_in_imag : in T y_in_real : in T y_in_imag : in T select_s1 : in bit x_out_real : out T x_out_imag : out T y_out_real : out T y_out_imag : out T begin if (select_s1 == 1) x_out_real = convert(T, x_in_real - y_in_real) x_out_imag = convert(T, x_in_imag - y_in_imag) y_out_real = convert(T, x_in_real + y_in_real) y_out_imag = convert(T, x_in_imag + y_in_imag) else x_out_real = y_in_real x_out_imag = y_in_imag y_out_real = x_in_real y_out_imag = x_in_imag end end # ----------------------------------------------------------------------------- # Radix-2 butterfly (Stage 2) # # This butterfly stage implements the previous stage preceded by an # optional twiddle factor at the y input: # - Apply a twiddle factor (-j) (select_s2 = 1) # - Bypass twiddle (-j) (select_s2 = 0) # # From the previous stage: # - Butterfly operation (select_s1 = 1) # - Bypass (select_s1 = 0) # Used to bypass the operation and route the FIFO to I/O # ----------------------------------------------------------------------------- component bf23_s2 T : generic type x_in_real : in T x_in_imag : in T y_in_real : in T y_in_imag : in T select_s1 : in bit select_s2 : in bit x_out_real : out T x_out_imag : out T y_out_real : out T y_out_imag : out T variable # Variables for the input mux mux_real : T mux_imag : T generate bf_int : bf23_s1 T = T x_in_real => x_in_real x_in_imag => x_in_imag y_in_real => mux_real y_in_imag => mux_imag select_s1 => select_s1 x_out_real => x_out_real x_out_imag => x_out_imag y_out_real => y_out_real y_out_imag => y_out_imag begin if (select_s2 == 1) mux_real = y_in_imag mux_imag = -y_in_real else mux_real = y_in_real mux_imag = y_in_imag end end # ----------------------------------------------------------------------------- # Radix-2 butterfly (Stage 3) # # This butterfly stage implements the previous stage preceded by yet # another optional twiddle factor at the y input: # # - Apply a twiddle factor (-W8) (select_s3 = 1) # - Bypass twiddle (-W8) (select_s3 = 0) # # From the previous stages: # - Butterfly operation (select_s1 = 1) # - Bypass (select_s1 = 0) # Used to bypass the operation and route the FIFO to I/O # - Apply a twiddle factor (-j) (select_s2 = 1) # - Bypass twiddle (-j) (select_s2 = 0) # ----------------------------------------------------------------------------- component bf23_s3 T : generic type x_in_real : in T x_in_imag : in T y_in_real : in T y_in_imag : in T select_s1 : in bit select_s2 : in bit select_s3 : in bit x_out_real : out T x_out_imag : out T y_out_real : out T y_out_imag : out T variable y_sum : T y_sub : T # Variables for the input mux mux_real : T mux_imag : T constant W8 : T = 0.707106781 generate bf_int : bf23_s2 T = T x_in_real => x_in_real x_in_imag => x_in_imag y_in_real => mux_real y_in_imag => mux_imag select_s1 => select_s1 select_s2 => select_s2 x_out_real => x_out_real x_out_imag => x_out_imag y_out_real => y_out_real y_out_imag => y_out_imag begin # Complex multiplication: # (a+jb)*(c+jd) = (ac - bd) + j(ad + bc) # Since c = -d # c(a + b) + jc(a - b) y_sum = convert(T, y_in_real + y_in_imag) y_sub = convert(T, y_in_imag - y_in_real) if (select_s3 == 1) mux_real = convert(T, y_sum * W8) mux_imag = convert(T, y_sub * W8) else mux_real = y_in_real mux_imag = y_in_imag end end # ----------------------------------------------------------------------------- # Radix-2^3 butterfly # # Generics: # - N: order number corresponding to the butterfly position; N=64 for # the first stage, and N=8 for the second. It is used to compute the # FIFO sizes. # # - COUNT_RATE: the number of LSBs discarded from counters on behalf # of control. COUNT_RATE = log2(N) - 3, but the current version of # Arx has some troubles to parameterize the component with a single # generic. # ----------------------------------------------------------------------------- component bf23 T : generic type N : generic integer = 8 COUNT_RATE : generic integer = 0 data_in_real : in T data_in_imag : in T data_out_real : out T data_out_imag : out T # Control input for the muxes counter : in unsigned(COUNT_RATE+3) register # Internal registers (Used as FIFO) # # Note: An additional buffer is added for stage 3 to avoid an array # of 1 This register is never used however implemented to avoid a # VHDL generation bug reg_s1_real : array[(N/2)] of T = 0 reg_s1_imag : array[(N/2)] of T = 0 reg_s2_real : array[(N/4)] of T = 0 reg_s2_imag : array[(N/4)] of T = 0 reg_s3_real : array[(N/8)+1] of T = 0 reg_s3_imag : array[(N/8)+1] of T = 0 variable # Mux control wires bf1_select_s1 : bit bf2_select_s1 : bit bf2_select_s2 : bit bf3_select_s1 : bit bf3_select_s2 : bit bf3_select_s3 : bit # Control wires counter_bf1 : unsigned(COUNT_RATE+3) counter_bf2 : unsigned(COUNT_RATE+3) counter_bf3 : unsigned(COUNT_RATE+3) # Wires to the FIFO for stage 1 reg_s1_in_real : T reg_s1_in_imag : T reg_s1_out_real : T reg_s1_out_imag : T # Wires to the FIFO for stage 2 reg_s2_in_real : T reg_s2_in_imag : T reg_s2_out_real : T reg_s2_out_imag : T # Wires to the FIFO for stage 3 reg_s3_in_real : T reg_s3_in_imag : T reg_s3_out_real : T reg_s3_out_imag : T # Storage for butterfly outputs register bf1_out_real : T = 0 bf1_out_imag : T = 0 bf2_out_real : T = 0 bf2_out_imag : T = 0 bf3_out_real : T = 0 bf3_out_imag : T = 0 generate # instantiate butterflies # note that the FIFO inputs connect to butterfly outputs and vice # versa bf1 : bf23_s1 T = T x_in_real => reg_s1_out_real x_in_imag => reg_s1_out_imag y_in_real => data_in_real y_in_imag => data_in_imag select_s1 => bf1_select_s1 x_out_real => reg_s1_in_real x_out_imag => reg_s1_in_imag y_out_real => bf1_out_real y_out_imag => bf1_out_imag bf2 : bf23_s2 T = T x_in_real => reg_s2_out_real x_in_imag => reg_s2_out_imag y_in_real => bf1_out_real y_in_imag => bf1_out_imag select_s1 => bf2_select_s1 select_s2 => bf2_select_s2 x_out_real => reg_s2_in_real x_out_imag => reg_s2_in_imag y_out_real => bf2_out_real y_out_imag => bf2_out_imag bf3 : bf23_s3 T = T x_in_real => reg_s3_out_real x_in_imag => reg_s3_out_imag y_in_real => bf2_out_real y_in_imag => bf2_out_imag select_s1 => bf3_select_s1 select_s2 => bf3_select_s2 select_s3 => bf3_select_s3 x_out_real => reg_s3_in_real x_out_imag => reg_s3_in_imag y_out_real => bf3_out_real y_out_imag => bf3_out_imag begin # Derive the control signals for each stage from the incoming counter. counter_bf1 = counter >> COUNT_RATE counter_bf2 = counter - 1 >> COUNT_RATE counter_bf3 = counter - 2 >> COUNT_RATE # Control R23BF by setting the muxes for each stage case counter_bf1 when 0 bf1_select_s1 = 0 when 1 bf1_select_s1 = 0 when 2 bf1_select_s1 = 0 when 3 bf1_select_s1 = 0 when 4 bf1_select_s1 = 1 when 5 bf1_select_s1 = 1 when 6 bf1_select_s1 = 1 else bf1_select_s1 = 1 end case counter_bf2 when 0 bf2_select_s2 = 0 bf2_select_s1 = 0 when 1 bf2_select_s2 = 0 bf2_select_s1 = 0 when 2 bf2_select_s2 = 1 bf2_select_s1 = 1 when 3 bf2_select_s2 = 1 bf2_select_s1 = 1 when 4 bf2_select_s2 = 0 bf2_select_s1 = 0 when 5 bf2_select_s2 = 0 bf2_select_s1 = 0 when 6 bf2_select_s2 = 0 bf2_select_s1 = 1 else bf2_select_s2 = 0 bf2_select_s1 = 1 end case counter_bf3 when 0 bf3_select_s3 = 0 bf3_select_s2 = 0 bf3_select_s1 = 0 when 1 bf3_select_s3 = 0 bf3_select_s2 = 1 bf3_select_s1 = 1 when 2 bf3_select_s3 = 0 bf3_select_s2 = 0 bf3_select_s1 = 0 when 3 bf3_select_s3 = 1 bf3_select_s2 = 0 bf3_select_s1 = 1 when 4 bf3_select_s3 = 0 bf3_select_s2 = 0 bf3_select_s1 = 0 when 5 bf3_select_s3 = 1 bf3_select_s2 = 1 bf3_select_s1 = 1 when 6 bf3_select_s3 = 0 bf3_select_s2 = 0 bf3_select_s1 = 0 else bf3_select_s3 = 0 bf3_select_s2 = 0 bf3_select_s1 = 1 end # Update registers (stage 1) reg_s1_out_real = reg_s1_real[(N/2)-1] reg_s1_out_imag = reg_s1_imag[(N/2)-1] reg_s1_real[0] = reg_s1_in_real reg_s1_imag[0] = reg_s1_in_imag for i in 1:((N/2)-1) reg_s1_real[i] = reg_s1_real[i-1] reg_s1_imag[i] = reg_s1_imag[i-1] end # Update registers (stage 2) reg_s2_out_real = reg_s2_real[(N/4)-1] reg_s2_out_imag = reg_s2_imag[(N/4)-1] reg_s2_real[0] = reg_s2_in_real reg_s2_imag[0] = reg_s2_in_imag for i in 1:((N/4)-1) reg_s2_real[i] = reg_s2_real[i-1] reg_s2_imag[i] = reg_s2_imag[i-1] end # Update registers (stage 3) reg_s3_out_real = reg_s3_real[(N/8)-1] reg_s3_out_imag = reg_s3_imag[(N/8)-1] reg_s3_real[0] = reg_s3_in_real reg_s3_imag[0] = reg_s3_in_imag for i in 1:((N/8)-1) reg_s3_real[i] = reg_s3_real[i-1] reg_s3_imag[i] = reg_s3_imag[i-1] end # Connect outputs data_out_real = bf3_out_real data_out_imag = bf3_out_imag end # ----------------------------------------------------------------------------- # Complex multiplier # ----------------------------------------------------------------------------- component complex_mult # Generic - settings IO_WL : generic integer = 10 # Word length IO_IWL : generic integer = 2 # Integer word length # Generic - types T_IO : generic type = signed(IO_WL, IO_IWL) T_MULT : generic type = signed(2*IO_WL+1, 2*IO_IWL) # Ports x_real : in T_IO x_imag : in T_IO y_real : in T_IO y_imag : in T_IO z_real : out T_IO z_imag : out T_IO variable m1 : T_MULT m2 : T_MULT m3 : T_MULT m4 : T_MULT begin m1 = convert(T_MULT, x_real * y_real) m2 = convert(T_MULT, x_imag * y_imag) m3 = convert(T_MULT, x_real * y_imag) m4 = convert(T_MULT, x_imag * y_real) z_real = convert(T_IO, m1 - m2) z_imag = convert(T_IO, m3 + m4) end # ----------------------------------------------------------------------------- # Top component # ----------------------------------------------------------------------------- component top IO_WL : generic integer = 16 # Word length IO_IWL : generic integer = 8 # Integer word length T : generic type = signed(IO_WL, IO_IWL) T_MULT : generic type = signed(2*IO_WL+1, 2*IO_IWL) x_real : in T x_imag : in T twiddle_real : in T twiddle_imag : in T y_real : out T y_imag : out T variable bf1_out_real : T bf1_out_imag : T bf2_in_real : T bf2_in_imag : T bf1_control : unsigned(6) bf2_control : unsigned(3) register # Control counters for both stages. # The second stage is initialized with 5, to compensate # for the pipeline of the first stage. bf1_counter : unsigned(6) = 0 bf2_counter : unsigned(3) = 5 generate bf1 : bf23 T = T N = 64 COUNT_RATE = 3 data_in_real => x_real data_in_imag => x_imag data_out_real => bf1_out_real data_out_imag => bf1_out_imag counter => bf1_control cmult : complex_mult T_IO = T T_MULT = T_MULT x_real => bf1_out_real x_imag => bf1_out_imag y_real => twiddle_real y_imag => twiddle_imag z_real => bf2_in_real z_imag => bf2_in_imag bf2 : bf23 T = T N = 8 COUNT_RATE = 0 data_in_real => bf2_in_real data_in_imag => bf2_in_imag data_out_real => y_real data_out_imag => y_imag counter => bf2_control begin # Counter 1 for the control of butterfly 1 if (bf1_counter == 63) bf1_counter = 0 else bf1_counter = bf1_counter + 1 end bf1_control = bf1_counter # Counter 2 for the control of butterfly 2 if (bf2_counter == 7) bf2_counter = 0 else bf2_counter = bf2_counter + 1 end bf2_control = bf2_counter end