This commit is contained in:
grimmad102979 2025-12-16 09:58:21 +01:00
parent c90753aa23
commit 0baa59d050
6 changed files with 351 additions and 65 deletions

View File

@ -26,48 +26,131 @@ entity add is
end entity add; end entity add;
architecture rtl of add is architecture rtl of add is
type AddState is (z0_ADD_IDLE, z1_ADD_READ_FIFO, z2_ADD_CALC, z3_ADD_STORE_RESULT);
signal current_task_state : work.task.State; signal current_task_state : work.task.State;
signal next_task_state : work.task.State; signal next_task_state : work.task.State;
signal index : integer range 0 to work.task.STREAM_LEN; signal index : integer range 0 to work.task.STREAM_LEN;
-- Interne Signale für die Verbindung zur float_add Komponente
signal internal_start : std_logic;
signal internal_done : std_logic;
signal internal_sum : std_logic_vector(31 downto 0);
-- Signal für den internen Additions-Status
signal current_calc_state : AddState;
begin 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 => internal_start,
done => internal_done,
A => signal_a_readdata,
B => signal_b_readdata,
sum => internal_sum
);
task_state_transition : process (current_task_state, task_start, index ) is
begin begin
next_task_state <= current_task_state; next_task_state <= current_task_state;
case current_task_state is case current_task_state is
when work.task.TASK_IDLE => when work.task.TASK_IDLE =>
if ( task_start = '1' ) then if (task_start = '1') then
next_task_state <= work.task.TASK_RUNNING; next_task_state <= work.task.TASK_RUNNING;
end if; end if;
when work.task.TASK_RUNNING => when work.task.TASK_RUNNING =>
if ( index = work.task.STREAM_LEN - 1 ) then if (index = work.task.STREAM_LEN) then
next_task_state <= work.task.TASK_DONE; next_task_state <= work.task.TASK_DONE;
end if; end if;
when work.task.TASK_DONE => when work.task.TASK_DONE =>
if ( task_start = '1' ) then if (task_start = '1') then
next_task_state <= work.task.TASK_RUNNING; next_task_state <= work.task.TASK_RUNNING;
end if; end if;
end case; end case;
end process task_state_transitions; end process task_state_transition;
sync : process ( clk, reset ) is
sync : process (clk, reset) is
begin begin
if ( reset = '1' ) then if (reset = '1') then
current_task_state <= work.task.TASK_IDLE; current_task_state <= work.task.TASK_IDLE;
index <= 0; index <= 0;
elsif ( rising_edge( clk ) ) then
-- Reset
current_calc_state <= z1_ADD_READ_FIFO;
internal_start <= '0';
signal_a_read <= '0';
signal_b_read <= '0';
signal_write <= '0';
elsif (rising_edge(clk)) then
current_task_state <= next_task_state; current_task_state <= next_task_state;
-- defaults für Steuersignale
signal_a_read <= '0';
signal_b_read <= '0';
signal_write <= '0';
internal_start <= '0';
case next_task_state is case next_task_state is
when work.task.TASK_IDLE => when work.task.TASK_IDLE =>
index <= 0; index <= 0;
signal_write <= '0'; --signal_write <= '0';
current_calc_state <= z1_ADD_READ_FIFO; -- Reset für nächsten Lauf
when work.task.TASK_RUNNING => when work.task.TASK_RUNNING =>
index <= index + 1; --index <= index + 1;
--signal_write <= '1';
--signal_writedata <= (others => '0');
-- Sub State Machine
case current_calc_state is
when z1_ADD_READ_FIFO =>
-- Daten aus den FIFOs anfordern
if (index < work.task.STREAM_LEN) then
current_calc_state <= z2_ADD_CALC;
end if;
when z2_ADD_CALC =>
internal_start <= '1';
-- Warten bis float_add 'done' meldet
if (internal_done = '1') then
internal_start <= '0'; -- Trigger wegnehmen
current_calc_state <= z3_ADD_STORE_RESULT;
else
-- Bleibe hier und warte
current_calc_state <= z2_ADD_CALC;
end if;
when z3_ADD_STORE_RESULT =>
-- Ergebnis schreiben
signal_write <= '1'; signal_write <= '1';
signal_writedata <= ( others => '0' ); signal_writedata <= internal_sum;
-- nicht in Schritt z1_ADD_READ_FIFO!!
signal_a_read <= '1';
signal_b_read <= '1';
-- Index erhöhen
index <= index + 1;
-- Zurück zum Lesen für das nächste Paar
current_calc_state <= z1_ADD_READ_FIFO;
when others =>
current_calc_state <= z1_ADD_READ_FIFO;
end case;
when work.task.TASK_DONE => when work.task.TASK_DONE =>
index <= 0; index <= 0;
signal_write <= '0'; signal_write <= '0';
end case; end case;
end if; end if;
end process sync; end process sync;
@ -75,3 +158,7 @@ begin
task_state <= current_task_state; task_state <= current_task_state;
end architecture rtl; end architecture rtl;

