beckal87649 4d0bb79521 4.Test
2026-01-13 10:53:22 +01:00

143 lines
4.8 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.reg32.all;
use work.task.all;
entity rand is
port (
clk : in std_logic;
reset : in std_logic;
task_start : in std_logic;
task_state : out work.task.State;
seed : in work.reg32.word;
signal_write : out std_logic;
signal_writedata : out std_logic_vector(31 downto 0)
);
end entity rand;
architecture rtl of rand is
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;
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
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;
lfsr <= (others => '0');
signal_write <= '0';
signal_writedata <= (others => '0');
elsif rising_edge( clk ) then
-- State-Register
current_task_state <= next_task_state;
-- 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;
when work.task.TASK_DONE =>
index <= 0;
when others =>
null;
end case;
end if;
end if;
end process sync;
task_state <= current_task_state;
end architecture rtl;