diff --git a/LAB3/design/lab_3/hdl/lab_3_wrapper.vhd b/LAB3/design/lab_3/hdl/lab_3_wrapper.vhd
index 9d50214..8edec49 100644
--- a/LAB3/design/lab_3/hdl/lab_3_wrapper.vhd
+++ b/LAB3/design/lab_3/hdl/lab_3_wrapper.vhd
@@ -1,7 +1,7 @@
--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
---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)
--Command : generate_target lab_3_wrapper.bd
--Design : lab_3_wrapper
diff --git a/LAB3/design/lab_3/lab_3.bda b/LAB3/design/lab_3/lab_3.bda
index 3fa1797..8488c07 100644
--- a/LAB3/design/lab_3/lab_3.bda
+++ b/LAB3/design/lab_3/lab_3.bda
@@ -21,9 +21,8 @@
- 2
lab_3
- VR
+ BC
active
@@ -31,12 +30,13 @@
PM
+ 2
lab_3
- BC
+ VR
-
+
-
+
diff --git a/LAB3/sim/tb_LFO.vhd b/LAB3/sim/tb_LFO.vhd
index 1d49216..50fe8e1 100644
--- a/LAB3/sim/tb_LFO.vhd
+++ b/LAB3/sim/tb_LFO.vhd
@@ -100,7 +100,7 @@ BEGIN
-- Imposta parametri iniziali
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
-- Prepara il dato
@@ -134,10 +134,10 @@ BEGIN
-- Simula backpressure abbassando m_axis_tready ogni tanto
backpressure_proc : PROCESS
BEGIN
- WAIT FOR 60 ns;
+ WAIT FOR 200 ns;
WAIT UNTIL rising_edge(aclk);
m_axis_tready <= '0';
- WAIT FOR 20 ns;
+ WAIT FOR 500 ns;
WAIT UNTIL rising_edge(aclk);
m_axis_tready <= '1';
WAIT;
diff --git a/LAB3/src/LFO.vhd b/LAB3/src/LFO.vhd
index eed7142..2f51ce8 100644
--- a/LAB3/src/LFO.vhd
+++ b/LAB3/src/LFO.vhd
@@ -1,8 +1,5 @@
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
@@ -10,22 +7,19 @@ ENTITY LFO IS
CHANNEL_LENGHT : INTEGER := 24;
JOYSTICK_LENGHT : INTEGER := 10;
CLK_PERIOD_NS : INTEGER := 10;
- TRIANGULAR_COUNTER_LENGHT : INTEGER := 10 -- Triangular wave period length
+ TRIANGULAR_COUNTER_LENGHT : INTEGER := 10
);
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;
-
+ -- Slave AXI Stream interface
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;
-
+ -- Master AXI Stream interface
m_axis_tvalid : OUT STD_LOGIC;
m_axis_tdata : OUT STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0);
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_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 : 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 m_axis_tdata_temp : SIGNED(CHANNEL_LENGHT + TRIANGULAR_COUNTER_LENGHT DOWNTO 0) := (OTHERS => '0');
- SIGNAL m_axis_tvalid_int : STD_LOGIC := '0';
+ SIGNAL tri_counter_r2 : unsigned(TRIANGULAR_COUNTER_LENGHT - 1 DOWNTO 0) := (OTHERS => '0');
+ SIGNAL direction_up_r2 : STD_LOGIC := '1';
+ 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
- -- 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;
+ m_axis_tlast <= s_axis_tlast_r1;
- -- Optimized single process for LFO step and triangular waveform generation
+ -- Stage 1: Input registration and LFO period calculation
PROCESS (aclk)
BEGIN
IF rising_edge(aclk) THEN
-
IF aresetn = '0' THEN
+ s_axis_tdata_r1 <= (OTHERS => '0');
step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES;
- step_counter <= 0;
- tri_counter <= (OTHERS => '0');
- direction_up <= '1';
-
+ lfo_enable_r1 <= '0';
+ s_axis_tvalid_r1 <= '0';
+ s_axis_tlast_r1 <= '0';
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;
-
+ IF s_axis_tvalid = '1' AND s_axis_tready_i = '1' THEN
+ s_axis_tdata_r1 <= s_axis_tdata;
+ lfo_enable_r1 <= lfo_enable;
+ s_axis_tvalid_r1 <= '1';
+ s_axis_tlast_r1 <= s_axis_tlast;
+ ELSE
+ s_axis_tvalid_r1 <= '0';
END IF;
-
END IF;
-
END IF;
-
END PROCESS;
- -- Handshake logic for the AXIS interface
- AXIS: PROCESS (aclk)
+ -- Stage 2: Triangular counter control
+ 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';
-
+ step_counter_r2 <= 0;
+ tri_counter_r2 <= (OTHERS => '0');
+ direction_up_r2 <= '1';
+ lfo_enable_r2 <= '0';
+ s_axis_tvalid_r2 <= '0';
+ s_axis_tlast_r2 <= '0';
+ s_axis_tdata_r2 <= (OTHERS => '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;
+ lfo_enable_r2 <= lfo_enable_r1;
+ s_axis_tvalid_r2 <= s_axis_tvalid_r1;
+ s_axis_tlast_r2 <= s_axis_tlast_r1;
+ s_axis_tdata_r2 <= s_axis_tdata_r1;
+ IF lfo_enable_r1 = '1' THEN
+ IF step_counter_r2 < step_clk_cycles THEN
+ step_counter_r2 <= step_counter_r2 + 1;
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;
-
+ 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;
- trigger <= '1';
-
+ -- 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(
+ signed(s_axis_tdata_r2) * signed('0' & tri_counter_r2),
+ temp_r3'length
+ )
+ );
+ m_axis_tdata <= temp_r3(temp_r3'high DOWNTO TRIANGULAR_COUNTER_LENGHT);
+ ELSE
+ m_axis_tdata <= s_axis_tdata_r2;
+ END IF;
+ m_axis_tvalid_i <= '1';
+ ELSE
+ m_axis_tvalid_i <= '0';
END IF;
+ -- 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 PROCESS;
- END PROCESS AXIS;
+ s_axis_tready <= s_axis_tready_i;
+ m_axis_tvalid <= m_axis_tvalid_i;
END ARCHITECTURE Behavioral;
\ No newline at end of file
diff --git a/LAB3/src/LFO_1.vhd b/LAB3/src/LFO_1.vhd
new file mode 100644
index 0000000..d432a6e
--- /dev/null
+++ b/LAB3/src/LFO_1.vhd
@@ -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;
\ No newline at end of file
diff --git a/LAB3/vivado/LFO/LFO.xpr b/LAB3/vivado/LFO/LFO.xpr
index 55923f5..6467833 100644
--- a/LAB3/vivado/LFO/LFO.xpr
+++ b/LAB3/vivado/LFO/LFO.xpr
@@ -47,7 +47,7 @@
-
+