Lösung Praktikum HW/SW
This commit is contained in:
parent
c90753aa23
commit
b5e28ecc9d
@ -14,60 +14,216 @@ entity add is
|
||||
task_start : in std_logic;
|
||||
task_state : out work.task.State;
|
||||
|
||||
signal_a_read : out std_logic;
|
||||
signal_a_readdata : in std_logic_vector( 31 downto 0 );
|
||||
signal_a_read : out std_logic;
|
||||
signal_a_readdata : in std_logic_vector(31 downto 0);
|
||||
|
||||
signal_b_read : out std_logic;
|
||||
signal_b_readdata : in std_logic_vector( 31 downto 0 );
|
||||
signal_b_read : out std_logic;
|
||||
signal_b_readdata : in std_logic_vector(31 downto 0);
|
||||
|
||||
signal_write : out std_logic;
|
||||
signal_writedata : out std_logic_vector( 31 downto 0 )
|
||||
signal_write : out std_logic;
|
||||
signal_writedata : out std_logic_vector(31 downto 0)
|
||||
);
|
||||
end entity add;
|
||||
|
||||
architecture rtl of add is
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- äußere Task-FSM
|
||||
-------------------------------------------------------------------------
|
||||
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;
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- innere Add-FSM
|
||||
-------------------------------------------------------------------------
|
||||
type AddState is (
|
||||
ADD_IDLE, -- wartet auf run_calc
|
||||
ADD_REQ_SAMPLES, -- Read anfordern
|
||||
ADD_WAIT_DATA, -- einen Takt warten, bis FIFO-Daten gültig sind
|
||||
ADD_START, -- FIFO-Daten latches + float_add starten
|
||||
ADD_WAIT_DONE, -- auf done vom float_add warten
|
||||
ADD_WRITE -- Ergebnis in Senke schreiben
|
||||
);
|
||||
|
||||
signal current_add_state : AddState;
|
||||
signal next_add_state : AddState;
|
||||
|
||||
-- float_add-Schnittstelle
|
||||
signal start_calc : std_logic;
|
||||
signal add_done : std_logic;
|
||||
signal result_sum : std_logic_vector(31 downto 0);
|
||||
|
||||
-- Operanden-Register für den Addierer
|
||||
signal op_a_reg : std_logic_vector(31 downto 0);
|
||||
signal op_b_reg : std_logic_vector(31 downto 0);
|
||||
|
||||
-- Task läuft UND es sind noch Werte zu berechnen
|
||||
signal run_calc : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- float_add mit registrierten Operanden instanzieren
|
||||
-------------------------------------------------------------------------
|
||||
u_float_add : entity work.float_add
|
||||
port map (
|
||||
clk => clk,
|
||||
reset => reset,
|
||||
start => start_calc,
|
||||
A => op_a_reg,
|
||||
B => op_b_reg,
|
||||
done => add_done,
|
||||
sum => result_sum
|
||||
);
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- äußere Task-State-Maschine
|
||||
-------------------------------------------------------------------------
|
||||
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
|
||||
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
|
||||
-- wenn letztes Sample geschrieben wurde -> DONE
|
||||
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
|
||||
if task_start = '1' then
|
||||
next_task_state <= work.task.TASK_RUNNING;
|
||||
end if;
|
||||
|
||||
end case;
|
||||
end process task_state_transitions;
|
||||
|
||||
-- Task läuft UND es sind noch Werte zu berechnen
|
||||
run_calc <= '1' when (current_task_state = work.task.TASK_RUNNING
|
||||
and index < work.task.STREAM_LEN)
|
||||
else '0';
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- innere Add-FSM: kombinatorischer Teil
|
||||
-------------------------------------------------------------------------
|
||||
add_state_transitions : process ( current_add_state, run_calc, add_done, index ) is
|
||||
begin
|
||||
next_add_state <= current_add_state;
|
||||
|
||||
case current_add_state is
|
||||
|
||||
when ADD_IDLE =>
|
||||
if run_calc = '1' then
|
||||
next_add_state <= ADD_REQ_SAMPLES;
|
||||
end if;
|
||||
|
||||
when ADD_REQ_SAMPLES =>
|
||||
-- Read-Impuls, Daten stehen im nächsten Takt an
|
||||
next_add_state <= ADD_WAIT_DATA;
|
||||
|
||||
when ADD_WAIT_DATA =>
|
||||
-- jetzt liegen die neuen FIFO-Werte stabil an,
|
||||
-- im nächsten Zustand werden sie gelatcht + Addition gestartet
|
||||
next_add_state <= ADD_START;
|
||||
|
||||
when ADD_START =>
|
||||
-- Addierer starten, dann auf done warten
|
||||
next_add_state <= ADD_WAIT_DONE;
|
||||
|
||||
when ADD_WAIT_DONE =>
|
||||
if add_done = '1' then
|
||||
next_add_state <= ADD_WRITE;
|
||||
end if;
|
||||
|
||||
when ADD_WRITE =>
|
||||
if index = work.task.STREAM_LEN then
|
||||
next_add_state <= ADD_IDLE;
|
||||
else
|
||||
next_add_state <= ADD_REQ_SAMPLES;
|
||||
end if;
|
||||
|
||||
end case;
|
||||
end process add_state_transitions;
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- synchroner Prozess: Zustände + tatsächliche Ausgänge
|
||||
-------------------------------------------------------------------------
|
||||
sync : process ( clk, reset ) is
|
||||
begin
|
||||
if ( reset = '1' ) then
|
||||
if reset = '1' then
|
||||
current_task_state <= work.task.TASK_IDLE;
|
||||
index <= 0;
|
||||
elsif ( rising_edge( clk ) ) then
|
||||
current_add_state <= ADD_IDLE;
|
||||
index <= 0;
|
||||
|
||||
signal_a_read <= '0';
|
||||
signal_b_read <= '0';
|
||||
signal_write <= '0';
|
||||
signal_writedata <= (others => '0');
|
||||
start_calc <= '0';
|
||||
op_a_reg <= (others => '0');
|
||||
op_b_reg <= (others => '0');
|
||||
|
||||
elsif rising_edge(clk) then
|
||||
-- Zustände übernehmen
|
||||
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';
|
||||
current_add_state <= next_add_state;
|
||||
|
||||
-- Default-Ausgänge pro Takt
|
||||
signal_a_read <= '0';
|
||||
signal_b_read <= '0';
|
||||
signal_write <= '0';
|
||||
start_calc <= '0';
|
||||
|
||||
case current_task_state is
|
||||
|
||||
when work.task.TASK_IDLE =>
|
||||
-- beim Warten Index zurücksetzen
|
||||
index <= 0;
|
||||
|
||||
when work.task.TASK_RUNNING =>
|
||||
case current_add_state is
|
||||
|
||||
when ADD_IDLE =>
|
||||
null;
|
||||
|
||||
when ADD_REQ_SAMPLES =>
|
||||
-- neuen Wert aus beiden FIFOs anfordern
|
||||
signal_a_read <= '1';
|
||||
signal_b_read <= '1';
|
||||
-- FIFO-Daten latches und Addierer starten
|
||||
op_a_reg <= signal_a_readdata;
|
||||
op_b_reg <= signal_b_readdata;
|
||||
|
||||
when ADD_WAIT_DATA =>
|
||||
-- nur warten, bis FIFO-Daten stabil sind
|
||||
null;
|
||||
|
||||
when ADD_START =>
|
||||
start_calc <= '1'; -- Start HIGH
|
||||
|
||||
when ADD_WAIT_DONE =>
|
||||
-- Berechnung läuft weiter -> Start HIGH lassen,
|
||||
-- bis add_done='1' ist
|
||||
start_calc <= '1';
|
||||
|
||||
when ADD_WRITE =>
|
||||
-- Ergebnis schreiben und Index erhöhen
|
||||
signal_write <= '1';
|
||||
signal_writedata <= result_sum;
|
||||
index <= index + 1;
|
||||
|
||||
end case;
|
||||
|
||||
when work.task.TASK_DONE =>
|
||||
null;
|
||||
|
||||
end case;
|
||||
end if;
|
||||
end process sync;
|
||||
@ -75,3 +231,4 @@ begin
|
||||
task_state <= current_task_state;
|
||||
|
||||
end architecture rtl;
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.reg32.all;
|
||||
use work.task.all;
|
||||
@ -10,26 +9,35 @@ entity crc is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
task_start : in std_logic;
|
||||
task_state : out work.task.State;
|
||||
|
||||
signal_read : out std_logic;
|
||||
signal_readdata : in std_logic_vector( 31 downto 0 );
|
||||
|
||||
signal_write : out std_logic;
|
||||
signal_writedata : out std_logic_vector( 31 downto 0 )
|
||||
);
|
||||
end entity crc;
|
||||
|
||||
architecture rtl of crc is
|
||||
|
||||
constant CRC32_POLY_REVERSED : std_logic_vector(31 downto 0) := x"EDB88320";
|
||||
constant CRC32_INIT : std_logic_vector(31 downto 0) := x"FFFFFFFF";
|
||||
|
||||
signal current_task_state : work.task.State;
|
||||
signal next_task_state : work.task.State;
|
||||
signal index : integer range 0 to work.task.STREAM_LEN;
|
||||
|
||||
|
||||
-- CRC Berechnung
|
||||
signal crc_value : std_logic_vector(31 downto 0);
|
||||
|
||||
-- Zustandsmaschine für CRC-Berechnung
|
||||
signal bit_counter : integer range 0 to 32;
|
||||
signal word_buffer : std_logic_vector(31 downto 0);
|
||||
|
||||
type processing_state_t is (IDLE, READ_WAIT, COMPUTE);
|
||||
signal proc_state : processing_state_t;
|
||||
|
||||
begin
|
||||
task_state_transitions : process ( current_task_state, task_start, index ) is
|
||||
task_state_transitions : process ( current_task_state, task_start, index, proc_state ) is
|
||||
begin
|
||||
next_task_state <= current_task_state;
|
||||
case current_task_state is
|
||||
@ -38,7 +46,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 and proc_state = IDLE ) then
|
||||
next_task_state <= work.task.TASK_DONE;
|
||||
end if;
|
||||
when work.task.TASK_DONE =>
|
||||
@ -47,30 +55,91 @@ begin
|
||||
end if;
|
||||
end case;
|
||||
end process task_state_transitions;
|
||||
|
||||
|
||||
sync : process ( clk, reset ) is
|
||||
variable crc_temp : std_logic_vector(31 downto 0);
|
||||
variable bit_in : std_logic;
|
||||
begin
|
||||
if ( reset = '1' ) then
|
||||
current_task_state <= work.task.TASK_IDLE;
|
||||
index <= 0;
|
||||
crc_value <= CRC32_INIT;
|
||||
bit_counter <= 0;
|
||||
proc_state <= IDLE;
|
||||
signal_read <= '0';
|
||||
signal_write <= '0';
|
||||
signal_writedata <= (others => '0');
|
||||
word_buffer <= (others => '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';
|
||||
when work.task.TASK_IDLE =>
|
||||
index <= 0;
|
||||
crc_value <= CRC32_INIT;
|
||||
bit_counter <= 0;
|
||||
proc_state <= IDLE;
|
||||
signal_read <= '0';
|
||||
signal_write <= '0';
|
||||
|
||||
when work.task.TASK_RUNNING =>
|
||||
signal_write <= '0';
|
||||
|
||||
case proc_state is
|
||||
when IDLE =>
|
||||
if index < work.task.STREAM_LEN then
|
||||
-- Leseanfrage starten
|
||||
signal_read <= '1';
|
||||
proc_state <= READ_WAIT;
|
||||
end if;
|
||||
|
||||
when READ_WAIT =>
|
||||
-- Daten sind jetzt verfügbar (nach 1 Takt)
|
||||
signal_read <= '0';
|
||||
word_buffer <= signal_readdata;
|
||||
bit_counter <= 0;
|
||||
proc_state <= COMPUTE;
|
||||
|
||||
when COMPUTE =>
|
||||
-- Bitweise CRC berechnen (32 Bits pro Wort, LSB first)
|
||||
if bit_counter < 32 then
|
||||
crc_temp := crc_value;
|
||||
|
||||
-- Bit aus word_buffer extrahieren (LSB first)
|
||||
bit_in := word_buffer(bit_counter);
|
||||
|
||||
-- CRC Update für ein Bit
|
||||
if (crc_temp(0) xor bit_in) = '1' then
|
||||
crc_temp := ('0' & crc_temp(31 downto 1)) xor CRC32_POLY_REVERSED;
|
||||
else
|
||||
crc_temp := '0' & crc_temp(31 downto 1);
|
||||
end if;
|
||||
|
||||
crc_value <= crc_temp;
|
||||
bit_counter <= bit_counter + 1;
|
||||
else
|
||||
-- Wort fertig verarbeitet, nächstes Wort
|
||||
index <= index + 1;
|
||||
proc_state <= IDLE;
|
||||
end if;
|
||||
end case;
|
||||
|
||||
when work.task.TASK_DONE =>
|
||||
-- Finales CRC schreiben (invertiert)
|
||||
if proc_state = IDLE then
|
||||
signal_write <= '1';
|
||||
signal_writedata <= not crc_value;
|
||||
signal_read <= '0';
|
||||
else
|
||||
signal_write <= '0';
|
||||
proc_state <= IDLE;
|
||||
end if;
|
||||
|
||||
end case;
|
||||
end if;
|
||||
end process sync;
|
||||
|
||||
|
||||
task_state <= current_task_state;
|
||||
|
||||
|
||||
end architecture rtl;
|
||||
|
||||
|
||||
@ -9,69 +9,205 @@ library work;
|
||||
|
||||
entity sine is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
clk : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
task_start : in std_logic;
|
||||
task_state : out work.task.State;
|
||||
|
||||
step_size : in work.reg32.word;
|
||||
phase : in work.reg32.word;
|
||||
phase : in work.reg32.word;
|
||||
amplitude : in work.reg32.word;
|
||||
|
||||
signal_write : out std_logic;
|
||||
signal_writedata : out std_logic_vector( 31 downto 0 )
|
||||
signal_write : out std_logic;
|
||||
signal_writedata : out std_logic_vector(31 downto 0)
|
||||
);
|
||||
end entity sine;
|
||||
|
||||
architecture rtl of sine is
|
||||
|
||||
-- Task-FSM
|
||||
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;
|
||||
|
||||
-- Zähler
|
||||
signal samples_requested : integer range 0 to work.task.STREAM_LEN + 1;
|
||||
signal samples_written : integer range 0 to work.task.STREAM_LEN + 1;
|
||||
|
||||
-- Winkel-Register
|
||||
signal angle_current : signed(31 downto 0);
|
||||
signal step_value : signed(31 downto 0);
|
||||
|
||||
-- float_sine IP-Core Signale
|
||||
signal core_data_valid : std_logic;
|
||||
signal core_busy : std_logic;
|
||||
signal core_result_valid : std_logic;
|
||||
--signal core_angle : signed(31 downto 0);
|
||||
signal core_sine_out : signed(31 downto 0);
|
||||
|
||||
-- Zustandsmaschine für Ablaufsteuerung
|
||||
type calc_state_type is (IDLE, REQUEST, WAIT_RESULT, WRITE);
|
||||
signal calc_state : calc_state_type;
|
||||
|
||||
begin
|
||||
task_state_transitions : process ( current_task_state, task_start, index ) is
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- Task-State-Transitions (NICHT ÄNDERN laut Aufgabe)
|
||||
-------------------------------------------------------------------------
|
||||
task_state_transitions : process (current_task_state, task_start, samples_written) is
|
||||
begin
|
||||
next_task_state <= current_task_state;
|
||||
case current_task_state is
|
||||
when work.task.TASK_IDLE =>
|
||||
if ( task_start = '1' ) then
|
||||
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
|
||||
if samples_written >= 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
|
||||
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;
|
||||
end process;
|
||||
|
||||
task_state <= current_task_state;
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- float_sine IP-Core instanzieren
|
||||
-------------------------------------------------------------------------
|
||||
float_sine_inst : entity work.float_sine
|
||||
generic map (
|
||||
ITERATIONS => 16
|
||||
)
|
||||
port map (
|
||||
clk => clk,
|
||||
reset => reset,
|
||||
data_valid => core_data_valid,
|
||||
angle => angle_current,
|
||||
busy => core_busy,
|
||||
result_valid => core_result_valid,
|
||||
sine => core_sine_out
|
||||
);
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- Kombinatorischer Prozess: Skalierung
|
||||
-------------------------------------------------------------------------
|
||||
scale_output : process (core_sine_out, amplitude) is
|
||||
variable sine_word : std_logic_vector(31 downto 0);
|
||||
variable amp_word : std_logic_vector(31 downto 0);
|
||||
variable expo_sine : unsigned(7 downto 0);
|
||||
variable expo_amp : unsigned(7 downto 0);
|
||||
variable expo_result : unsigned(7 downto 0);
|
||||
variable scaled_word : std_logic_vector(31 downto 0);
|
||||
begin
|
||||
-- Float-Werte als std_logic_vector
|
||||
sine_word := std_logic_vector(core_sine_out);
|
||||
amp_word := amplitude;
|
||||
|
||||
-- Exponenten extrahieren
|
||||
expo_sine := unsigned(sine_word(30 downto 23));
|
||||
expo_amp := unsigned(amp_word(30 downto 23));
|
||||
|
||||
-- Neuer Exponent = Expo(Sine) + (Expo(Amplitude) - 127)
|
||||
expo_result := expo_sine + (expo_amp - to_unsigned(127, 8));
|
||||
|
||||
-- Skaliertes Ergebnis: Sign + Mantisse unverändert, nur Exponent ersetzen
|
||||
scaled_word := sine_word;
|
||||
scaled_word(30 downto 23) := std_logic_vector(expo_result);
|
||||
|
||||
signal_writedata <= scaled_word;
|
||||
end process;
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- Synchroner Prozess: Ablaufsteuerung
|
||||
-------------------------------------------------------------------------
|
||||
sync : process (clk, reset) is
|
||||
begin
|
||||
if reset = '1' then
|
||||
current_task_state <= work.task.TASK_IDLE;
|
||||
samples_requested <= 0;
|
||||
samples_written <= 0;
|
||||
angle_current <= (others => '0');
|
||||
step_value <= (others => '0');
|
||||
core_data_valid <= '0';
|
||||
signal_write <= '0';
|
||||
calc_state <= IDLE;
|
||||
|
||||
elsif rising_edge(clk) then
|
||||
|
||||
-- Task-State übernehmen
|
||||
current_task_state <= next_task_state;
|
||||
|
||||
-- Defaults
|
||||
signal_write <= '0';
|
||||
core_data_valid <= '0';
|
||||
|
||||
case current_task_state is
|
||||
|
||||
when work.task.TASK_IDLE =>
|
||||
samples_requested <= 0;
|
||||
samples_written <= 0;
|
||||
angle_current <= signed(phase);
|
||||
step_value <= signed(step_size);
|
||||
calc_state <= IDLE;
|
||||
|
||||
when work.task.TASK_RUNNING =>
|
||||
|
||||
-- Zustandsmaschine für die Berechnung
|
||||
case calc_state is
|
||||
|
||||
when IDLE =>
|
||||
-- Starte erste Berechnung
|
||||
if samples_requested < work.task.STREAM_LEN+1 then
|
||||
core_data_valid <= '1';
|
||||
samples_requested <= samples_requested + 1;
|
||||
calc_state <= WAIT_RESULT;
|
||||
end if;
|
||||
|
||||
when WAIT_RESULT =>
|
||||
-- Warte auf Ergebnis
|
||||
if core_result_valid = '1' and core_busy = '0' then
|
||||
|
||||
|
||||
-- Inkrementiere Winkel NACH dem Schreiben für nächste Berechnung
|
||||
angle_current <= angle_current + step_value;
|
||||
calc_state <= WRITE;
|
||||
end if;
|
||||
when WRITE =>
|
||||
if samples_written = 0 then
|
||||
calc_state <= REQUEST;
|
||||
samples_written <= samples_written + 1;
|
||||
|
||||
else
|
||||
signal_write <= '1';
|
||||
samples_written <= samples_written + 1;
|
||||
calc_state <= REQUEST;
|
||||
end if;
|
||||
|
||||
when REQUEST =>
|
||||
|
||||
-- Starte nächste Berechnung nur wenn Core nicht busy ist
|
||||
if samples_requested < work.task.STREAM_LEN +1 and core_busy = '0' then
|
||||
core_data_valid <= '1';
|
||||
samples_requested <= samples_requested + 1;
|
||||
calc_state <= WAIT_RESULT;
|
||||
elsif samples_requested >= work.task.STREAM_LEN then
|
||||
calc_state <= IDLE;
|
||||
end if;
|
||||
|
||||
end case;
|
||||
|
||||
when work.task.TASK_DONE =>
|
||||
calc_state <= IDLE;
|
||||
|
||||
end case;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture rtl;
|
||||
|
||||
@ -2,9 +2,26 @@
|
||||
#include "system/data_channel.h"
|
||||
#include "system/float_word.h"
|
||||
|
||||
int task_add_run( void * task ) {
|
||||
int task_add_run( void * task )
|
||||
{
|
||||
// Die Task-Einstellungen liegen als task_base_config vor
|
||||
task_base_config *config = (task_base_config *) task;
|
||||
|
||||
// TODO
|
||||
for (uint32_t i = 0; i < DATA_CHANNEL_DEPTH; i++) {
|
||||
|
||||
float_word a, b, c;
|
||||
|
||||
// aus Quelle 0 lesen
|
||||
data_channel_read(config->sources[0], &a.word);
|
||||
// aus Quelle 1 lesen
|
||||
data_channel_read(config->sources[1], &b.word);
|
||||
|
||||
// Addition der beiden Float-Werte
|
||||
c.value = a.value + b.value;
|
||||
|
||||
// Ergebnis in den Ziel-Data-Channel schreiben
|
||||
data_channel_write(config->sink, c.word);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2,10 +2,46 @@
|
||||
#include "system/data_channel.h"
|
||||
#include "system/float_word.h"
|
||||
|
||||
int task_crc_run( void * task ) {
|
||||
#define CRC32_POLY_REVERSED 0xEDB88320u
|
||||
|
||||
// TODO
|
||||
// CRC32-Update über ein komplettes 32-bit Wort (LSB-first)
|
||||
static inline uint32_t crc32_update_word(uint32_t crc, uint32_t word)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
uint8_t b = (word >> (8 * i)) & 0xFF; // LSB first!
|
||||
crc ^= b;
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
if (crc & 1)
|
||||
crc = (crc >> 1) ^ CRC32_POLY_REVERSED;
|
||||
else
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
int task_crc_run(void *task)
|
||||
{
|
||||
crc_config *config = (crc_config*)task;
|
||||
|
||||
// WICHTIG: Startwert invertieren (wie im PDF Seite 14 beschrieben)
|
||||
uint32_t crc = ~config->start; // = ~0xFFFFFFFF = 0x00000000
|
||||
|
||||
for (uint32_t i = 0; i < DATA_CHANNEL_DEPTH; i++)
|
||||
{
|
||||
uint32_t word;
|
||||
data_channel_read(config->base.sources[0], &word);
|
||||
crc = crc32_update_word(crc, word);
|
||||
}
|
||||
|
||||
// Endwert invertieren (zlib-Standard)
|
||||
crc = ~crc;
|
||||
|
||||
// Ergebnis schreiben
|
||||
data_channel_write(config->base.sink, crc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,35 @@
|
||||
#include "system/task_sine.h"
|
||||
#include "system/data_channel.h"
|
||||
#include "system/float_word.h"
|
||||
#include <math.h>
|
||||
|
||||
int task_sine_run( void * data ) {
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
// TODO
|
||||
int task_sine_run(void *data)
|
||||
{
|
||||
sine_config *task = (sine_config *) data;
|
||||
|
||||
uint32_t data_channel_base = task->base.sink;
|
||||
data_channel_clear(data_channel_base);
|
||||
|
||||
float amplitude = task->amplitude;
|
||||
float phase_rad = task->phase * (float)M_PI / 180.0f;
|
||||
float step = 2.0f * (float)M_PI / (float)task->samples_per_periode;
|
||||
|
||||
for (uint32_t i = 0; i < DATA_CHANNEL_DEPTH; i++)
|
||||
{
|
||||
float angle = phase_rad + i * step;
|
||||
float y = amplitude * sinf(angle);
|
||||
|
||||
float_word res;
|
||||
res.value = y;
|
||||
|
||||
data_channel_write(data_channel_base, res.word);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ sine_config COSINE_CONFIG = {
|
||||
.sink = DATA_CHANNEL_1_BASE,
|
||||
.cycle_count = 0 },
|
||||
.samples_per_periode = 200,
|
||||
.phase = M_PI / 2.0,
|
||||
.phase = 90.0,
|
||||
.amplitude = 2.0 };
|
||||
|
||||
uint32_t to_hardware_step_size( uint32_t steps ) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user