diff --git a/LAB3/sim/tb_balance_controller.vhd b/LAB3/sim/tb_balance_controller.vhd
new file mode 100644
index 0000000..ff9e6f9
--- /dev/null
+++ b/LAB3/sim/tb_balance_controller.vhd
@@ -0,0 +1,170 @@
+----------------------------------------------------------------------------------
+-- Testbench for balance_controller
+----------------------------------------------------------------------------------
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+
+ENTITY tb_balance_controller IS
+END tb_balance_controller;
+
+ARCHITECTURE Behavioral OF tb_balance_controller IS
+
+ CONSTANT TDATA_WIDTH : POSITIVE := 24;
+ CONSTANT BALANCE_WIDTH : POSITIVE := 10;
+ CONSTANT BALANCE_STEP_2 : POSITIVE := 6;
+ CONSTANT N_SAMPLES : INTEGER := 8;
+ CONSTANT N_BALANCES : INTEGER := 5;
+
+ COMPONENT balance_controller IS
+ GENERIC (
+ TDATA_WIDTH : POSITIVE := 24;
+ BALANCE_WIDTH : POSITIVE := 10;
+ BALANCE_STEP_2 : POSITIVE := 6
+ );
+ 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 COMPONENT;
+
+ SIGNAL aclk : STD_LOGIC := '0';
+ SIGNAL aresetn : STD_LOGIC := '0';
+ SIGNAL s_axis_tvalid : STD_LOGIC := '0';
+ SIGNAL s_axis_tdata : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0) := (OTHERS => '0');
+ SIGNAL s_axis_tlast : STD_LOGIC := '0';
+ SIGNAL s_axis_tready : STD_LOGIC;
+ SIGNAL m_axis_tvalid : STD_LOGIC;
+ SIGNAL m_axis_tdata : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0);
+ SIGNAL m_axis_tlast : STD_LOGIC;
+ SIGNAL m_axis_tready : STD_LOGIC := '1';
+ SIGNAL balance : STD_LOGIC_VECTOR(BALANCE_WIDTH - 1 DOWNTO 0) := (OTHERS => '0');
+
+ -- Test input samples
+ TYPE sample_mem_type IS ARRAY(0 TO N_SAMPLES-1) OF STD_LOGIC_VECTOR(TDATA_WIDTH-1 DOWNTO 0);
+ SIGNAL sample_mem : sample_mem_type := (
+ x"000100", -- +256
+ x"FFFE00", -- -512
+ x"000001", -- +1
+ x"FFFFFF", -- -1 (2's comp)
+ x"7FFFFF", -- max positive
+ x"800000", -- max negative
+ x"000A00", -- +2560
+ x"FFF600" -- -2560
+ );
+
+ -- Balance values: left, center, right, slightly left, slightly right
+ TYPE balance_mem_type IS ARRAY(0 TO N_BALANCES-1) OF STD_LOGIC_VECTOR(BALANCE_WIDTH-1 DOWNTO 0);
+ SIGNAL balance_mem : balance_mem_type := (
+ std_logic_vector(to_unsigned(0, BALANCE_WIDTH)), -- full left
+ std_logic_vector(to_unsigned(480, BALANCE_WIDTH)), -- center
+ std_logic_vector(to_unsigned(1023, BALANCE_WIDTH)), -- full right
+ std_logic_vector(to_unsigned(240, BALANCE_WIDTH)), -- slightly left
+ std_logic_vector(to_unsigned(800, BALANCE_WIDTH)) -- slightly right
+ );
+
+BEGIN
+
+ -- Clock generation
+ aclk <= NOT aclk AFTER 5 ns;
+
+ -- DUT instantiation
+ uut: balance_controller
+ GENERIC MAP (
+ TDATA_WIDTH => TDATA_WIDTH,
+ BALANCE_WIDTH => BALANCE_WIDTH,
+ BALANCE_STEP_2 => BALANCE_STEP_2
+ )
+ PORT MAP (
+ aclk => aclk,
+ aresetn => aresetn,
+ s_axis_tvalid => s_axis_tvalid,
+ s_axis_tdata => s_axis_tdata,
+ s_axis_tready => s_axis_tready,
+ s_axis_tlast => s_axis_tlast,
+ m_axis_tvalid => m_axis_tvalid,
+ m_axis_tdata => m_axis_tdata,
+ m_axis_tready => m_axis_tready,
+ m_axis_tlast => m_axis_tlast,
+ balance => balance
+ );
+
+ -- Stimulus process
+ stimulus : PROCESS
+ BEGIN
+ -- Reset
+ WAIT FOR 10 ns;
+ aresetn <= '1';
+ WAIT UNTIL rising_edge(aclk);
+
+ -- Set balance to center
+ balance <= balance_mem(1);
+ WAIT UNTIL rising_edge(aclk);
+
+ -- Send all samples (center)
+ FOR i IN 0 TO N_SAMPLES-1 LOOP
+ s_axis_tdata <= sample_mem(i);
+ s_axis_tvalid <= '1';
+ IF i = N_SAMPLES-1 THEN
+ s_axis_tlast <= '1';
+ ELSE
+ s_axis_tlast <= '0';
+ END IF;
+ WAIT UNTIL rising_edge(aclk);
+ WHILE s_axis_tready = '0' LOOP
+ WAIT UNTIL rising_edge(aclk);
+ END LOOP;
+ END LOOP;
+ s_axis_tvalid <= '0';
+ s_axis_tlast <= '0';
+
+ -- Change balance to full left
+ WAIT FOR 20 ns;
+ balance <= balance_mem(0);
+
+ -- Send one more sample (left)
+ WAIT UNTIL rising_edge(aclk);
+ s_axis_tdata <= x"000100";
+ s_axis_tvalid <= '1';
+ s_axis_tlast <= '1';
+ WAIT UNTIL rising_edge(aclk);
+ WHILE s_axis_tready = '0' LOOP
+ WAIT UNTIL rising_edge(aclk);
+ END LOOP;
+ s_axis_tvalid <= '0';
+ s_axis_tlast <= '0';
+
+ -- Sweep through other balance values
+ FOR i IN 2 TO N_BALANCES-1 LOOP
+ WAIT FOR 20 ns;
+ balance <= balance_mem(i);
+ WAIT UNTIL rising_edge(aclk);
+ END LOOP;
+
+ -- Wait and finish
+ WAIT FOR 100 ns;
+ WAIT;
+ END PROCESS;
+
+ -- Optionally, block m_axis_tready to test backpressure
+ PROCESS
+ BEGIN
+ WAIT FOR 60 ns;
+ WAIT UNTIL rising_edge(aclk);
+ m_axis_tready <= '0';
+ WAIT FOR 20 ns;
+ WAIT UNTIL rising_edge(aclk);
+ m_axis_tready <= '1';
+ WAIT;
+ END PROCESS;
+
+END Behavioral;
\ No newline at end of file
diff --git a/LAB3/src/balance_controller.vhd b/LAB3/src/balance_controller.vhd
index 45cb94a..4ec0d23 100644
--- a/LAB3/src/balance_controller.vhd
+++ b/LAB3/src/balance_controller.vhd
@@ -6,7 +6,7 @@ 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
+ BALANCE_STEP_2 : POSITIVE := 6 -- i.e., balance_values_per_step = 2**BALANCE_STEP_2
);
PORT (
aclk : IN STD_LOGIC;
@@ -27,128 +27,92 @@ ENTITY balance_controller IS
END balance_controller;
ARCHITECTURE Behavioral OF balance_controller IS
-
- CONSTANT CENTER_VALUE : INTEGER := 2 ** (BALANCE_WIDTH - 1) - 1; -- 511 per BALANCE_WIDTH=10
- CONSTANT DEADZONE : INTEGER := 32; -- Deadzone da -32 a +32
- CONSTANT MAX_SHIFT : INTEGER := TDATA_WIDTH - 1; -- Massimo shift possibile
- SIGNAL balance_signed : signed(BALANCE_WIDTH - 1 DOWNTO 0);
- SIGNAL shift_amount_left, shift_amount_right : NATURAL RANGE 0 TO MAX_SHIFT;
+ CONSTANT BALANCE_STEPS : INTEGER := (2 ** (BALANCE_WIDTH - 1)) / (2 ** BALANCE_STEP_2) + 1;
+ CONSTANT BAL_MID : INTEGER := 2 ** (BALANCE_WIDTH - 1); -- 512 for 10 bit
+ CONSTANT BLOCK_SIZE : INTEGER := 2 ** BALANCE_STEP_2;
+ CONSTANT DEAD_ZONE : INTEGER := BLOCK_SIZE / 2;
- -- Registri di pipeline
- SIGNAL audio_in_reg : signed(TDATA_WIDTH - 1 DOWNTO 0);
- SIGNAL tlast_reg : STD_LOGIC;
- SIGNAL valid_reg : STD_LOGIC;
+ SIGNAL left_channel : INTEGER RANGE 0 TO BALANCE_STEPS := 0;
+ SIGNAL right_channel : INTEGER RANGE 0 TO BALANCE_STEPS := 0;
- -- Segnali di controllo
- SIGNAL ready_int : STD_LOGIC;
- SIGNAL processing_active : STD_LOGIC;
+ SIGNAL m_axis_tvalid_int : STD_LOGIC;
BEGIN
- -- Convert balance input to signed (-512 to +511)
- balance_signed <= signed(balance);
+ -- Assigning the output signals
+ m_axis_tvalid <= m_axis_tvalid_int;
+ s_axis_tready <= m_axis_tready AND aresetn;
- -- Calcolo dello shift amount con deadzone e scaling esponenziale
- PROCESS (balance_signed)
- VARIABLE centered_value : signed(BALANCE_WIDTH - 1 DOWNTO 0);
- VARIABLE abs_value : unsigned(BALANCE_WIDTH - 2 DOWNTO 0);
- VARIABLE exp_shift : INTEGER;
- BEGIN
- -- Centra il valore intorno a 0 (da -512 a +511 -> da -511 a +511)
- centered_value := balance_signed - to_signed(CENTER_VALUE, BALANCE_WIDTH);
-
- -- Inizializzazione
- shift_amount_left <= 0;
- shift_amount_right <= 0;
-
- -- Calcola il valore assoluto
- IF centered_value(BALANCE_WIDTH - 1) = '1' THEN -- negativo
- abs_value := unsigned(-centered_value(BALANCE_WIDTH - 2 DOWNTO 0));
- ELSE
- abs_value := unsigned(centered_value(BALANCE_WIDTH - 2 DOWNTO 0));
- END IF;
-
- -- Applica deadzone e calcola shift
- IF centered_value > DEADZONE THEN
- -- Calcola lo shift per il canale sinistro (valori positivi)
- exp_shift := (to_integer(abs_value) - DEADZONE) / 2 ** BALANCE_STEP_2 + 1;
-
- IF exp_shift > MAX_SHIFT THEN
- shift_amount_left <= MAX_SHIFT;
- ELSE
- shift_amount_left <= exp_shift;
- END IF;
-
- ELSIF centered_value <- DEADZONE THEN
- -- Calcola lo shift per il canale destro (valori negativi)
- exp_shift := (to_integer(abs_value) - DEADZONE) / 2 ** BALANCE_STEP_2 + 1;
-
- IF exp_shift > MAX_SHIFT THEN
- shift_amount_right <= MAX_SHIFT;
- ELSE
- shift_amount_right <= exp_shift;
- END IF;
- END IF;
- END PROCESS;
-
- -- Il resto del codice rimane IDENTICO alla versione originale
- -- Logica di controllo AXI
+ -- Balance to exp
PROCESS (aclk)
- VARIABLE temp : signed(TDATA_WIDTH + MAX_SHIFT - 1 DOWNTO 0);
BEGIN
+
IF rising_edge(aclk) THEN
+
IF aresetn = '0' THEN
- -- Reset asincrono
- valid_reg <= '0';
- audio_in_reg <= (OTHERS => '0');
- tlast_reg <= '0';
- processing_active <= '0';
+ left_channel <= 0;
+ right_channel <= 0;
+
ELSE
- -- Gestione del flusso dati
- IF ready_int = '1' THEN
- valid_reg <= '0';
-
- IF s_axis_tvalid = '1' THEN
- -- Registrazione degli ingressi
- audio_in_reg <= signed(s_axis_tdata);
- tlast_reg <= s_axis_tlast;
- valid_reg <= '1';
- processing_active <= '1';
- ELSE
- processing_active <= '0';
- END IF;
+ -- Balance left and right channels
+ IF unsigned(balance) > (BAL_MID + DEAD_ZONE) THEN
+ left_channel <= to_integer((unsigned(balance) - (BAL_MID + DEAD_ZONE)) SRL BALANCE_STEP_2) + 1;
+ ELSE
+ left_channel <= 0;
END IF;
- -- Elaborazione del dato (sempre attiva)
- IF processing_active = '1' OR valid_reg = '1' THEN
- temp := resize(audio_in_reg, temp'length);
-
- IF tlast_reg = '0' THEN
- temp := shift_right(temp, shift_amount_left);
- ELSE
- temp := shift_right(temp, shift_amount_right);
- END IF;
-
- -- Saturazione
- IF temp > 2 ** (TDATA_WIDTH - 1) - 1 THEN
- m_axis_tdata <= STD_LOGIC_VECTOR(to_signed(2 ** (TDATA_WIDTH - 1) - 1, TDATA_WIDTH));
- ELSIF temp <- 2 ** (TDATA_WIDTH - 1) THEN
- m_axis_tdata <= STD_LOGIC_VECTOR(to_signed(-2 ** (TDATA_WIDTH - 1), TDATA_WIDTH));
- ELSE
- m_axis_tdata <= STD_LOGIC_VECTOR(temp(TDATA_WIDTH - 1 DOWNTO 0));
- END IF;
-
- m_axis_tlast <= tlast_reg;
+ IF unsigned(balance) < (BAL_MID - DEAD_ZONE) THEN
+ right_channel <= to_integer(((BAL_MID - DEAD_ZONE) - unsigned(balance)) SRL BALANCE_STEP_2) + 1;
+ ELSE
+ right_channel <= 0;
END IF;
+
END IF;
+
END IF;
+
END PROCESS;
- -- Logica combinazionale per tready
- ready_int <= m_axis_tready OR NOT valid_reg;
- s_axis_tready <= ready_int;
+ -- Handle AXIS stream
+ PROCESS (aclk)
+ BEGIN
- -- Assegnazione del valid in uscita
- m_axis_tvalid <= valid_reg;
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ m_axis_tvalid_int <= '0';
+ m_axis_tlast <= '0';
+ m_axis_tdata <= (OTHERS => '0');
+
+ ELSE
+ -- Default output signals
+ m_axis_tlast <= '0';
+
+ -- Clear valid flag when master interface is ready
+ IF m_axis_tready = '1' THEN
+ m_axis_tvalid_int <= '0';
+ END IF;
+
+ -- Handle the data flow
+ IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN
+ -- Joystick datasheet: (x-axis) a 0 value corresponds to the axis
+ -- being tilted fully to the left and a value of 1023
+ -- corresponds fully to the right
+ IF s_axis_tlast = '0' THEN -- left
+ m_axis_tdata <= STD_LOGIC_VECTOR(shift_right(signed(s_axis_tdata), left_channel));
+ ELSE -- right
+ m_axis_tdata <= STD_LOGIC_VECTOR(shift_right(signed(s_axis_tdata), right_channel));
+ END IF;
+
+ m_axis_tvalid_int <= '1';
+ m_axis_tlast <= s_axis_tlast;
+
+ END IF;
+
+ END IF;
+
+ END IF;
+
+ END PROCESS;
END Behavioral;
\ No newline at end of file
diff --git a/LAB3/src/volume_multiplier.vhd b/LAB3/src/volume_multiplier.vhd
index 86a9bc9..5217502 100644
--- a/LAB3/src/volume_multiplier.vhd
+++ b/LAB3/src/volume_multiplier.vhd
@@ -83,6 +83,8 @@ BEGIN
-- Handle the data flow
IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN
-- Multiply the input data with the volume and assign to output
+ -- Joystick datasheet: (y-axis) a value of 0 when it is tilted all the way down
+ -- and a value of 1023 when it is tilted all the way up
IF volume_exp_mult >= 0 THEN
m_axis_tdata <= STD_LOGIC_VECTOR(
shift_left(
diff --git a/LAB3/vivado/balance_controller/balance_controller.xpr b/LAB3/vivado/balance_controller/balance_controller.xpr
new file mode 100644
index 0000000..76aebba
--- /dev/null
+++ b/LAB3/vivado/balance_controller/balance_controller.xpr
@@ -0,0 +1,214 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Vivado Synthesis Defaults
+
+
+
+
+
+
+
+
+
+
+ Default settings for Implementation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ default_dashboard
+
+
+
diff --git a/LAB3/vivado/balance_controller/tb_balance_controller_behav.wcfg b/LAB3/vivado/balance_controller/tb_balance_controller_behav.wcfg
new file mode 100644
index 0000000..b6a040f
--- /dev/null
+++ b/LAB3/vivado/balance_controller/tb_balance_controller_behav.wcfg
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ aclk
+ aclk
+
+
+ aresetn
+ aresetn
+
+
+ Balance
+ label
+
+
+ balance[9:0]
+ balance[9:0]
+ UNSIGNEDDECRADIX
+
+
+ left_shift
+ left_shift
+
+
+ right_shift
+ right_shift
+
+
+ s_axis
+ label
+
+
+ s_axis_tdata[23:0]
+ s_axis_tdata[23:0]
+ SIGNEDDECRADIX
+
+
+ s_axis_tlast
+ s_axis_tlast
+
+
+ s_axis_tvalid
+ s_axis_tvalid
+ #00FFFF
+ true
+
+
+ s_axis_tready
+ s_axis_tready
+ #FFD700
+ true
+
+
+ m_axis
+ label
+
+
+ m_axis_tdata[23:0]
+ m_axis_tdata[23:0]
+ SIGNEDDECRADIX
+
+
+ m_axis_tlast
+ m_axis_tlast
+
+
+ m_axis_tvalid
+ m_axis_tvalid
+ #00FFFF
+ true
+
+
+ m_axis_tready
+ m_axis_tready
+ #FFD700
+ true
+
+