mhmert
Newbie level 4
Hi!
I'm a student which not much real-life experience in VHDL and FPGA programming but I do have some basic knowledge (I think). Anyhow, I would like to learn by asking this question.
I have an FPGA to take samples from an 10 bit ADC, so I take a 10 bit sample every t time.
Those samples are put into an sfixed type from the fixed_pkg package in the ieee_proposed library, as a "real" number.
I have created a type "complex" with two sfixed(18, -12) vectors in it. The sample is the first one and the 2nd sfixed is (others => '0') for now.
I want to apply some signal processing so I need to apply the hilbert transform to obtain the analytical signal. I do so by storing the "complex" sample in an array of 256 complex samples. Those 256 samples are submitted to an 256-point FFT, the transform is applied and then they are submitted to an 256-point IFFT.
This process is very, very slow in simulation and synthesis does take like a day or so.
- Is this to be expected?
- would this effect its performance when put onto the FPGA
- How could I improve my "code"*
- Is there a better way to achieve what I'm trying to do?
* VHDL, is it defined as programming / coding? if not, what then?
My code: (reduced to 8-point for simplicity)
(VHDL) Taking samples:
(VHDL) Hilbert (8 point)
(VHDL) 8 Point FFT
(VHDL) Butterfly function
(VHDL) Complex functions
I'm a student which not much real-life experience in VHDL and FPGA programming but I do have some basic knowledge (I think). Anyhow, I would like to learn by asking this question.
I have an FPGA to take samples from an 10 bit ADC, so I take a 10 bit sample every t time.
Those samples are put into an sfixed type from the fixed_pkg package in the ieee_proposed library, as a "real" number.
I have created a type "complex" with two sfixed(18, -12) vectors in it. The sample is the first one and the 2nd sfixed is (others => '0') for now.
I want to apply some signal processing so I need to apply the hilbert transform to obtain the analytical signal. I do so by storing the "complex" sample in an array of 256 complex samples. Those 256 samples are submitted to an 256-point FFT, the transform is applied and then they are submitted to an 256-point IFFT.
This process is very, very slow in simulation and synthesis does take like a day or so.
- Is this to be expected?
- would this effect its performance when put onto the FPGA
- How could I improve my "code"*
- Is there a better way to achieve what I'm trying to do?
* VHDL, is it defined as programming / coding? if not, what then?
My code: (reduced to 8-point for simplicity)
(VHDL) Taking samples:
Code:
architecture Behavioral of Sampler is
begin
process(Trigger) is
variable var_shiftBuffer : complex_array_256 := (others => ((others => '0'), (others => '0')));
variable var_sample : integer := 0;
begin
if rising_edge(Trigger) then
var_sample := 0;
if D0 = '1' then var_sample := 1; end if;
if D1 = '1' then var_sample := var_sample + 2; end if;
if D2 = '1' then var_sample := var_sample + 4; end if;
if D3 = '1' then var_sample := var_sample + 8; end if;
if D4 = '1' then var_sample := var_sample + 16; end if;
if D5 = '1' then var_sample := var_sample + 32; end if;
if D6 = '1' then var_sample := var_sample + 64; end if;
if D7 = '1' then var_sample := var_sample + 128; end if;
if D8 = '1' then var_sample := var_sample + 256; end if;
if D9 = '1' then var_sample := var_sample + 512; end if;
for i in 0 to 254 loop
var_shiftBuffer(i) := var_shiftBuffer(i + 1);
end loop;
var_shiftBuffer(255) := (to_sfixed(var_sample, 18, -12), (others => '0'));
Samples <= var_shiftBuffer;
end if;
end process;
end Behavioral;
(VHDL) Hilbert (8 point)
Code:
architecture Behavioral of Hilbert8 is
signal sig_fftOut : complex_array_8 := (others => ((others => '0'), (others => '0')));
signal sig_ifftIn : complex_array_8 := (others => ((others => '0'), (others => '0')));
constant const_MultTwo : complex := (to_sfixed(2, 16, -8), (others => '0'));
component FFT8 is
port (
x : in complex_array_8;
Y : out complex_array_8
);
end component;
component IFFT8 is
port (
Y : in complex_array_8;
x : out complex_array_8
);
end component;
begin
-- -- Take FFT
comp_fft : FFT8 port map (realArrayIn, sig_fftOut);
-- -- perform Hilbert
sig_ifftIn(0) <= sig_fftOut(0);
sig_ifftIn(1) <= mult(sig_fftOut(1), const_MultTwo);
sig_ifftIn(2) <= mult(sig_fftOut(2), const_MultTwo);
sig_ifftIn(3) <= mult(sig_fftOut(3), const_MultTwo);
sig_ifftIn(4) <= sig_fftOut(4);
-- -- Take IFFT
comp_ifft : IFFT8 port map (sig_ifftIn, complexArrayOut);
end Behavioral;
(VHDL) 8 Point FFT
Code:
architecture Behavioral of FFT8 is
constant const_N : integer := 8;
signal signal_1 : complex_array_8 := (others => ((others => '0'), (others => '0')));
signal signal_2 : complex_array_8 := (others => ((others => '0'), (others => '0')));
signal signal_3 : complex_array_8 := (others => ((others => '0'), (others => '0')));
-- W_N^k = cos(2*pi*k/N) - j * sin(2*pi*k/N)
constant const_W : complex_array_4 := (
(to_sfixed(1.0, 18, -12),to_sfixed(0.0, 18, -12)),
(to_sfixed(0.7071, 18, -12),to_sfixed(-0.7071, 18, -12)),
(to_sfixed(0.0, 18, -12),to_sfixed(-1.0, 18, -12)),
(to_sfixed(-0.7071, 18, -12),to_sfixed(-0.7071, 18, -12))
);
constant const_div : complex := (to_sfixed(0.125, 18, -12), (others => '0'));
component butterfly is
port(
s1,s2 : in complex; --inputs
w :in complex; -- phase factor
g1,g2 :out complex -- outputs
);
end component;
begin
--Stage 1
comp_bf_1_0 : butterfly port map(x(0), x(4), const_W(0), signal_2(0), signal_2(1));
comp_bf_1_1 : butterfly port map(x(2), x(6), const_W(0), signal_2(2), signal_2(3));
comp_bf_1_2 : butterfly port map(x(1), x(5), const_W(0), signal_2(4), signal_2(5));
comp_bf_1_3 : butterfly port map(x(3), x(7), const_W(0), signal_2(6), signal_2(7));
--Stage 2
comp_bf_2_0 : butterfly port map(signal_2(0), signal_2(2), const_W(0), signal_3(0), signal_3(2));
comp_bf_2_1 : butterfly port map(signal_2(1), signal_2(3), const_W(2), signal_3(1), signal_3(3));
comp_bf_2_2 : butterfly port map(signal_2(4), signal_2(6), const_W(0), signal_3(4), signal_3(6));
comp_bf_2_3 : butterfly port map(signal_2(5), signal_2(7), const_W(2), signal_3(5), signal_3(7));
--Stage 3
comp_bf_3_0 : butterfly port map(signal_3(0), signal_3(4), const_W(0), Y(0), Y(4));
comp_bf_3_1 : butterfly port map(signal_3(1), signal_3(5), const_W(1), Y(1), Y(5));
comp_bf_3_2 : butterfly port map(signal_3(2), signal_3(6), const_W(2), Y(2), Y(6));
comp_bf_3_3 : butterfly port map(signal_3(3), signal_3(7), const_W(3), Y(3), Y(7));
end Behavioral;
(VHDL) Butterfly function
Code:
architecture Behavioral of butterfly is
begin
--butterfly equations.
g1 <= add(s1,mult(s2,w));
g2 <= sub(s1,mult(s2,w));
end Behavioral;
(VHDL) Complex functions
Code:
package fft_pkg is
type complex is
record
r : sfixed(18 downto -12);
i : sfixed(18 downto -12);
end record;
type complex_array_256 is array (0 to 255) of complex;
type complex_array_128 is array (0 to 127) of complex;
type complex_array_64 is array (0 to 63) of complex;
type complex_array_32 is array (0 to 31) of complex;
type complex_array_16 is array (0 to 15) of complex;
type complex_array_8 is array (0 to 7) of complex;
type complex_array_4 is array (0 to 3) of complex;
function add (n1,n2 : complex) return complex;
function sub (n1,n2 : complex) return complex;
function mult (n1,n2 : complex) return complex;
function fftAbs(x : complex) return integer;
function positiveValues(x : complex) return boolean;
-- function complex_shift_right (x : complex; n : natural) return complex;
end fft_pkg;
package body fft_pkg is
--addition of complex numbers
function add (n1,n2 : complex) return complex is
variable sum : complex;
begin
sum.r:=resize(n1.r + n2.r, 18, -12);
sum.i:=resize(n1.i + n2.i, 18, -12);
return sum;
end add;
--subtraction of complex numbers.
function sub (n1,n2 : complex) return complex is
variable diff : complex;
begin
diff.r:=resize(n1.r - n2.r, 18, -12);
diff.i:=resize(n1.i - n2.i, 18, -12);
return diff;
end sub;
--multiplication of complex numbers.
function mult (n1,n2 : complex) return complex is
variable prod : complex;
begin
prod.r:= resize((n1.r * n2.r) - (n1.i * n2.i), 18, -12);
prod.i:= resize((n1.r * n2.i) + (n1.i * n2.r), 18, -12);
return prod;
end mult;
-- function complex_shift_right (x : complex; n : natural) return complex is
-- begin
-- return (SHIFT_RIGHT(x.r, n), SHIFT_RIGHT(x.i, n));
-- end complex_shift_right;
--absolute values
function fftAbs (x : complex) return integer is
variable a : sfixed(32 downto -12);
begin
a := resize(x.r * x.r + x.i * x.i, 32, -12);
return to_integer(signed(to_slv(a(32 downto 0))));
end fftAbs;
function positiveValues(x : complex) return boolean is
begin
if x.r > to_sfixed(0.0, 18, -12) and x.i > to_sfixed(0.0, 18, -12) then
return true;
else
return false;
end if;
end positiveValues;
end fft_pkg;