Lösung ADD und FFT
This commit is contained in:
@@ -22,6 +22,8 @@ entity add is
|
||||
|
||||
signal_write : out std_logic;
|
||||
signal_writedata : out std_logic_vector( 31 downto 0 )
|
||||
|
||||
|
||||
);
|
||||
end entity add;
|
||||
|
||||
@@ -29,20 +31,41 @@ architecture rtl of add is
|
||||
signal current_task_state : work.task.State;
|
||||
signal next_task_state : work.task.State;
|
||||
signal index : integer range 0 to work.task.STREAM_LEN;
|
||||
SIGNAL float_sum : STD_LOGIC_VECTOR(31 downto 0);
|
||||
SIGNAL fa_start: std_logic;
|
||||
SIGNAl fa_done: std_logic;
|
||||
|
||||
begin
|
||||
task_state_transitions : process ( current_task_state, task_start, index ) is
|
||||
|
||||
u_float_add : entity work.float_add
|
||||
port map(
|
||||
clk => clk,
|
||||
reset => reset,
|
||||
start => fa_start,
|
||||
done => fa_done,
|
||||
A => signal_a_readdata,
|
||||
B => signal_b_readdata,
|
||||
sum => float_sum
|
||||
);
|
||||
|
||||
|
||||
-- Zustandsübergangslogik:
|
||||
-- in TASK_RUNNING erst dann nach TASK_DONE, wenn die letzte Addition fertig ist
|
||||
task_state_transitions : process ( current_task_state, task_start, index, fa_done ) is
|
||||
begin
|
||||
next_task_state <= current_task_state;
|
||||
|
||||
case current_task_state is
|
||||
when work.task.TASK_IDLE =>
|
||||
if ( task_start = '1' ) then
|
||||
next_task_state <= work.task.TASK_RUNNING;
|
||||
end if;
|
||||
|
||||
when work.task.TASK_RUNNING =>
|
||||
if ( index = work.task.STREAM_LEN - 1 ) then
|
||||
if ( fa_done = '1' and index = work.task.STREAM_LEN -1 ) then
|
||||
next_task_state <= work.task.TASK_DONE;
|
||||
end if;
|
||||
|
||||
when work.task.TASK_DONE =>
|
||||
if ( task_start = '1' ) then
|
||||
next_task_state <= work.task.TASK_RUNNING;
|
||||
@@ -54,20 +77,59 @@ begin
|
||||
begin
|
||||
if ( reset = '1' ) then
|
||||
current_task_state <= work.task.TASK_IDLE;
|
||||
index <= 0;
|
||||
index <= 0;
|
||||
|
||||
signal_write <= '0';
|
||||
signal_a_read <= '0';
|
||||
signal_b_read <= '0';
|
||||
-- signal_writedata <= (others => '0');
|
||||
fa_start <= '0';
|
||||
|
||||
elsif ( rising_edge( clk ) ) then
|
||||
-- Zustand updaten
|
||||
current_task_state <= next_task_state;
|
||||
case next_task_state is
|
||||
when work.task.TASK_IDLE =>
|
||||
index <= 0;
|
||||
signal_write <= '0';
|
||||
when work.task.TASK_RUNNING =>
|
||||
index <= index + 1;
|
||||
signal_write <= '1';
|
||||
signal_writedata <= ( others => '0' );
|
||||
when work.task.TASK_DONE =>
|
||||
index <= 0;
|
||||
signal_write <= '0';
|
||||
|
||||
case current_task_state is
|
||||
when work.task.TASK_IDLE =>
|
||||
index <= 0;
|
||||
signal_write <= '0';
|
||||
signal_a_read <= '0';
|
||||
signal_b_read <= '0';
|
||||
-- signal_writedata <= (others => '0');
|
||||
fa_start <= '0';
|
||||
|
||||
when work.task.TASK_RUNNING =>
|
||||
-- Standardwerte im RUNNING-Zustand
|
||||
signal_write <= '0'; -- nur bei fertig berechneter Summe auf '1'
|
||||
signal_a_read <= '0';
|
||||
signal_b_read <= '0';
|
||||
|
||||
|
||||
if (fa_start = '0' and fa_done = '0') then
|
||||
-- neue Addition starten: Daten anfordern und start setzen
|
||||
signal_a_read <= '1';
|
||||
signal_b_read <= '1';
|
||||
fa_start <= '1';
|
||||
|
||||
elsif (fa_start = '1' and fa_done = '1') then
|
||||
-- Ergebnis ist gültig (OUTPUT_STATE von float_add)
|
||||
signal_writedata <= float_sum;
|
||||
signal_write <= '1';
|
||||
|
||||
-- ein Sample fertig
|
||||
index <= index + 1;
|
||||
|
||||
-- start zurücknehmen, damit float_add wieder in WAIT_STATE geht
|
||||
fa_start <= '0';
|
||||
end if;
|
||||
|
||||
when work.task.TASK_DONE =>
|
||||
index <= 0;
|
||||
signal_write <= '0';
|
||||
signal_a_read <= '0';
|
||||
signal_b_read <= '0';
|
||||
signal_writedata <= (others => '0');
|
||||
fa_start <= '0';
|
||||
end case;
|
||||
end if;
|
||||
end process sync;
|
||||
|
||||
@@ -66,6 +66,39 @@ architecture rtl of fft is
|
||||
signal index : integer range 0 to work.task.STREAM_LEN;
|
||||
--signal index : integer range 0 to 2000;
|
||||
|
||||
-- FFT Ablaufzustandsmaschine
|
||||
type fft_state_type is (FFT_IDLE, FFT_READ, FFT_WAIT, FFT_WRITE);
|
||||
|
||||
signal fft_state : fft_state_type;
|
||||
signal fft_next_state : fft_state_type;
|
||||
|
||||
function scale_exponent(arg : signed; delta : integer) return signed is
|
||||
variable tmp : signed(arg'range);
|
||||
begin
|
||||
tmp := arg;
|
||||
|
||||
-- Exponent (Bits 30..23) extrahieren, in signed umwandeln, delta addieren,
|
||||
-- und Ergebnis wieder als signed zurückschreiben
|
||||
tmp(30 downto 23) := signed(tmp(30 downto 23)) + to_signed(delta, 8);
|
||||
|
||||
return tmp;
|
||||
end function;
|
||||
|
||||
function scale_value(idx : integer) return integer is
|
||||
begin
|
||||
if idx = 0 then
|
||||
return 6; -- DC-Bin → ×64 statt ×32
|
||||
else
|
||||
return 5; -- Rest → ×32 statt ×16
|
||||
end if;
|
||||
end function;
|
||||
|
||||
|
||||
|
||||
|
||||
-- Zähler für eingelesene Samples
|
||||
signal sample_cnt : integer range 0 to work.task.STREAM_LEN;
|
||||
|
||||
-- component des Verilog IP-Cores fuer die FFT
|
||||
component fftmain is
|
||||
port(
|
||||
@@ -118,39 +151,39 @@ begin
|
||||
-- Hier muss der Verilog FFT IP-Core instanziert werden
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
--u_fft : fftmain
|
||||
-- port map (
|
||||
-- clock => , -- system clock
|
||||
-- reset => , -- Active High Asynchronous Reset
|
||||
-- di_en => , -- Input Data Enable
|
||||
-- di_re => , -- Input Data (Real)
|
||||
-- di_im => , -- Input Data (Imag)
|
||||
-- do_en => , -- Output Data Enable
|
||||
-- do_re => , -- Output Data (Real)
|
||||
-- do_im => -- Output Data (Imag)
|
||||
-- );
|
||||
u_fft : fftmain
|
||||
port map (
|
||||
clock => clk, -- system clock
|
||||
reset => reset, -- Active High Asynchronous Reset
|
||||
di_en => fft_input_data_enable, -- Input Data Enable
|
||||
di_re => data_in_re, -- Input Data (Real)
|
||||
di_im => data_in_im, -- Input Data (Imag)
|
||||
do_en => fft_output_valid, -- Output Data Enable
|
||||
do_re => data_out_re, -- Output Data (Real)
|
||||
do_im => data_out_im -- Output Data (Imag)
|
||||
);
|
||||
|
||||
fft_output_valid <= '0';
|
||||
data_out_re <= (others => '0');
|
||||
data_out_im <= (others => '0');
|
||||
-- fft_output_valid <= '0';
|
||||
-- data_out_re <= (others => '0');
|
||||
-- data_out_im <= (others => '0');
|
||||
|
||||
-----------------------------------------------------------------------------------------------
|
||||
-- Hier muss der VHDL Magnitue IP-COre instanziert werden
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
-- u_fft_mag_calc : entity work.fft_magnitude_calc
|
||||
-- port map (
|
||||
-- clk => , -- system clock
|
||||
-- reset => , -- Active High Asynchronous Reset
|
||||
-- input_valid => , -- Input Data Valid
|
||||
-- input_re => , -- Input Realteil in Fixpoint format
|
||||
-- input_im => , -- Input Imaginaerteil in Fixpoint format
|
||||
-- output_valid => , -- Output Data Valid
|
||||
-- output_magnitude => -- Magnitude Output in Fixpoint format
|
||||
-- );
|
||||
u_fft_mag_calc : entity work.fft_magnitude_calc
|
||||
port map (
|
||||
clk => clk, -- system clock
|
||||
reset => reset, -- Active High Asynchronous Reset
|
||||
input_valid => fft_output_valid, -- Input Data Valid
|
||||
input_re => data_out_re, -- Input Realteil in Fixpoint format
|
||||
input_im => data_out_im, -- Input Imaginaerteil in Fixpoint format
|
||||
output_valid => fft_mag_calc_valid, -- Output Data Valid
|
||||
output_magnitude => fft_mag_calc_result -- Magnitude Output in Fixpoint format
|
||||
);
|
||||
|
||||
fft_mag_calc_valid <= '1' when index = 0 else '0';
|
||||
fft_mag_calc_result <= (others => '0');
|
||||
-- fft_mag_calc_valid <= '1' when index = 0 else '0';
|
||||
-- fft_mag_calc_result <= (others => '0');
|
||||
|
||||
-----------------------------------------------------------------------------------------------
|
||||
-- Zustandsmaschine fuer die Taskabarbeitung (Uebergangsschaltnetz)
|
||||
@@ -176,10 +209,69 @@ begin
|
||||
|
||||
-----------------------------------------------------------------------------------------------
|
||||
-- Zustandsmaschine fuer die eigentliche Ablaufsteuerung fuer die FFT (Uebergangsschaltnetz)
|
||||
|
||||
-- - FFT_IDLE : Warten auf TASK_RUNNING
|
||||
-- - FFT_READ : STREAM_LEN Samples aus dem Eingangs-FIFO lesen und in FFT schieben
|
||||
-- - FFT_WAIT : Warten, bis alle FFT-/Magnitude-Ergebnisse im Speicher sind (index wird 1)
|
||||
-- - FFT_WRITE: Schreiben in Ausgangs-FIFO (gesteuert über vorhandene wr_fifo/index-Logik)
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
-- Hier soll Ihre Ablaufsteuerung fuer die FFT stehen
|
||||
|
||||
fft_next_state_machine : process (all) is
|
||||
begin
|
||||
-- Default-Ausgänge
|
||||
signal_read <= '0';
|
||||
fft_input_data_enable <= '0';
|
||||
|
||||
fft_next_state <= fft_state;
|
||||
|
||||
case fft_state is
|
||||
when FFT_IDLE => -- auf Start der Aufgabe warten
|
||||
if current_task_state = work.task.TASK_RUNNING then
|
||||
fft_next_state <= FFT_READ;
|
||||
end if;
|
||||
|
||||
when FFT_READ => -- Eingänge aus FIFO lesen und in FFT schieben
|
||||
signal_read <= '1';
|
||||
fft_input_data_enable <= '1';
|
||||
|
||||
if sample_cnt = work.task.STREAM_LEN - 1 then
|
||||
fft_next_state <= FFT_WAIT;
|
||||
end if;
|
||||
|
||||
when FFT_WAIT => -- Warten bis alle Magnitude-Wete im Speicher liegen
|
||||
if index = 1 then
|
||||
fft_next_state <= FFT_WRITE;
|
||||
end if;
|
||||
|
||||
when FFT_WRITE =>
|
||||
|
||||
if next_task_state = TASK_DONE then
|
||||
|
||||
fft_next_state <= FFT_IDLE;
|
||||
|
||||
end if;
|
||||
|
||||
end case;
|
||||
end process fft_next_state_machine;
|
||||
|
||||
process(clk, reset)
|
||||
begin
|
||||
if reset = '1' then
|
||||
fft_state <= FFT_IDLE;
|
||||
sample_cnt <= 0;
|
||||
elsif rising_edge(clk) then
|
||||
fft_state <= fft_next_state;
|
||||
|
||||
if fft_state = FFT_IDLE then
|
||||
sample_cnt <= 0;
|
||||
elsif fft_state = FFT_READ then
|
||||
sample_cnt <= sample_cnt + 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
-----------------------------------------------------------------------------------------------
|
||||
-- Ausgangsschaltnetz/Zustandsspeicher fuer die Task und FFT Zustandsmaschine
|
||||
@@ -231,9 +323,12 @@ begin
|
||||
|
||||
fft_float_input <= signed(signal_readdata);
|
||||
|
||||
fft_float_scaled_input <= fft_float_input; -- Der Eingang muss noch entsprechend skaliert werden
|
||||
|
||||
fft_float_scaled_input <= scale_exponent(fft_float_input, -4); -- E = E-4 Der Eingang muss noch entsprechend skaliert werden
|
||||
|
||||
data_in_re <= to_fixed(std_logic_vector(fft_float_scaled_input));
|
||||
|
||||
data_in_im <= (others => '0'); -- Imaginärteil = 0
|
||||
|
||||
-----------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Skalierung der Eingangswerte welche vom FIFO gelesen werden
|
||||
@@ -245,7 +340,7 @@ begin
|
||||
-- By selecting the amplitude as a power of two (e.g. 2 ** 2) the
|
||||
-- multiplication is a simple addition of the exponents.
|
||||
-- In the following calculation the inputs are scaled from FP in range +-1 to FP in range +-16
|
||||
-- the first frequency bin (DC-bin) needs a multiplication by two compared to the other frequency bins (the used fft ip-core divides the result of the first frequency bin by N instead of the correct N/2)
|
||||
-- the first frequency bin (DC-bin) needs a multiplication by two compared to the other frequency bins (the used fft ip-core divides the result of the first frequency bin by N instead of the correct N/2)
|
||||
-- This means an divsion through 16 is required for the first frequency bin (DC Part) -> exponent needs an addition of +4
|
||||
-- This means an divsion through 32 is required for the first frequency bin (DC Part) -> exponent needs an addition of +5
|
||||
--
|
||||
@@ -253,9 +348,16 @@ begin
|
||||
-- fft_float_scaled = soll der skalierte float Wert der Magnitude seien
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
data_out_mag_signed_float <= signed(to_float(fft_mag_calc_result));
|
||||
data_out_mag_signed_float <= signed(to_float(fft_mag_calc_result));
|
||||
|
||||
fft_float_scaled <= data_out_mag_signed_float; -- Der Ausgang muss noch entsprechend skaliert werden
|
||||
fft_float_scaled <= (others => '0')
|
||||
when fft_mag_calc_valid = '0'
|
||||
else scale_exponent(
|
||||
data_out_mag_signed_float,
|
||||
scale_value(index_output)
|
||||
);
|
||||
|
||||
-- Der Ausgang muss noch entsprechend skaliert werden
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user