This commit is contained in:
beckal87649 2026-01-13 10:53:22 +01:00
parent c90753aa23
commit 4d0bb79521
4 changed files with 528 additions and 135 deletions

View File

@ -26,52 +26,170 @@ entity add is
end entity add;
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;
-- Task FSM
signal current_task_state : work.task.State := work.task.TASK_IDLE;
signal next_task_state : work.task.State := work.task.TASK_IDLE;
signal index : integer range 0 to work.task.STREAM_LEN-1 := 0;
-- task_start rising edge detect (combinational pulse)
signal task_start_d : std_logic := '0';
signal task_start_re : std_logic;
-- float_add IP core
signal fa_start : std_logic := '0';
signal fa_done : std_logic := '0';
signal fa_sum : std_logic_vector(31 downto 0);
signal a_value : std_logic_vector(31 downto 0) := (others => '0');
signal b_value : std_logic_vector(31 downto 0) := (others => '0');
-- Calc FSM
type calc_state_t is (
C_IDLE,
C_READ_A,
C_READ_B,
C_START_ADD,
C_WAIT_ADD,
C_WRITE_RESULT
);
signal calc_state : calc_state_t := C_IDLE;
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;
-- combinational rising edge detect
task_start_re <= task_start and not task_start_d;
task_state <= current_task_state;
-- float_add instance
u_float_add : entity work.float_add
port map (
A => a_value,
B => b_value,
clk => clk,
reset => reset,
start => fa_start,
done => fa_done,
sum => fa_sum
);
-- Task FSM transitions (ONLY driver of next_task_state)
task_state_transitions : process(current_task_state, task_start_re, index, calc_state)
begin
next_task_state <= current_task_state;
case current_task_state is
when work.task.TASK_IDLE =>
if task_start_re = '1' then
next_task_state <= work.task.TASK_RUNNING;
end if;
when work.task.TASK_RUNNING =>
if (index = work.task.STREAM_LEN - 1) and (calc_state = C_WRITE_RESULT) then
next_task_state <= work.task.TASK_DONE;
end if;
when work.task.TASK_DONE =>
if task_start_re = '1' then
next_task_state <= work.task.TASK_RUNNING;
end if;
end case;
end process;
-- Synchronous process
sync : process(clk, reset)
begin
if reset = '1' then
current_task_state <= work.task.TASK_IDLE;
index <= 0;
task_start_d <= '0';
calc_state <= C_IDLE;
fa_start <= '0';
signal_a_read <= '0';
signal_b_read <= '0';
signal_write <= '0';
signal_writedata <= (others => '0');
a_value <= (others => '0');
b_value <= (others => '0');
elsif rising_edge(clk) then
-- register delayed start for edge detect
task_start_d <= task_start;
-- defaults
signal_a_read <= '0';
signal_b_read <= '0';
signal_write <= '0';
fa_start <= '0';
-- update task state
current_task_state <= next_task_state;
-- index update
case current_task_state is
when work.task.TASK_IDLE =>
index <= 0;
when work.task.TASK_RUNNING =>
if calc_state = C_WRITE_RESULT then
if index < work.task.STREAM_LEN - 1 then
index <= index + 1;
end if;
end if;
when work.task.TASK_DONE =>
index <= 0;
end case;
-- calc FSM
case calc_state is
when C_IDLE =>
if current_task_state = work.task.TASK_RUNNING then
calc_state <= C_READ_A;
end if;
when C_READ_A =>
signal_a_read <= '1';
a_value <= signal_a_readdata;
calc_state <= C_READ_B;
when C_READ_B =>
signal_b_read <= '1';
b_value <= signal_b_readdata;
calc_state <= C_START_ADD;
when C_START_ADD =>
fa_start <= '1';
calc_state <= C_WAIT_ADD;
when C_WAIT_ADD =>
fa_start <= '1';
if fa_done = '1' then
calc_state <= C_WRITE_RESULT;
end if;
when C_WRITE_RESULT =>
signal_write <= '1';
signal_writedata <= fa_sum;
if index = work.task.STREAM_LEN - 1 then
calc_state <= C_IDLE;
else
calc_state <= C_READ_A;
end if;
end case;
end if;
end process;
end architecture rtl;

View File

