143 lines
4.8 KiB
VHDL
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;
|
|
|