# ----------------------------------------------------------------------------- # (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_bf.arx # Description : 2^3 butterfly for FFT pipeline # Author : Sabih Gerez, Bibix # based on work by Rene Moll (DSE) & # David van Kampen (UT, 2006) # Creation date: October 23, 2011 # ----------------------------------------------------------------------------- # $Rev: 174 $ # $Author: sabih $ # $Date: 2011-11-03 23:03:29 +0100 (Thu, 03 Nov 2011) $ # $Log$ # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # 8 Point Radix-2^3 FFT # # This file implements a butterfly with control logic in the form of a # counter. A butterfly consists of a cascade of stage 1, 2 and 3 with # FIFOs and additional control logic. # # +----+ +----+ +----+ # data_in -> | s1 | -> | s2 | -> | s3 | -> data_out # +----+ +----+ +----+ # | | | # +-------+ | | # counter -> | LOGIC | --+---------+ # +-------+ # # A normal operation cycle starts when the counter is zero. # # FIFO sizing: # - Butterfly order N = 8^n # - Stage 1 FIFO = N/2 # - Stage 2 FIFO = N/4 # - Stage 3 FIFO = N/8 # # In all butterflies: # - x refers to the top input/output # - y refers to the bottom input/output # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # 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 # ----------------------------------------------------------------------------- component bf23 T : generic type # FFT order the butterfly represents (must be a power of 8) N : generic integer = 8 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(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 # 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 # Control R23BF by setting the muxes case counter when 0 bf1_select_s1 = 0 bf2_select_s2 = 0 bf2_select_s1 = 1 bf3_select_s3 = 0 bf3_select_s2 = 0 bf3_select_s1 = 0 when 1 bf1_select_s1 = 0 bf2_select_s2 = 0 bf2_select_s1 = 0 bf3_select_s3 = 0 bf3_select_s2 = 0 bf3_select_s1 = 1 when 2 bf1_select_s1 = 0 bf2_select_s2 = 0 bf2_select_s1 = 0 bf3_select_s3 = 0 bf3_select_s2 = 0 bf3_select_s1 = 0 when 3 bf1_select_s1 = 0 bf2_select_s2 = 1 bf2_select_s1 = 1 bf3_select_s3 = 0 bf3_select_s2 = 1 bf3_select_s1 = 1 when 4 bf1_select_s1 = 1 bf2_select_s2 = 1 bf2_select_s1 = 1 bf3_select_s3 = 0 bf3_select_s2 = 0 bf3_select_s1 = 0 when 5 bf1_select_s1 = 1 bf2_select_s2 = 0 bf2_select_s1 = 0 bf3_select_s3 = 1 bf3_select_s2 = 0 bf3_select_s1 = 1 when 6 bf1_select_s1 = 1 bf2_select_s2 = 0 bf2_select_s1 = 0 bf3_select_s3 = 0 bf3_select_s2 = 0 bf3_select_s1 = 0 else bf1_select_s1 = 1 bf2_select_s2 = 0 bf2_select_s1 = 1 bf3_select_s3 = 1 bf3_select_s2 = 1 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 # ----------------------------------------------------------------------------- # Top component # ----------------------------------------------------------------------------- component top T : generic type = signed(12, 6) x_real : in T x_imag : in T y_real : out T y_imag : out T register # counter : unsigned(3) = 7 counter : unsigned(3) = 0 generate bf1 : bf23 T = T N = 8 data_in_real => x_real data_in_imag => x_imag data_out_real => y_real data_out_imag => y_imag counter => counter begin counter = counter + 1 end