Add initial implementations for various audio processing components

- Created LFO entity for low-frequency oscillation control.
- Added all_pass_filter entity for signal processing.
- Implemented balance_controller for audio balance adjustments.
- Developed debouncer to stabilize input signals.
- Introduced digilent_jstk2 for joystick data handling.
- Added edge_detector_toggle for edge detection functionality.
- Created effect_selector to manage audio effects based on joystick input.
- Implemented jstk_uart_bridge for communication between joystick and UART.
- Developed led_controller for LED management.
- Introduced led_level_controller for controlling multiple LEDs.
- Created moving_average_filter for smoothing input signals.
- Added moving_average_filter_en with enable functionality.
- Implemented mute_controller to handle mute functionality.
- Developed volume_controller for volume adjustments.
- Introduced volume_multiplier for scaling audio signals.
- Created volume_saturator to ensure audio signals stay within bounds.
This commit is contained in:
2025-05-11 12:43:38 +02:00
parent 1daab56299
commit 9c20fe7e7c
17 changed files with 745 additions and 294 deletions

40
LAB3/src/LFO.vhd Normal file
View File

@@ -0,0 +1,40 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
entity LFO is
generic(
CHANNEL_LENGHT : integer := 24;
JOYSTICK_LENGHT : integer := 10;
CLK_PERIOD_NS : integer := 10;
TRIANGULAR_COUNTER_LENGHT : integer := 10 -- Triangular wave period length
);
Port (
aclk : in std_logic;
aresetn : in std_logic;
lfo_period : in std_logic_vector(JOYSTICK_LENGHT-1 downto 0);
lfo_enable : in std_logic;
s_axis_tvalid : in std_logic;
s_axis_tdata : in std_logic_vector(CHANNEL_LENGHT-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(CHANNEL_LENGHT-1 downto 0);
m_axis_tlast : out std_logic;
m_axis_tready : in std_logic
);
end entity LFO;
architecture Behavioral of LFO is
begin
end architecture;

View File

@@ -0,0 +1,29 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity all_pass_filter is
generic (
TDATA_WIDTH : positive := 24
);
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;
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 all_pass_filter;
architecture Behavioral of all_pass_filter is
begin
end Behavioral;

View File

@@ -0,0 +1,33 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity balance_controller is
generic (
TDATA_WIDTH : positive := 24;
BALANCE_WIDTH : positive := 10;
BALANCE_STEP_2 : positive := 6 -- i.e., balance_values_per_step = 2**VOLUME_STEP_2
);
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_tready : out std_logic;
s_axis_tlast : in std_logic;
m_axis_tvalid : out std_logic;
m_axis_tdata : out std_logic_vector(TDATA_WIDTH-1 downto 0);
m_axis_tready : in std_logic;
m_axis_tlast : out std_logic;
balance : in std_logic_vector(BALANCE_WIDTH-1 downto 0)
);
end balance_controller;
architecture Behavioral of balance_controller is
begin
end Behavioral;

66
LAB3/src/debouncer.vhd Normal file
View File

@@ -0,0 +1,66 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
-- This module can be used to remove the "bouncing" of a signal, so that the
-- output changes no more than once every DEBOUNCE_MS milliseconds
entity debouncer is
generic (
DEBOUNCE_MS : positive := 10;
CLOCK_FREQ : positive := 100_000_000
);
Port (
-- Clock and reset
clk : in std_logic;
reset : in std_logic;
-- I/Os
input_signal : in std_logic;
debounced : out std_logic
);
end debouncer;
architecture Behavioral of debouncer is
constant COUNTER_HIGH : integer := CLOCK_FREQ / 1000 * DEBOUNCE_MS - 1;
signal debounced_int : std_logic;
signal counter : integer range 0 to COUNTER_HIGH;
begin
-- To be able to read the value of input_debounced (which is an "out" port)
-- we have to declare a signal and assign that to the external port.
debounced <= debounced_int;
process(clk, reset)
begin
if reset = '1' then
debounced_int <= input_signal;
counter <= 0;
elsif rising_edge(clk) then
if counter = 0 then
-- Keep sampling input_signal.
debounced_int <= input_signal;
-- If input_signal has changed from the last sample, start
-- the timer.
if debounced_int /= input_signal then
counter <= COUNTER_HIGH;
end if;
else
-- When the timer is running, no change is recorded, so the
-- output stays constant.
counter <= counter - 1;
end if;
end if;
end process;
end Behavioral;

