Lösung ADD und FFT

This commit is contained in:
schullersh61298
2026-01-13 10:02:54 +01:00
parent 1c6c6a26d9
commit 3844b6a593
154 changed files with 21964 additions and 52 deletions
+76 -14
View File
@@ -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;
+133 -31
View File
@@ -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
-----------------------------------------------------------------------------------------------