@ -22,11 +22,15 @@ end entity rand;
architecture rtl of rand 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 current_task_state : work.task.State := work.task.TASK_IDLE;
signal next_task_state : work.task.State := work.task.TASK_IDLE;
signal index : integer range 0 to work.task.STREAM_LEN-1 := 0;
signal lfsr : std_logic_vector(31 downto 0) := (others => '0');
begin
-- task_state_transitions
task_state_transitions : process ( current_task_state, task_start, index ) is
begin
next_task_state <= current_task_state;
@ -47,27 +51,92 @@ begin
end process task_state_transitions;
sync : process ( clk, reset ) is
variable fb : std_logic;
variable lfsr_work : std_logic_vector(31 downto 0);
variable lfsr_next : std_logic_vector(31 downto 0);
variable exp_rand : std_logic_vector(7 downto 0);
variable exp_new : std_logic_vector(7 downto 0);
variable out_word : std_logic_vector(31 downto 0);
variable do_run : boolean;
variable entering : boolean;
begin
if ( reset = '1' ) then
current_task_state <= work.task.TASK_IDLE;
index <= 0;
elsif ( rising_edge( clk ) ) then
lfsr <= (others => '0');
signal_write <= '0';
signal_writedata <= (others => '0');
elsif rising_edge( clk ) then
-- State-Register
current_task_state <= next_task_state;
case next_task_state is
-- Defaults (wichtig für assert_level)
signal_write <= '0';
signal_writedata <= (others => '0');
-- Datapath-Steuerung:
-- RUNNING-Aktionen ausführen, wenn
-- a) gerade RUNNING sind (auch wenn next schon DONE ist -> letztes Sample!)
-- b) in RUNNING eintreten (IDLE/DONE -> RUNNING)
entering := (current_task_state /= work.task.TASK_RUNNING) and (next_task_state = work.task.TASK_RUNNING);
do_run := (current_task_state = work.task.TASK_RUNNING) or entering;
if do_run then
-- LFSR-Quelle: beim Eintritt seed, sonst aktueller lfsr
if entering then
lfsr_work := seed;
index <= 0; -- erstes Sample hat Index 0
else
lfsr_work := lfsr;
end if;
-- Output aus aktuellem Zustand bauen
exp_rand := lfsr_work(30 downto 23);
if exp_rand(7) = '1' then
exp_new(7) := '1';
exp_new(6 downto 1) := (others => '0');
exp_new(0) := exp_rand(0);
else
exp_new(7) := '0';
exp_new(6 downto 2) := (others => '1');
exp_new(1 downto 0) := exp_rand(1 downto 0);
end if;
out_word(31) := lfsr_work(31);
out_word(30 downto 23) := exp_new;
out_word(22 downto 0) := lfsr_work(22 downto 0);
signal_write <= '1';
signal_writedata <= out_word;
-- LFSR Schritt nach Ausgabe
fb := lfsr_work(31) xor lfsr_work(21) xor lfsr_work(1) xor lfsr_work(0);
lfsr_next := lfsr_work(30 downto 0) & fb;
lfsr <= lfsr_next;
-- Index nach Write erhöhen
if index < work.task.STREAM_LEN - 1 then
index <= index + 1;
end if;
else
case current_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 others =>
null;
end case;
end if;
end if;
end process sync;
task_state <= current_task_state;
end architecture rtl;

View File

