1 |
3 |
wzab |
-------------------------------------------------------------------------------
|
2 |
|
|
-- Title : butterfly and twiddle factor multiplier
|
3 |
|
|
-- Project :
|
4 |
|
|
-------------------------------------------------------------------------------
|
5 |
|
|
-- File : butterfly.vhd
|
6 |
|
|
-- Author : Wojciech Zabolotny wzab01<at>gmail.com
|
7 |
|
|
-- Company :
|
8 |
|
|
-- Licanse : BSD
|
9 |
|
|
-- Created : 2014-01-19
|
10 |
|
|
-- Last update: 2014-05-02
|
11 |
|
|
-- Platform :
|
12 |
|
|
-- Standard : VHDL'87
|
13 |
|
|
-------------------------------------------------------------------------------
|
14 |
|
|
-- Description: This block performs the buttefly calculation
|
15 |
|
|
-- And multiplies the result by the twiddle factor
|
16 |
|
|
-- Input data and output data are in our icpx_number format
|
17 |
|
|
-------------------------------------------------------------------------------
|
18 |
|
|
-- Copyright (c) 2014
|
19 |
|
|
-------------------------------------------------------------------------------
|
20 |
|
|
-- Revisions :
|
21 |
|
|
-- Date Version Author Description
|
22 |
|
|
-- 2014-01-19 1.0 wzab Created
|
23 |
|
|
-------------------------------------------------------------------------------
|
24 |
|
|
library ieee;
|
25 |
|
|
use ieee.std_logic_1164.all;
|
26 |
|
|
use ieee.numeric_std.all;
|
27 |
|
|
library work;
|
28 |
|
|
use work.fft_len.all;
|
29 |
|
|
use work.icpx.all;
|
30 |
|
|
-------------------------------------------------------------------------------
|
31 |
|
|
|
32 |
|
|
|
33 |
|
|
entity butterfly is
|
34 |
|
|
generic (
|
35 |
|
|
LATENCY : integer := 0);
|
36 |
|
|
port (
|
37 |
|
|
-- Input data
|
38 |
|
|
din0 : in icpx_number;
|
39 |
|
|
din1 : in icpx_number;
|
40 |
|
|
-- Twiddle factor
|
41 |
|
|
tf : in icpx_number;
|
42 |
|
|
-- Output data: real and imaginary parts
|
43 |
|
|
dout0 : out icpx_number;
|
44 |
|
|
dout1 : out icpx_number;
|
45 |
|
|
-- System interface
|
46 |
|
|
clk : in std_logic;
|
47 |
|
|
rst_n : in std_logic
|
48 |
|
|
);
|
49 |
|
|
|
50 |
|
|
end butterfly;
|
51 |
|
|
|
52 |
|
|
architecture beh1 of butterfly is
|
53 |
|
|
|
54 |
|
|
signal vdr0, vdr0_d, vdr0_d2, vdi0, vdi0_d, vdi0_d2 : signed(ICPX_WIDTH downto 0);
|
55 |
|
|
signal vdr1, vdi1 : signed(ICPX_WIDTH downto 0);
|
56 |
|
|
|
57 |
|
|
signal sout1r, sout1i : signed(2*ICPX_WIDTH downto 0);
|
58 |
|
|
signal sout1r_a, sout1i_a : signed(2*ICPX_WIDTH downto 0);
|
59 |
|
|
signal sout1r_b, sout1i_b : signed(2*ICPX_WIDTH downto 0);
|
60 |
|
|
signal stf, stf_d0 : icpx_number;
|
61 |
|
|
type T_DELIN is array (1 to LATENCY) of ICPX_NUMBER;
|
62 |
|
|
signal vin0, vin1, vtf : T_DELIN := (others => icpx_zero);
|
63 |
|
|
|
64 |
|
|
begin -- beh1
|
65 |
|
|
-- If requested, we introduce latency on the input
|
66 |
|
|
-- The register balancing function will distribute it
|
67 |
|
|
p1 : process (clk, rst_n)
|
68 |
|
|
begin -- process p1
|
69 |
|
|
if rst_n = '0' then -- asynchronous reset (active low)
|
70 |
|
|
vin0 <= (others => icpx_zero);
|
71 |
|
|
vin1 <= (others => icpx_zero);
|
72 |
|
|
vtf <= (others => icpx_zero);
|
73 |
|
|
elsif clk'event and clk = '1' then -- rising clock edge
|
74 |
|
|
-- delayed by 1 clock
|
75 |
|
|
vdr1 <= resize(din0.re, ICPX_WIDTH+1) - resize(din1.re, ICPX_WIDTH+1);
|
76 |
|
|
vdi1 <= resize(din0.im, ICPX_WIDTH+1) - resize(din1.im, ICPX_WIDTH+1);
|
77 |
|
|
vdr0 <= resize(din0.re, ICPX_WIDTH+1) + resize(din1.re, ICPX_WIDTH+1);
|
78 |
|
|
vdi0 <= resize(din0.im, ICPX_WIDTH+1) + resize(din1.im, ICPX_WIDTH+1);
|
79 |
|
|
stf_d0 <= tf;
|
80 |
|
|
-- delayed by 2 clocks
|
81 |
|
|
vdr0_d <= vdr0;
|
82 |
|
|
vdi0_d <= vdi0;
|
83 |
|
|
sout1r_a <= vdr1 * stf_d0.re;
|
84 |
|
|
sout1r_b <= vdi1 * stf_d0.im;
|
85 |
|
|
sout1i_a <= vdr1 * stf_d0.im;
|
86 |
|
|
sout1i_b <= vdi1 * stf_d0.re;
|
87 |
|
|
-- delayed by 3 clocks
|
88 |
|
|
vdr0_d2 <= vdr0_d;
|
89 |
|
|
vdi0_d2 <= vdi0_d;
|
90 |
|
|
sout1r <= sout1r_a - sout1r_b;
|
91 |
|
|
sout1i <= sout1i_a + sout1i_b;
|
92 |
|
|
end if;
|
93 |
|
|
end process p1;
|
94 |
|
|
dout1.re <= resize(sout1r(2*ICPX_WIDTH-1 downto ICPX_WIDTH-1), ICPX_WIDTH);
|
95 |
|
|
dout1.im <= resize(sout1i(2*ICPX_WIDTH-1 downto ICPX_WIDTH-1), ICPX_WIDTH);
|
96 |
|
|
dout0.re <= resize(vdr0_d2(ICPX_WIDTH downto 1), ICPX_WIDTH);
|
97 |
|
|
dout0.im <= resize(vdi0_d2(ICPX_WIDTH downto 1), ICPX_WIDTH);
|
98 |
|
|
|
99 |
|
|
-- Result may have one bit more, we add 1 for better rounding
|
100 |
|
|
|
101 |
|
|
|
102 |
|
|
-- Multiple by the twiddle factor
|
103 |
|
|
|
104 |
|
|
|
105 |
|
|
-- Now we drop the lower bits
|
106 |
|
|
-- first step - leave one more bit for rounding
|
107 |
|
|
end beh1;
|