Team 1 Lösung
This commit is contained in:
@@ -26,11 +26,36 @@ 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;
|
||||
|
||||
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 fa_start: std_logic;
|
||||
signal fa_done: std_logic;
|
||||
signal fa_sum: std_logic_vector(31 downto 0);
|
||||
signal a_value: std_logic_vector(31 downto 0);
|
||||
signal b_value: std_logic_vector(31 downto 0);
|
||||
signal sample_done: std_logic;
|
||||
signal calc_cnt_int: integer range 0 to 15;
|
||||
type calc_state_t is (
|
||||
C_IDLE,
|
||||
C_READ_A_REQ, C_READ_A_LATCH,
|
||||
C_READ_B_REQ, C_READ_B_LATCH,
|
||||
C_START_ADD, C_WAIT_ADD,
|
||||
C_WRITE_RESULT
|
||||
);
|
||||
signal calc_state: calc_state_t:=C_IDLE;
|
||||
begin
|
||||
|
||||
u_float_add : entity work.float_add
|
||||
port map(
|
||||
clk => clk,
|
||||
reset => reset,
|
||||
start => fa_start,
|
||||
done => fa_done,
|
||||
A => a_value,
|
||||
B => b_value,
|
||||
sum => fa_sum
|
||||
);
|
||||
task_state_transitions : process ( current_task_state, task_start, index ) is
|
||||
begin
|
||||
next_task_state <= current_task_state;
|
||||
@@ -50,13 +75,33 @@ begin
|
||||
end case;
|
||||
end process task_state_transitions;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sync : process ( clk, reset ) is
|
||||
begin
|
||||
if ( reset = '1' ) then
|
||||
current_task_state <= work.task.TASK_IDLE;
|
||||
if ( reset = '1' ) then
|
||||
current_task_state <= work.task.TASK_IDLE;
|
||||
calc_state <= C_IDLE;
|
||||
signal_a_read <= '0';
|
||||
signal_b_read <= '0';
|
||||
signal_write <= '0';
|
||||
signal_writedata <= (others => '0');
|
||||
calc_cnt_int <= 0;
|
||||
fa_start <= '0';
|
||||
a_value <= (others => '0');
|
||||
b_value <= (others => '0');
|
||||
sample_done <= '0';
|
||||
|
||||
index <= 0;
|
||||
elsif ( rising_edge( clk ) ) then
|
||||
current_task_state <= next_task_state;
|
||||
fa_start <= '0';
|
||||
signal_a_read <= '0';
|
||||
signal_b_read <= '0';
|
||||
signal_write <= '0';
|
||||
sample_done <= '0';
|
||||
case next_task_state is
|
||||
when work.task.TASK_IDLE =>
|
||||
index <= 0;
|
||||
@@ -69,9 +114,58 @@ begin
|
||||
index <= 0;
|
||||
signal_write <= '0';
|
||||
end case;
|
||||
end if;
|
||||
case calc_state is
|
||||
when C_IDLE =>
|
||||
if current_task_state = work.task.TASK_RUNNING then
|
||||
calc_state <= C_READ_A_REQ;
|
||||
end if;
|
||||
when C_READ_A_REQ =>
|
||||
signal_a_read <= '1';
|
||||
calc_state <= C_READ_A_LATCH;
|
||||
|
||||
when C_READ_A_LATCH =>
|
||||
a_value <= signal_a_readdata;
|
||||
calc_state <= C_READ_B_REQ;
|
||||
|
||||
when C_READ_B_REQ =>
|
||||
signal_b_read <= '1';
|
||||
calc_state <= C_READ_B_LATCH;
|
||||
|
||||
when C_READ_B_LATCH =>
|
||||
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 =>
|
||||
if ( fa_done = '1' ) then
|
||||
calc_state <= C_WRITE_RESULT;
|
||||
end if;
|
||||
|
||||
when C_WRITE_RESULT =>
|
||||
signal_write <= '1' ;
|
||||
signal_writedata <= fa_sum;
|
||||
calc_cnt_int <= calc_cnt_int + 1;
|
||||
|
||||
|
||||
end case;
|
||||
end if;
|
||||
end process sync;
|
||||
|
||||
task_state <= current_task_state;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end architecture rtl;
|
||||
|
||||
@@ -1,77 +1,261 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.reg32.all;
|
||||
use work.float.all;
|
||||
use work.task.all;
|
||||
use work.reg32.all;
|
||||
use work.float.all;
|
||||
use work.task.all;
|
||||
|
||||
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;
|
||||
task_start : in std_logic; --Startsignal
|
||||
task_state : out work.task.State; --Ausgang
|
||||
|
||||
step_size : in work.reg32.word;
|
||||
phase : in work.reg32.word;
|
||||
amplitude : in work.reg32.word;
|
||||
step_size : in work.reg32.word; --Winkelinkrement pro Sample
|
||||
phase : in work.reg32.word; --Startwinkel
|
||||
amplitude : in work.reg32.word; --Amplitude
|
||||
|
||||
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
|
||||
|
||||
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 := 0;
|
||||
--Flanken-Erkennung
|
||||
signal task_start_d : std_logic := '0';
|
||||
signal task_start_re : std_logic := '0';
|
||||
--float_sine-IP-core
|
||||
signal fs_data_valid : std_logic := '0'; --eingabe
|
||||
signal fs_busy : std_logic; -- Steuerung
|
||||
signal fs_result_valid : std_logic;
|
||||
signal fs_angle : signed(31 downto 0) := (others => '0');
|
||||
signal fs_sine : signed(31 downto 0); --Ausgabe
|
||||
--Datenpfad
|
||||
signal angle_reg : signed(31 downto 0) := (others => '0'); --aktueller Winkel
|
||||
signal sine_raw_fp : std_logic_vector(31 downto 0) := (others => '0'); --Ergebnis des IP-Cores
|
||||
signal sine_scaled_fp : std_logic_vector(31 downto 0) := (others => '0'); --skaliertes Ergebnis
|
||||
--Calc-FSM
|
||||
type calc_state_t is (
|
||||
C_IDLE,
|
||||
C_START,
|
||||
C_WAIT,
|
||||
C_SCALE,
|
||||
C_WRITE
|
||||
);
|
||||
|
||||
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;
|
||||
|
||||
task_state <= current_task_state;
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Task-FSM transitions
|
||||
--------------------------------------------------------------------------
|
||||
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 ) 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, --Eingabe starten
|
||||
busy => fs_busy, --Core arbeitet
|
||||
result_valid => fs_result_valid, --Ergebnis fertig
|
||||
angle => fs_angle, --Eingabewinkel
|
||||
sine => fs_sine --Ergebnis
|
||||
);
|
||||
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Sync / Datenpfad
|
||||
--------------------------------------------------------------------------
|
||||
--Multiplikation über: neuer_exponent = sin_exp + (amp_exp -127)
|
||||
sync : process(clk, reset)
|
||||
variable sin_exp : unsigned(7 downto 0); --Speichern Sinuszahl
|
||||
variable amp_exp : unsigned(7 downto 0); --Speichern Amplitude
|
||||
variable new_exp : unsigned(7 downto 0); --Speichern neuen Exponenten
|
||||
|
||||
--Exponenten als Integerwerte für Berechnung
|
||||
variable sin_e_i : integer range -255 to 511;
|
||||
variable amp_e_i : integer range -255 to 511;
|
||||
variable new_e_i : integer range -255 to 511;
|
||||
|
||||
begin
|
||||
if reset = '1' then
|
||||
|
||||
current_task_state <= work.task.TASK_IDLE;
|
||||
index <= 0;
|
||||
|
||||
task_start_d <= '0';
|
||||
task_start_re <= '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');
|
||||
|
||||
elsif rising_edge(clk) then
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- rising edge detect
|
||||
------------------------------------------------------------------
|
||||
task_start_re <= task_start and not task_start_d;
|
||||
task_start_d <= task_start;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Defaults
|
||||
------------------------------------------------------------------
|
||||
signal_write <= '0';
|
||||
fs_data_valid <= '0';
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Task-FSM update
|
||||
------------------------------------------------------------------
|
||||
current_task_state <= next_task_state;
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Berechnungs-FSM
|
||||
------------------------------------------------------------------
|
||||
case calc_state is
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Start: Sofort mit erstem Winkel beginnen
|
||||
------------------------------------------------------------------
|
||||
when C_IDLE =>
|
||||
if (current_task_state = work.task.TASK_RUNNING) then
|
||||
angle_reg <= signed(phase);
|
||||
calc_state <= C_START;
|
||||
end if;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Wert in den Core laden, sobald busy='0'
|
||||
------------------------------------------------------------------
|
||||
when C_START =>
|
||||
if fs_busy = '0' then --Wenn Core ist frei
|
||||
fs_data_valid <= '1'; --Input-Latch im Core
|
||||
calc_state <= C_WAIT;
|
||||
end if;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Warten auf Ergebnis
|
||||
------------------------------------------------------------------
|
||||
when C_WAIT => --Warten auf Ergebnis
|
||||
if fs_result_valid = '1' then
|
||||
sine_raw_fp <= std_logic_vector(fs_sine);
|
||||
calc_state <= C_SCALE;
|
||||
end if;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Skalierung
|
||||
------------------------------------------------------------------
|
||||
when C_SCALE =>
|
||||
sin_exp := unsigned(sine_raw_fp(30 downto 23)); --Liest die 8 Exponentenbits des Sinuswerts
|
||||
amp_exp := unsigned(amplitude(30 downto 23)); --Liese die 8 der Amplitude
|
||||
|
||||
sin_e_i := to_integer(sin_exp); --Umwandlung in Integer
|
||||
amp_e_i := to_integer(amp_exp);
|
||||
|
||||
new_e_i := sin_e_i + (amp_e_i - 127); --Eigentliche Multiplikation
|
||||
|
||||
if new_e_i < 0 then -- Falls Wert negativ
|
||||
new_exp := (others => '0'); --Setze Wert auf 0
|
||||
else
|
||||
new_exp := to_unsigned(new_e_i, 8); --Zurückwandeln in 8-Bit-Exponent
|
||||
end if;
|
||||
|
||||
--Berechnten Exponenten wieder zusammensetzen
|
||||
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;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Schreiben + nächsten Winkel
|
||||
------------------------------------------------------------------
|
||||
when C_WRITE =>
|
||||
signal_write <= '1';
|
||||
signal_writedata <= sine_scaled_fp;
|
||||
|
||||
if index = work.task.STREAM_LEN then
|
||||
calc_state <= C_IDLE;
|
||||
else
|
||||
angle_reg <= angle_reg + signed(step_size);
|
||||
calc_state <= C_START;
|
||||
end if;
|
||||
|
||||
end case;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Index update
|
||||
------------------------------------------------------------------
|
||||
case next_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 then
|
||||
index <= index + 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when work.task.TASK_DONE =>
|
||||
index <= 0;
|
||||
|
||||
end case;
|
||||
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture rtl;
|
||||
|
||||
Reference in New Issue
Block a user