View File

@@ -0,0 +1,49 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity digilent_jstk2 is
generic (
DELAY_US : integer := 25; -- Delay (in us) between two packets
CLKFREQ : integer := 100_000_000; -- Frequency of the aclk signal (in Hz)
SPI_SCLKFREQ : integer := 66_666 -- Frequency of the SPI SCLK clock signal (in Hz)
);
Port (
aclk : in STD_LOGIC;
aresetn : in STD_LOGIC;
-- Data going TO the SPI IP-Core (and so, to the JSTK2 module)
m_axis_tvalid : out STD_LOGIC;
m_axis_tdata : out STD_LOGIC_VECTOR(7 downto 0);
m_axis_tready : in STD_LOGIC;
-- Data coming FROM the SPI IP-Core (and so, from the JSTK2 module)
-- There is no tready signal, so you must be always ready to accept and use the incoming data, or it will be lost!
s_axis_tvalid : in STD_LOGIC;
s_axis_tdata : in STD_LOGIC_VECTOR(7 downto 0);
-- Joystick and button values read from the module
jstk_x : out std_logic_vector(9 downto 0);
jstk_y : out std_logic_vector(9 downto 0);
btn_jstk : out std_logic;
btn_trigger : out std_logic;
-- LED color to send to the module
led_r : in std_logic_vector(7 downto 0);
led_g : in std_logic_vector(7 downto 0);
led_b : in std_logic_vector(7 downto 0)
);
end digilent_jstk2;
architecture Behavioral of digilent_jstk2 is
-- Code for the SetLEDRGB command, see the JSTK2 datasheet.
constant CMDSETLEDRGB : std_logic_vector(7 downto 0) := x"84";
-- Do not forget that you MUST wait a bit between two packets. See the JSTK2 datasheet (and the SPI IP-Core README).
------------------------------------------------------------
begin
-- ...
end architecture;

View File

@@ -0,0 +1,20 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity edge_detector_toggle is
generic (
EDGE_RISING : boolean := true
);
port (
input_signal : in std_logic;
clk : in std_logic;
reset : in std_logic;
output_signal : out std_logic
);
end edge_detector_toggle;
architecture Behavioral of edge_detector_toggle is
begin
end Behavioral;

View File

@@ -0,0 +1,54 @@
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 04/29/2024 10:12:03 AM
-- Design Name:
-- Module Name: effect_selector - Behavioral
-- Project Name:
-- Target Devices:
-- Tool Versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity effect_selector is
generic(
JOYSTICK_LENGHT : integer := 10
);
Port (
aclk : in STD_LOGIC;
aresetn : in STD_LOGIC;
effect : in STD_LOGIC;
jstck_x : in STD_LOGIC_VECTOR(JOYSTICK_LENGHT-1 downto 0);
jstck_y : in STD_LOGIC_VECTOR(JOYSTICK_LENGHT-1 downto 0);
volume : out STD_LOGIC_VECTOR(JOYSTICK_LENGHT-1 downto 0);
balance : out STD_LOGIC_VECTOR(JOYSTICK_LENGHT-1 downto 0);
lfo_period : out STD_LOGIC_VECTOR(JOYSTICK_LENGHT-1 downto 0)
);
end effect_selector;
architecture Behavioral of effect_selector is
begin
end Behavioral;

View File

