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; task_state : out work.task.State; step_size : 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 ) ); end entity sine; architecture rtl of sine is type SineState is(S_IDLE, S_CALC_START, S_WAIT_CALC, S_WRITE); signal current_sine_state : SineState; signal s_data_valid : std_logic; signal s_angle : signed(31 downto 0); signal s_busy : std_logic; signal s_result_valid : std_logic; signal s_sine_out : signed(31 downto 0); signal current_angle_reg : unsigned(31 downto 0); signal current_task_state : work.task.State; signal next_task_state : work.task.State; signal index : integer range 0 to work.task.STREAM_LEN; begin u_float_sine : entity work.float_sine generic map ( ITERATIONS => 8 ) port map ( clk => clk, reset => reset, data_valid => s_data_valid, angle => s_angle, busy => s_busy, result_valid => s_result_valid, sine => s_sine_out ); 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 ) 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 v_exp_sine : unsigned(7 downto 0); variable v_exp_amp : unsigned(7 downto 0); variable v_exp_new : unsigned(7 downto 0); begin if ( reset = '1' ) then current_task_state <= work.task.TASK_IDLE; index <= 0; signal_write <= '0'; signal_writedata <= (others => '0'); s_data_valid <= '0'; s_angle <= (others => '0'); current_angle_reg <= (others => '0'); current_sine_state <= S_IDLE; elsif ( rising_edge( clk ) ) then current_task_state <= next_task_state; signal_write <= '0'; s_data_valid <= '0'; case next_task_state is when work.task.TASK_IDLE => index <= 0; current_sine_state <= S_CALC_START; current_angle_reg <= unsigned(phase); when work.task.TASK_RUNNING => case current_sine_state is when S_CALC_START => s_data_valid <= '1'; s_angle <= signed(current_angle_reg); if s_busy = '1' then s_data_valid <= '0'; -- startpulse beenden index <= index + 1; current_sine_state <= S_WAIT_CALC; end if; when S_WAIT_CALC => if s_result_valid = '1' and s_busy = '0' then current_sine_state <= S_WRITE; end if; when S_WRITE => v_exp_sine := unsigned(s_sine_out(30 downto 23)); -- nur Exponent (30-23) v_exp_amp := unsigned(amplitude(30 downto 23)); -- (V)errechnen:E_neu = E_sin + E_amp - 127 (127 = bias/verschiebung) v_exp_new := v_exp_sine + v_exp_amp - 127; -- ergebnis der mul von sinus und amplitude wieder zusammenstzen -- da amp immer positiv ist, wird nur vorzeichen von s_sine_out verwendet signal_writedata <= std_logic(s_sine_out(31)) & std_logic_vector(v_exp_new) & std_logic_vector(s_sine_out(22 downto 0)); signal_write <= '1'; current_angle_reg <= current_angle_reg + unsigned(step_size); current_sine_state <= S_CALC_START; when others => current_sine_state <= S_CALC_START; end case; when work.task.TASK_DONE => index <= 0; signal_write <= '0'; end case; end if; end process sync; task_state <= current_task_state; end architecture rtl;