Add comments
This commit is contained in:
@@ -2,137 +2,169 @@ LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
-- Entity: volume_controller
|
||||
-- Purpose: Controls audio volume by scaling audio samples according to volume control input
|
||||
-- Implements a two-stage processing pipeline: multiplication followed by saturation
|
||||
-- This approach prevents overflow and distortion in the audio signal
|
||||
ENTITY volume_controller IS
|
||||
GENERIC (
|
||||
TDATA_WIDTH : POSITIVE := 24;
|
||||
VOLUME_WIDTH : POSITIVE := 10;
|
||||
VOLUME_STEP_2 : POSITIVE := 6; -- i.e., volume_values_per_step = 2**VOLUME_STEP_2
|
||||
HIGHER_BOUND : INTEGER := 2 ** 23 - 1; -- Inclusive
|
||||
LOWER_BOUND : INTEGER := - 2 ** 23 -- Inclusive
|
||||
);
|
||||
PORT (
|
||||
aclk : IN STD_LOGIC;
|
||||
aresetn : IN STD_LOGIC;
|
||||
GENERIC (
|
||||
TDATA_WIDTH : POSITIVE := 24; -- Width of audio data bus (24-bit audio samples)
|
||||
VOLUME_WIDTH : POSITIVE := 10; -- Width of volume control input (10-bit = 0-1023 range)
|
||||
VOLUME_STEP_2 : POSITIVE := 6; -- Log2 of volume values per step (2^6 = 64 values per step)
|
||||
HIGHER_BOUND : INTEGER := 2 ** 23 - 1; -- Maximum positive value for saturation (inclusive)
|
||||
LOWER_BOUND : INTEGER := - 2 ** 23 -- Maximum negative value for saturation (inclusive)
|
||||
);
|
||||
PORT (
|
||||
-- Clock and reset signals
|
||||
aclk : IN STD_LOGIC; -- Main clock input
|
||||
aresetn : IN STD_LOGIC; -- Active-low asynchronous reset
|
||||
|
||||
s_axis_tvalid : IN STD_LOGIC;
|
||||
s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0);
|
||||
s_axis_tlast : IN STD_LOGIC;
|
||||
s_axis_tready : OUT STD_LOGIC;
|
||||
-- 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_tlast : IN STD_LOGIC; -- Channel indicator (0=left, 1=right)
|
||||
s_axis_tready : OUT STD_LOGIC; -- Ready to accept input data
|
||||
|
||||
m_axis_tvalid : OUT STD_LOGIC;
|
||||
m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0);
|
||||
m_axis_tlast : OUT STD_LOGIC;
|
||||
m_axis_tready : IN STD_LOGIC;
|
||||
-- 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_tlast : OUT STD_LOGIC; -- Channel indicator passthrough
|
||||
m_axis_tready : IN STD_LOGIC; -- Downstream ready signal
|
||||
|
||||
volume : IN STD_LOGIC_VECTOR(VOLUME_WIDTH - 1 DOWNTO 0)
|
||||
);
|
||||
-- Volume control input
|
||||
volume : IN STD_LOGIC_VECTOR(VOLUME_WIDTH - 1 DOWNTO 0) -- Volume level (0=minimum, 1023=maximum)
|
||||
);
|
||||
END volume_controller;
|
||||
|
||||
ARCHITECTURE Behavioral OF volume_controller IS
|
||||
|
||||
-- Component declarations
|
||||
COMPONENT volume_multiplier IS
|
||||
GENERIC (
|
||||
TDATA_WIDTH : POSITIVE := 24;
|
||||
VOLUME_WIDTH : POSITIVE := 10;
|
||||
VOLUME_STEP_2 : POSITIVE := 6 -- i.e., volume_values_per_step = 2**VOLUME_STEP_2
|
||||
);
|
||||
PORT (
|
||||
aclk : IN STD_LOGIC;
|
||||
aresetn : IN STD_LOGIC;
|
||||
-- Component declaration for volume multiplier
|
||||
-- First stage: multiplies audio samples by volume scaling factor
|
||||
-- Output has wider bit width to accommodate multiplication results
|
||||
COMPONENT volume_multiplier IS
|
||||
GENERIC (
|
||||
TDATA_WIDTH : POSITIVE := 24; -- Input audio data width
|
||||
VOLUME_WIDTH : POSITIVE := 10; -- Volume control width
|
||||
VOLUME_STEP_2 : POSITIVE := 6 -- Step size for volume control
|
||||
);
|
||||
PORT (
|
||||
aclk : IN STD_LOGIC;
|
||||
aresetn : IN STD_LOGIC;
|
||||
|
||||
s_axis_tvalid : IN STD_LOGIC;
|
||||
s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0);
|
||||
s_axis_tlast : IN STD_LOGIC;
|
||||
s_axis_tready : OUT STD_LOGIC;
|
||||
-- Input AXI4-Stream interface
|
||||
s_axis_tvalid : IN STD_LOGIC;
|
||||
s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0);
|
||||
s_axis_tlast : IN STD_LOGIC;
|
||||
s_axis_tready : OUT STD_LOGIC;
|
||||
|
||||
m_axis_tvalid : OUT STD_LOGIC;
|
||||
m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) DOWNTO 0);
|
||||
m_axis_tlast : OUT STD_LOGIC;
|
||||
m_axis_tready : IN STD_LOGIC;
|
||||
-- Output AXI4-Stream interface (wider data width due to multiplication)
|
||||
m_axis_tvalid : OUT STD_LOGIC;
|
||||
m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) DOWNTO 0);
|
||||
m_axis_tlast : OUT STD_LOGIC;
|
||||
m_axis_tready : IN STD_LOGIC;
|
||||
|
||||
volume : IN STD_LOGIC_VECTOR(VOLUME_WIDTH - 1 DOWNTO 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
volume : IN STD_LOGIC_VECTOR(VOLUME_WIDTH - 1 DOWNTO 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
COMPONENT volume_saturator IS
|
||||
GENERIC (
|
||||
TDATA_WIDTH : POSITIVE := 24;
|
||||
VOLUME_WIDTH : POSITIVE := 10;
|
||||
VOLUME_STEP_2 : POSITIVE := 6; -- i.e., number_of_steps = 2**VOLUME_STEP_2
|
||||
HIGHER_BOUND : INTEGER := 2 ** 15 - 1; -- Inclusive
|
||||
LOWER_BOUND : INTEGER := - 2 ** 15 -- Inclusive
|
||||
);
|
||||
PORT (
|
||||
aclk : IN STD_LOGIC;
|
||||
aresetn : IN STD_LOGIC;
|
||||
-- Component declaration for volume saturator
|
||||
-- Second stage: clips multiplication results to prevent overflow and distortion
|
||||
-- Reduces bit width back to original audio format
|
||||
COMPONENT volume_saturator IS
|
||||
GENERIC (
|
||||
TDATA_WIDTH : POSITIVE := 24; -- Final audio data width
|
||||
VOLUME_WIDTH : POSITIVE := 10; -- Volume control width
|
||||
VOLUME_STEP_2 : POSITIVE := 6; -- Step size for volume control
|
||||
HIGHER_BOUND : INTEGER := 2 ** 15 - 1; -- Upper saturation limit (inclusive)
|
||||
LOWER_BOUND : INTEGER := - 2 ** 15 -- Lower saturation limit (inclusive)
|
||||
);
|
||||
PORT (
|
||||
aclk : IN STD_LOGIC;
|
||||
aresetn : IN STD_LOGIC;
|
||||
|
||||
s_axis_tvalid : IN STD_LOGIC;
|
||||
s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) DOWNTO 0);
|
||||
s_axis_tlast : IN STD_LOGIC;
|
||||
s_axis_tready : OUT STD_LOGIC;
|
||||
-- Input AXI4-Stream interface (wide data from multiplier)
|
||||
s_axis_tvalid : IN STD_LOGIC;
|
||||
s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) DOWNTO 0);
|
||||
s_axis_tlast : IN STD_LOGIC;
|
||||
s_axis_tready : OUT STD_LOGIC;
|
||||
|
||||
m_axis_tvalid : OUT STD_LOGIC;
|
||||
m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0);
|
||||
m_axis_tlast : OUT STD_LOGIC;
|
||||
m_axis_tready : IN STD_LOGIC
|
||||
);
|
||||
END COMPONENT;
|
||||
-- Output AXI4-Stream interface (original audio data width)
|
||||
m_axis_tvalid : OUT STD_LOGIC;
|
||||
m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0);
|
||||
m_axis_tlast : OUT STD_LOGIC;
|
||||
m_axis_tready : IN STD_LOGIC
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
-- Internal AXIS signals
|
||||
SIGNAL int_axis_tvalid : STD_LOGIC;
|
||||
SIGNAL int_axis_tready : STD_LOGIC;
|
||||
SIGNAL int_axis_tdata : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) DOWNTO 0);
|
||||
SIGNAL int_axis_tlast : STD_LOGIC;
|
||||
-- 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_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
|
||||
|
||||
BEGIN
|
||||
|
||||
-- Instantiate volume_multiplier
|
||||
volume_multiplier_inst : volume_multiplier
|
||||
GENERIC MAP(
|
||||
TDATA_WIDTH => TDATA_WIDTH,
|
||||
VOLUME_WIDTH => VOLUME_WIDTH,
|
||||
VOLUME_STEP_2 => VOLUME_STEP_2
|
||||
)
|
||||
PORT MAP(
|
||||
aclk => aclk,
|
||||
aresetn => aresetn,
|
||||
-- Instantiate volume_multiplier (First Stage)
|
||||
-- Multiplies incoming audio samples by volume scaling factor
|
||||
-- Output has extended bit width to prevent loss of precision
|
||||
volume_multiplier_inst : volume_multiplier
|
||||
GENERIC MAP(
|
||||
TDATA_WIDTH => TDATA_WIDTH, -- Input audio sample width
|
||||
VOLUME_WIDTH => VOLUME_WIDTH, -- Volume control resolution
|
||||
VOLUME_STEP_2 => VOLUME_STEP_2 -- Volume step size
|
||||
)
|
||||
PORT MAP(
|
||||
aclk => aclk,
|
||||
aresetn => aresetn,
|
||||
|
||||
s_axis_tvalid => s_axis_tvalid,
|
||||
s_axis_tdata => s_axis_tdata,
|
||||
s_axis_tlast => s_axis_tlast,
|
||||
s_axis_tready => s_axis_tready,
|
||||
-- Connect to external input interface
|
||||
s_axis_tvalid => s_axis_tvalid,
|
||||
s_axis_tdata => s_axis_tdata,
|
||||
s_axis_tlast => s_axis_tlast,
|
||||
s_axis_tready => s_axis_tready,
|
||||
|
||||
m_axis_tvalid => int_axis_tvalid,
|
||||
m_axis_tdata => int_axis_tdata,
|
||||
m_axis_tlast => int_axis_tlast,
|
||||
m_axis_tready => int_axis_tready,
|
||||
-- Connect to internal interface (wide data)
|
||||
m_axis_tvalid => int_axis_tvalid,
|
||||
m_axis_tdata => int_axis_tdata,
|
||||
m_axis_tlast => int_axis_tlast,
|
||||
m_axis_tready => int_axis_tready,
|
||||
|
||||
volume => volume
|
||||
);
|
||||
volume => volume
|
||||
);
|
||||
|
||||
-- Instantiate volume_saturator
|
||||
volume_saturator_inst : volume_saturator
|
||||
GENERIC MAP(
|
||||
TDATA_WIDTH => TDATA_WIDTH,
|
||||
VOLUME_WIDTH => VOLUME_WIDTH,
|
||||
VOLUME_STEP_2 => VOLUME_STEP_2,
|
||||
HIGHER_BOUND => HIGHER_BOUND,
|
||||
LOWER_BOUND => LOWER_BOUND
|
||||
)
|
||||
PORT MAP(
|
||||
aclk => aclk,
|
||||
aresetn => aresetn,
|
||||
-- Instantiate volume_saturator (Second Stage)
|
||||
-- Clips multiplication results to prevent overflow and distortion
|
||||
-- Reduces bit width back to original audio format for output
|
||||
volume_saturator_inst : volume_saturator
|
||||
GENERIC MAP(
|
||||
TDATA_WIDTH => TDATA_WIDTH, -- Final audio sample width
|
||||
VOLUME_WIDTH => VOLUME_WIDTH, -- Volume control resolution
|
||||
VOLUME_STEP_2 => VOLUME_STEP_2, -- Volume step size
|
||||
HIGHER_BOUND => HIGHER_BOUND, -- Upper saturation limit
|
||||
LOWER_BOUND => LOWER_BOUND -- Lower saturation limit
|
||||
)
|
||||
PORT MAP(
|
||||
aclk => aclk,
|
||||
aresetn => aresetn,
|
||||
|
||||
s_axis_tvalid => int_axis_tvalid,
|
||||
s_axis_tdata => int_axis_tdata,
|
||||
s_axis_tlast => int_axis_tlast,
|
||||
s_axis_tready => int_axis_tready,
|
||||
-- Connect to internal interface (wide data from multiplier)
|
||||
s_axis_tvalid => int_axis_tvalid,
|
||||
s_axis_tdata => int_axis_tdata,
|
||||
s_axis_tlast => int_axis_tlast,
|
||||
s_axis_tready => int_axis_tready,
|
||||
|
||||
m_axis_tvalid => m_axis_tvalid,
|
||||
m_axis_tdata => m_axis_tdata,
|
||||
m_axis_tlast => m_axis_tlast,
|
||||
m_axis_tready => m_axis_tready
|
||||
);
|
||||
-- Connect to external output interface
|
||||
m_axis_tvalid => m_axis_tvalid,
|
||||
m_axis_tdata => m_axis_tdata,
|
||||
m_axis_tlast => m_axis_tlast,
|
||||
m_axis_tready => m_axis_tready
|
||||
);
|
||||
|
||||
-- Pipeline Operation:
|
||||
-- 1. Audio samples enter volume_multiplier with original bit width
|
||||
-- 2. Multiplier scales samples by volume factor, output has extended bit width
|
||||
-- 3. Saturator clips results to prevent overflow, reduces to original bit width
|
||||
-- 4. Final audio samples has adjusted volume and bit width, ready for downstream processing
|
||||
|
||||
END Behavioral;
|
||||
Reference in New Issue
Block a user