@@ -0,0 +1,174 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity jstk_uart_bridge is
generic (
HEADER_CODE : std_logic_vector(7 downto 0) := x"c0";
TX_DELAY : positive := 1_000_000;
JSTK_BITS : integer range 1 to 7 := 7
);
Port (
aclk : in STD_LOGIC;
aresetn : in STD_LOGIC;
m_axis_tvalid : out STD_LOGIC;
m_axis_tdata : out STD_LOGIC_VECTOR(7 downto 0);
m_axis_tready : in STD_LOGIC;
s_axis_tvalid : in STD_LOGIC;
s_axis_tdata : in STD_LOGIC_VECTOR(7 downto 0);
s_axis_tready : out STD_LOGIC;
jstk_x : in std_logic_vector(9 downto 0);
jstk_y : in std_logic_vector(9 downto 0);
btn_jstk : in std_logic;
btn_trigger : in std_logic;
led_r : out std_logic_vector(7 downto 0);
led_g : out std_logic_vector(7 downto 0);
led_b : out std_logic_vector(7 downto 0)
);
end jstk_uart_bridge;
architecture Behavioral of jstk_uart_bridge is
type tx_state_type is (DELAY, SEND_HEADER, SEND_JSTK_X, SEND_JSTK_Y, SEND_BUTTONS);
signal tx_state : tx_state_type;
signal tx_delay_counter : integer range 0 to TX_DELAY-1;
signal jstk_x_msb : std_logic_vector(m_axis_tdata'range);
signal jstk_y_msb : std_logic_vector(m_axis_tdata'range);
signal buttons : std_logic_vector(m_axis_tdata'range);
--------------------------------------------
type rx_state_type is (IDLE, GET_HEADER, GET_LED_R, GET_LED_G, GET_LED_B);
signal rx_state : rx_state_type;
signal led_r_temp : std_logic_vector(led_r'range);
signal led_g_temp : std_logic_vector(led_r'range);
begin
-- JSTK -> UART: Joystick position and buttons
with tx_state select m_axis_tvalid <=
'0' when DELAY,
'1' when SEND_HEADER,
'1' when SEND_JSTK_X,
'1' when SEND_JSTK_Y,
'1' when SEND_BUTTONS;
with tx_state select m_axis_tdata <=
(others => '-') when DELAY,
HEADER_CODE when SEND_HEADER,
jstk_x_msb when SEND_JSTK_X,
jstk_y_msb when SEND_JSTK_Y,
buttons when SEND_BUTTONS;
jstk_x_msb <= (jstk_x_msb'high downto JSTK_BITS => '0') & jstk_x(jstk_x'high downto jstk_x'high-JSTK_BITS+1);
jstk_y_msb <= (jstk_y_msb'high downto JSTK_BITS => '0') & jstk_y(jstk_y'high downto jstk_y'high-JSTK_BITS+1);
buttons <= (buttons'high downto 2 => '0') & btn_trigger & btn_jstk;
process (aclk)
begin
if rising_edge(aclk) then
if aresetn = '0' then
tx_state <= DELAY;
tx_delay_counter <= 0;
else
case tx_state is
when DELAY =>
if tx_delay_counter = TX_DELAY-1 then
tx_delay_counter <= 0;
tx_state <= SEND_HEADER;
else
tx_delay_counter <= tx_delay_counter + 1;
end if;
when SEND_HEADER =>
if m_axis_tready = '1' then
tx_state <= SEND_JSTK_X;
end if;
when SEND_JSTK_X =>
if m_axis_tready = '1' then
tx_state <= SEND_JSTK_Y;
end if;
when SEND_JSTK_Y =>
if m_axis_tready = '1' then
tx_state <= SEND_BUTTONS;
end if;
when SEND_BUTTONS =>
if m_axis_tready = '1' then
tx_state <= DELAY;
end if;
end case;
end if;
end if;
end process;
-----------------------------------------------------------------------
-- UART -> JSTK: LEDs color
with rx_state select s_axis_tready <=
'0' when IDLE,
'1' when GET_HEADER,
'1' when GET_LED_R,
'1' when GET_LED_G,
'1' when GET_LED_B;
process (aclk)
begin
if rising_edge(aclk) then
if aresetn = '0' then
rx_state <= IDLE;
else
case rx_state is
when IDLE =>
rx_state <= GET_HEADER;
when GET_HEADER =>
if s_axis_tvalid = '1' and s_axis_tdata = HEADER_CODE then
rx_state <= GET_LED_R;
else
-- Was expecting header, got something else: drop the value and stay in this state
end if;
when GET_LED_R =>
if s_axis_tvalid = '1' then
led_r_temp <= s_axis_tdata;
rx_state <= GET_LED_G;
end if;
when GET_LED_G =>
if s_axis_tvalid = '1' then
led_g_temp <= s_axis_tdata;
rx_state <= GET_LED_B;
end if;
when GET_LED_B =>
if s_axis_tvalid = '1' then
led_r <= led_r_temp;
led_g <= led_g_temp;
led_b <= s_axis_tdata;
rx_state <= GET_HEADER;
end if;
end case;
end if;
end if;
end process;
end Behavioral;

View File

@@ -0,0 +1,22 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity led_controller is
Generic (
LED_WIDTH : positive := 8
);
Port (
mute_enable : in std_logic;
filter_enable : in std_logic;
led_r : out std_logic_vector(LED_WIDTH-1 downto 0);
led_g : out std_logic_vector(LED_WIDTH-1 downto 0);
led_b : out std_logic_vector(LED_WIDTH-1 downto 0)
);
end led_controller;
architecture Behavioral of led_controller is
begin
end Behavioral;

View File

@@ -0,0 +1,60 @@
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 22.05.2021 15:42:35
-- Design Name:
-- Module Name: led_level_controller - Behavioral
-- Project Name:
-- Target Devices:
-- Tool Versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity led_level_controller is
generic(
NUM_LEDS : positive := 16;
CHANNEL_LENGHT : positive := 24;
refresh_time_ms: positive :=1;
clock_period_ns: positive :=10
);
Port (
aclk : in std_logic;
aresetn : in std_logic;
led : out std_logic_vector(NUM_LEDS-1 downto 0);
s_axis_tvalid : in std_logic;
s_axis_tdata : in std_logic_vector(CHANNEL_LENGHT-1 downto 0);
s_axis_tlast : in std_logic;
s_axis_tready : out std_logic
);
end led_level_controller;
architecture Behavioral of led_level_controller is
begin
end Behavioral;

View File

@@ -0,0 +1,32 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity moving_average_filter is
generic (
-- Filter order expressed as 2^(FILTER_ORDER_POWER)
FILTER_ORDER_POWER : integer := 5;
TDATA_WIDTH : positive := 24
);
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;
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 moving_average_filter;
architecture Behavioral of moving_average_filter is
begin
end Behavioral;

View File

@@ -0,0 +1,34 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity moving_average_filter_en is
generic (
-- Filter order expressed as 2^(FILTER_ORDER_POWER)
FILTER_ORDER_POWER : integer := 5;
TDATA_WIDTH : positive := 24
);
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;
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;
enable_filter : in std_logic
);
end moving_average_filter_en;
architecture Behavioral of moving_average_filter_en is
begin
end Behavioral;

View File

@@ -0,0 +1,31 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity mute_controller is
Generic (
TDATA_WIDTH : positive := 24
);
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;
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;
mute : in std_logic
);
end mute_controller;
architecture Behavioral of mute_controller is
begin
end Behavioral;

View File

@@ -0,0 +1,35 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
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;
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 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 volume_controller;
architecture Behavioral of volume_controller is
begin
end Behavioral;

View File

@@ -0,0 +1,33 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity 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;
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;
volume : in std_logic_vector(VOLUME_WIDTH-1 downto 0)
);
end volume_multiplier;
architecture Behavioral of volume_multiplier is
begin
end Behavioral;

View File

@@ -0,0 +1,33 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity 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;
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 volume_saturator;
architecture Behavioral of volume_saturator is
begin
end Behavioral;