164 lines
5.1 KiB
VHDL
164 lines
5.1 KiB
VHDL
LIBRARY IEEE;
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
|
|
|
-- Uncomment the following library declaration if using
|
|
-- arithmetic functions with Signed or Unsigned values
|
|
USE IEEE.NUMERIC_STD.ALL;
|
|
|
|
ENTITY LFO IS
|
|
GENERIC (
|
|
CHANNEL_LENGHT : INTEGER := 24;
|
|
JOYSTICK_LENGHT : INTEGER := 10;
|
|
CLK_PERIOD_NS : INTEGER := 10;
|
|
TRIANGULAR_COUNTER_LENGHT : INTEGER := 10 -- Triangular wave period length
|
|
);
|
|
PORT (
|
|
|
|
aclk : IN STD_LOGIC;
|
|
aresetn : IN STD_LOGIC;
|
|
|
|
lfo_period : IN STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0);
|
|
|
|
lfo_enable : IN STD_LOGIC;
|
|
|
|
s_axis_tvalid : IN STD_LOGIC;
|
|
s_axis_tdata : IN STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0);
|
|
s_axis_tlast : IN STD_LOGIC;
|
|
s_axis_tready : OUT STD_LOGIC;
|
|
|
|
m_axis_tvalid : OUT STD_LOGIC;
|
|
m_axis_tdata : OUT STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0);
|
|
m_axis_tlast : OUT STD_LOGIC;
|
|
m_axis_tready : IN STD_LOGIC
|
|
);
|
|
END ENTITY LFO;
|
|
|
|
ARCHITECTURE Behavioral OF LFO IS
|
|
|
|
CONSTANT LFO_COUNTER_BASE_PERIOD_US : INTEGER := 1000; -- 1ms
|
|
CONSTANT ADJUSTMENT_FACTOR : INTEGER := 90;
|
|
CONSTANT JSTK_CENTER_VALUE : INTEGER := 2 ** (JOYSTICK_LENGHT - 1);
|
|
constant LFO_COUNTER_BASE_CLK_CYCLES : INTEGER := LFO_COUNTER_BASE_PERIOD_US * 1000 / CLK_PERIOD_NS;
|
|
|
|
SIGNAL step_clk_cycles : INTEGER := LFO_COUNTER_BASE_CLK_CYCLES;
|
|
SIGNAL step_counter : INTEGER := 1;
|
|
SIGNAL tri_counter : signed(TRIANGULAR_COUNTER_LENGHT - 1 DOWNTO 0) := (OTHERS => '0');
|
|
SIGNAL direction_up : STD_LOGIC := '1';
|
|
SIGNAL lfo_product : STD_LOGIC_VECTOR(CHANNEL_LENGHT + TRIANGULAR_COUNTER_LENGHT - 1 DOWNTO 0) := (OTHERS => '0');
|
|
|
|
SIGNAL trigger : STD_LOGIC := '0';
|
|
|
|
SIGNAL s_axis_tready_int : STD_LOGIC := '0';
|
|
SIGNAL m_axis_tvalid_int : STD_LOGIC := '0';
|
|
|
|
BEGIN
|
|
|
|
-- Output assignments
|
|
s_axis_tready <= s_axis_tready_int;
|
|
m_axis_tvalid <= m_axis_tvalid_int;
|
|
|
|
-- LFO period adjustment process
|
|
PROCESS (aclk)
|
|
BEGIN
|
|
IF rising_edge(aclk) THEN
|
|
step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES - ADJUSTMENT_FACTOR * to_integer(JSTK_CENTER_VALUE - unsigned(lfo_period));
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
-- Optimized single process for LFO step and triangular waveform generation
|
|
PROCESS (aclk)
|
|
BEGIN
|
|
IF rising_edge(aclk) THEN
|
|
|
|
IF aresetn = '0' THEN
|
|
step_counter <= 0;
|
|
tri_counter <= (OTHERS => '0');
|
|
direction_up <= '1';
|
|
|
|
ELSE
|
|
|
|
IF lfo_enable = '1' THEN
|
|
|
|
IF step_counter < step_clk_cycles THEN
|
|
step_counter <= step_counter + 1;
|
|
|
|
ELSE
|
|
step_counter <= 0;
|
|
|
|
IF direction_up = '1' THEN
|
|
|
|
IF tri_counter = 2 ** TRIANGULAR_COUNTER_LENGHT - 1 THEN
|
|
direction_up <= '0';
|
|
tri_counter <= tri_counter - 1;
|
|
ELSE
|
|
tri_counter <= tri_counter + 1;
|
|
END IF;
|
|
|
|
ELSE
|
|
IF tri_counter = 0 THEN
|
|
direction_up <= '1';
|
|
tri_counter <= tri_counter + 1;
|
|
ELSE
|
|
tri_counter <= tri_counter - 1;
|
|
END IF;
|
|
|
|
END IF;
|
|
|
|
END IF;
|
|
|
|
END IF;
|
|
|
|
END IF;
|
|
|
|
END IF;
|
|
|
|
END PROCESS;
|
|
|
|
-- Handshake logic for the AXIS interface
|
|
PROCESS (aclk)
|
|
BEGIN
|
|
IF rising_edge(aclk) THEN
|
|
|
|
IF aresetn = '0' THEN
|
|
s_axis_tready_int <= '0';
|
|
m_axis_tvalid_int <= '0';
|
|
m_axis_tdata <= (OTHERS => '0');
|
|
m_axis_tlast <= '0';
|
|
|
|
ELSE
|
|
-- Set the ready signal for the slave interface
|
|
s_axis_tready_int <= m_axis_tready OR NOT m_axis_tvalid_int;
|
|
|
|
-- Clear valid flag when master interface is ready
|
|
IF m_axis_tready = '1' THEN
|
|
m_axis_tvalid_int <= '0';
|
|
END IF;
|
|
|
|
IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
|
|
m_axis_tvalid_int <= '1';
|
|
m_axis_tlast <= s_axis_tlast;
|
|
m_axis_tdata <= lfo_product(CHANNEL_LENGHT + TRIANGULAR_COUNTER_LENGHT - 1 DOWNTO TRIANGULAR_COUNTER_LENGHT);
|
|
|
|
trigger <= '0';
|
|
END IF;
|
|
|
|
-- Handle input data
|
|
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
|
|
IF lfo_enable = '1' THEN
|
|
lfo_product <= STD_LOGIC_VECTOR(
|
|
signed(s_axis_tdata) * tri_counter
|
|
);
|
|
ELSE
|
|
lfo_product <= s_axis_tdata;
|
|
END IF;
|
|
|
|
trigger <= '1';
|
|
END IF;
|
|
|
|
END IF;
|
|
|
|
END IF;
|
|
|
|
END PROCESS;
|
|
|
|
END ARCHITECTURE Behavioral; |