Lab 3: Audio Processing System #3
@@ -8,24 +8,24 @@ USE IEEE.MATH_REAL.ALL;
|
|||||||
-- Processes stereo audio samples and drives a bar graph LED display
|
-- Processes stereo audio samples and drives a bar graph LED display
|
||||||
ENTITY led_level_controller IS
|
ENTITY led_level_controller IS
|
||||||
GENERIC (
|
GENERIC (
|
||||||
NUM_LEDS : POSITIVE := 16; -- Number of LEDs in the level meter display
|
NUM_LEDS : POSITIVE := 16; -- Number of LEDs in the level meter display
|
||||||
CHANNEL_LENGHT : POSITIVE := 24; -- Width of audio data (24-bit audio samples)
|
CHANNEL_LENGHT : POSITIVE := 24; -- Width of audio data (24-bit audio samples)
|
||||||
refresh_time_ms : POSITIVE := 1; -- LED refresh rate in milliseconds (1ms = 1kHz update rate)
|
refresh_time_ms : POSITIVE := 1; -- LED refresh rate in milliseconds (1ms = 1kHz update rate)
|
||||||
clock_period_ns : POSITIVE := 10 -- System clock period in nanoseconds (10ns = 100MHz)
|
clock_period_ns : POSITIVE := 10 -- System clock period in nanoseconds (10ns = 100MHz)
|
||||||
);
|
);
|
||||||
PORT (
|
PORT (
|
||||||
-- Clock and reset signals
|
-- Clock and reset signals
|
||||||
aclk : IN STD_LOGIC; -- Main clock input
|
aclk : IN STD_LOGIC; -- Main clock input
|
||||||
aresetn : IN STD_LOGIC; -- Active-low asynchronous reset
|
aresetn : IN STD_LOGIC; -- Active-low asynchronous reset
|
||||||
|
|
||||||
-- LED output array (bar graph display)
|
-- LED output array (bar graph display)
|
||||||
led : OUT STD_LOGIC_VECTOR(NUM_LEDS - 1 DOWNTO 0); -- LED control signals (1=on, 0=off)
|
led : OUT STD_LOGIC_VECTOR(NUM_LEDS - 1 DOWNTO 0); -- LED control signals (1=on, 0=off)
|
||||||
|
|
||||||
-- AXI4-Stream Slave Interface (Audio Input)
|
-- AXI4-Stream Slave Interface (Audio Input)
|
||||||
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(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=right, 1=left)
|
s_axis_tlast : IN STD_LOGIC; -- Channel indicator (0=right, 1=left)
|
||||||
s_axis_tready : OUT STD_LOGIC -- Always ready to accept data
|
s_axis_tready : OUT STD_LOGIC -- Always ready to accept data
|
||||||
);
|
);
|
||||||
END led_level_controller;
|
END led_level_controller;
|
||||||
|
|
||||||
@@ -43,7 +43,8 @@ ARCHITECTURE Behavioral OF led_level_controller IS
|
|||||||
|
|
||||||
-- Audio amplitude storage for both stereo channels
|
-- Audio amplitude storage for both stereo channels
|
||||||
-- Stores absolute values (magnitude) of left and right audio channels
|
-- Stores absolute values (magnitude) of left and right audio channels
|
||||||
SIGNAL abs_l, abs_r : UNSIGNED(CHANNEL_LENGHT - 1 DOWNTO 0) := (OTHERS => '0'); -- Absolute amplitude registers
|
SIGNAL abs_l : UNSIGNED(CHANNEL_LENGHT - 1 DOWNTO 0) := (OTHERS => '0'); -- Absolute left channel amplitude registers
|
||||||
|
SIGNAL combined_amp : UNSIGNED(CHANNEL_LENGHT - 1 DOWNTO 0) := (OTHERS => '0'); -- Combined amplitude for LED level calculation
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
@@ -52,9 +53,6 @@ BEGIN
|
|||||||
|
|
||||||
-- Capture absolute value of input sample for left/right channel
|
-- Capture absolute value of input sample for left/right channel
|
||||||
PROCESS (aclk)
|
PROCESS (aclk)
|
||||||
|
|
||||||
VARIABLE signed_sample : SIGNED(CHANNEL_LENGHT - 1 DOWNTO 0);
|
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
IF rising_edge(aclk) THEN
|
IF rising_edge(aclk) THEN
|
||||||
@@ -62,20 +60,24 @@ BEGIN
|
|||||||
IF aresetn = '0' THEN
|
IF aresetn = '0' THEN
|
||||||
-- Reset: Clear both channel amplitude registers
|
-- Reset: Clear both channel amplitude registers
|
||||||
abs_l <= (OTHERS => '0');
|
abs_l <= (OTHERS => '0');
|
||||||
abs_r <= (OTHERS => '0');
|
combined_amp <= (OTHERS => '0');
|
||||||
|
|
||||||
ELSIF s_axis_tvalid = '1' THEN
|
ELSIF s_axis_tvalid = '1' THEN
|
||||||
-- Valid audio data received: Process the sample
|
-- Valid audio data received: Process the sample
|
||||||
signed_sample := SIGNED(s_axis_tdata); -- Convert input to signed for ABS operation
|
|
||||||
|
|
||||||
-- Channel routing based on AXI4-Stream tlast signal
|
-- Channel routing based on AXI4-Stream tlast signal
|
||||||
-- tlast = '1' indicates left channel, tlast = '0' indicates right channel
|
-- tlast = '1' indicates right channel, tlast = '0' indicates left channel
|
||||||
IF s_axis_tlast = '1' THEN
|
IF s_axis_tlast = '1' THEN
|
||||||
-- Left channel: Store absolute value of audio sample
|
-- Right channel: Combine left and right channel amplitudes
|
||||||
abs_l <= UNSIGNED(ABS(signed_sample));
|
-- RESIZE ensures the sum fits within the variable's bit width.
|
||||||
|
-- There isn't data loss since both abs_l and abs(s_axis_tdata) are one bit shorter than combined_amp,
|
||||||
|
-- due to the absolute value operation.
|
||||||
|
combined_amp <= RESIZE(abs_l + UNSIGNED(ABS(SIGNED(s_axis_tdata))), combined_amp'LENGTH);
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
-- Right channel: Store absolute value of audio sample
|
-- Left channel: Store absolute value of audio sample
|
||||||
abs_r <= UNSIGNED(ABS(signed_sample));
|
abs_l <= UNSIGNED(ABS(SIGNED(s_axis_tdata)));
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
@@ -117,7 +119,6 @@ BEGIN
|
|||||||
-- Updates only when refresh_tick is active to maintain stable visual display
|
-- Updates only when refresh_tick is active to maintain stable visual display
|
||||||
PROCESS (aclk)
|
PROCESS (aclk)
|
||||||
|
|
||||||
VARIABLE combined_amp : UNSIGNED(CHANNEL_LENGHT - 1 DOWNTO 0);
|
|
||||||
VARIABLE led_level : INTEGER RANGE 0 TO 2 ** NUMLEDS_BITS := 0;
|
VARIABLE led_level : INTEGER RANGE 0 TO 2 ** NUMLEDS_BITS := 0;
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
@@ -131,29 +132,28 @@ BEGIN
|
|||||||
ELSIF refresh_tick = '1' THEN
|
ELSIF refresh_tick = '1' THEN
|
||||||
-- LED update cycle: Calculate new LED pattern based on audio amplitude
|
-- LED update cycle: Calculate new LED pattern based on audio amplitude
|
||||||
|
|
||||||
-- Combine left and right channel amplitudes
|
|
||||||
-- RESIZE ensures the sum fits within the variable's bit width.
|
|
||||||
-- There isn't data loss 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);
|
|
||||||
|
|
||||||
-- Linear scale to LED level conversion to get the best visual effect
|
-- Linear scale to LED level conversion to get the best visual effect
|
||||||
IF combined_amp = 0 THEN
|
IF combined_amp = 0 THEN
|
||||||
led_level := 0; -- No audio signal, turn off all LEDs
|
led_level := 0; -- No audio signal, turn off all LEDs
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
led_level := 1 + to_integer(shift_right(combined_amp, CHANNEL_LENGHT - NUMLEDS_BITS));
|
led_level := 1 + to_integer(shift_right(combined_amp, CHANNEL_LENGHT - NUMLEDS_BITS));
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- Saturation protection: Limit LED level to maximum available LEDs
|
-- Saturation protection: Limit LED level to maximum available LEDs
|
||||||
-- Prevents overflow and ensures the LED index stays within bounds.
|
-- Prevents overflow and ensures the LED index stays within bounds.
|
||||||
IF led_level > NUM_LEDS THEN
|
IF led_level > NUM_LEDS THEN
|
||||||
led_level := NUM_LEDS;
|
led_level := NUM_LEDS;
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- Update LED output based on calculated level
|
-- Update LED output based on calculated level
|
||||||
led <= (OTHERS => '0');
|
led <= (OTHERS => '0');
|
||||||
|
|
||||||
IF led_level > 0 THEN
|
IF led_level > 0 THEN
|
||||||
led(led_level - 1 DOWNTO 0) <= (OTHERS => '1');
|
led(led_level - 1 DOWNTO 0) <= (OTHERS => '1');
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|||||||
Reference in New Issue
Block a user