Update LFO simulation parameters and add new LFO entity; adjust timing and signal handling
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
--Copyright 1986-2020 Xilinx, Inc. All Rights Reserved.
|
--Copyright 1986-2020 Xilinx, Inc. All Rights Reserved.
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
--Tool Version: Vivado v.2020.2 (win64) Build 3064766 Wed Nov 18 09:12:45 MST 2020
|
--Tool Version: Vivado v.2020.2 (win64) Build 3064766 Wed Nov 18 09:12:45 MST 2020
|
||||||
--Date : Tue May 27 14:09:13 2025
|
--Date : Tue May 27 15:42:43 2025
|
||||||
--Host : Davide-Samsung running 64-bit major release (build 9200)
|
--Host : Davide-Samsung running 64-bit major release (build 9200)
|
||||||
--Command : generate_target lab_3_wrapper.bd
|
--Command : generate_target lab_3_wrapper.bd
|
||||||
--Design : lab_3_wrapper
|
--Design : lab_3_wrapper
|
||||||
|
|||||||
@@ -21,9 +21,8 @@
|
|||||||
<key attr.name="vert_type" attr.type="string" for="node" id="VT"/>
|
<key attr.name="vert_type" attr.type="string" for="node" id="VT"/>
|
||||||
<graph edgedefault="undirected" id="G" parse.edgeids="canonical" parse.nodeids="canonical" parse.order="nodesfirst">
|
<graph edgedefault="undirected" id="G" parse.edgeids="canonical" parse.nodeids="canonical" parse.order="nodesfirst">
|
||||||
<node id="n0">
|
<node id="n0">
|
||||||
<data key="VH">2</data>
|
|
||||||
<data key="VM">lab_3</data>
|
<data key="VM">lab_3</data>
|
||||||
<data key="VT">VR</data>
|
<data key="VT">BC</data>
|
||||||
</node>
|
</node>
|
||||||
<node id="n1">
|
<node id="n1">
|
||||||
<data key="TU">active</data>
|
<data key="TU">active</data>
|
||||||
@@ -31,12 +30,13 @@
|
|||||||
<data key="VT">PM</data>
|
<data key="VT">PM</data>
|
||||||
</node>
|
</node>
|
||||||
<node id="n2">
|
<node id="n2">
|
||||||
|
<data key="VH">2</data>
|
||||||
<data key="VM">lab_3</data>
|
<data key="VM">lab_3</data>
|
||||||
<data key="VT">BC</data>
|
<data key="VT">VR</data>
|
||||||
</node>
|
</node>
|
||||||
<edge id="e0" source="n2" target="n0">
|
<edge id="e0" source="n0" target="n2">
|
||||||
</edge>
|
</edge>
|
||||||
<edge id="e1" source="n0" target="n1">
|
<edge id="e1" source="n2" target="n1">
|
||||||
</edge>
|
</edge>
|
||||||
</graph>
|
</graph>
|
||||||
</graphml>
|
</graphml>
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ BEGIN
|
|||||||
|
|
||||||
-- Imposta parametri iniziali
|
-- Imposta parametri iniziali
|
||||||
lfo_enable <= '1';
|
lfo_enable <= '1';
|
||||||
lfo_period <= std_logic_vector(to_unsigned(1, JOYSTICK_LENGHT));
|
lfo_period <= std_logic_vector(to_unsigned(1023, JOYSTICK_LENGHT));
|
||||||
|
|
||||||
WHILE TRUE LOOP
|
WHILE TRUE LOOP
|
||||||
-- Prepara il dato
|
-- Prepara il dato
|
||||||
@@ -134,10 +134,10 @@ BEGIN
|
|||||||
-- Simula backpressure abbassando m_axis_tready ogni tanto
|
-- Simula backpressure abbassando m_axis_tready ogni tanto
|
||||||
backpressure_proc : PROCESS
|
backpressure_proc : PROCESS
|
||||||
BEGIN
|
BEGIN
|
||||||
WAIT FOR 60 ns;
|
WAIT FOR 200 ns;
|
||||||
WAIT UNTIL rising_edge(aclk);
|
WAIT UNTIL rising_edge(aclk);
|
||||||
m_axis_tready <= '0';
|
m_axis_tready <= '0';
|
||||||
WAIT FOR 20 ns;
|
WAIT FOR 500 ns;
|
||||||
WAIT UNTIL rising_edge(aclk);
|
WAIT UNTIL rising_edge(aclk);
|
||||||
m_axis_tready <= '1';
|
m_axis_tready <= '1';
|
||||||
WAIT;
|
WAIT;
|
||||||
|
|||||||
205
LAB3/src/LFO.vhd
205
LAB3/src/LFO.vhd
@@ -1,8 +1,5 @@
|
|||||||
LIBRARY IEEE;
|
LIBRARY IEEE;
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
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;
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
ENTITY LFO IS
|
ENTITY LFO IS
|
||||||
@@ -10,22 +7,19 @@ ENTITY LFO IS
|
|||||||
CHANNEL_LENGHT : INTEGER := 24;
|
CHANNEL_LENGHT : INTEGER := 24;
|
||||||
JOYSTICK_LENGHT : INTEGER := 10;
|
JOYSTICK_LENGHT : INTEGER := 10;
|
||||||
CLK_PERIOD_NS : INTEGER := 10;
|
CLK_PERIOD_NS : INTEGER := 10;
|
||||||
TRIANGULAR_COUNTER_LENGHT : INTEGER := 10 -- Triangular wave period length
|
TRIANGULAR_COUNTER_LENGHT : INTEGER := 10
|
||||||
);
|
);
|
||||||
PORT (
|
PORT (
|
||||||
|
|
||||||
aclk : IN STD_LOGIC;
|
aclk : IN STD_LOGIC;
|
||||||
aresetn : IN STD_LOGIC;
|
aresetn : IN STD_LOGIC;
|
||||||
|
|
||||||
lfo_period : IN STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0);
|
lfo_period : IN STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0);
|
||||||
|
|
||||||
lfo_enable : IN STD_LOGIC;
|
lfo_enable : IN STD_LOGIC;
|
||||||
|
-- Slave AXI Stream interface
|
||||||
s_axis_tvalid : IN STD_LOGIC;
|
s_axis_tvalid : IN STD_LOGIC;
|
||||||
s_axis_tdata : IN STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0);
|
s_axis_tdata : IN STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0);
|
||||||
s_axis_tlast : IN STD_LOGIC;
|
s_axis_tlast : IN STD_LOGIC;
|
||||||
s_axis_tready : OUT STD_LOGIC;
|
s_axis_tready : OUT STD_LOGIC;
|
||||||
|
-- Master AXI Stream interface
|
||||||
m_axis_tvalid : OUT STD_LOGIC;
|
m_axis_tvalid : OUT STD_LOGIC;
|
||||||
m_axis_tdata : OUT STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0);
|
m_axis_tdata : OUT STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0);
|
||||||
m_axis_tlast : OUT STD_LOGIC;
|
m_axis_tlast : OUT STD_LOGIC;
|
||||||
@@ -42,135 +36,146 @@ ARCHITECTURE Behavioral OF LFO IS
|
|||||||
CONSTANT LFO_CLK_CYCLES_MIN : INTEGER := LFO_COUNTER_BASE_CLK_CYCLES - ADJUSTMENT_FACTOR * (2 ** (JOYSTICK_LENGHT - 1)); -- 53_920 clk cycles
|
CONSTANT LFO_CLK_CYCLES_MIN : INTEGER := LFO_COUNTER_BASE_CLK_CYCLES - ADJUSTMENT_FACTOR * (2 ** (JOYSTICK_LENGHT - 1)); -- 53_920 clk cycles
|
||||||
CONSTANT LFO_CLK_CYCLES_MAX : INTEGER := LFO_COUNTER_BASE_CLK_CYCLES + ADJUSTMENT_FACTOR * (2 ** (JOYSTICK_LENGHT - 1) - 1); -- 145_990 clk cycles
|
CONSTANT LFO_CLK_CYCLES_MAX : INTEGER := LFO_COUNTER_BASE_CLK_CYCLES + ADJUSTMENT_FACTOR * (2 ** (JOYSTICK_LENGHT - 1) - 1); -- 145_990 clk cycles
|
||||||
|
|
||||||
|
-- Signals for LFO operation
|
||||||
SIGNAL step_clk_cycles_delta : INTEGER RANGE - 2 ** (JOYSTICK_LENGHT - 1) * ADJUSTMENT_FACTOR TO (2 ** (JOYSTICK_LENGHT - 1) - 1) * ADJUSTMENT_FACTOR := 0;
|
SIGNAL step_clk_cycles_delta : INTEGER RANGE - 2 ** (JOYSTICK_LENGHT - 1) * ADJUSTMENT_FACTOR TO (2 ** (JOYSTICK_LENGHT - 1) - 1) * ADJUSTMENT_FACTOR := 0;
|
||||||
SIGNAL step_clk_cycles : INTEGER RANGE LFO_CLK_CYCLES_MIN TO LFO_CLK_CYCLES_MAX := LFO_COUNTER_BASE_CLK_CYCLES;
|
SIGNAL step_clk_cycles : INTEGER RANGE LFO_CLK_CYCLES_MIN TO LFO_CLK_CYCLES_MAX := LFO_COUNTER_BASE_CLK_CYCLES;
|
||||||
SIGNAL step_counter : INTEGER RANGE 0 TO LFO_CLK_CYCLES_MAX := 0;
|
|
||||||
SIGNAL tri_counter : SIGNED(TRIANGULAR_COUNTER_LENGHT DOWNTO 0) := (OTHERS => '0');
|
|
||||||
SIGNAL direction_up : STD_LOGIC := '1';
|
|
||||||
|
|
||||||
SIGNAL trigger : STD_LOGIC := '0';
|
-- Pipeline stage registers
|
||||||
|
SIGNAL s_axis_tdata_r1 : STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0) := (OTHERS => '0');
|
||||||
|
SIGNAL lfo_enable_r1 : STD_LOGIC := '0';
|
||||||
|
SIGNAL s_axis_tvalid_r1 : STD_LOGIC := '0';
|
||||||
|
SIGNAL s_axis_tlast_r1 : STD_LOGIC := '0';
|
||||||
|
|
||||||
SIGNAL s_axis_tlast_reg : STD_LOGIC := '0';
|
SIGNAL tri_counter_r2 : unsigned(TRIANGULAR_COUNTER_LENGHT - 1 DOWNTO 0) := (OTHERS => '0');
|
||||||
SIGNAL m_axis_tdata_temp : SIGNED(CHANNEL_LENGHT + TRIANGULAR_COUNTER_LENGHT DOWNTO 0) := (OTHERS => '0');
|
SIGNAL direction_up_r2 : STD_LOGIC := '1';
|
||||||
SIGNAL m_axis_tvalid_int : STD_LOGIC := '0';
|
SIGNAL step_counter_r2 : NATURAL RANGE 0 TO LFO_CLK_CYCLES_MAX := 0;
|
||||||
|
SIGNAL lfo_enable_r2 : STD_LOGIC := '0';
|
||||||
|
SIGNAL s_axis_tvalid_r2 : STD_LOGIC := '0';
|
||||||
|
SIGNAL s_axis_tlast_r2 : STD_LOGIC := '0';
|
||||||
|
SIGNAL s_axis_tdata_r2 : STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0) := (OTHERS => '0');
|
||||||
|
|
||||||
|
SIGNAL temp_r3 : STD_LOGIC_VECTOR(CHANNEL_LENGHT + TRIANGULAR_COUNTER_LENGHT - 1 DOWNTO 0) := (OTHERS => '0');
|
||||||
|
SIGNAL m_axis_tvalid_i : STD_LOGIC := '0';
|
||||||
|
SIGNAL s_axis_tready_i : STD_LOGIC := '1';
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
-- Assigning the output signals
|
m_axis_tlast <= s_axis_tlast_r1;
|
||||||
m_axis_tvalid <= m_axis_tvalid_int;
|
|
||||||
s_axis_tready <= (m_axis_tready OR NOT m_axis_tvalid_int) AND aresetn;
|
|
||||||
|
|
||||||
-- Optimized single process for LFO step and triangular waveform generation
|
-- Stage 1: Input registration and LFO period calculation
|
||||||
PROCESS (aclk)
|
PROCESS (aclk)
|
||||||
BEGIN
|
BEGIN
|
||||||
IF rising_edge(aclk) THEN
|
IF rising_edge(aclk) THEN
|
||||||
|
|
||||||
IF aresetn = '0' THEN
|
IF aresetn = '0' THEN
|
||||||
|
s_axis_tdata_r1 <= (OTHERS => '0');
|
||||||
step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES;
|
step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES;
|
||||||
step_counter <= 0;
|
lfo_enable_r1 <= '0';
|
||||||
tri_counter <= (OTHERS => '0');
|
s_axis_tvalid_r1 <= '0';
|
||||||
direction_up <= '1';
|
s_axis_tlast_r1 <= '0';
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
-- Set the step_clk_cycles based on the joystick input
|
-- Set the step_clk_cycles based on the joystick input
|
||||||
step_clk_cycles_delta <= (to_integer(unsigned(lfo_period)) - JSTK_CENTER_VALUE) * ADJUSTMENT_FACTOR;
|
step_clk_cycles_delta <= (to_integer(unsigned(lfo_period)) - JSTK_CENTER_VALUE) * ADJUSTMENT_FACTOR;
|
||||||
step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES - step_clk_cycles_delta;
|
step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES - step_clk_cycles_delta;
|
||||||
|
|
||||||
IF lfo_enable = '1' THEN
|
IF s_axis_tvalid = '1' AND s_axis_tready_i = '1' THEN
|
||||||
|
s_axis_tdata_r1 <= s_axis_tdata;
|
||||||
IF step_counter >= step_clk_cycles THEN
|
lfo_enable_r1 <= lfo_enable;
|
||||||
step_counter <= 0;
|
s_axis_tvalid_r1 <= '1';
|
||||||
|
s_axis_tlast_r1 <= s_axis_tlast;
|
||||||
IF tri_counter = (2 ** TRIANGULAR_COUNTER_LENGHT) - 2 THEN
|
|
||||||
direction_up <= '0';
|
|
||||||
|
|
||||||
ELSIF tri_counter = 1 THEN
|
|
||||||
direction_up <= '1';
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
IF direction_up = '1' THEN
|
|
||||||
tri_counter <= tri_counter + 1;
|
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
tri_counter <= tri_counter - 1;
|
s_axis_tvalid_r1 <= '0';
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
ELSE
|
|
||||||
step_counter <= step_counter + 1;
|
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END PROCESS;
|
END PROCESS;
|
||||||
|
|
||||||
-- Handshake logic for the AXIS interface
|
-- Stage 2: Triangular counter control
|
||||||
AXIS: PROCESS (aclk)
|
PROCESS (aclk)
|
||||||
BEGIN
|
BEGIN
|
||||||
IF rising_edge(aclk) THEN
|
IF rising_edge(aclk) THEN
|
||||||
|
|
||||||
IF aresetn = '0' THEN
|
IF aresetn = '0' THEN
|
||||||
s_axis_tlast_reg <= '0';
|
step_counter_r2 <= 0;
|
||||||
m_axis_tdata_temp <= (OTHERS => '0');
|
tri_counter_r2 <= (OTHERS => '0');
|
||||||
m_axis_tvalid_int <= '0';
|
direction_up_r2 <= '1';
|
||||||
m_axis_tlast <= '0';
|
lfo_enable_r2 <= '0';
|
||||||
|
s_axis_tvalid_r2 <= '0';
|
||||||
|
s_axis_tlast_r2 <= '0';
|
||||||
|
s_axis_tdata_r2 <= (OTHERS => '0');
|
||||||
ELSE
|
ELSE
|
||||||
-- Clear valid flag when master interface is ready
|
lfo_enable_r2 <= lfo_enable_r1;
|
||||||
IF m_axis_tready = '1' THEN
|
s_axis_tvalid_r2 <= s_axis_tvalid_r1;
|
||||||
m_axis_tvalid_int <= '0';
|
s_axis_tlast_r2 <= s_axis_tlast_r1;
|
||||||
END IF;
|
s_axis_tdata_r2 <= s_axis_tdata_r1;
|
||||||
|
|
||||||
-- Data output logic
|
IF lfo_enable_r1 = '1' THEN
|
||||||
IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
|
IF step_counter_r2 < step_clk_cycles THEN
|
||||||
m_axis_tdata <= STD_LOGIC_VECTOR(
|
step_counter_r2 <= step_counter_r2 + 1;
|
||||||
|
ELSE
|
||||||
|
step_counter_r2 <= 0;
|
||||||
|
IF direction_up_r2 = '1' THEN
|
||||||
|
IF tri_counter_r2 = (2 ** TRIANGULAR_COUNTER_LENGHT) - 1 THEN
|
||||||
|
direction_up_r2 <= '0';
|
||||||
|
tri_counter_r2 <= tri_counter_r2 - 1;
|
||||||
|
ELSE
|
||||||
|
tri_counter_r2 <= tri_counter_r2 + 1;
|
||||||
|
END IF;
|
||||||
|
ELSE
|
||||||
|
IF tri_counter_r2 = 0 THEN
|
||||||
|
direction_up_r2 <= '1';
|
||||||
|
tri_counter_r2 <= tri_counter_r2 + 1;
|
||||||
|
ELSE
|
||||||
|
tri_counter_r2 <= tri_counter_r2 - 1;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
ELSE
|
||||||
|
step_counter_r2 <= 0;
|
||||||
|
tri_counter_r2 <= (OTHERS => '0');
|
||||||
|
direction_up_r2 <= '1';
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END PROCESS;
|
||||||
|
|
||||||
|
-- Stage 3: Optimized modulation and output handling
|
||||||
|
PROCESS (aclk)
|
||||||
|
BEGIN
|
||||||
|
IF rising_edge(aclk) THEN
|
||||||
|
IF aresetn = '0' THEN
|
||||||
|
m_axis_tdata <= (OTHERS => '0');
|
||||||
|
m_axis_tvalid_i <= '0';
|
||||||
|
s_axis_tready_i <= '1';
|
||||||
|
ELSE
|
||||||
|
IF m_axis_tvalid_i = '1' AND m_axis_tready = '0' THEN
|
||||||
|
m_axis_tvalid_i <= '1';
|
||||||
|
ELSIF s_axis_tvalid_r2 = '1' THEN
|
||||||
|
IF lfo_enable_r2 = '1' THEN
|
||||||
|
temp_r3 <= STD_LOGIC_VECTOR(
|
||||||
resize(
|
resize(
|
||||||
shift_right(
|
signed(s_axis_tdata_r2) * signed('0' & tri_counter_r2),
|
||||||
m_axis_tdata_temp,
|
temp_r3'length
|
||||||
TRIANGULAR_COUNTER_LENGHT
|
|
||||||
),
|
|
||||||
CHANNEL_LENGHT
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
m_axis_tlast <= s_axis_tlast_reg;
|
m_axis_tdata <= temp_r3(temp_r3'high DOWNTO TRIANGULAR_COUNTER_LENGHT);
|
||||||
|
|
||||||
m_axis_tvalid_int <= '1';
|
|
||||||
trigger <= '0';
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
-- Data input logic
|
|
||||||
IF s_axis_tvalid = '1' AND (m_axis_tready = '1' OR m_axis_tvalid_int = '0') THEN
|
|
||||||
IF lfo_enable = '1' THEN
|
|
||||||
m_axis_tdata_temp <= signed(s_axis_tdata) * tri_counter;
|
|
||||||
s_axis_tlast_reg <= s_axis_tlast;
|
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
m_axis_tdata_temp <= shift_left(
|
m_axis_tdata <= s_axis_tdata_r2;
|
||||||
resize(
|
END IF;
|
||||||
signed(s_axis_tdata),
|
m_axis_tvalid_i <= '1';
|
||||||
m_axis_tdata_temp'length
|
ELSE
|
||||||
),
|
m_axis_tvalid_i <= '0';
|
||||||
TRIANGULAR_COUNTER_LENGHT
|
|
||||||
);
|
|
||||||
s_axis_tlast_reg <= s_axis_tlast;
|
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
trigger <= '1';
|
-- Ready signal management
|
||||||
|
IF m_axis_tvalid_i = '1' AND m_axis_tready = '1' THEN
|
||||||
|
s_axis_tready_i <= '1';
|
||||||
|
ELSIF s_axis_tvalid = '1' AND s_axis_tready_i = '1' THEN
|
||||||
|
s_axis_tready_i <= '0';
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
END PROCESS;
|
||||||
|
|
||||||
END PROCESS AXIS;
|
s_axis_tready <= s_axis_tready_i;
|
||||||
|
m_axis_tvalid <= m_axis_tvalid_i;
|
||||||
|
|
||||||
END ARCHITECTURE Behavioral;
|
END ARCHITECTURE Behavioral;
|
||||||
176
LAB3/src/LFO_1.vhd
Normal file
176
LAB3/src/LFO_1.vhd
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
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); -- 512 for 10 bits
|
||||||
|
CONSTANT LFO_COUNTER_BASE_CLK_CYCLES : INTEGER := LFO_COUNTER_BASE_PERIOD_US * 1000 / CLK_PERIOD_NS; -- 1ms = 100_000 clk cycles
|
||||||
|
CONSTANT LFO_CLK_CYCLES_MIN : INTEGER := LFO_COUNTER_BASE_CLK_CYCLES - ADJUSTMENT_FACTOR * (2 ** (JOYSTICK_LENGHT - 1)); -- 53_920 clk cycles
|
||||||
|
CONSTANT LFO_CLK_CYCLES_MAX : INTEGER := LFO_COUNTER_BASE_CLK_CYCLES + ADJUSTMENT_FACTOR * (2 ** (JOYSTICK_LENGHT - 1) - 1); -- 145_990 clk cycles
|
||||||
|
|
||||||
|
SIGNAL step_clk_cycles_delta : INTEGER RANGE - 2 ** (JOYSTICK_LENGHT - 1) * ADJUSTMENT_FACTOR TO (2 ** (JOYSTICK_LENGHT - 1) - 1) * ADJUSTMENT_FACTOR := 0;
|
||||||
|
SIGNAL step_clk_cycles : INTEGER RANGE LFO_CLK_CYCLES_MIN TO LFO_CLK_CYCLES_MAX := LFO_COUNTER_BASE_CLK_CYCLES;
|
||||||
|
SIGNAL step_counter : NATURAL RANGE 0 TO LFO_CLK_CYCLES_MAX := 0;
|
||||||
|
SIGNAL tri_counter : SIGNED(TRIANGULAR_COUNTER_LENGHT DOWNTO 0) := (OTHERS => '0');
|
||||||
|
SIGNAL direction_up : STD_LOGIC := '1';
|
||||||
|
|
||||||
|
SIGNAL trigger : STD_LOGIC := '0';
|
||||||
|
|
||||||
|
SIGNAL s_axis_tlast_reg : STD_LOGIC := '0';
|
||||||
|
SIGNAL m_axis_tdata_temp : SIGNED(CHANNEL_LENGHT + TRIANGULAR_COUNTER_LENGHT DOWNTO 0) := (OTHERS => '0');
|
||||||
|
SIGNAL m_axis_tvalid_int : STD_LOGIC := '0';
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
-- Assigning the output signals
|
||||||
|
m_axis_tvalid <= m_axis_tvalid_int;
|
||||||
|
s_axis_tready <= (m_axis_tready OR NOT m_axis_tvalid_int) AND aresetn;
|
||||||
|
|
||||||
|
-- Optimized single process for LFO step and triangular waveform generation
|
||||||
|
PROCESS (aclk)
|
||||||
|
BEGIN
|
||||||
|
IF rising_edge(aclk) THEN
|
||||||
|
|
||||||
|
IF aresetn = '0' THEN
|
||||||
|
step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES;
|
||||||
|
step_counter <= 0;
|
||||||
|
tri_counter <= (OTHERS => '0');
|
||||||
|
direction_up <= '1';
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
-- Set the step_clk_cycles based on the joystick input
|
||||||
|
step_clk_cycles_delta <= (to_integer(unsigned(lfo_period)) - JSTK_CENTER_VALUE) * ADJUSTMENT_FACTOR;
|
||||||
|
step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES - step_clk_cycles_delta;
|
||||||
|
|
||||||
|
IF lfo_enable = '1' THEN
|
||||||
|
|
||||||
|
IF step_counter >= step_clk_cycles THEN
|
||||||
|
step_counter <= 0;
|
||||||
|
|
||||||
|
IF tri_counter = (2 ** TRIANGULAR_COUNTER_LENGHT) - 2 THEN
|
||||||
|
direction_up <= '0';
|
||||||
|
|
||||||
|
ELSIF tri_counter = 1 THEN
|
||||||
|
direction_up <= '1';
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF direction_up = '1' THEN
|
||||||
|
tri_counter <= tri_counter + 1;
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
tri_counter <= tri_counter - 1;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
step_counter <= step_counter + 1;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
END PROCESS;
|
||||||
|
|
||||||
|
-- Handshake logic for the AXIS interface
|
||||||
|
AXIS: PROCESS (aclk)
|
||||||
|
BEGIN
|
||||||
|
IF rising_edge(aclk) THEN
|
||||||
|
|
||||||
|
IF aresetn = '0' THEN
|
||||||
|
s_axis_tlast_reg <= '0';
|
||||||
|
m_axis_tdata_temp <= (OTHERS => '0');
|
||||||
|
m_axis_tvalid_int <= '0';
|
||||||
|
m_axis_tlast <= '0';
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
-- Clear valid flag when master interface is ready
|
||||||
|
IF m_axis_tready = '1' THEN
|
||||||
|
m_axis_tvalid_int <= '0';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Data output logic
|
||||||
|
IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
|
||||||
|
m_axis_tdata <= STD_LOGIC_VECTOR(
|
||||||
|
resize(
|
||||||
|
shift_right(
|
||||||
|
m_axis_tdata_temp,
|
||||||
|
TRIANGULAR_COUNTER_LENGHT
|
||||||
|
),
|
||||||
|
CHANNEL_LENGHT
|
||||||
|
)
|
||||||
|
);
|
||||||
|
m_axis_tlast <= s_axis_tlast_reg;
|
||||||
|
|
||||||
|
m_axis_tvalid_int <= '1';
|
||||||
|
trigger <= '0';
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Data input logic
|
||||||
|
IF s_axis_tvalid = '1' AND (m_axis_tready = '1' OR m_axis_tvalid_int = '0') THEN
|
||||||
|
IF lfo_enable = '1' THEN
|
||||||
|
m_axis_tdata_temp <= signed(s_axis_tdata) * tri_counter;
|
||||||
|
s_axis_tlast_reg <= s_axis_tlast;
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
m_axis_tdata_temp <= shift_left(
|
||||||
|
resize(
|
||||||
|
signed(s_axis_tdata),
|
||||||
|
m_axis_tdata_temp'length
|
||||||
|
),
|
||||||
|
TRIANGULAR_COUNTER_LENGHT
|
||||||
|
);
|
||||||
|
s_axis_tlast_reg <= s_axis_tlast;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
trigger <= '1';
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
END PROCESS AXIS;
|
||||||
|
|
||||||
|
END ARCHITECTURE Behavioral;
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
|
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
|
||||||
<Option Name="EnableBDX" Val="FALSE"/>
|
<Option Name="EnableBDX" Val="FALSE"/>
|
||||||
<Option Name="DSABoardId" Val="basys3"/>
|
<Option Name="DSABoardId" Val="basys3"/>
|
||||||
<Option Name="WTXSimLaunchSim" Val="53"/>
|
<Option Name="WTXSimLaunchSim" Val="79"/>
|
||||||
<Option Name="WTModelSimLaunchSim" Val="0"/>
|
<Option Name="WTModelSimLaunchSim" Val="0"/>
|
||||||
<Option Name="WTQuestaLaunchSim" Val="0"/>
|
<Option Name="WTQuestaLaunchSim" Val="0"/>
|
||||||
<Option Name="WTIesLaunchSim" Val="0"/>
|
<Option Name="WTIesLaunchSim" Val="0"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user