View File

@ -26,7 +26,11 @@ architecture rtl of rand is
signal next_task_state : work.task.State; signal next_task_state : work.task.State;
signal index : integer range 0 to work.task.STREAM_LEN; signal index : integer range 0 to work.task.STREAM_LEN;
-- Register für den LFSR Zustand
signal lfsr_reg : std_logic_vector(31 downto 0);
begin begin
task_state_transitions : process ( current_task_state, task_start, index ) is task_state_transitions : process ( current_task_state, task_start, index ) is
begin begin
next_task_state <= current_task_state; next_task_state <= current_task_state;
@ -36,7 +40,7 @@ begin
next_task_state <= work.task.TASK_RUNNING; next_task_state <= work.task.TASK_RUNNING;
end if; end if;
when work.task.TASK_RUNNING => when work.task.TASK_RUNNING =>
if ( index = work.task.STREAM_LEN - 1 ) then if ( index = work.task.STREAM_LEN ) then
next_task_state <= work.task.TASK_DONE; next_task_state <= work.task.TASK_DONE;
end if; end if;
when work.task.TASK_DONE => when work.task.TASK_DONE =>
@ -47,20 +51,57 @@ begin
end process task_state_transitions; end process task_state_transitions;
sync : process ( clk, reset ) is sync : process ( clk, reset ) is
variable v_feedback : std_logic;
variable v_lfsr_next : std_logic_vector(31 downto 0);
variable v_send_cycle : boolean := true; -- toggle um signal_write nur einen Takt auszugeben
begin begin
if ( reset = '1' ) then if ( reset = '1' ) then
current_task_state <= work.task.TASK_IDLE; current_task_state <= work.task.TASK_IDLE;
index <= 0; index <= 0;
lfsr_reg <= (others => '0');
signal_write <= '0';
signal_writedata <= (others => '0');
v_send_cycle := true;
elsif ( rising_edge( clk ) ) then elsif ( rising_edge( clk ) ) then
current_task_state <= next_task_state; current_task_state <= next_task_state;
case next_task_state is case next_task_state is
when work.task.TASK_IDLE => when work.task.TASK_IDLE =>
index <= 0; index <= 0;
signal_write <= '0'; signal_write <= '0';
lfsr_reg <= seed;
v_send_cycle := true; -- Reset toggle für nächsten Start
when work.task.TASK_RUNNING => when work.task.TASK_RUNNING =>
if v_send_cycle = true then
index <= index + 1; index <= index + 1;
-- 1. LFSR Feedback berechnen (Polynom x^31 + x^21 + x^1 + 1)
v_feedback := lfsr_reg(31) xor lfsr_reg(21) xor lfsr_reg(1) xor lfsr_reg(0);
-- 2. Schieben und neues Bit einfügen
v_lfsr_next := lfsr_reg(30 downto 0) & v_feedback;
-- Register aktualisieren für den nächsten Takt
lfsr_reg <= v_lfsr_next;
-- 3. Daten schreiben und Bit-Manipulation
signal_write <= '1'; signal_write <= '1';
signal_writedata <= ( others => '0' ); -- Wir nutzen hier v_lfsr_next, damit der geschriebene Wert
-- dem aktuellen Berechnungsschritt entspricht.
if v_lfsr_next(30) = '1' then
-- Fall A: Bit 30 ist 1. Bits 29-24 löschen
-- Maske: AND mit 1100 0000 ... (0xC0...)
signal_writedata <= v_lfsr_next and x"C0FFFFFF";
else
-- Fall B: Bit 30 ist 0. Bits 29-25 setzen
-- Maske: OR mit 0011 1110 ... (0x3E...)
signal_writedata <= v_lfsr_next or x"3E000000";
end if;
v_send_cycle := false;
else
signal_write <= '0';
v_send_cycle := true;
end if;
when work.task.TASK_DONE => when work.task.TASK_DONE =>
index <= 0; index <= 0;
signal_write <= '0'; signal_write <= '0';
@ -71,3 +112,4 @@ begin
task_state <= current_task_state; task_state <= current_task_state;
end architecture rtl; end architecture rtl;

