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 @@