From 4e3d7c45a2c0e10766d7a78db534e351bd34f480 Mon Sep 17 00:00:00 2001 From: Cd16d Date: Wed, 21 May 2025 00:31:23 +0200 Subject: [PATCH] Add Vivado project files and testbench configurations for volume multiplier and volume saturator - Created `tb_volume_multiplier_behav.wcfg` for waveform configuration of the volume multiplier testbench. - Added `volume_multiplier.xpr` project file for the volume multiplier design. - Created `volume_saturator.xpr` project file for the volume saturator design. - Added `volume_saturator_tb_behav.wcfg` for waveform configuration of the volume saturator testbench. --- LAB3/design/lab_3/hdl/lab_3_wrapper.vhd | 2 +- LAB3/design/lab_3/lab_3.bd | 121 +++++- LAB3/sim/tb_volume_multiplier.vhd | 156 +++++++ LAB3/sim/tb_volume_saturator.vhd | 157 +++++++ LAB3/src/LFO.vhd | 92 ++-- LAB3/src/volume_multiplier.vhd | 30 +- LAB3/src/volume_saturator.vhd | 14 +- LAB3/vivado/lab3/lab3.xpr | 201 +++++---- .../tb_volume_multiplier_behav.wcfg | 93 +++++ .../volume_multiplier/volume_multiplier.xpr | 394 ++++++++++++++++++ .../volume_saturator/volume_saturator.xpr | 214 ++++++++++ .../volume_saturator_tb_behav.wcfg | 80 ++++ 12 files changed, 1357 insertions(+), 197 deletions(-) create mode 100644 LAB3/sim/tb_volume_multiplier.vhd create mode 100644 LAB3/sim/tb_volume_saturator.vhd create mode 100644 LAB3/vivado/volume_multiplier/tb_volume_multiplier_behav.wcfg create mode 100644 LAB3/vivado/volume_multiplier/volume_multiplier.xpr create mode 100644 LAB3/vivado/volume_saturator/volume_saturator.xpr create mode 100644 LAB3/vivado/volume_saturator/volume_saturator_tb_behav.wcfg diff --git a/LAB3/design/lab_3/hdl/lab_3_wrapper.vhd b/LAB3/design/lab_3/hdl/lab_3_wrapper.vhd index 1709770..9f928f5 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 : Mon May 12 14:54:08 2025 +--Date : Mon May 19 16:34:49 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.bd b/LAB3/design/lab_3/lab_3.bd index 9b22386..672426c 100644 --- a/LAB3/design/lab_3/lab_3.bd +++ b/LAB3/design/lab_3/lab_3.bd @@ -6,7 +6,8 @@ "name": "lab_3", "rev_ctrl_bd_flag": "RevCtrlBdOff", "synth_flow_mode": "None", - "tool_version": "2020.2" + "tool_version": "2020.2", + "validated": "true" }, "design_tree": { "clk_wiz_0": "", @@ -39,9 +40,21 @@ "type": "clk", "direction": "I", "parameters": { + "CLK_DOMAIN": { + "value": "lab_3_sys_clock", + "value_src": "default" + }, "FREQ_HZ": { "value": "100000000" }, + "FREQ_TOLERANCE_HZ": { + "value": "0", + "value_src": "default" + }, + "INSERT_VIP": { + "value": "0", + "value_src": "default" + }, "PHASE": { "value": "0.000" } @@ -51,6 +64,10 @@ "type": "rst", "direction": "I", "parameters": { + "INSERT_VIP": { + "value": "0", + "value_src": "default" + }, "POLARITY": { "value": "ACTIVE_HIGH" } @@ -1419,6 +1436,18 @@ "HAS_TLAST": { "value": "0", "value_src": "constant" + }, + "FREQ_HZ": { + "value": "100000000", + "value_src": "ip_prop" + }, + "PHASE": { + "value": "0.0", + "value_src": "ip_prop" + }, + "CLK_DOMAIN": { + "value": "/clk_wiz_0_clk_out1", + "value_src": "ip_prop" } }, "port_maps": { @@ -1473,6 +1502,18 @@ "HAS_TLAST": { "value": "0", "value_src": "constant" + }, + "FREQ_HZ": { + "value": "100000000", + "value_src": "ip_prop" + }, + "PHASE": { + "value": "0.0", + "value_src": "ip_prop" + }, + "CLK_DOMAIN": { + "value": "/clk_wiz_0_clk_out1", + "value_src": "ip_prop" } }, "port_maps": { @@ -1501,6 +1542,18 @@ "ASSOCIATED_RESET": { "value": "aresetn", "value_src": "constant" + }, + "FREQ_HZ": { + "value": "100000000", + "value_src": "ip_prop" + }, + "PHASE": { + "value": "0.0", + "value_src": "ip_prop" + }, + "CLK_DOMAIN": { + "value": "/clk_wiz_0_clk_out1", + "value_src": "ip_prop" } } }, @@ -1598,6 +1651,18 @@ "HAS_TLAST": { "value": "1", "value_src": "constant" + }, + "FREQ_HZ": { + "value": "100000000", + "value_src": "ip_prop" + }, + "PHASE": { + "value": "0.0", + "value_src": "ip_prop" + }, + "CLK_DOMAIN": { + "value": "/clk_wiz_0_clk_out1", + "value_src": "ip_prop" } }, "port_maps": { @@ -1656,6 +1721,18 @@ "HAS_TLAST": { "value": "1", "value_src": "constant" + }, + "FREQ_HZ": { + "value": "100000000", + "value_src": "ip_prop" + }, + "PHASE": { + "value": "0.0", + "value_src": "ip_prop" + }, + "CLK_DOMAIN": { + "value": "/clk_wiz_0_clk_out1", + "value_src": "ip_prop" } }, "port_maps": { @@ -1692,6 +1769,18 @@ "ASSOCIATED_RESET": { "value": "aresetn", "value_src": "constant" + }, + "FREQ_HZ": { + "value": "100000000", + "value_src": "ip_prop" + }, + "PHASE": { + "value": "0.0", + "value_src": "ip_prop" + }, + "CLK_DOMAIN": { + "value": "/clk_wiz_0_clk_out1", + "value_src": "ip_prop" } } }, @@ -1729,10 +1818,10 @@ "axi4stream_spi_master_0/S_AXIS" ] }, - "axi4stream_spi_master_0_SPI_M": { + "moving_average_filte_0_m_axis": { "interface_ports": [ - "SPI_M_0", - "axi4stream_spi_master_0/SPI_M" + "balance_controller_0/s_axis", + "moving_average_filte_0/m_axis" ] }, "axis_broadcaster_0_M01_AXIS": { @@ -1741,10 +1830,10 @@ "led_level_controller_0/s_axis" ] }, - "LFO_0_m_axis": { + "balance_controller_0_m_axis": { "interface_ports": [ - "LFO_0/m_axis", - "mute_controller_0/s_axis" + "balance_controller_0/m_axis", + "volume_controller_0/s_axis" ] }, "volume_controller_0_m_axis": { @@ -1759,10 +1848,16 @@ "axis_dual_i2s_0/s_axis" ] }, - "balance_controller_0_m_axis": { + "LFO_0_m_axis": { "interface_ports": [ - "balance_controller_0/m_axis", - "volume_controller_0/s_axis" + "LFO_0/m_axis", + "mute_controller_0/s_axis" + ] + }, + "axi4stream_spi_master_0_SPI_M": { + "interface_ports": [ + "SPI_M_0", + "axi4stream_spi_master_0/SPI_M" ] }, "axis_dual_i2s_0_m_axis": { @@ -1771,12 +1866,6 @@ "moving_average_filte_0/s_axis" ] }, - "moving_average_filte_0_m_axis": { - "interface_ports": [ - "balance_controller_0/s_axis", - "moving_average_filte_0/m_axis" - ] - }, "mute_controller_0_m_axis": { "interface_ports": [ "mute_controller_0/m_axis", diff --git a/LAB3/sim/tb_volume_multiplier.vhd b/LAB3/sim/tb_volume_multiplier.vhd new file mode 100644 index 0000000..914b30d --- /dev/null +++ b/LAB3/sim/tb_volume_multiplier.vhd @@ -0,0 +1,156 @@ +---------------------------------------------------------------------------------- +-- Testbench for volume_multiplier +---------------------------------------------------------------------------------- +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; + +ENTITY tb_volume_multiplier IS +END tb_volume_multiplier; + +ARCHITECTURE Behavioral OF tb_volume_multiplier IS + + CONSTANT TDATA_WIDTH : POSITIVE := 24; + CONSTANT VOLUME_WIDTH : POSITIVE := 10; + CONSTANT VOLUME_STEP_2 : POSITIVE := 6; + CONSTANT N_SAMPLES : INTEGER := 8; + + -- Output width calculation (as in DUT) + CONSTANT TDATA_OUT_WIDTH : INTEGER := TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) + 1; + + COMPONENT volume_multiplier IS + GENERIC ( + TDATA_WIDTH : POSITIVE := 24; + VOLUME_WIDTH : POSITIVE := 10; + VOLUME_STEP_2 : POSITIVE := 6 + ); + PORT ( + aclk : IN STD_LOGIC; + aresetn : IN STD_LOGIC; + s_axis_tvalid : IN STD_LOGIC; + s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 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(TDATA_OUT_WIDTH - 1 DOWNTO 0); + m_axis_tlast : OUT STD_LOGIC; + m_axis_tready : IN STD_LOGIC; + volume : IN STD_LOGIC_VECTOR(VOLUME_WIDTH - 1 DOWNTO 0) + ); + END COMPONENT; + + SIGNAL aclk : STD_LOGIC := '0'; + SIGNAL aresetn : STD_LOGIC := '0'; + SIGNAL s_axis_tvalid : STD_LOGIC := '0'; + SIGNAL s_axis_tdata : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL s_axis_tlast : STD_LOGIC := '0'; + SIGNAL s_axis_tready : STD_LOGIC; + SIGNAL m_axis_tvalid : STD_LOGIC; + SIGNAL m_axis_tdata : STD_LOGIC_VECTOR(TDATA_OUT_WIDTH - 1 DOWNTO 0); + SIGNAL m_axis_tlast : STD_LOGIC; + SIGNAL m_axis_tready : STD_LOGIC := '1'; + SIGNAL volume : STD_LOGIC_VECTOR(VOLUME_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); + + -- Test input samples + TYPE sample_mem_type IS ARRAY(0 TO N_SAMPLES-1) OF STD_LOGIC_VECTOR(TDATA_WIDTH-1 DOWNTO 0); + SIGNAL sample_mem : sample_mem_type := ( + x"000100", -- +256 + x"FFFE00", -- -512 + x"000001", -- +1 + x"FFFFFF", -- -1 (2's comp) + x"7FFFFF", -- max positive + x"800000", -- max negative + x"000A00", -- +2560 + x"FFF600" -- -2560 + ); + +BEGIN + + -- Clock generation + aclk <= NOT aclk AFTER 5 ns; + + -- DUT instantiation + uut: volume_multiplier + GENERIC MAP ( + TDATA_WIDTH => TDATA_WIDTH, + VOLUME_WIDTH => VOLUME_WIDTH, + VOLUME_STEP_2 => VOLUME_STEP_2 + ) + PORT MAP ( + aclk => aclk, + aresetn => aresetn, + s_axis_tvalid => s_axis_tvalid, + s_axis_tdata => s_axis_tdata, + s_axis_tlast => s_axis_tlast, + s_axis_tready => s_axis_tready, + m_axis_tvalid => m_axis_tvalid, + m_axis_tdata => m_axis_tdata, + m_axis_tlast => m_axis_tlast, + m_axis_tready => m_axis_tready, + volume => volume + ); + + -- Stimulus process + stimulus : PROCESS + BEGIN + -- Reset + WAIT FOR 10 ns; + aresetn <= '1'; + WAIT UNTIL rising_edge(aclk); + + -- Set volume to mid (no gain/loss) + volume <= std_logic_vector(to_unsigned(511, VOLUME_WIDTH)); + WAIT UNTIL rising_edge(aclk); + + -- Send all samples + FOR i IN 0 TO N_SAMPLES-1 LOOP + s_axis_tdata <= sample_mem(i); + s_axis_tvalid <= '1'; + IF i = N_SAMPLES-1 THEN + s_axis_tlast <= '1'; + ELSE + s_axis_tlast <= '0'; + END IF; + -- Wait for handshake + WAIT UNTIL rising_edge(aclk); + WHILE s_axis_tready = '0' LOOP + WAIT UNTIL rising_edge(aclk); + END LOOP; + END LOOP; + s_axis_tvalid <= '0'; + s_axis_tlast <= '0'; + + -- Change volume (attenuate) + WAIT FOR 20 ns; + volume <= std_logic_vector(to_unsigned(256, VOLUME_WIDTH)); -- attenuate + + -- Send one more sample + WAIT UNTIL rising_edge(aclk); + s_axis_tdata <= x"000100"; + s_axis_tvalid <= '1'; + s_axis_tlast <= '1'; + WAIT UNTIL rising_edge(aclk); + WHILE s_axis_tready = '0' LOOP + WAIT UNTIL rising_edge(aclk); + END LOOP; + s_axis_tvalid <= '0'; + s_axis_tlast <= '0'; + + -- Wait and finish + WAIT FOR 100 ns; + WAIT; + END PROCESS; + + -- Optionally, block m_axis_tready to test backpressure + PROCESS + BEGIN + WAIT FOR 60 ns; + WAIT UNTIL rising_edge(aclk); + m_axis_tready <= '0'; + WAIT FOR 20 ns; + WAIT UNTIL rising_edge(aclk); + m_axis_tready <= '1'; + WAIT; + END PROCESS; + +END Behavioral; \ No newline at end of file diff --git a/LAB3/sim/tb_volume_saturator.vhd b/LAB3/sim/tb_volume_saturator.vhd new file mode 100644 index 0000000..4782913 --- /dev/null +++ b/LAB3/sim/tb_volume_saturator.vhd @@ -0,0 +1,157 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 05/20/2025 +-- Design Name: +-- Module Name: tb_volume_saturator - Behavioral +-- Project Name: +-- Target Devices: +-- Tool Versions: Vivado 2020.2 +-- Description: Testbench for volume_saturator (stereo, L->R, tlast on R) +-- +---------------------------------------------------------------------------------- +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; + +ENTITY tb_volume_saturator IS +END tb_volume_saturator; + +ARCHITECTURE Behavioral OF tb_volume_saturator IS + + CONSTANT TDATA_WIDTH : POSITIVE := 24; + CONSTANT VOLUME_WIDTH : POSITIVE := 10; + CONSTANT VOLUME_STEP_2 : POSITIVE := 6; + CONSTANT STEREO_SAMPLES : INTEGER := 8; + + -- Calculate s_axis_tdata width + CONSTANT TDATA_IN_WIDTH : INTEGER := TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) + 1; + + COMPONENT volume_saturator IS + GENERIC ( + TDATA_WIDTH : POSITIVE := 24; + VOLUME_WIDTH : POSITIVE := 10; + VOLUME_STEP_2 : POSITIVE := 6; -- i.e., number_of_steps = 2**(VOLUME_STEP_2) + HIGHER_BOUND : INTEGER := 2 ** 15 - 1; -- Inclusive + LOWER_BOUND : INTEGER := - 2 ** 15 -- Inclusive + ); + PORT ( + aclk : IN STD_LOGIC; + aresetn : IN STD_LOGIC; + + s_axis_tvalid : IN STD_LOGIC; + s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 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(TDATA_WIDTH - 1 DOWNTO 0); + m_axis_tlast : OUT STD_LOGIC; + m_axis_tready : IN STD_LOGIC + ); + END COMPONENT; + + SIGNAL aclk : STD_LOGIC := '0'; + SIGNAL aresetn : STD_LOGIC := '0'; + SIGNAL s_axis_tvalid : STD_LOGIC := '0'; + SIGNAL s_axis_tdata : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) DOWNTO 0) := (OTHERS => '0'); + SIGNAL s_axis_tlast : STD_LOGIC := '0'; + SIGNAL s_axis_tready : STD_LOGIC; + SIGNAL m_axis_tvalid : STD_LOGIC; + SIGNAL m_axis_tdata : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); + SIGNAL m_axis_tlast : STD_LOGIC; + SIGNAL m_axis_tready : STD_LOGIC := '1'; + + -- Example stereo audio: L, R, L, R, ... (tlast on R) + TYPE stereo_mem_type IS ARRAY(0 TO 2 * STEREO_SAMPLES - 1) OF STD_LOGIC_VECTOR(TDATA_IN_WIDTH - 1 DOWNTO 0); + SIGNAL stereo_mem : stereo_mem_type := ( + x"00009C40", -- +40000 (clipping positivo) + x"00007FFF", -- +32767 (HIGHER_BOUND) + x"00007FFE", -- +32766 (appena sotto HIGHER_BOUND) + x"00000000", -- 0 + x"FFFF8001", -- -32767 (appena sopra LOWER_BOUND) + x"FFFF8000", -- -32768 (LOWER_BOUND) + x"FFFF63C0", -- -40000 (clipping negativo) + x"00003039", -- +12345 (valore positivo intermedio) + x"FFFFCFC7", -- -12345 (valore negativo intermedio) + x"00007FFF", -- +32767 (HIGHER_BOUND, ripetuto) + x"FFFF8000", -- -32768 (LOWER_BOUND, ripetuto) + x"00009C40", -- +40000 (clipping positivo, ripetuto) + x"FFFF63C0", -- -40000 (clipping negativo, ripetuto) + x"00000001", -- +1 + x"FFFFFFFF", -- -1 + x"00000000" -- 0 (ripetuto) + ); + +BEGIN + + -- Clock generation + aclk <= NOT aclk AFTER 5 ns; + + -- DUT instantiation + uut : volume_saturator + GENERIC MAP( + TDATA_WIDTH => TDATA_WIDTH, + VOLUME_WIDTH => VOLUME_WIDTH, + VOLUME_STEP_2 => VOLUME_STEP_2, + HIGHER_BOUND => 2 ** 15 - 1, + LOWER_BOUND => - 2 ** 15 + ) + PORT MAP( + aclk => aclk, + aresetn => aresetn, + s_axis_tvalid => s_axis_tvalid, + s_axis_tdata => s_axis_tdata, + s_axis_tlast => s_axis_tlast, + s_axis_tready => s_axis_tready, + m_axis_tvalid => m_axis_tvalid, + m_axis_tdata => m_axis_tdata, + m_axis_tlast => m_axis_tlast, + m_axis_tready => m_axis_tready + ); + + -- Stimulus process: send stereo samples, tlast on R + stimulus : PROCESS + BEGIN + -- Reset + WAIT FOR 10 ns; + aresetn <= '1'; + WAIT UNTIL rising_edge(aclk); + + FOR i IN 0 TO stereo_mem'high LOOP + s_axis_tdata <= stereo_mem(i); + s_axis_tvalid <= '1'; + -- tlast asserted on every R channel (odd index) + IF (i MOD 2) = 1 THEN + s_axis_tlast <= '1'; + ELSE + s_axis_tlast <= '0'; + END IF; + -- Wait for handshake + WAIT UNTIL rising_edge(aclk); + WHILE s_axis_tready = '0' LOOP + WAIT UNTIL rising_edge(aclk); + END LOOP; + END LOOP; + s_axis_tvalid <= '0'; + s_axis_tlast <= '0'; + + -- Wait and finish + WAIT FOR 100 ns; + WAIT; + END PROCESS; + + -- Optionally, block m_axis_tready for a few cycles to test backpressure + PROCESS + BEGIN + WAIT FOR 80 ns; + WAIT UNTIL rising_edge(aclk); + m_axis_tready <= '0'; + WAIT FOR 30 ns; + WAIT UNTIL rising_edge(aclk); + m_axis_tready <= '1'; + WAIT; + END PROCESS; + +END Behavioral; \ No newline at end of file diff --git a/LAB3/src/LFO.vhd b/LAB3/src/LFO.vhd index dc0d4be..be8272b 100644 --- a/LAB3/src/LFO.vhd +++ b/LAB3/src/LFO.vhd @@ -38,15 +38,12 @@ 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; - + 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 step_counter : INTEGER RANGE 0 TO 2 ** TRIANGULAR_COUNTER_LENGHT - 1 := 0; 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'; @@ -57,14 +54,6 @@ BEGIN 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 @@ -76,34 +65,37 @@ BEGIN direction_up <= '1'; ELSE + -- Clamp step_clk_cycles to a minimum of 1 to avoid negative or zero values + IF (LFO_COUNTER_BASE_CLK_CYCLES - ADJUSTMENT_FACTOR * to_integer(JSTK_CENTER_VALUE - unsigned(lfo_period))) < 1 THEN + step_clk_cycles <= 1; + ELSE + step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES - ADJUSTMENT_FACTOR * to_integer(JSTK_CENTER_VALUE - unsigned(lfo_period)); + END IF; IF lfo_enable = '1' THEN - IF step_counter < step_clk_cycles THEN - step_counter <= step_counter + 1; - - ELSE + IF step_counter >= step_clk_cycles THEN step_counter <= 0; - IF direction_up = '1' THEN + IF tri_counter = 2 ** TRIANGULAR_COUNTER_LENGHT - 2 THEN + direction_up <= '0'; - 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; + 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; @@ -126,33 +118,31 @@ BEGIN 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 + IF s_axis_tvalid = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + IF lfo_enable = '1' THEN + m_axis_tdata <= STD_LOGIC_VECTOR( + resize( + signed(s_axis_tdata) * tri_counter, + m_axis_tdata'LENGTH + ) + ); + + ELSE + m_axis_tdata <= s_axis_tdata; + + END IF; + s_axis_tready_int <= '1'; 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; + ELSE + s_axis_tready_int <= '0'; - -- 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 & (TRIANGULAR_COUNTER_LENGHT - 1 downto 0 => '0'); - END IF; - - trigger <= '1'; END IF; END IF; diff --git a/LAB3/src/volume_multiplier.vhd b/LAB3/src/volume_multiplier.vhd index 8aa60fc..997c281 100644 --- a/LAB3/src/volume_multiplier.vhd +++ b/LAB3/src/volume_multiplier.vhd @@ -28,21 +28,18 @@ END volume_multiplier; ARCHITECTURE Behavioral OF volume_multiplier IS - CONSTANT VOLUME_STEPS : INTEGER := (2 ** VOLUME_WIDTH) / (2 ** (VOLUME_STEP_2 + 1)); + CONSTANT VOLUME_STEPS : INTEGER := (2 ** VOLUME_WIDTH) / (2 ** VOLUME_STEP_2); + CONSTANT CENTER_VOLUME_STEP : INTEGER := (2 ** (VOLUME_WIDTH - 1) - 1) / (2 ** VOLUME_STEP_2) + 1; SIGNAL volume_exp_mult : INTEGER RANGE -VOLUME_STEPS TO VOLUME_STEPS := 0; - signal volume_centered : SIGNED(VOLUME_WIDTH - 1 DOWNTO 0); - SIGNAL s_axis_tready_int : STD_LOGIC; + SIGNAL m_axis_tvalid_int : STD_LOGIC; BEGIN -- Assigning the output signals - s_axis_tready <= s_axis_tready_int; m_axis_tvalid <= m_axis_tvalid_int; - - -- Volume to signed and centered - volume_centered <= signed(unsigned(volume) - to_unsigned(511, VOLUME_WIDTH)); + s_axis_tready <= m_axis_tready AND aresetn; -- Volume to exp PROCESS (aclk) @@ -54,7 +51,10 @@ BEGIN volume_exp_mult <= 0; ELSE - volume_exp_mult <= to_integer(volume_centered(VOLUME_WIDTH - 1 DOWNTO VOLUME_STEP_2)); + -- Volume to signed and centered and convert to power of 2 exponent + volume_exp_mult <= to_integer( + shift_right(signed('0' & volume), VOLUME_STEP_2) - CENTER_VOLUME_STEP + ); END IF; @@ -69,9 +69,9 @@ BEGIN IF rising_edge(aclk) THEN IF aresetn = '0' THEN - s_axis_tready_int <= '0'; m_axis_tvalid_int <= '0'; m_axis_tlast <= '0'; + m_axis_tdata <= (OTHERS => '0'); ELSE -- Clear valid flag when master interface is ready @@ -79,7 +79,9 @@ BEGIN m_axis_tvalid_int <= '0'; END IF; - IF s_axis_tvalid = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + -- Handle the data flow + IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN + -- Multiply the input data with the volume and assign to output IF volume_exp_mult >= 0 THEN m_axis_tdata <= STD_LOGIC_VECTOR( shift_left( @@ -90,6 +92,7 @@ BEGIN volume_exp_mult ) ); + ELSE m_axis_tdata <= STD_LOGIC_VECTOR( shift_right( @@ -97,16 +100,15 @@ BEGIN signed(s_axis_tdata), m_axis_tdata'LENGTH ), - -volume_exp_mult + - volume_exp_mult ) ); + END IF; - s_axis_tready_int <= '1'; + m_axis_tvalid_int <= '1'; m_axis_tlast <= s_axis_tlast; - ELSE - s_axis_tready_int <= '0'; END IF; END IF; diff --git a/LAB3/src/volume_saturator.vhd b/LAB3/src/volume_saturator.vhd index 10744c0..9a9ab01 100644 --- a/LAB3/src/volume_saturator.vhd +++ b/LAB3/src/volume_saturator.vhd @@ -28,13 +28,12 @@ END volume_saturator; ARCHITECTURE Behavioral OF volume_saturator IS - SIGNAL s_axis_tready_int : STD_LOGIC; SIGNAL m_axis_tvalid_int : STD_LOGIC; BEGIN -- Output assignments - s_axis_tready <= s_axis_tready_int; m_axis_tvalid <= m_axis_tvalid_int; + s_axis_tready <= m_axis_tready AND aresetn; PROCESS (aclk) BEGIN @@ -42,7 +41,6 @@ BEGIN IF rising_edge(aclk) THEN IF aresetn = '0' THEN - s_axis_tready_int <= '0'; m_axis_tvalid_int <= '0'; m_axis_tlast <= '0'; m_axis_tdata <= (OTHERS => '0'); @@ -53,23 +51,23 @@ BEGIN m_axis_tvalid_int <= '0'; END IF; - IF s_axis_tvalid = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + -- Handle the data flow + IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN -- Check if the input data is within the bounds else saturate IF signed(s_axis_tdata) > to_signed(HIGHER_BOUND, s_axis_tdata'length) THEN m_axis_tdata <= STD_LOGIC_VECTOR(to_signed(HIGHER_BOUND, TDATA_WIDTH)); + ELSIF signed(s_axis_tdata) < to_signed(LOWER_BOUND, s_axis_tdata'length) THEN m_axis_tdata <= STD_LOGIC_VECTOR(to_signed(LOWER_BOUND, TDATA_WIDTH)); + ELSE m_axis_tdata <= STD_LOGIC_VECTOR(resize(signed(s_axis_tdata), TDATA_WIDTH)); + END IF; - s_axis_tready_int <= '1'; m_axis_tvalid_int <= '1'; m_axis_tlast <= s_axis_tlast; - ELSE - s_axis_tready_int <= '0'; - END IF; END IF; diff --git a/LAB3/vivado/lab3/lab3.xpr b/LAB3/vivado/lab3/lab3.xpr index ca8d493..7e2c548 100644 --- a/LAB3/vivado/lab3/lab3.xpr +++ b/LAB3/vivado/lab3/lab3.xpr @@ -77,6 +77,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -90,97 +180,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -188,20 +187,6 @@ - - - - - - - - - - - - - -