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;