@@ -1,9 +1,10 @@ | |||
vhdl_srcs = down_counter_int.vhd \ | |||
top_entity.vhd \ | |||
test_top_entity.vhd \ | |||
vhdl_srcs = ../scripts/test_utility.vhd \ | |||
squareRoot_pipe.vhd \ | |||
fft_magnitude_calc.vhd \ | |||
test_fsm.vhd \ | |||
main = test_top_entity | |||
main = tb_fft_magnitude_calc | |||
CHECK_RESULTS = true | |||
@@ -0,0 +1,153 @@ | |||
------------------------------------------------------------------------ | |||
-- fft_magnitude_calc | |||
-- | |||
-- calculation of FFT magnitude sqrt(real_part²+im_part²) | |||
-- Inputs: | |||
-- input_re in: +-1 signed Fixpoint (0.5=0x40000000, -0.5=0xC0000000 (negative numbers in 2K) | |||
-- input_im in: +-1 signed Fixpoint (0.5=0x40000000, -0.5=0xC0000000 (negative numbers in 2K) | |||
-- input_valid: high = inputs are valid for data processing | |||
-- Outputs | |||
-- output_magnitude: Fixpoint 0.5=0x40000000 (always positive) | |||
-- output_valid: high = magnitude data is valid | |||
----------------------------------------------------------------------- | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
use ieee.numeric_std.all; | |||
entity fft_magnitude_calc is | |||
port ( | |||
clk : in std_logic; -- Takt | |||
reset : in std_logic; -- Reset | |||
input_valid: in std_logic; -- Eingangsdaten gueltig | |||
input_re : in std_logic_vector( 31 downto 0 ); -- Realteil in Fixpoint | |||
input_im : in std_logic_vector( 31 downto 0 ); -- Imaginaerteil in Fixpoint | |||
output_valid : out std_logic; -- Ausgangsdaten gueltig | |||
output_magnitude : out std_logic_vector( 31 downto 0 ) -- Berechnete magnitude | |||
); | |||
end entity fft_magnitude_calc; | |||
architecture rtl of fft_magnitude_calc is | |||
-- Zustaende fuer die Zustandsmaschine fuer die Berechnung | |||
type CalcState is ( | |||
CALC_IDLE, -- Zustand Leerlauf | |||
CALC_MULTIPLY, -- Zustand Berechnung real_part² und im_part² | |||
CALC_ADD, -- Zustand Berecnung Addition real_part²+im_part² | |||
CALC_SQRT, -- Zustand Berechnung der sqrt(real_part²+im_part²) | |||
CALC_STORE_RESULT -- Zustand Setzen von output_valid und output_magnitude | |||
); | |||
-- Legen Sie die Signale current_calc_state und next_calc_state fuer die Zustandsmaschine CalcState an | |||
-- Legen Sie die Signale re_multiply_re und im_multiply_im als signed (63 downto 0) an | |||
-- Legen Sie die Signal re2_add_im2 als signed (63 downto 0) an | |||
-- Legen Sie die Signal output_sqrt als std_logic_vector (31 downto 0) an | |||
-- Legen Sie die Signal output_sqrt als std_logic_vector (15 downto 0) an | |||
-- Legen Sie das Signal start_sqrt_calc als std_logic an | |||
-- Legen Sie das Signal sqrt_out_valid_flag als std_logic an | |||
begin | |||
-- uebergangsschaltnetz der Zustandsmaschine fuer die Berechnung (Strukturvariante 2 Process Zustandsmaschine) | |||
-- Beschreiben Sie den Prozess fuer das uebergangsschaltnetz (Case-Anweisung) | |||
-- CALC_IDLE -> CALC_MULTIPLY wenn input_valid = 1 | |||
-- CALC_MULTIPLY -> CALC_ADD | |||
-- CALC_ADD -> CALC_SQRT | |||
-- CALC_SQRT -> CALC_STORE_RESULT wenn sqrt_out_valid_flag = 1 | |||
-- CALC_STORE_RESULT -> CALC_IDLE | |||
calc_state_transitions : process ( all ) is | |||
begin | |||
end process calc_state_transitions; | |||
-- Zustandsspeicher und Ausgangsschaltnetz zu der Steuerung der Berechnung (Strukturvariante 2 Process Zustandsmaschine) | |||
sync : process ( clk, reset ) is | |||
begin | |||
-- Der Prozess steuert folgende Signale setzen Sie fuer alle passende Resetwerte | |||
-- current_calc_state | |||
-- re_multiply_re | |||
-- im_multiply_im | |||
-- re2_add_im2 | |||
-- input_sqrt | |||
-- start_sqrt_calc | |||
-- output_valid | |||
-- output_magnitude | |||
if ( reset = '1' ) then | |||
elsif ( rising_edge( clk ) ) then | |||
-- Machen Sie Anweisungen um start_sqrt_calc und output_valid auf 0 zu setzen | |||
-- Realisieren Sie den Zustandsspeicher current_calc_state | |||
-- Vervollstaendigen Sie das Ausgangsschaltnetz | |||
case next_calc_state is | |||
when CALC_IDLE=> null; | |||
-- calculation of real_part² and im_part² | |||
-- Anweisung fuer die Berechnung von re_multiply_re = input_re² (Datentypen beachten) | |||
-- Anweisung fuer die Berechnung von im_multiply_im = input_im² (Datentypen beachten) | |||
when CALC_MULTIPLY => | |||
-- calculation of real_part²*+im_part² | |||
-- Anweisung fuer die Berechnung von re2_add_im2 = re_multiply_re + im_multiply_im | |||
when CALC_ADD => | |||
-- calculation of sqrt(real_part²+im_part²) | |||
-- Anweisung um input_sqrt mit den obersten 32-Bit von re2_add_im2 zu belegen (Datentypen beachten) | |||
-- Anweisung um start_sqrt_calc mit 1 zu setzen | |||
when CALC_SQRT => | |||
-- Setzen der Entity-Ausgaenge | |||
-- Anweisung um die obersten 16 bit von output_magnitude mit output_sqrt zu setzen und die untern 16 Bit mit 0 | |||
-- Anweisung um output_valid mit 1 zu setzen | |||
when CALC_STORE_RESULT => | |||
when others => NUll; | |||
end case; | |||
end if; | |||
end process sync; | |||
-- Instanziierung des SQRT Moduls fuer die Berechnung der Quardratwurzel | |||
-- Weisen Sie die Signale output_sqrt, reset, input_sqrt und clk richtig zu | |||
sqrt_module : entity work.squareRoot_pipe | |||
generic map ( | |||
G_DATA_W => 32 | |||
) | |||
port map ( | |||
clk => , | |||
rst => , | |||
iv_data => , | |||
ov_res => | |||
); | |||
-- Dieser Prozess sorgt dafuer, dass 16 Takte nachdem start_sqrt_calc 1 geworden ist sqrt_out_valid_flag zu 1 wird | |||
-- Wird benoetigt um die Berechnungsdauer des sqrt_module anzueigen | |||
-- Hier muss nichts veraendert werden | |||
p_sqrt_out_valid_flag: process ( clk, reset ) is | |||
variable delay_sqrt_out_valid_flag : std_logic_vector(14 downto 0); | |||
begin | |||
if ( reset = '1' ) then | |||
sqrt_out_valid_flag <= '0'; | |||
delay_sqrt_out_valid_flag := (others => '0'); | |||
elsif ( rising_edge( clk ) ) then | |||
sqrt_out_valid_flag <= delay_sqrt_out_valid_flag(14); | |||
delay_sqrt_out_valid_flag := delay_sqrt_out_valid_flag(13 downto 0) & start_sqrt_calc; | |||
if sqrt_out_valid_flag = '1' then | |||
delay_sqrt_out_valid_flag := (others => '0'); | |||
end if; | |||
end if; | |||
end process p_sqrt_out_valid_flag; | |||
end architecture rtl; | |||
@@ -0,0 +1,119 @@ | |||
---------------------------------------------------------------------------------------------------- | |||
-- Component : squareRoot_pipe | |||
-- Author : pwkolas | |||
---------------------------------------------------------------------------------------------------- | |||
-- File : squareRoot_pipe.vhd | |||
-- Mod. Date : XX.XX.XXXX | |||
-- Version : 1.00 | |||
---------------------------------------------------------------------------------------------------- | |||
-- Description : Square root calculator. | |||
-- Based on | |||
-- "A New Non-Restoring Square Root Algorithm and Its VLSI Implementations" | |||
-- | |||
---------------------------------------------------------------------------------------------------- | |||
-- Modification History : | |||
-- | |||
---------------------------------------------------------------------------------------------------- | |||
-- Comments : | |||
-- | |||
---------------------------------------------------------------------------------------------------- | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
use ieee.numeric_std.all; | |||
entity squareRoot_pipe is | |||
generic ( | |||
G_DATA_W : integer := 32 | |||
); | |||
port ( | |||
clk : in std_logic; | |||
rst : in std_logic; | |||
iv_data : in std_logic_vector(G_DATA_W-1 downto 0); | |||
ov_res : out std_logic_vector((G_DATA_W/2)-1 downto 0) | |||
); | |||
end entity squareRoot_pipe; | |||
architecture squareRoot_pipe_rtl of squareRoot_pipe is | |||
constant C_ALU_W : integer := ((G_DATA_W/2) + 2); | |||
constant C_PIPE_L : integer := G_DATA_W/2; | |||
constant C_OFFSET : integer := 3; -- width of start vectors going to ALU | |||
type t_arr_pipe_x_data is array (C_PIPE_L-1 downto 0) of unsigned(G_DATA_W-1 downto 0); | |||
signal a_data : t_arr_pipe_x_data; -- (D) | |||
signal a_R : t_arr_pipe_x_data; -- (R) | |||
type t_arr_pipe_x_alu is array (C_PIPE_L-1 downto 0) of unsigned(C_ALU_W-1 downto 0); | |||
type t_arr_pipe_x_res is array (C_PIPE_L-1 downto 0) of unsigned(G_DATA_W/2-1 downto 0); | |||
signal a_Q : t_arr_pipe_x_res; -- (ALU Q out) | |||
signal nextOp : std_logic_vector(C_PIPE_L-1 downto 0); | |||
begin | |||
sqrt_p : process (clk, rst) | |||
variable va_AluInR : t_arr_pipe_x_alu; -- (ALU R in) | |||
variable va_AluInQ : t_arr_pipe_x_alu; -- (ALU Q in) | |||
variable va_AluOut : t_arr_pipe_x_alu; -- (ALU Q out) | |||
begin | |||
if (rst = '1') then | |||
a_data <= (others => (others => '0')); | |||
a_R <= (others => (others => '0')); | |||
a_Q <= (others => (others => '0')); | |||
va_AluInR := (others => (others => '0')); | |||
va_AluInQ := (others => (others => '0')); | |||
va_AluOut := (others => (others => '0')); | |||
nextOp <= (others => '0'); | |||
elsif rising_edge(clk) then | |||
-- stage 0 start conditions, ALU inputs | |||
va_AluInR(0) := (others => '0'); | |||
va_AluInR(0)(1 downto 0) := unsigned(iv_data(G_DATA_W-1 downto G_DATA_W-1-1)); | |||
va_AluInQ(0) := (others => '0'); | |||
va_AluInQ(0)(0) := '1'; | |||
-- stage 0 calculations | |||
va_AluOut(0) := va_AluInR(0) - va_AluInQ(0); | |||
-- stage 0 result registers, ALU output | |||
a_data(0) <= shift_left(unsigned(iv_data), 2); | |||
a_R(0) <= (others => '0'); | |||
a_R(0)(G_DATA_W-1 downto G_DATA_W-1-1) <= va_AluOut(0)(1 downto 0); | |||
a_Q(0) <= (others => '0'); | |||
a_Q(0)(0) <= not va_AluOut(0)(2); | |||
nextOp(0) <= not va_AluOut(0)(2); | |||
-- next stages | |||
for i in 1 to C_PIPE_L-1 loop | |||
-- prepare inputs for next stage | |||
va_AluInR(i) := (others => '0'); | |||
va_AluInR(i)(C_OFFSET+i-1 downto 2) := a_R(i-1)(G_DATA_W-(i-1)-1 downto G_DATA_W-(2*i)); | |||
va_AluInR(i)(2-1 downto 0) := a_data(i-1)(G_DATA_W-1 downto G_DATA_W-1-1); | |||
va_AluInQ(i) := (others => '0'); | |||
va_AluInQ(i)(C_OFFSET+(i-1)-1 downto 2) := a_Q(i-1)(i-1 downto 0); | |||
va_AluInQ(i)(1) := not a_Q(i-1)(0); | |||
va_AluInQ(i)(0) := '1'; | |||
-- ALU ADD/SUB | |||
if (nextOp(i-1) = '1') then | |||
va_AluOut(i) := va_AluInR(i) - va_AluInQ(i); | |||
else | |||
va_AluOut(i) := va_AluInR(i) + va_AluInQ(i); | |||
end if; | |||
-- result registers | |||
a_data(i) <= shift_left(unsigned(a_data(i-1)), 2); | |||
a_R(i) <= (others => '0'); | |||
a_R(i)(G_DATA_W-i-1 downto G_DATA_W-2*(i+1)) <= va_AluOut(i)(i+1 downto 0); | |||
a_Q(i) <= shift_left(unsigned(a_Q(i-1)), 1); | |||
a_Q(i)(0) <= not va_AluOut(i)(i+2); | |||
nextOp(i) <= not va_AluOut(i)(i+2); | |||
end loop; | |||
end if; | |||
end process; | |||
ov_res <= std_logic_vector(a_Q(C_PIPE_L-1)); | |||
end architecture squareRoot_pipe_rtl; |
@@ -0,0 +1,89 @@ | |||
------------------------------------------------------------------------ | |||
-- fft_magnitude_calc | |||
-- | |||
-- calculation of FFT magnitude sqrt(real_part²+im_part²) | |||
-- Inputs: | |||
-- input_re in: +-1 signed Fixpoint (0.5=0x40000000, -0.5=0xC0000000 (negative numbers in 2K) | |||
-- input_im in: +-1 signed Fixpoint (0.5=0x40000000, -0.5=0xC0000000 (negative numbers in 2K) | |||
-- input_valid: high = inputs are valid for data processing | |||
-- Outputs | |||
-- output_magnitude: Fixpoint 0.5=0x40000000 (always positive) | |||
-- output_valid: high = magnitude data is valid | |||
----------------------------------------------------------------------- | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
use ieee.numeric_std.all; | |||
entity tb_fft_magnitude_calc is | |||
generic( GUI_MODE : boolean; CHECK_RESULTS : boolean ); | |||
end entity tb_fft_magnitude_calc; | |||
architecture rtl of tb_fft_magnitude_calc is | |||
signal clk : std_logic := '0'; -- Takt | |||
signal reset : std_logic := '1'; -- Reset | |||
signal input_valid: std_logic := '0'; -- Eingangsdaten gültig | |||
signal input_re : std_logic_vector( 31 downto 0 ) := X"40000000"; -- Realteil in Fixpoint | |||
signal input_im : std_logic_vector( 31 downto 0 ):= X"40000000"; -- Imaginärteil in Fixpoint | |||
signal output_valid : std_logic; -- Ausgangsdaten gültig | |||
signal output_magnitude : std_logic_vector( 31 downto 0 ); | |||
begin | |||
clk <= not clk after 10 ns; | |||
reset_release : process is | |||
begin | |||
wait for 435 ns; | |||
reset <= '0'; | |||
wait; | |||
end process reset_release; | |||
-- Instanziierung des SQRT Moduls für die Berechnung der Quardratwurzel | |||
-- Weisen Sie die Signale output_sqrt, reset, input_sqrt und clk richtig zu | |||
fft_magnitude_calc_module : entity work.fft_magnitude_calc | |||
port map ( | |||
clk => clk, | |||
reset => reset, | |||
input_valid => input_valid, -- Eingangsdaten gültig | |||
input_re => input_re, -- Realteil in Fixpoint | |||
input_im => input_im, -- Imaginärteil in Fixpoint | |||
output_valid => output_valid, -- Ausgangsdaten gültig | |||
output_magnitude => output_magnitude -- Berechnete magnitude | |||
); | |||
stimulus: process is | |||
begin | |||
wait until falling_edge( reset ); | |||
wait until falling_edge( clk ); | |||
input_valid <= '1'; | |||
wait until falling_edge( clk ); | |||
input_valid <= '0'; | |||
wait until falling_edge( output_valid ); | |||
wait for 200 ns; | |||
wait until falling_edge( clk ); | |||
input_valid <= '1'; | |||
input_re <= X"20000000"; | |||
input_im <= X"20000000"; | |||
wait until falling_edge( clk ); | |||
input_valid <= '0'; | |||
wait until falling_edge( output_valid ); | |||
wait until falling_edge( clk ); | |||
if ( GUI_MODE ) then | |||
std.env.stop; | |||
else | |||
std.env.finish; | |||
end if; | |||
end process stimulus; | |||
end architecture rtl; |
@@ -0,0 +1,3 @@ | |||
onerror {resume} | |||
quietly WaveActivateNextPane {} 0 | |||
add wave -noupdate /tb_fft_magnitude_calc/fft_magnitude_calc_module/* |