- update comments
- add led_level_controller Const
This commit is contained in:
@@ -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
|
||||
@@ -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,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
|
||||
|
||||
@@ -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