From dff2eb439d7f8eb58e03313ed2214292e1f8bf65 Mon Sep 17 00:00:00 2001 From: Davide Date: Tue, 3 Jun 2025 14:55:23 +0200 Subject: [PATCH] - update comments - add led_level_controller Const --- LAB3/src/LFO.vhd | 18 +++++++++--------- LAB3/src/all_pass_filter.vhd | 16 ++++++++-------- LAB3/src/balance_controller.vhd | 8 ++++---- LAB3/src/digilent_jstk2.vhd | 15 ++++++++------- LAB3/src/effect_selector.vhd | 10 ++++++---- LAB3/src/led_level_controller.vhd | 14 ++++++++++---- LAB3/src/moving_average_filter.vhd | 14 +++++++------- LAB3/src/moving_average_filter_en.vhd | 4 ++-- LAB3/src/volume_controller.vhd | 10 +++++----- LAB3/src/volume_multiplier.vhd | 19 ++++++++++--------- LAB3/src/volume_saturator.vhd | 17 ++++------------- 11 files changed, 73 insertions(+), 72 deletions(-) diff --git a/LAB3/src/LFO.vhd b/LAB3/src/LFO.vhd index 8387f93..5279f36 100644 --- a/LAB3/src/LFO.vhd +++ b/LAB3/src/LFO.vhd @@ -3,7 +3,7 @@ USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; -- Entity: LFO (Low Frequency Oscillator) - Alternative Implementation --- Purpose: Applies tremolo effect to audio by modulating amplitude with a triangular wave +-- Purpose: Applies effect to audio by modulating amplitude with a triangular wave -- This is a simplified, single-process implementation compared to the pipelined version -- Provides real-time audio amplitude modulation for musical effects ENTITY LFO IS @@ -24,13 +24,13 @@ ENTITY LFO IS -- Slave AXI Stream interface (audio input) s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal - s_axis_tdata : IN STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0); -- Audio sample input + s_axis_tdata : IN STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0); -- Audio sample input s_axis_tlast : IN STD_LOGIC; -- Channel indicator (0=left, 1=right) s_axis_tready : OUT STD_LOGIC; -- Ready to accept input data -- Master AXI Stream interface (audio output) m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal - m_axis_tdata : OUT STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0); -- Modulated audio sample output + m_axis_tdata : OUT STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0); -- Modulated audio sample output m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough m_axis_tready : IN STD_LOGIC -- Downstream ready signal ); @@ -57,7 +57,7 @@ ARCHITECTURE Behavioral OF LFO IS -- Triangular wave generation signals -- Note: Using signed counter with extra bit to handle full range calculations - SIGNAL tri_counter : SIGNED(TRIANGULAR_COUNTER_LENGHT DOWNTO 0) := (OTHERS => '0'); -- Triangular wave amplitude + SIGNAL tri_counter : SIGNED(TRIANGULAR_COUNTER_LENGHT DOWNTO 0) := (OTHERS => '0'); -- Triangular wave amplitude SIGNAL direction_up : STD_LOGIC := '1'; -- Wave direction: '1' = ascending, '0' = descending -- AXI4-Stream control signals @@ -106,7 +106,7 @@ BEGIN step_counter <= 0; -- Reset counter for next period -- Check for triangular wave direction changes at extremes - -- Note: Using (2^n - 2) and 1 instead of (2^n - 1) and 0 to avoid edge cases + -- Note: Using (2^n - 2) and 1 instead of (2^n - 1) and 0 due to process signal assignment IF tri_counter = (2 ** TRIANGULAR_COUNTER_LENGHT) - 2 THEN direction_up <= '0'; -- Switch to descending at near-maximum @@ -180,8 +180,8 @@ BEGIN -- Data input logic: Process new audio samples when available and output is ready IF s_axis_tvalid = '1' AND (m_axis_tready = '1' OR m_axis_tvalid_int = '0') THEN IF lfo_enable = '1' THEN - -- Apply LFO tremolo effect: multiply audio sample by triangular wave - -- This creates amplitude modulation (tremolo effect) + -- Apply LFO effect: multiply audio sample by triangular wave + -- This creates amplitude modulation (effect) m_axis_tdata_temp <= signed(s_axis_tdata) * tri_counter; s_axis_tlast_reg <= s_axis_tlast; -- Register channel indicator @@ -212,11 +212,11 @@ BEGIN -- LFO Implementation Summary: -- 1. Generates triangular wave at frequency controlled by joystick input - -- 2. When enabled: multiplies audio samples by triangular wave (tremolo effect) + -- 2. When enabled: multiplies audio samples by triangular wave (multiplier value range from 0 to 1) -- 3. When disabled: passes audio through unchanged (bypass mode) -- 4. Uses proper AXI4-Stream handshaking for real-time audio processing -- - -- Tremolo Effect Characteristics: + -- Effect Characteristics: -- - Frequency range: Approximately 0.1Hz to 10Hz (typical for audio LFO) -- - Modulation depth: Controlled by TRIANGULAR_COUNTER_LENGHT generic -- - Waveform: Triangular (linear amplitude changes, smooth transitions) diff --git a/LAB3/src/all_pass_filter.vhd b/LAB3/src/all_pass_filter.vhd index 262d02e..4a4a782 100644 --- a/LAB3/src/all_pass_filter.vhd +++ b/LAB3/src/all_pass_filter.vhd @@ -4,7 +4,7 @@ USE ieee.numeric_std.ALL; -- Entity: all_pass_filter -- Purpose: A pass-through filter that maintains the same interface and timing --- characteristics as a moving average filter but passes data unchanged. +-- characteristics as the moving average filter but passes data unchanged. ENTITY all_pass_filter IS GENERIC ( TDATA_WIDTH : POSITIVE := 24 -- Width of the data bus in bits @@ -16,13 +16,13 @@ ENTITY all_pass_filter IS -- AXI4-Stream Slave Interface (Input) s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal - s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Input data + s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Input data s_axis_tlast : IN STD_LOGIC; -- Input end-of-packet signal s_axis_tready : OUT STD_LOGIC; -- Ready to accept input data -- AXI4-Stream Master Interface (Output) m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal - m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Output data + m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Output data m_axis_tlast : OUT STD_LOGIC; -- Output end-of-packet signal m_axis_tready : IN STD_LOGIC -- Downstream ready signal ); @@ -36,9 +36,9 @@ ARCHITECTURE Behavioral OF all_pass_filter IS -- Internal slave interface signals SIGNAL s_axis_tready_int : STD_LOGIC := '0'; -- Internal ready signal for input SIGNAL s_axis_tlast_reg : STD_LOGIC := '0'; -- Registered version of input tlast + SIGNAL s_axis_tdata_reg : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); -- Temporary storage for input data -- Internal data storage and master interface signals - SIGNAL m_axis_tdata_temp : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); -- Temporary storage for input data SIGNAL m_axis_tvalid_int : STD_LOGIC := '0'; -- Internal valid signal for output BEGIN @@ -66,10 +66,10 @@ BEGIN -- Asynchronous reset logic (active low) IF aresetn = '0' THEN -- Reset all internal signals to known states - trigger <= '0'; -- Clear data processing trigger + trigger <= '0'; -- Clear data processing trigger s_axis_tlast_reg <= '0'; -- Clear registered tlast s_axis_tready_int <= '0'; -- Not ready to accept data during reset - m_axis_tdata_temp <= (OTHERS => '0'); -- Clear temporary data storage + s_axis_tdata_reg <= (OTHERS => '0'); -- Clear temporary data storage m_axis_tvalid_int <= '0'; -- No valid data on output during reset m_axis_tlast <= '0'; -- Clear output tlast @@ -88,7 +88,7 @@ BEGIN -- (either no valid data pending OR downstream is ready) IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN -- Transfer stored data to output - m_axis_tdata <= m_axis_tdata_temp; -- Output the stored input data unchanged + m_axis_tdata <= s_axis_tdata_reg; -- Output the stored input data unchanged m_axis_tlast <= s_axis_tlast_reg; -- Output the registered tlast signal -- Set output control signals @@ -101,7 +101,7 @@ BEGIN IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN -- Store input signals for later output s_axis_tlast_reg <= s_axis_tlast; -- Register the tlast signal - m_axis_tdata_temp <= s_axis_tdata; -- Store input data (pass-through, no processing) + s_axis_tdata_reg <= s_axis_tdata; -- Store input data (pass-through, no processing) -- Set trigger to indicate data is ready for output trigger <= '1'; diff --git a/LAB3/src/balance_controller.vhd b/LAB3/src/balance_controller.vhd index 99479d7..9abd755 100644 --- a/LAB3/src/balance_controller.vhd +++ b/LAB3/src/balance_controller.vhd @@ -19,25 +19,25 @@ ENTITY balance_controller IS -- AXI4-Stream Slave Interface (Audio Input) s_axis_tvalid : IN STD_LOGIC; -- Input data valid - s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample data + s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample data s_axis_tready : OUT STD_LOGIC; -- Ready to accept input s_axis_tlast : IN STD_LOGIC; -- Channel indicator (0=left, 1=right) -- AXI4-Stream Master Interface (Audio Output) m_axis_tvalid : OUT STD_LOGIC; -- Output data valid - m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Balanced audio sample + m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Balanced audio sample m_axis_tready : IN STD_LOGIC; -- Downstream ready m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough -- Balance Control Input - balance : IN STD_LOGIC_VECTOR(BALANCE_WIDTH - 1 DOWNTO 0) -- Balance position (0=full left, 1023=full right, 512=center) + balance : IN STD_LOGIC_VECTOR(BALANCE_WIDTH - 1 DOWNTO 0) -- Balance position (0=full left, 1023=full right, 512=center) ); END balance_controller; ARCHITECTURE Behavioral OF balance_controller IS -- Balance calculation constants - CONSTANT BALANCE_STEPS : INTEGER := (2 ** (BALANCE_WIDTH - 1)) / (2 ** BALANCE_STEP_2) + 1; -- Number of attenuation steps (9 steps for 10-bit balance) + CONSTANT BALANCE_STEPS : INTEGER := (2 ** (BALANCE_WIDTH - 1)) / (2 ** BALANCE_STEP_2) + 1; -- Number of attenuation steps (9 steps for 10-bit balance) CONSTANT BAL_MID : INTEGER := 2 ** (BALANCE_WIDTH - 1); -- Center balance position (512 for 10-bit) CONSTANT DEAD_ZONE : INTEGER := (2 ** BALANCE_STEP_2) / 2; -- Dead zone around center (32 for step size 64) diff --git a/LAB3/src/digilent_jstk2.vhd b/LAB3/src/digilent_jstk2.vhd index 40268a8..1872503 100644 --- a/LAB3/src/digilent_jstk2.vhd +++ b/LAB3/src/digilent_jstk2.vhd @@ -16,17 +16,17 @@ ENTITY digilent_jstk2 IS -- AXI4-Stream Master Interface: Data going TO the SPI IP-Core (and so, to the JSTK2 module) m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal - m_axis_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8-bit data to send via SPI + m_axis_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8-bit data to send via SPI m_axis_tready : IN STD_LOGIC; -- SPI IP-Core ready to accept data -- AXI4-Stream Slave Interface: Data coming FROM the SPI IP-Core (and so, from the JSTK2 module) -- Note: There is no tready signal, so you must be always ready to accept incoming data, or it will be lost! s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal - s_axis_tdata : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8-bit data received via SPI + s_axis_tdata : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8-bit data received via SPI -- Joystick and button values read from the JSTK2 module - jstk_x : OUT STD_LOGIC_VECTOR(9 DOWNTO 0); -- X-axis joystick position (10-bit, 0-1023) - jstk_y : OUT STD_LOGIC_VECTOR(9 DOWNTO 0); -- Y-axis joystick position (10-bit, 0-1023) + jstk_x : OUT STD_LOGIC_VECTOR(9 DOWNTO 0); -- X-axis joystick position (10-bit, 0-1023) + jstk_y : OUT STD_LOGIC_VECTOR(9 DOWNTO 0); -- Y-axis joystick position (10-bit, 0-1023) btn_jstk : OUT STD_LOGIC; -- Joystick button state (1=pressed) btn_trigger : OUT STD_LOGIC; -- Trigger button state (1=pressed) @@ -44,7 +44,7 @@ ARCHITECTURE Behavioral OF digilent_jstk2 IS -- Calculate delay in clock cycles: (delay_period + 1_SPI_clock_period) * clock_frequency -- This ensures proper timing between SPI packets as required by JSTK2 datasheet - CONSTANT DELAY_CLK_CYCLES : INTEGER := (DELAY_US + 1_000_000 / SPI_SCLKFREQ) * (CLKFREQ / 1_000_000); + CONSTANT DELAY_CLK_CYCLES : INTEGER := (DELAY_US + 1_000_000 / SPI_SCLKFREQ) * (CLKFREQ / 1_000_000) - 1; -- State machine type definitions TYPE tx_state_type IS (DELAY, SEND_CMD, SEND_RED, SEND_GREEN, SEND_BLUE, SEND_DUMMY); @@ -56,7 +56,7 @@ ARCHITECTURE Behavioral OF digilent_jstk2 IS -- Timing and data storage signals SIGNAL tx_delay_counter : INTEGER RANGE 0 TO DELAY_CLK_CYCLES := 0; -- Counter for inter-packet delay timing - SIGNAL rx_cache : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Temporary storage for multi-byte data reception + SIGNAL rx_cache : STD_LOGIC_VECTOR(s_axis_tdata'range); -- Temporary storage for multi-byte data reception BEGIN @@ -80,7 +80,8 @@ BEGIN "01101001" WHEN SEND_DUMMY; -- Dummy byte to complete 5-byte transaction -- TX State Machine: Sends LED color commands to JSTK2 module - -- Protocol: Command(1) + Red(1) + Green(1) + Blue(1) + Dummy(1) = 5 bytes total + -- Protocol: Command(1) + Red(1) + Green(1) + Blue(1) + Dummy(1) = 5 bytes total > Delay before next command + -- The delay is required by the JSTK datasheet to ensure proper timing between SPI transactions TX : PROCESS (aclk) BEGIN IF rising_edge(aclk) THEN diff --git a/LAB3/src/effect_selector.vhd b/LAB3/src/effect_selector.vhd index cc9255b..fee2456 100644 --- a/LAB3/src/effect_selector.vhd +++ b/LAB3/src/effect_selector.vhd @@ -28,7 +28,7 @@ END effect_selector; ARCHITECTURE Behavioral OF effect_selector IS - constant JOYSTICK_DEFAULT : STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0) := STD_LOGIC_VECTOR(to_unsigned(2 ** (JOYSTICK_LENGHT - 1), JOYSTICK_LENGHT)); -- Default joystick value + constant JOYSTICK_DEFAULT : STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0) := STD_LOGIC_VECTOR(to_unsigned(2 ** (JOYSTICK_LENGHT - 1), JOYSTICK_LENGHT)); -- Default joystick value (center position for 10-bit joystick is 512) BEGIN @@ -52,9 +52,11 @@ BEGIN -- X-axis behavior differs between modes -- Note: When switching between modes, some outputs are reset while others preserved IF effect = '1' THEN - -- LFO Mode: Y-axis controls Low Frequency Oscillator period - -- Used for tremolo, vibrato, or other modulation effects + -- LFO Mode: + -- Y-axis controls Low Frequency Oscillator period + -- X-axis is ignored in this mode lfo_period <= jstck_y; + -- Volume remains at last set value (preserved from previous mode) -- Reset balance to center/default position when in LFO mode @@ -64,9 +66,9 @@ BEGIN -- Volume/Balance Mode: -- Y-axis controls overall volume level -- X-axis controls left/right audio balance - -- Traditional audio mixer control mode volume <= jstck_y; balance <= jstck_x; + -- LFO period remains at last set value (preserved from previous LFO mode) END IF; diff --git a/LAB3/src/led_level_controller.vhd b/LAB3/src/led_level_controller.vhd index 227348c..d42dac1 100644 --- a/LAB3/src/led_level_controller.vhd +++ b/LAB3/src/led_level_controller.vhd @@ -1,6 +1,7 @@ LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; +USE IEEE.MATH_REAL.ALL; -- Entity: led_level_controller -- Purpose: Audio level meter using LEDs to display real-time audio amplitude @@ -34,7 +35,10 @@ ARCHITECTURE Behavioral OF led_level_controller IS -- Calculate clock cycles needed for LED refresh timing -- Formula: (refresh_time_ms * 1_000_000 ns/ms) / clock_period_ns -- Example: (1ms * 1,000,000) / 10ns = 100,000 cycles for 1ms refresh at 100MHz - CONSTANT REFRESH_CYCLES : INTEGER := (refresh_time_ms * 1_000_000) / clock_period_ns; + CONSTANT REFRESH_CYCLES : INTEGER := (refresh_time_ms * 1_000_000) / clock_period_ns - 1; + + -- Calculate the number of bits needed to represent the number of LEDs + CONSTANT NUMLEDS_BITS : INTEGER := INTEGER(ceil(log2(real(NUM_LEDS)))); -- LED refresh timing control signals SIGNAL refresh_counter : INTEGER RANGE 0 TO REFRESH_CYCLES := 0; -- Counts clock cycles between LED updates @@ -91,7 +95,7 @@ BEGIN refresh_tick <= '0'; ELSE -- Normal operation: Count clock cycles and generate refresh tick - IF refresh_counter = REFRESH_CYCLES - 1 THEN + IF refresh_counter = REFRESH_CYCLES THEN -- End of refresh period: Reset counter and generate tick pulse refresh_counter <= 0; refresh_tick <= '1'; -- Single clock cycle pulse for LED update @@ -109,7 +113,7 @@ BEGIN -- Updates only when refresh_tick is active to maintain stable visual display PROCESS (aclk) VARIABLE combined_amp : UNSIGNED(CHANNEL_LENGHT - 1 DOWNTO 0); -- Combined amplitude of both channels - VARIABLE led_level : INTEGER RANGE 0 TO NUM_LEDS := 0; -- Calculated LED level for bar graph display + VARIABLE led_level : INTEGER RANGE 0 TO 2**NUMLEDS_BITS := 0; -- Calculated LED level for bar graph display BEGIN IF rising_edge(aclk) THEN IF aresetn = '0' THEN @@ -123,6 +127,8 @@ BEGIN -- Combine left and right channel amplitudes -- The sum of the absolute values of both channels gives a measure of total audio energy. -- RESIZE ensures the sum fits within the variable's bit width. + -- There isn't data loss here since both abs_l and abs_r are one bit shorter than combined_amp, + -- due to the absolute value operation. combined_amp := RESIZE(abs_l + abs_r, combined_amp'LENGTH); -- Normalize combined amplitude to LED scale (0 to NUM_LEDS) @@ -130,7 +136,7 @@ BEGIN -- For 24-bit audio, shifting by (CHANNEL_LENGHT - 4) reduces the range to approximately 4 bits (0-15). -- Adding 1 ensures that at least one LED lights up for any non-zero audio input. -- Example: For 24-bit input, 1 + (combined_amp >> 20) gives a range from 1 to 16. - led_level := 1 + to_integer(shift_right(combined_amp, CHANNEL_LENGHT - 4)); + led_level := 1 + to_integer(shift_right(combined_amp, CHANNEL_LENGHT - NUMLEDS_BITS)); -- Saturation protection: Limit LED level to maximum available LEDs -- Prevents overflow and ensures the LED index stays within bounds. diff --git a/LAB3/src/moving_average_filter.vhd b/LAB3/src/moving_average_filter.vhd index 881fa57..bd307a6 100644 --- a/LAB3/src/moving_average_filter.vhd +++ b/LAB3/src/moving_average_filter.vhd @@ -3,7 +3,7 @@ USE IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; -- Entity: moving_average_filter --- Purpose: Implements a finite impulse response (FIR) low-pass filter using moving average +-- Purpose: Implements a moving average filter for audio data -- Maintains separate circular buffers for left and right audio channels -- Filter order is configurable as 2^(FILTER_ORDER_POWER) samples ENTITY moving_average_filter IS @@ -21,13 +21,13 @@ ENTITY moving_average_filter IS -- AXI4-Stream Slave Interface (Audio Input) s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal - s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample input + s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample input s_axis_tlast : IN STD_LOGIC; -- Channel indicator (0=left, 1=right) s_axis_tready : OUT STD_LOGIC; -- Ready to accept input data -- AXI4-Stream Master Interface (Audio Output) m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal - m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Filtered audio sample output + m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Filtered audio sample output m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough m_axis_tready : IN STD_LOGIC -- Downstream ready signal ); @@ -42,14 +42,14 @@ ARCHITECTURE Behavioral OF moving_average_filter IS TYPE sample_array IS ARRAY (0 TO FILTER_ORDER - 1) OF signed(TDATA_WIDTH - 1 DOWNTO 0); -- Right channel (RX) processing signals - SIGNAL samples_rx : sample_array := (OTHERS => (OTHERS => '0')); -- Circular buffer for right channel samples + SIGNAL samples_rx : sample_array := (OTHERS => (OTHERS => '0')); -- Circular buffer for right channel samples SIGNAL sum_rx : signed(TDATA_WIDTH + FILTER_ORDER_POWER - 1 DOWNTO 0) := (OTHERS => '0'); -- Running sum of right channel samples - SIGNAL wr_ptr_rx : INTEGER RANGE 0 TO FILTER_ORDER - 1 := 0; -- Write pointer for right channel buffer + SIGNAL wr_ptr_rx : INTEGER RANGE 0 TO FILTER_ORDER - 1 := 0; -- Write pointer for right channel buffer -- Left channel (LX) processing signals - SIGNAL samples_lx : sample_array := (OTHERS => (OTHERS => '0')); -- Circular buffer for left channel samples + SIGNAL samples_lx : sample_array := (OTHERS => (OTHERS => '0')); -- Circular buffer for left channel samples SIGNAL sum_lx : signed(TDATA_WIDTH + FILTER_ORDER_POWER - 1 DOWNTO 0) := (OTHERS => '0'); -- Running sum of left channel samples - SIGNAL wr_ptr_lx : INTEGER RANGE 0 TO FILTER_ORDER - 1 := 0; -- Write pointer for left channel buffer + SIGNAL wr_ptr_lx : INTEGER RANGE 0 TO FILTER_ORDER - 1 := 0; -- Write pointer for left channel buffer -- Control and interface signals SIGNAL trigger : STD_LOGIC := '0'; -- Trigger signal to indicate when to output filtered data diff --git a/LAB3/src/moving_average_filter_en.vhd b/LAB3/src/moving_average_filter_en.vhd index 3386a56..5a57442 100644 --- a/LAB3/src/moving_average_filter_en.vhd +++ b/LAB3/src/moving_average_filter_en.vhd @@ -22,13 +22,13 @@ ENTITY moving_average_filter_en IS -- AXI4-Stream Slave Interface (Audio Input) s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal - s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample input + s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample input s_axis_tlast : IN STD_LOGIC; -- Channel indicator (0=left, 1=right) s_axis_tready : OUT STD_LOGIC; -- Ready to accept input data -- AXI4-Stream Master Interface (Audio Output) m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal - m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample output (filtered or unfiltered) + m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample output (filtered or unfiltered) m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough m_axis_tready : IN STD_LOGIC; -- Downstream ready signal diff --git a/LAB3/src/volume_controller.vhd b/LAB3/src/volume_controller.vhd index b251243..d567757 100644 --- a/LAB3/src/volume_controller.vhd +++ b/LAB3/src/volume_controller.vhd @@ -21,13 +21,13 @@ ENTITY volume_controller IS -- AXI4-Stream Slave Interface (Audio Input) s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal - s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample input + s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample input s_axis_tlast : IN STD_LOGIC; -- Channel indicator (0=left, 1=right) s_axis_tready : OUT STD_LOGIC; -- Ready to accept input data -- AXI4-Stream Master Interface (Audio Output) m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal - m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample output (volume adjusted) + m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample output (volume adjusted) m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough m_axis_tready : IN STD_LOGIC; -- Downstream ready signal @@ -98,10 +98,10 @@ ARCHITECTURE Behavioral OF volume_controller IS -- Internal AXI4-Stream signals between multiplier and saturator -- These signals carry the wide multiplication results before saturation - SIGNAL int_axis_tvalid : STD_LOGIC; -- Valid signal between stages - SIGNAL int_axis_tready : STD_LOGIC; -- Ready signal between stages + SIGNAL int_axis_tvalid : STD_LOGIC; -- Valid signal between stages + SIGNAL int_axis_tready : STD_LOGIC; -- Ready signal between stages SIGNAL int_axis_tdata : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) DOWNTO 0); -- Wide data between stages - SIGNAL int_axis_tlast : STD_LOGIC; -- Channel indicator between stages + SIGNAL int_axis_tlast : STD_LOGIC; -- Channel indicator between stages BEGIN diff --git a/LAB3/src/volume_multiplier.vhd b/LAB3/src/volume_multiplier.vhd index 45648a1..26c2d49 100644 --- a/LAB3/src/volume_multiplier.vhd +++ b/LAB3/src/volume_multiplier.vhd @@ -19,15 +19,15 @@ ENTITY volume_multiplier IS -- AXI4-Stream Slave Interface (Audio Input) s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal - s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample input + s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample input s_axis_tlast : IN STD_LOGIC; -- Channel indicator (0=left, 1=right) s_axis_tready : OUT STD_LOGIC; -- Ready to accept input data -- AXI4-Stream Master Interface (Audio Output with extended width) - m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal + m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) DOWNTO 0); -- Extended width output data - m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough - m_axis_tready : IN STD_LOGIC; -- Downstream ready signal + m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough + m_axis_tready : IN STD_LOGIC; -- Downstream ready signal -- Volume control input volume : IN STD_LOGIC_VECTOR(VOLUME_WIDTH - 1 DOWNTO 0) -- Volume level (0=minimum, 1023=maximum) @@ -37,7 +37,7 @@ END volume_multiplier; ARCHITECTURE Behavioral OF volume_multiplier IS -- Calculate volume control parameters based on generics - CONSTANT VOLUME_STEPS : INTEGER := (2 ** (VOLUME_WIDTH - 1)) / (2 ** VOLUME_STEP_2) + 1; -- Number of volume steps (9 steps for 10-bit) + CONSTANT VOLUME_STEPS : INTEGER := (2 ** (VOLUME_WIDTH - 1)) / (2 ** VOLUME_STEP_2) + 1; -- Number of volume steps (9 steps for 10-bit) CONSTANT VOL_MID : INTEGER := 2 ** (VOLUME_WIDTH - 1); -- Center volume position (512 for 10-bit) CONSTANT DEAD_ZONE : INTEGER := (2 ** VOLUME_STEP_2) / 2; -- Dead zone around center (32 for step size 64) @@ -58,7 +58,7 @@ BEGIN -- Volume to exponent conversion process -- Converts joystick y-axis position to bit-shift amount for exponential volume scaling - PROCESS (aclk) + VOLUME_CALC : PROCESS (aclk) BEGIN IF rising_edge(aclk) THEN @@ -78,6 +78,7 @@ BEGIN -- volume = 0-479: Negative exponent (attenuation, right shift) -- volume = 480-543: Zero exponent (unity gain, dead zone) -- volume = 544-1023: Positive exponent (amplification, left shift) + volume_exp_mult <= to_integer( shift_right( signed('0' & volume) - to_signed(VOL_MID - DEAD_ZONE, volume'length + 1), @@ -89,11 +90,11 @@ BEGIN END IF; - END PROCESS; + END PROCESS VOLUME_CALC; -- AXI4-Stream data processing -- Applies exponential volume scaling using bit-shifting multiplication - PROCESS (aclk) + AXIS : PROCESS (aclk) BEGIN IF rising_edge(aclk) THEN @@ -155,7 +156,7 @@ BEGIN END IF; - END PROCESS; + END PROCESS AXIS; -- Example scaling factors (VOLUME_STEP_2 = 6, 64 values per step): -- volume_exp_mult = -3: Divide by 8 (>>3) diff --git a/LAB3/src/volume_saturator.vhd b/LAB3/src/volume_saturator.vhd index 9f19d2c..697e44e 100644 --- a/LAB3/src/volume_saturator.vhd +++ b/LAB3/src/volume_saturator.vhd @@ -20,14 +20,14 @@ ENTITY volume_saturator IS aresetn : IN STD_LOGIC; -- Active-low asynchronous reset -- AXI4-Stream Slave Interface (Extended width input from multiplier) - s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal + s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) DOWNTO 0); -- Wide input data from multiplier - s_axis_tlast : IN STD_LOGIC; -- Channel indicator (0=left, 1=right) - s_axis_tready : OUT STD_LOGIC; -- Ready to accept input data + s_axis_tlast : IN STD_LOGIC; -- Channel indicator (0=left, 1=right) + s_axis_tready : OUT STD_LOGIC; -- Ready to accept input data -- AXI4-Stream Master Interface (Original width output for audio) m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal - m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Saturated audio sample output + m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Saturated audio sample output m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough m_axis_tready : IN STD_LOGIC -- Downstream ready signal ); @@ -82,12 +82,10 @@ BEGIN IF signed(s_axis_tdata) > signed(HIGHER_BOUND_VEC) THEN -- Positive overflow: Clip to maximum positive value - -- This prevents "wraparound" distortion from mathematical overflow m_axis_tdata <= HIGHER_BOUND_VEC; ELSIF signed(s_axis_tdata) < signed(LOWER_BOUND_VEC) THEN -- Negative overflow: Clip to maximum negative value - -- This prevents "wraparound" distortion from mathematical underflow m_axis_tdata <= LOWER_BOUND_VEC; ELSE @@ -109,11 +107,4 @@ BEGIN END PROCESS; - -- Saturation Purpose and Benefits: - -- 1. Prevents audio distortion from mathematical overflow - -- 2. Maintains audio dynamic range within valid bit representation - -- 3. Reduces wide multiplication results back to standard audio format - -- 4. Provides "soft limiting" behavior for volume control - -- 5. Ensures compatibility with downstream audio processing blocks - END Behavioral; \ No newline at end of file