Lab 3: Audio Processing System #3
@@ -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)
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user