library ieee; 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; entity sine is port ( clk : in std_logic; reset : in std_logic; task_start : in std_logic; --Startsignal task_state : out work.task.State; --Ausgang 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) ); end entity sine; architecture rtl of sine is --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 <= 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;