fertig
This commit is contained in:
parent
c90753aa23
commit
0baa59d050
@ -26,52 +26,139 @@ entity add is
|
||||
end entity add;
|
||||
|
||||
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 next_task_state : work.task.State;
|
||||
signal index : integer range 0 to work.task.STREAM_LEN;
|
||||
signal next_task_state : work.task.State;
|
||||
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
|
||||
task_state_transitions : process ( current_task_state, task_start, index ) 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
|
||||
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;
|
||||
end if;
|
||||
end case;
|
||||
end process task_state_transitions;
|
||||
|
||||
sync : process ( clk, reset ) is
|
||||
begin
|
||||
if ( reset = '1' ) then
|
||||
current_task_state <= work.task.TASK_IDLE;
|
||||
index <= 0;
|
||||
elsif ( rising_edge( clk ) ) then
|
||||
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';
|
||||
end case;
|
||||
end if;
|
||||
end process sync;
|
||||
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 <= current_task_state;
|
||||
task_state_transition : process (current_task_state, task_start, index ) 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) 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;
|
||||
end if;
|
||||
end case;
|
||||
end process task_state_transition;
|
||||
|
||||
|
||||
sync : process (clk, reset) is
|
||||
begin
|
||||
if (reset = '1') then
|
||||
current_task_state <= work.task.TASK_IDLE;
|
||||
index <= 0;
|
||||
|
||||
-- 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;
|
||||
|
||||
-- defaults für Steuersignale
|
||||
signal_a_read <= '0';
|
||||
signal_b_read <= '0';
|
||||
signal_write <= '0';
|
||||
internal_start <= '0';
|
||||
|
||||
case next_task_state is
|
||||
when work.task.TASK_IDLE =>
|
||||
index <= 0;
|
||||
--signal_write <= '0';
|
||||
current_calc_state <= z1_ADD_READ_FIFO; -- Reset für nächsten Lauf
|
||||
when work.task.TASK_RUNNING =>
|
||||
--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_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 =>
|
||||
index <= 0;
|
||||
signal_write <= '0';
|
||||
|
||||
|
||||
end case;
|
||||
end if;
|
||||
end process sync;
|
||||
|
||||
task_state <= current_task_state;
|
||||
|
||||
end architecture rtl;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -26,7 +26,11 @@ architecture rtl of rand is
|
||||
signal next_task_state : work.task.State;
|
||||
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
|
||||
|
||||
task_state_transitions : process ( current_task_state, task_start, index ) is
|
||||
begin
|
||||
next_task_state <= current_task_state;
|
||||
@ -36,7 +40,7 @@ begin
|
||||
next_task_state <= work.task.TASK_RUNNING;
|
||||
end if;
|
||||
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;
|
||||
end if;
|
||||
when work.task.TASK_DONE =>
|
||||
@ -47,23 +51,60 @@ begin
|
||||
end process task_state_transitions;
|
||||
|
||||
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
|
||||
if ( reset = '1' ) then
|
||||
current_task_state <= work.task.TASK_IDLE;
|
||||
index <= 0;
|
||||
lfsr_reg <= (others => '0');
|
||||
signal_write <= '0';
|
||||
signal_writedata <= (others => '0');
|
||||
v_send_cycle := true;
|
||||
|
||||
elsif ( rising_edge( clk ) ) then
|
||||
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';
|
||||
when work.task.TASK_IDLE =>
|
||||
index <= 0;
|
||||
signal_write <= '0';
|
||||
lfsr_reg <= seed;
|
||||
v_send_cycle := true; -- Reset toggle für nächsten Start
|
||||
when work.task.TASK_RUNNING =>
|
||||
if v_send_cycle = true then
|
||||
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';
|
||||
-- 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 =>
|
||||
index <= 0;
|
||||
signal_write <= '0';
|
||||
end case;
|
||||
end if;
|
||||
end process sync;
|
||||
@ -71,3 +112,4 @@ begin
|
||||
task_state <= current_task_state;
|
||||
|
||||
end architecture rtl;
|
||||
|
||||
|
||||
@ -25,12 +25,38 @@ entity sine is
|
||||
end entity sine;
|
||||
|
||||
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 next_task_state : work.task.State;
|
||||
signal index : integer range 0 to work.task.STREAM_LEN;
|
||||
|
||||
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
|
||||
begin
|
||||
next_task_state <= current_task_state;
|
||||
@ -40,7 +66,7 @@ begin
|
||||
next_task_state <= work.task.TASK_RUNNING;
|
||||
end if;
|
||||
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;
|
||||
end if;
|
||||
when work.task.TASK_DONE =>
|
||||
@ -51,20 +77,79 @@ begin
|
||||
end process task_state_transitions;
|
||||
|
||||
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
|
||||
if ( reset = '1' ) then
|
||||
current_task_state <= work.task.TASK_IDLE;
|
||||
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
|
||||
current_task_state <= next_task_state;
|
||||
|
||||
signal_write <= '0';
|
||||
s_data_valid <= '0';
|
||||
|
||||
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_IDLE =>
|
||||
index <= 0;
|
||||
|
||||
current_sine_state <= S_CALC_START;
|
||||
current_angle_reg <= unsigned(phase);
|
||||
|
||||
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;
|
||||
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';
|
||||
|
||||
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 =>
|
||||
index <= 0;
|
||||
signal_write <= '0';
|
||||
@ -75,3 +160,4 @@ begin
|
||||
task_state <= current_task_state;
|
||||
|
||||
end architecture rtl;
|
||||
|
||||
|
||||
@ -4,8 +4,24 @@
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,43 @@
|
||||
#include "system/task_rand.h"
|
||||
#include "system/task_rand.h"
|
||||
#include "system/hardware_task.h"
|
||||
#include "system/data_channel.h"
|
||||
#include "system/float_word.h"
|
||||
#include <stdio.h>
|
||||
#include <system.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1,10 +1,33 @@
|
||||
#include "system/task_sine.h"
|
||||
#include "system/data_channel.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 ) {
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user