Compare commits
9 Commits
a52023733d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| dc5ba6c745 | |||
| 2da1ff0ea7 | |||
| 902163424b | |||
| 1109f8b130 | |||
| 2968db7e3f | |||
| c4a48db729 | |||
| dff2eb439d | |||
| 79373768fa | |||
| 9828eed333 |
39
LAB2/Readme.md
Normal file
39
LAB2/Readme.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# LAB2 Project Presentation
|
||||
|
||||
## Project Description
|
||||
|
||||
The LAB2 project consists of the design and implementation of a digital system for image processing and data communication. The system is composed of several functional blocks, each responsible for a specific task in the processing pipeline. The main objectives are:
|
||||
|
||||
- Receive and process image data
|
||||
- Perform color space conversion (e.g., RGB to grayscale)
|
||||
- Apply convolution filters to the image
|
||||
- Packetize the processed data for transmission
|
||||
- Support loopback and test modes for verification
|
||||
|
||||
## Block Diagram
|
||||
|
||||
Below is a conceptual block diagram of the LAB2 system:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
IN[PC] -.-> UART[UART]
|
||||
UART -.-> IN
|
||||
UART --> DEPACK[Depack]
|
||||
DEPACK --> C2G[Color to Grayscale Converter]
|
||||
C2G --> BRAM[BRAM Writer]
|
||||
BRAM --> Underflow
|
||||
BRAM -->Overflow
|
||||
BRAM -->Ok
|
||||
BRAM <-.-> CONV[Convolution Filter]
|
||||
BRAM <-.-> CONV
|
||||
CONV --> PACK[Packetizer]
|
||||
PACK --> UART
|
||||
```
|
||||
|
||||
## Areas for Improvement
|
||||
|
||||
- In loopback mode, when sending an empty packet (FFF1), the module temporarily stores H and F and prepends them to the header of the next packet. There is an error in the pack/depack logic.
|
||||
- The implementation of the depacketizer is complex, and the precise error has not been identified.
|
||||
- The color conversion (C2G) uses a divider by 3, but the approximation method is unclear (it sums half of the power-of-two factor used in the divider—why?). -> Just add comments explainig how it works
|
||||
- Convolution is performed with various unconstrained integers.
|
||||
- In general, the VHDL code is somewhat complex, although generally correct. Aim to simplify and make the code more readable.
|
||||
16
LAB3/Readme.md
Normal file
16
LAB3/Readme.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# LAB3 Project Presentation
|
||||
|
||||
## Project Description
|
||||
|
||||
*To be completed: Add a description of the LAB3 project here.*
|
||||
|
||||
## Block Diagram
|
||||
|
||||
*To be completed: Add a block diagram of the LAB3 system here (e.g., using Mermaid or an image).*
|
||||
|
||||
## Areas for Improvement
|
||||
|
||||
- JSTK: Non-atomicity in writing to the RGB LED; the rest is well done and clear.
|
||||
- Mute: (IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN) AXIS error; s_axis_tready should be checked. The original would be correct if s_axis_tready was directly connected to m_axis_tready. As written, it waits for ready to assert valid.
|
||||
- Volume controller: Waits for ready to assert valid (IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN).
|
||||
- Balance: (IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN) AXI condition is incorrect; the rest is correct.
|
||||
@@ -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
|
||||
@@ -92,11 +92,11 @@ BEGIN
|
||||
ELSE
|
||||
-- Calculate LFO period based on joystick input
|
||||
-- Joystick mapping:
|
||||
-- 0-511: Faster than base frequency (shorter period, higher frequency)
|
||||
-- 0-511: Slower than base frequency (longer period, lower frequency)
|
||||
-- 512: Base frequency (1kHz)
|
||||
-- 513-1023: Slower than base frequency (longer period, lower frequency)
|
||||
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;
|
||||
-- 513-1023: Faster than base frequency (shorter period, higher frequency)
|
||||
step_clk_cycles_delta <= (to_integer(unsigned(lfo_period)) - JSTK_CENTER_VALUE);
|
||||
step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES - step_clk_cycles_delta * ADJUSTMENT_FACTOR;
|
||||
|
||||
-- Generate triangular wave when LFO is enabled
|
||||
IF lfo_enable = '1' THEN
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -69,7 +69,7 @@ BEGIN
|
||||
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';
|
||||
|
||||
@@ -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,11 +1,11 @@
|
||||
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
|
||||
-- Processes stereo audio samples and drives a bar graph LED display
|
||||
-- Provides visual feedback of audio signal strength for both channels combined
|
||||
ENTITY led_level_controller IS
|
||||
GENERIC (
|
||||
NUM_LEDS : POSITIVE := 16; -- Number of LEDs in the level meter display
|
||||
@@ -32,9 +32,10 @@ END led_level_controller;
|
||||
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
|
||||
@@ -42,112 +43,123 @@ ARCHITECTURE Behavioral OF led_level_controller IS
|
||||
|
||||
-- Audio amplitude storage for both stereo 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
|
||||
|
||||
-- AXI4-Stream interface: Always ready to receive audio data
|
||||
-- This ensures continuous audio processing without backpressure
|
||||
-- Always ready for AXI4-Stream input
|
||||
s_axis_tready <= '1';
|
||||
|
||||
-- Audio sample acquisition process based on channel identification
|
||||
-- Processes incoming stereo audio samples and converts to absolute amplitude values
|
||||
-- Uses s_axis_tlast to distinguish between left (1) and right (0) channels
|
||||
-- Capture absolute value of input sample for left/right channel
|
||||
PROCESS (aclk)
|
||||
VARIABLE signed_sample : SIGNED(CHANNEL_LENGHT - 1 DOWNTO 0); -- Temporary variable for signed arithmetic
|
||||
BEGIN
|
||||
|
||||
IF rising_edge(aclk) THEN
|
||||
|
||||
IF aresetn = '0' THEN
|
||||
-- Reset: Clear both channel amplitude registers
|
||||
abs_l <= (OTHERS => '0');
|
||||
abs_r <= (OTHERS => '0');
|
||||
combined_amp <= (OTHERS => '0');
|
||||
|
||||
ELSIF s_axis_tvalid = '1' THEN
|
||||
-- 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
|
||||
-- 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
|
||||
-- Left channel: Store absolute value of audio sample
|
||||
abs_l <= UNSIGNED(ABS(signed_sample));
|
||||
-- Right channel: 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(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
|
||||
-- Right channel: Store absolute value of audio sample
|
||||
abs_r <= UNSIGNED(ABS(signed_sample));
|
||||
-- Left channel: Store absolute value of audio sample
|
||||
abs_l <= UNSIGNED(ABS(SIGNED(s_axis_tdata)));
|
||||
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
|
||||
END PROCESS;
|
||||
|
||||
-- LED refresh timing generator process
|
||||
-- Creates a periodic tick signal to control LED update rate
|
||||
-- Prevents LED flickering by limiting update frequency to human-visible rates
|
||||
-- LED refresh tick generator
|
||||
PROCESS (aclk)
|
||||
BEGIN
|
||||
|
||||
IF rising_edge(aclk) THEN
|
||||
|
||||
IF aresetn = '0' THEN
|
||||
-- Reset: Initialize counter and tick signal
|
||||
refresh_counter <= 0;
|
||||
refresh_tick <= '0';
|
||||
|
||||
ELSE
|
||||
-- Normal operation: Count clock cycles and generate refresh tick
|
||||
IF refresh_counter = REFRESH_CYCLES - 1 THEN
|
||||
-- End of refresh period: Reset counter and generate tick pulse
|
||||
IF refresh_counter = REFRESH_CYCLES THEN
|
||||
refresh_counter <= 0;
|
||||
refresh_tick <= '1'; -- Single clock cycle pulse for LED update
|
||||
refresh_tick <= '1';
|
||||
|
||||
ELSE
|
||||
-- Continue counting: Increment counter, no tick
|
||||
refresh_counter <= refresh_counter + 1;
|
||||
refresh_tick <= '0';
|
||||
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
|
||||
END PROCESS;
|
||||
|
||||
-- LED level calculation and bar graph generation process
|
||||
-- Combines left and right channel amplitudes and converts to LED display pattern
|
||||
-- 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;
|
||||
|
||||
BEGIN
|
||||
|
||||
IF rising_edge(aclk) THEN
|
||||
|
||||
IF aresetn = '0' THEN
|
||||
-- Reset: Turn off all LEDs and reset level counter
|
||||
led <= (OTHERS => '0');
|
||||
|
||||
ELSIF refresh_tick = '1' THEN
|
||||
-- LED update cycle: Calculate new LED pattern based on audio amplitude
|
||||
-- This section is executed once per refresh_tick to avoid flicker and ensure a stable display.
|
||||
|
||||
-- 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.
|
||||
combined_amp := RESIZE(abs_l + abs_r, combined_amp'LENGTH);
|
||||
-- Linear scale to LED level conversion to get the best visual effect
|
||||
IF combined_amp = 0 THEN
|
||||
led_level := 0; -- No audio signal, turn off all LEDs
|
||||
|
||||
-- Normalize combined amplitude to LED scale (0 to NUM_LEDS)
|
||||
-- The combined amplitude is mapped to the number of LEDs using a right shift.
|
||||
-- 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));
|
||||
ELSE
|
||||
led_level := 1 + to_integer(shift_right(combined_amp, CHANNEL_LENGHT - NUMLEDS_BITS));
|
||||
|
||||
END IF;
|
||||
|
||||
-- Saturation protection: Limit LED level to maximum available LEDs
|
||||
-- Prevents overflow and ensures the LED index stays within bounds.
|
||||
IF led_level > NUM_LEDS THEN
|
||||
led_level := NUM_LEDS;
|
||||
|
||||
END IF;
|
||||
|
||||
-- Generate bar graph LED pattern
|
||||
-- Implements a "thermometer" style display: all LEDs from 0 up to (led_level-1) are ON.
|
||||
-- All higher LEDs remain OFF.
|
||||
-- The assignment first turns all LEDs OFF, then sets the lower 'led_level' LEDs ON.
|
||||
-- Update LED output based on calculated level
|
||||
led <= (OTHERS => '0');
|
||||
|
||||
IF led_level > 0 THEN
|
||||
led(led_level - 1 DOWNTO 0) <= (OTHERS => '1');
|
||||
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
|
||||
END PROCESS;
|
||||
|
||||
END Behavioral;
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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