View File

@ -26,11 +26,37 @@ end entity sine;
architecture rtl of sine is architecture rtl of sine is
type SineState is(S_IDLE, S_CALC_START, S_WAIT_CALC, S_WRITE);
signal current_sine_state : SineState;
signal s_data_valid : std_logic;
signal s_angle : signed(31 downto 0);
signal s_busy : std_logic;
signal s_result_valid : std_logic;
signal s_sine_out : signed(31 downto 0);
signal current_angle_reg : unsigned(31 downto 0);
signal current_task_state : work.task.State; signal current_task_state : work.task.State;
signal next_task_state : work.task.State; signal next_task_state : work.task.State;
signal index : integer range 0 to work.task.STREAM_LEN; signal index : integer range 0 to work.task.STREAM_LEN;
begin begin
u_float_sine : entity work.float_sine
generic map (
ITERATIONS => 8
)
port map (
clk => clk,
reset => reset,
data_valid => s_data_valid,
angle => s_angle,
busy => s_busy,
result_valid => s_result_valid,
sine => s_sine_out
);
task_state_transitions : process ( current_task_state, task_start, index ) is task_state_transitions : process ( current_task_state, task_start, index ) is
begin begin
next_task_state <= current_task_state; next_task_state <= current_task_state;
@ -40,7 +66,7 @@ begin
next_task_state <= work.task.TASK_RUNNING; next_task_state <= work.task.TASK_RUNNING;
end if; end if;
when work.task.TASK_RUNNING => when work.task.TASK_RUNNING =>
if ( index = work.task.STREAM_LEN - 1 ) then if ( index = work.task.STREAM_LEN ) then
next_task_state <= work.task.TASK_DONE; next_task_state <= work.task.TASK_DONE;
end if; end if;
when work.task.TASK_DONE => when work.task.TASK_DONE =>
@ -51,20 +77,79 @@ begin
end process task_state_transitions; end process task_state_transitions;
sync : process ( clk, reset ) is sync : process ( clk, reset ) is
variable v_exp_sine : unsigned(7 downto 0);
variable v_exp_amp : unsigned(7 downto 0);
variable v_exp_new : unsigned(7 downto 0);
begin begin
if ( reset = '1' ) then if ( reset = '1' ) then
current_task_state <= work.task.TASK_IDLE; current_task_state <= work.task.TASK_IDLE;
index <= 0; index <= 0;
signal_write <= '0';
signal_writedata <= (others => '0');
s_data_valid <= '0';
s_angle <= (others => '0');
current_angle_reg <= (others => '0');
current_sine_state <= S_IDLE;
elsif ( rising_edge( clk ) ) then elsif ( rising_edge( clk ) ) then
current_task_state <= next_task_state; current_task_state <= next_task_state;
signal_write <= '0';
s_data_valid <= '0';
case next_task_state is case next_task_state is
when work.task.TASK_IDLE => when work.task.TASK_IDLE =>
index <= 0; index <= 0;
signal_write <= '0';
current_sine_state <= S_CALC_START;
current_angle_reg <= unsigned(phase);
when work.task.TASK_RUNNING => when work.task.TASK_RUNNING =>
case current_sine_state is
when S_CALC_START =>
s_data_valid <= '1';
s_angle <= signed(current_angle_reg);
if s_busy = '1' then
s_data_valid <= '0'; -- startpulse beenden
index <= index + 1; index <= index + 1;
current_sine_state <= S_WAIT_CALC;
end if;
when S_WAIT_CALC =>
if s_result_valid = '1' and s_busy = '0' then
current_sine_state <= S_WRITE;
end if;
when S_WRITE =>
v_exp_sine := unsigned(s_sine_out(30 downto 23)); -- nur Exponent (30-23)
v_exp_amp := unsigned(amplitude(30 downto 23));
-- (V)errechnen:E_neu = E_sin + E_amp - 127 (127 = bias/verschiebung)
v_exp_new := v_exp_sine + v_exp_amp - 127;
-- ergebnis der mul von sinus und amplitude wieder zusammenstzen
-- da amp immer positiv ist, wird nur vorzeichen von s_sine_out verwendet
signal_writedata <= std_logic(s_sine_out(31)) &
std_logic_vector(v_exp_new) &
std_logic_vector(s_sine_out(22 downto 0));
signal_write <= '1'; signal_write <= '1';
signal_writedata <= ( others => '0' );
current_angle_reg <= current_angle_reg + unsigned(step_size);
current_sine_state <= S_CALC_START;
when others =>
current_sine_state <= S_CALC_START;
end case;
when work.task.TASK_DONE => when work.task.TASK_DONE =>
index <= 0; index <= 0;
signal_write <= '0'; signal_write <= '0';
@ -75,3 +160,4 @@ begin
task_state <= current_task_state; task_state <= current_task_state;
end architecture rtl; end architecture rtl;

