# -----------------------------------------------------------------------------
# (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