@ -22,56 +22,235 @@ entity sine is
signal_write : out std_logic;
signal_writedata : out std_logic_vector(31 downto 0)
);
end entity sine;
end entity;
architecture rtl of sine 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;
-- Task FSM states
signal current_task_state : work.task.State := work.task.TASK_IDLE;
signal next_task_state : work.task.State := work.task.TASK_IDLE;
signal index : integer range 0 to work.task.STREAM_LEN-1 := 0;
-- Rising-edge detector (only task_start_d is registered)
signal task_start_d : std_logic := '0';
signal task_start_re : std_logic;
-- float_sine IP core
signal fs_data_valid : std_logic := '0';
signal fs_busy : std_logic;
signal fs_result_valid : std_logic;
signal fs_angle : signed(31 downto 0) := (others => '0');
signal fs_sine : signed(31 downto 0);
-- Data pipeline
signal angle_reg : signed(31 downto 0) := (others => '0');
signal sine_raw_fp : std_logic_vector(31 downto 0) := (others => '0');
signal sine_scaled_fp : std_logic_vector(31 downto 0) := (others => '0');
-- Calculation FSM
type calc_state_t is (
C_IDLE,
C_PREPARE,
C_START,
C_WAIT,
C_SCALE,
C_WRITE
);
signal calc_state : calc_state_t := C_IDLE;
-- Pipeline warm-up fix (CORDIC output invalid on first result_valid)
signal first_result_seen : std_logic := '0';
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;
-- combinational rising-edge detect (1-cycle faster than registered pulse)
task_start_re <= task_start and not task_start_d;
-- Output current task state
task_state <= current_task_state;
end architecture rtl;
-- Task FSM (combinational)
task_fsm : process(current_task_state, task_start_re, index, calc_state)
begin
next_task_state <= current_task_state;
case current_task_state is
when work.task.TASK_IDLE =>
if task_start_re = '1' then
next_task_state <= work.task.TASK_RUNNING;
end if;
when work.task.TASK_RUNNING =>
if (index = work.task.STREAM_LEN - 1) and (calc_state = C_WRITE) then
next_task_state <= work.task.TASK_DONE;
end if;
when work.task.TASK_DONE =>
if task_start_re = '1' then
next_task_state <= work.task.TASK_RUNNING;
end if;
end case;
end process;
-- float_sine instantiation
fs_angle <= angle_reg;
u_float_sine : entity work.float_sine
generic map (
ITERATIONS => 8
)
port map (
clk => clk,
reset => reset,
data_valid => fs_data_valid,
busy => fs_busy,
result_valid => fs_result_valid,
angle => fs_angle,
sine => fs_sine
);
sync : process(clk, reset)
variable sin_exp : unsigned(7 downto 0);
variable amp_exp : unsigned(7 downto 0);
variable new_exp : unsigned(7 downto 0);
variable sin_e_i : integer;
variable amp_e_i : integer;
variable new_e_i : integer;
begin
if reset = '1' then
current_task_state <= work.task.TASK_IDLE;
index <= 0;
task_start_d <= '0';
calc_state <= C_IDLE;
angle_reg <= (others => '0');
sine_raw_fp <= (others => '0');
sine_scaled_fp <= (others => '0');
fs_data_valid <= '0';
signal_write <= '0';
signal_writedata <= (others => '0');
first_result_seen <= '0';
elsif rising_edge(clk) then
task_start_d <= task_start;
-- Default outputs
signal_write <= '0';
fs_data_valid <= '0';
-- Update Task FSM
current_task_state <= next_task_state;
-- Index update
case current_task_state is
when work.task.TASK_IDLE =>
index <= 0;
when work.task.TASK_RUNNING =>
if calc_state = C_WRITE then
if index < work.task.STREAM_LEN - 1 then
index <= index + 1;
end if;
end if;
when work.task.TASK_DONE =>
index <= 0;
end case;
-- Calculation FSM
case calc_state is
when C_IDLE =>
if current_task_state = work.task.TASK_RUNNING then
angle_reg <= signed(phase);
first_result_seen <= '0';
calc_state <= C_PREPARE;
end if;
when C_PREPARE =>
calc_state <= C_START;
when C_START =>
if fs_busy = '0' then
fs_data_valid <= '1';
calc_state <= C_WAIT;
end if;
when C_WAIT =>
if fs_result_valid = '1' then
if first_result_seen = '0' then
first_result_seen <= '1';
angle_reg <= angle_reg + signed(step_size);
calc_state <= C_START;
else
sine_raw_fp <= std_logic_vector(fs_sine);
calc_state <= C_SCALE;
end if;
end if;
when C_SCALE =>
sin_exp := unsigned(sine_raw_fp(30 downto 23));
amp_exp := unsigned(amplitude(30 downto 23));
sin_e_i := to_integer(sin_exp);
amp_e_i := to_integer(amp_exp);
new_e_i := sin_e_i + (amp_e_i - 127);
if new_e_i < 0 then
new_exp := (others => '0');
else
new_exp := to_unsigned(new_e_i, 8);
end if;
sine_scaled_fp(31) <= sine_raw_fp(31);
sine_scaled_fp(30 downto 23) <= std_logic_vector(new_exp);
sine_scaled_fp(22 downto 0) <= sine_raw_fp(22 downto 0);
calc_state <= C_WRITE;
when C_WRITE =>
signal_write <= '1';
signal_writedata <= sine_scaled_fp;
if index = work.task.STREAM_LEN - 1 then
calc_state <= C_IDLE;
else
angle_reg <= angle_reg + signed(step_size);
calc_state <= C_START;
end if;
end case;
end if;
end process;
end architecture;

View File

@ -3,10 +3,37 @@
#include "system/data_channel.h"
#include "system/float_word.h"
int task_rand_run( void * task ) {
int task_rand_run(void *task)
{
rand_config *config = (rand_config *)task;
// TODO
uint32_t data_channel_base = config->base.sink;
data_channel_clear(data_channel_base);
float_word seed_fw = { .value = config->seed };
uint32_t lfsr = seed_fw.word;
for (uint32_t i = 0; i < DATA_CHANNEL_DEPTH; ++i) {
uint32_t sign = (lfsr >> 31) & 0x1u;
uint32_t mant = lfsr & 0x007FFFFFu; // 23 Bit Mantisse
uint32_t exp_rand = (lfsr >> 23) & 0xFFu; // 8 Bit Exponent
uint32_t exp_new;
if (exp_rand & 0x80u) {
exp_new = 0x80u | (exp_rand & 0x01u);
} else {
exp_new = 0x7Cu | (exp_rand & 0x03u);
}
float_word out;
out.word = (sign << 31) | (exp_new << 23) | mant;
data_channel_write(data_channel_base, out.word);
uint32_t fb = ((lfsr >> 31) ^ (lfsr >> 21) ^ (lfsr >> 1) ^ (lfsr >> 0)) & 0x1u;
lfsr = (lfsr << 1) | fb;
}
return 0;
}