2025-12-23 10:56:59 +01:00

158 lines
5.0 KiB
VHDL

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
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 angle_reg : signed(31 downto 0);
signal step_size_s : signed(31 downto 0);
signal phase_s : signed(31 downto 0);
signal fs_data_valid : std_logic;
signal fs_busy : std_logic;
signal fs_result_valid: std_logic;
signal fs_sine : signed(31 downto 0);
signal sine_sample : std_logic_vector(31 downto 0);
signal fs_result_valid_d : std_logic;
begin
u_float_sine : entity work.float_sine
generic map (
ITERATIONS => 8
)
port map (
clk => clk,
reset => reset,
data_valid => fs_data_valid,
busy => fs_busy,
result_valid => fs_result_valid,
angle => angle_reg,
sine => fs_sine
);
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 sine_word : std_logic_vector(31 downto 0);
variable sign_bit : std_logic;
variable exp_bits : unsigned(30 downto 23);
variable man_bits : std_logic_vector(22 downto 0);
variable amp_exp : unsigned(30 downto 23);
variable new_exp : unsigned(30 downto 23);
begin
if ( reset = '1' ) then
current_task_state <= work.task.TASK_IDLE;
index <= 0;
angle_reg <= (others => '0');
step_size_s <= (others => '0');
phase_s <= (others => '0');
fs_data_valid <= '0';
signal_write <= '0';
signal_writedata <= (others => '0');
sine_sample <= (others => '0');
fs_result_valid_d <= '0';
elsif ( rising_edge( clk ) ) then
current_task_state <= next_task_state;
fs_data_valid <= '0';
signal_write <= '0';
fs_result_valid_d <= fs_result_valid;
case next_task_state is
when work.task.TASK_IDLE =>
index <= 0;
step_size_s <= signed( step_size );
phase_s <= signed( phase );
angle_reg <= signed( phase );
when work.task.TASK_RUNNING =>
if (index = 0 and fs_busy = '0') then
fs_data_valid <= '1';
end if;
if (fs_result_valid = '1' and fs_result_valid_d = '0') then
sine_word := std_logic_vector(fs_sine);
sign_bit := sine_word(31);
exp_bits := unsigned(sine_word(30 downto 23));
man_bits := sine_word(22 downto 0);
amp_exp := unsigned(amplitude(30 downto 23));
new_exp := exp_bits + (amp_exp - to_unsigned(127, 8));
sine_word(31) := sign_bit;
sine_word(30 downto 23) := std_logic_vector(new_exp);
sine_word(22 downto 0) := man_bits;
signal_write <= '1';
signal_writedata <= sine_word;
angle_reg <= angle_reg + step_size_s;
index <= index + 1;
fs_data_valid <= '1';
end if;
when work.task.TASK_DONE =>
index <= 0;
end case;
end if;
end process sync;
task_state <= current_task_state;
end architecture rtl;