View File

@ -4,7 +4,23 @@
int task_add_run( void * task ) { int task_add_run( void * task ) {
// TODO add_config * config = ( add_config * ) task;
for ( uint32_t i = 0; i < DATA_CHANNEL_DEPTH; ++i ) {
float sinus;
// & pointer Adresse von sinus
data_channel_read( config->sources[0], (uint32_t *) & sinus);
float cosinus;
// & pointer Adresse von cosinus
data_channel_read( config->sources[1], (uint32_t *) & cosinus);
float_word result;
result.value = sinus + cosinus;
data_channel_write( config->sink, result.word);
}
return 0; return 0;
} }

View File

@ -2,10 +2,42 @@
#include "system/hardware_task.h" #include "system/hardware_task.h"
#include "system/data_channel.h" #include "system/data_channel.h"
#include "system/float_word.h" #include "system/float_word.h"
#include <stdio.h>
#include <system.h>
int task_rand_run( void * task ) { int task_rand_run( void * task ) {
// TODO rand_config * config = ( rand_config * ) task;
// seed auslesen (Startwert für Algorithmus)
float_word seed = { .value = config->seed };
// LFSR (linear feedback shift register)
uint32_t lfsr = seed.word;
for ( uint32_t i = 0; i < DATA_CHANNEL_DEPTH; ++i ) {
// LFSR Algorithmus
// Polynom: x^31 + x^21 + x^1 + 1
// Bits an Stellen 31, 21, 1 und 0 verknüpfen mit XOR
uint32_t bit = ((lfsr >> 31) ^ (lfsr >> 21) ^ (lfsr >> 1) ^ (lfsr >> 0)) & 1;
// Schiebe links und das neue Bit hinten anfügen
lfsr = (lfsr << 1) | bit;
// IEEE 754 Bit-Manipulation für Exponenten
float_word res;
res.word = lfsr;
// Prüfe Bit 30 (das höchste Bit des Exponenten 127 bias)
if ( res.word & (1 << 30) ) {
// Fall: Hoher Exponent -> Bits 29 bis 24 auf 0 setzen
// Das erzeugt Werte im Bereich um 2^2 (z.B. 4.0 bis 8.0)
res.word &= ~(0x3F << 24);
} else {
// Fall: Niedriger Exponent -> Bits 29 bis 25 auf 1 zwingen
// Das erzeugt Werte im Bereich um 2^-3 (z.B. 0.125)
res.word |= (0x1F << 25);
}
data_channel_write( config->base.sink, res.word );
}
return 0; return 0;
} }

View File

@ -1,10 +1,33 @@
#include "system/task_sine.h" #include "system/task_sine.h"
#include "system/data_channel.h" #include "system/data_channel.h"
#include "system/float_word.h" #include "system/float_word.h"
#include "system/hardware_task.h"
#include "system/sine_config.h"
#include <math.h>
#include <stdio.h>
#include <limits.h>
#include <system.h>
int task_sine_run( void * data ) { int task_sine_run( void * data ) {
// TODO sine_config * task = ( sine_config * ) data;
// Daten aus Konfig holen
uint32_t data_channel_base = task->base.sink;
double period_len = (double)task->samples_per_periode;
float amp = task->amplitude;
double phase = (double)task->phase;
for ( uint32_t i = 0; i < DATA_CHANNEL_DEPTH; ++i ) {
float_word res;
double angle = 2.0 * M_PI * ((double)i / period_len);
res.value = amp * (float)sin(angle + phase);
data_channel_write( data_channel_base, res.word);
}
return 0; return 0;
} }