diff --git a/LAB3/design/diligent_jstk/diligent_jstk.bd b/LAB3/design/diligent_jstk/diligent_jstk.bd index dbd3add..d4628ee 100644 --- a/LAB3/design/diligent_jstk/diligent_jstk.bd +++ b/LAB3/design/diligent_jstk/diligent_jstk.bd @@ -71,7 +71,7 @@ "proc_sys_reset_0": { "vlnv": "xilinx.com:ip:proc_sys_reset:5.0", "xci_name": "diligent_jstk_proc_sys_reset_0_0", - "xci_path": "ip\\diligent_jstk_proc_sys_reset_0_0_1\\diligent_jstk_proc_sys_reset_0_0.xci", + "xci_path": "ip\\diligent_jstk_proc_sys_reset_0_0\\diligent_jstk_proc_sys_reset_0_0.xci", "inst_hier_path": "proc_sys_reset_0", "parameters": { "RESET_BOARD_INTERFACE": { @@ -85,7 +85,7 @@ "clk_wiz_0": { "vlnv": "xilinx.com:ip:clk_wiz:6.0", "xci_name": "diligent_jstk_clk_wiz_0_0", - "xci_path": "ip\\diligent_jstk_clk_wiz_0_0_1\\diligent_jstk_clk_wiz_0_0.xci", + "xci_path": "ip\\diligent_jstk_clk_wiz_0_0\\diligent_jstk_clk_wiz_0_0.xci", "inst_hier_path": "clk_wiz_0", "parameters": { "CLK_IN1_BOARD_INTERFACE": { @@ -99,7 +99,7 @@ "AXI4Stream_UART_0": { "vlnv": "DigiLAB:ip:AXI4Stream_UART:1.1", "xci_name": "diligent_jstk_AXI4Stream_UART_0_0", - "xci_path": "ip\\diligent_jstk_AXI4Stream_UART_0_0_1\\diligent_jstk_AXI4Stream_UART_0_0.xci", + "xci_path": "ip\\diligent_jstk_AXI4Stream_UART_0_0\\diligent_jstk_AXI4Stream_UART_0_0.xci", "inst_hier_path": "AXI4Stream_UART_0", "parameters": { "UART_BAUD_RATE": { @@ -116,7 +116,7 @@ "jstk_uart_bridge_0": { "vlnv": "xilinx.com:module_ref:jstk_uart_bridge:1.0", "xci_name": "diligent_jstk_jstk_uart_bridge_0_0", - "xci_path": "ip\\diligent_jstk_jstk_uart_bridge_0_0_1\\diligent_jstk_jstk_uart_bridge_0_0.xci", + "xci_path": "ip\\diligent_jstk_jstk_uart_bridge_0_0\\diligent_jstk_jstk_uart_bridge_0_0.xci", "inst_hier_path": "jstk_uart_bridge_0", "reference_info": { "ref_type": "hdl", @@ -330,7 +330,7 @@ "axi4stream_spi_master_0": { "vlnv": "DigiLAB:ip:axi4stream_spi_master:1.0", "xci_name": "diligent_jstk_axi4stream_spi_master_0_0", - "xci_path": "ip\\diligent_jstk_axi4stream_spi_master_0_0_1\\diligent_jstk_axi4stream_spi_master_0_0.xci", + "xci_path": "ip\\diligent_jstk_axi4stream_spi_master_0_0\\diligent_jstk_axi4stream_spi_master_0_0.xci", "inst_hier_path": "axi4stream_spi_master_0", "parameters": { "c_sclkfreq": { @@ -341,7 +341,7 @@ "system_ila_0": { "vlnv": "xilinx.com:ip:system_ila:1.1", "xci_name": "diligent_jstk_system_ila_0_0", - "xci_path": "ip\\diligent_jstk_system_ila_0_0_1\\diligent_jstk_system_ila_0_0.xci", + "xci_path": "ip\\diligent_jstk_system_ila_0_0\\diligent_jstk_system_ila_0_0.xci", "inst_hier_path": "system_ila_0", "parameters": { "C_MON_TYPE": { @@ -377,7 +377,7 @@ "digilent_jstk2_0": { "vlnv": "xilinx.com:module_ref:digilent_jstk2:1.0", "xci_name": "diligent_jstk_digilent_jstk2_0_0", - "xci_path": "ip\\diligent_jstk_digilent_jstk2_0_0_1\\diligent_jstk_digilent_jstk2_0_0.xci", + "xci_path": "ip\\diligent_jstk_digilent_jstk2_0_0\\diligent_jstk_digilent_jstk2_0_0.xci", "inst_hier_path": "digilent_jstk2_0", "parameters": { "SPI_SCLKFREQ": { @@ -591,12 +591,6 @@ } }, "interface_nets": { - "AXI4Stream_UART_0_UART": { - "interface_ports": [ - "usb_uart", - "AXI4Stream_UART_0/UART" - ] - }, "axi4stream_spi_master_0_M_AXIS": { "interface_ports": [ "axi4stream_spi_master_0/M_AXIS", @@ -610,10 +604,16 @@ "jstk_uart_bridge_0/s_axis" ] }, - "jstk_uart_bridge_0_m_axis": { + "axi4stream_spi_master_0_SPI_M": { "interface_ports": [ - "AXI4Stream_UART_0/S00_AXIS_TX", - "jstk_uart_bridge_0/m_axis" + "SPI_M_0", + "axi4stream_spi_master_0/SPI_M" + ] + }, + "AXI4Stream_UART_0_UART": { + "interface_ports": [ + "usb_uart", + "AXI4Stream_UART_0/UART" ] }, "digilent_jstk2_0_m_axis": { @@ -623,10 +623,10 @@ "system_ila_0/SLOT_0_AXIS" ] }, - "axi4stream_spi_master_0_SPI_M": { + "jstk_uart_bridge_0_m_axis": { "interface_ports": [ - "SPI_M_0", - "axi4stream_spi_master_0/SPI_M" + "AXI4Stream_UART_0/S00_AXIS_TX", + "jstk_uart_bridge_0/m_axis" ] } }, diff --git a/LAB3/design/diligent_jstk/hdl/diligent_jstk_wrapper.vhd b/LAB3/design/diligent_jstk/hdl/diligent_jstk_wrapper.vhd index 460a63b..39455a0 100644 --- a/LAB3/design/diligent_jstk/hdl/diligent_jstk_wrapper.vhd +++ b/LAB3/design/diligent_jstk/hdl/diligent_jstk_wrapper.vhd @@ -1,8 +1,8 @@ --Copyright 1986-2020 Xilinx, Inc. All Rights Reserved. ---------------------------------------------------------------------------------- --Tool Version: Vivado v.2020.2 (win64) Build 3064766 Wed Nov 18 09:12:45 MST 2020 ---Date : Sun May 18 23:39:32 2025 ---Host : DavideASUS running 64-bit major release (build 9200) +--Date : Mon May 19 09:11:39 2025 +--Host : Davide-Samsung running 64-bit major release (build 9200) --Command : generate_target diligent_jstk_wrapper.bd --Design : diligent_jstk_wrapper --Purpose : IP block netlist @@ -29,6 +29,8 @@ architecture STRUCTURE of diligent_jstk_wrapper is port ( reset : in STD_LOGIC; sys_clock : in STD_LOGIC; + usb_uart_txd : out STD_LOGIC; + usb_uart_rxd : in STD_LOGIC; SPI_M_0_sck_t : out STD_LOGIC; SPI_M_0_io1_o : out STD_LOGIC; SPI_M_0_ss_t : out STD_LOGIC; @@ -40,9 +42,7 @@ architecture STRUCTURE of diligent_jstk_wrapper is SPI_M_0_sck_o : out STD_LOGIC; SPI_M_0_ss_i : in STD_LOGIC; SPI_M_0_io1_i : in STD_LOGIC; - SPI_M_0_io0_i : in STD_LOGIC; - usb_uart_txd : out STD_LOGIC; - usb_uart_rxd : in STD_LOGIC + SPI_M_0_io0_i : in STD_LOGIC ); end component diligent_jstk; component IOBUF is diff --git a/LAB3/src/all_pass_filter.vhd b/LAB3/src/all_pass_filter.vhd index b3bed43..43796f8 100644 --- a/LAB3/src/all_pass_filter.vhd +++ b/LAB3/src/all_pass_filter.vhd @@ -24,9 +24,6 @@ END all_pass_filter; ARCHITECTURE Behavioral OF all_pass_filter IS - SIGNAL trigger : STD_LOGIC := '0'; -- Used to control when to send data - - SIGNAL s_axis_tlast_reg : STD_LOGIC := '0'; SIGNAL s_axis_tready_int : STD_LOGIC := '0'; SIGNAL m_axis_tvalid_int : STD_LOGIC := '0'; @@ -49,29 +46,21 @@ BEGIN m_axis_tvalid_int <= '0'; ELSE - -- Set the ready signal for the slave interface - s_axis_tready_int <= m_axis_tready OR NOT m_axis_tvalid_int; - - -- Get the data from the slave interface - IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN - s_axis_tlast_reg <= s_axis_tlast; -- Store the last signal - trigger <= '1'; -- Trigger the output - - END IF; - -- Clear valid flag when master interface is ready IF m_axis_tready = '1' THEN m_axis_tvalid_int <= '0'; END IF; - -- Send data to the master interface - IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN - m_axis_tvalid_int <= '1'; -- Set valid flag for master interface - m_axis_tlast <= s_axis_tlast_reg; + -- Hndle data transfer + IF s_axis_tvalid = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + s_axis_tready_int <= '1'; + m_axis_tvalid_int <= '1'; m_axis_tdata <= s_axis_tdata; + m_axis_tlast <= s_axis_tlast; + + ELSE + s_axis_tready_int <= '0'; - -- Reset trigger - trigger <= '0'; END IF; END IF; diff --git a/LAB3/src/balance_controller.vhd b/LAB3/src/balance_controller.vhd index 1d5f90c..01b41cd 100644 --- a/LAB3/src/balance_controller.vhd +++ b/LAB3/src/balance_controller.vhd @@ -1,33 +1,88 @@ -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; -use ieee.numeric_std.all; +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 +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; + 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; + 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; + 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) + balance : IN STD_LOGIC_VECTOR(BALANCE_WIDTH - 1 DOWNTO 0) ); -end balance_controller; +END balance_controller; -architecture Behavioral of balance_controller is +ARCHITECTURE Behavioral OF balance_controller IS -begin + CONSTANT BAL_MID : INTEGER := 2 ** (BALANCE_WIDTH - 1); -- 512 per 10 bit + CONSTANT DEAD_ZONE : INTEGER := 32; + CONSTANT BLOCK_SIZE : INTEGER := 64; -end Behavioral; + SIGNAL tvalid_reg : STD_LOGIC := '0'; + SIGNAL tdata_reg : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL tlast_reg : STD_LOGIC := '0'; + + SIGNAL left_shift : INTEGER RANGE 0 TO BALANCE_WIDTH := 0; + SIGNAL right_shift : INTEGER RANGE 0 TO BALANCE_WIDTH := 0; + SIGNAL bal_int : INTEGER; + +BEGIN + + -- Handshake & cattura dati in ingresso + PROCESS (aclk) + BEGIN + IF rising_edge(aclk) THEN + IF aresetn = '0' THEN + tvalid_reg <= '0'; + tdata_reg <= (OTHERS => '0'); + tlast_reg <= '0'; + ELSIF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN + tvalid_reg <= '1'; + tdata_reg <= s_axis_tdata; + tlast_reg <= s_axis_tlast; + ELSIF m_axis_tready = '1' THEN + tvalid_reg <= '0'; + END IF; + END IF; + END PROCESS; + + s_axis_tready <= m_axis_tready; + + bal_int <= to_integer(unsigned(balance)); + + -- Calcolo shift esponenziale per balance con zona morta centrale e blocchi da 64 + left_shift <= ((bal_int - (BAL_MID + DEAD_ZONE)) / BLOCK_SIZE) WHEN bal_int > (BAL_MID + DEAD_ZONE) ELSE 0; + right_shift <= (((BAL_MID - DEAD_ZONE) - bal_int) / BLOCK_SIZE) WHEN bal_int < (BAL_MID - DEAD_ZONE) ELSE 0; + + -- Applicazione gain esponenziale tramite shift (process combinatorio) + PROCESS (tvalid_reg, tlast_reg, tdata_reg, left_shift, right_shift) + BEGIN + IF tvalid_reg = '1' THEN + IF tlast_reg = '0' THEN -- left + m_axis_tdata <= STD_LOGIC_VECTOR(shift_right(signed(tdata_reg), left_shift)); + ELSE -- right + m_axis_tdata <= STD_LOGIC_VECTOR(shift_right(signed(tdata_reg), right_shift)); + END IF; + ELSE + m_axis_tdata <= (OTHERS => '0'); + END IF; + END PROCESS; + + m_axis_tvalid <= tvalid_reg; + m_axis_tlast <= tlast_reg; + +END Behavioral; \ No newline at end of file diff --git a/LAB3/src/edge_detector_toggle.vhd b/LAB3/src/edge_detector_toggle.vhd index 061c3fa..441a64a 100644 --- a/LAB3/src/edge_detector_toggle.vhd +++ b/LAB3/src/edge_detector_toggle.vhd @@ -15,6 +15,39 @@ end edge_detector_toggle; architecture Behavioral of edge_detector_toggle is + signal output_signal_int : std_logic; + signal input_signal_old : std_logic; + begin + -- We will have to read output_signal, but it's an output port, so we have to + -- define a new signal and connect it directly with the output port. + -- In this way signal and output port have the exact same value without delays, + -- but the signal can be read. + output_signal <= output_signal_int; + + process(clk) + begin + if rising_edge(clk) then + + if reset = '1' then + output_signal_int <= '0'; + input_signal_old <= '0'; + else + + -- Sample the old input_signal + -- In this way, at each clock cycle, we have the current value and the previous one. + input_signal_old <= input_signal; + + -- Toggle output_signal if we see a 0 --> 1 transition (or 1 --> 0 for the falling edge case). + if (EDGE_RISING = true and input_signal_old = '0' and input_signal = '1') or + (EDGE_RISING = false and input_signal_old = '1' and input_signal = '0') then + output_signal_int <= not output_signal_int; + end if; + + end if; + + end if; + end process; + end Behavioral; diff --git a/LAB3/src/effect_selector.vhd b/LAB3/src/effect_selector.vhd index 4efe6d7..ff97a30 100644 --- a/LAB3/src/effect_selector.vhd +++ b/LAB3/src/effect_selector.vhd @@ -1,34 +1,55 @@ -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; +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 +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) + 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; +END effect_selector; -architecture Behavioral of effect_selector is +ARCHITECTURE Behavioral OF effect_selector IS -begin +BEGIN -end Behavioral; + PROCESS (aclk) + BEGIN + + IF rising_edge(aclk) THEN + + IF aresetn = '0' THEN + volume <= (OTHERS => '0'); + balance <= (OTHERS => '0'); + lfo_period <= (OTHERS => '0'); + + ELSE + balance <= jstck_x; + + IF effect = '0' THEN + -- volume/balance control + volume <= jstck_y; + lfo_period <= (OTHERS => '0'); + + ELSE + -- LFO control + lfo_period <= jstck_y; + + END IF; + + END IF; + + END IF; + + END PROCESS; + +END Behavioral; \ No newline at end of file diff --git a/LAB3/src/led_controller.vhd b/LAB3/src/led_controller.vhd index 023a503..ebeae91 100644 --- a/LAB3/src/led_controller.vhd +++ b/LAB3/src/led_controller.vhd @@ -1,22 +1,37 @@ -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; -entity led_controller is - Generic ( - LED_WIDTH : positive := 8 +ENTITY led_controller IS + GENERIC ( + LED_WIDTH : POSITIVE := 8 ); - Port ( - mute_enable : in std_logic; - filter_enable : in std_logic; + 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) + 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; +END led_controller; -architecture Behavioral of led_controller is +ARCHITECTURE Behavioral OF led_controller IS -begin + -- constant for "ON" and "OFF" + CONSTANT ALL_ON : STD_LOGIC_VECTOR(LED_WIDTH - 1 DOWNTO 0) := (OTHERS => '1'); + CONSTANT ALL_OFF : STD_LOGIC_VECTOR(LED_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); -end Behavioral; +BEGIN + + -- If mute_enable = '1' Red LEDs on, others off + -- Else if filter_enable='1' Blue LEDs on, others off + -- Else Green LEDs on, others off + + led_r <= ALL_ON WHEN mute_enable = '1' ELSE + ALL_OFF; + led_b <= ALL_ON WHEN (mute_enable = '0' AND filter_enable = '1') ELSE + ALL_OFF; + led_g <= ALL_ON WHEN (mute_enable = '0' AND filter_enable = '0') ELSE + ALL_OFF; + +END Behavioral; \ No newline at end of file diff --git a/LAB3/src/led_level_controller.vhd b/LAB3/src/led_level_controller.vhd index 01f2cf0..69ea691 100644 --- a/LAB3/src/led_level_controller.vhd +++ b/LAB3/src/led_level_controller.vhd @@ -1,36 +1,7 @@ ----------------------------------------------------------------------------------- --- 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; @@ -54,7 +25,83 @@ entity led_level_controller is end led_level_controller; architecture Behavioral of led_level_controller is + constant REFRESH_CYCLES : natural := (refresh_time_ms * 1_000_000) / clock_period_ns; + + signal volume_value : signed(CHANNEL_LENGHT-1 downto 0) := (others => '0'); + signal abs_audio : unsigned(CHANNEL_LENGHT-2 downto 0) := (others => '0'); + signal leds_int : std_logic_vector(NUM_LEDS-1 downto 0) := (others => '0'); + signal led_update : std_logic := '0'; + signal refresh_counter : natural range 0 to REFRESH_CYCLES-1 := 0; begin + led <= leds_int; + s_axis_tready <= '1'; + -- Register the audio absolute value + + process(aclk) + begin + if rising_edge(aclk) then + if aresetn = '0' then + volume_value <= (others => '0'); + elsif s_axis_tvalid = '1' then + volume_value <= signed(s_axis_tdata); + if volume_value(volume_value'high) = '1' then + abs_audio <= unsigned(-volume_value(CHANNEL_LENGHT-2 downto 0)); + else + abs_audio <= unsigned(volume_value(CHANNEL_LENGHT-2 downto 0)); + end if; + end if; + end if; + end process; + + -- Refresh counter + process(aclk) + begin + if rising_edge(aclk) then + if aresetn = '0' then + refresh_counter <= 0; + led_update <= '0'; + else + if refresh_counter = REFRESH_CYCLES-1 then + refresh_counter <= 0; + led_update <= '1'; + else + refresh_counter <= refresh_counter + 1; + led_update <= '0'; + end if; + end if; + end if; + end process; + + -- Linear scaling of the audio signal to LED levels + process(aclk) + variable leds_on : natural range 0 to NUM_LEDS; + variable temp_led_level : integer range 0 to NUM_LEDS; + begin + if rising_edge(aclk) then + if aresetn = '0' then + leds_int <= (others => '0'); + elsif led_update = '1' then + -- Automatic linear scaling calculation: + if to_integer(abs_audio) = 0 then + temp_led_level := 0; + else -- -1 bit for sign, -4 to get 15+1 levels + temp_led_level := to_integer(shift_right(abs_audio,CHANNEL_LENGHT-4-1))+1; + end if; + + -- Limit to maximum number of LEDs + if temp_led_level > NUM_LEDS then + leds_on := NUM_LEDS; + else + leds_on := temp_led_level; + end if; + + leds_int <= (others => '0'); + if leds_on > 0 then + leds_int(leds_on-1 downto 0) <= (others => '1'); + end if; + end if; + end if; + end process; end Behavioral; diff --git a/LAB3/src/moving_average_filter.vhd b/LAB3/src/moving_average_filter.vhd index d60c722..c31ab83 100644 --- a/LAB3/src/moving_average_filter.vhd +++ b/LAB3/src/moving_average_filter.vhd @@ -30,14 +30,18 @@ ARCHITECTURE Behavioral OF moving_average_filter IS CONSTANT FILTER_ORDER : INTEGER := 2 ** FILTER_ORDER_POWER; TYPE sample_array IS ARRAY (0 TO FILTER_ORDER - 1) OF signed(TDATA_WIDTH - 1 DOWNTO 0); - SIGNAL samples : sample_array := (OTHERS => (OTHERS => '0')); - SIGNAL sum : signed(TDATA_WIDTH + FILTER_ORDER_POWER - 1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL wr_ptr : INTEGER RANGE 0 TO FILTER_ORDER - 1 := 0; - SIGNAL trigger : STD_LOGIC := '0'; -- Used to control when to send data + -- DX + SIGNAL samples_dx : sample_array := (OTHERS => (OTHERS => '0')); + SIGNAL sum_dx : signed(TDATA_WIDTH + FILTER_ORDER_POWER - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL wr_ptr_dx : INTEGER RANGE 0 TO FILTER_ORDER - 1 := 0; + + -- SX + SIGNAL samples_sx : sample_array := (OTHERS => (OTHERS => '0')); + SIGNAL sum_sx : signed(TDATA_WIDTH + FILTER_ORDER_POWER - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL wr_ptr_sx : INTEGER RANGE 0 TO FILTER_ORDER - 1 := 0; SIGNAL s_axis_tready_int : STD_LOGIC := '0'; - SIGNAL s_axis_tlast_reg : STD_LOGIC := '0'; SIGNAL m_axis_tvalid_int : STD_LOGIC := '0'; BEGIN @@ -52,11 +56,9 @@ BEGIN IF rising_edge(aclk) THEN IF aresetn = '0' THEN - samples <= (OTHERS => (OTHERS => '0')); - sum <= (OTHERS => '0'); - wr_ptr <= 0; - - trigger <= '0'; + samples_dx <= (OTHERS => (OTHERS => '0')); + sum_dx <= (OTHERS => '0'); + wr_ptr_dx <= 0; s_axis_tready_int <= '0'; m_axis_tvalid_int <= '0'; @@ -65,39 +67,62 @@ BEGIN m_axis_tdata <= (OTHERS => '0'); ELSE - -- Set the ready signal for the slave interface - s_axis_tready_int <= m_axis_tready OR NOT m_axis_tvalid_int; - - -- Get and process input data - IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN - -- Circular buffer overwrite oldest saple with the new one from next clk cycle - samples(wr_ptr) <= signed(s_axis_tdata); - - -- Update the write pointer - wr_ptr <= (wr_ptr + 1) MOD FILTER_ORDER; - - -- Update the sum removing the oldest sample and adding the new one - sum <= sum - samples(wr_ptr) + signed(s_axis_tdata); - - s_axis_tlast_reg <= s_axis_tlast; -- Store the last signal - trigger <= '1'; -- Trigger the output - - END IF; - -- Clear valid flag when master interface is ready IF m_axis_tready = '1' THEN m_axis_tvalid_int <= '0'; END IF; - -- Send data when triggered and receiver is ready - IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN - m_axis_tvalid_int <= '1'; - m_axis_tlast <= s_axis_tlast_reg; - m_axis_tdata <= STD_LOGIC_VECTOR(sum(sum'high DOWNTO FILTER_ORDER_POWER)); -- Average value - - -- Reset trigger - trigger <= '0'; - + -- Get and process data + IF s_axis_tvalid = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + IF s_axis_tlast = '1' THEN + -- Circular buffer overwrite oldest saple with the new one from next clk cycle + samples_dx(wr_ptr_dx) <= signed(s_axis_tdata); + + -- Update the write pointer + wr_ptr_dx <= (wr_ptr_dx + 1) MOD FILTER_ORDER; + + -- Update the sum_dx removing the oldest sample and adding the new one + sum_dx <= sum_dx - samples_dx(wr_ptr_dx) + signed(s_axis_tdata); + + -- Calculate the average and send it to the master interface + m_axis_tdata <= STD_LOGIC_VECTOR( + resize( + shift_right( + sum_dx - samples_dx(wr_ptr_dx) + signed(s_axis_tdata), + FILTER_ORDER_POWER + ), + m_axis_tdata'length + ) + ); + ELSE + -- Circular buffer overwrite oldest saple with the new one from next clk cycle + samples_sx(wr_ptr_sx) <= signed(s_axis_tdata); + + -- Update the write pointer + wr_ptr_sx <= (wr_ptr_sx + 1) MOD FILTER_ORDER; + + -- Update the sum_dx removing the oldest sample and adding the new one + sum_sx <= sum_sx - samples_sx(wr_ptr_sx) + signed(s_axis_tdata); + + -- Calculate the average and send it to the master interface + m_axis_tdata <= STD_LOGIC_VECTOR( + resize( + shift_right( + sum_sx - samples_sx(wr_ptr_sx) + signed(s_axis_tdata), + FILTER_ORDER_POWER + ), + m_axis_tdata'length + ) + ); + END IF; + + s_axis_tready_int <= '1'; + m_axis_tvalid_int <= '1'; + m_axis_tlast <= s_axis_tlast; + + ELSE + s_axis_tready_int <= '0'; + END IF; END IF; diff --git a/LAB3/src/moving_average_filter_en.vhd b/LAB3/src/moving_average_filter_en.vhd deleted file mode 100644 index e768456..0000000 --- a/LAB3/src/moving_average_filter_en.vhd +++ /dev/null @@ -1,148 +0,0 @@ -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 - - -- Component declarations - COMPONENT 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 COMPONENT; - - COMPONENT moving_average_filter IS - GENERIC ( - 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 COMPONENT; - - -- Internal signals for the all-pass filter - SIGNAL all_pass_s_tvalid : STD_LOGIC; - SIGNAL all_pass_s_tready : STD_LOGIC; - - SIGNAL all_pass_m_tvalid : STD_LOGIC; - SIGNAL all_pass_m_tdata : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); - SIGNAL all_pass_m_tlast : STD_LOGIC; - SIGNAL all_pass_m_tready : STD_LOGIC; - - -- Internal signals for the moving average filter - SIGNAL moving_avg_s_tvalid : STD_LOGIC; - SIGNAL moving_avg_s_tready : STD_LOGIC; - - SIGNAL moving_avg_m_tvalid : STD_LOGIC; - SIGNAL moving_avg_m_tdata : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); - SIGNAL moving_avg_m_tlast : STD_LOGIC; - SIGNAL moving_avg_m_tready : STD_LOGIC; - -BEGIN - - -- Instantiate the all-pass filter - all_pass_inst : all_pass_filter - GENERIC MAP( - TDATA_WIDTH => TDATA_WIDTH - ) - PORT MAP( - aclk => aclk, - aresetn => aresetn, - - s_axis_tvalid => all_pass_s_tvalid, - s_axis_tdata => s_axis_tdata, - s_axis_tlast => s_axis_tlast, - s_axis_tready => all_pass_s_tready, - - m_axis_tvalid => all_pass_m_tvalid, - m_axis_tdata => all_pass_m_tdata, - m_axis_tlast => all_pass_m_tlast, - m_axis_tready => all_pass_m_tready - ); - - -- Instantiate the moving average filter - moving_avg_inst : moving_average_filter - GENERIC MAP( - FILTER_ORDER_POWER => FILTER_ORDER_POWER, - TDATA_WIDTH => TDATA_WIDTH - ) - PORT MAP( - aclk => aclk, - aresetn => aresetn, - - s_axis_tvalid => moving_avg_s_tvalid, - s_axis_tdata => s_axis_tdata, - s_axis_tlast => s_axis_tlast, - s_axis_tready => moving_avg_s_tready, - - m_axis_tvalid => moving_avg_m_tvalid, - m_axis_tdata => moving_avg_m_tdata, - m_axis_tlast => moving_avg_m_tlast, - m_axis_tready => moving_avg_m_tready - ); - - -- Assign filter control signals based on enable_filter - all_pass_s_tvalid <= s_axis_tvalid WHEN enable_filter = '0' ELSE '0'; - moving_avg_s_tvalid <= s_axis_tvalid WHEN enable_filter = '1' ELSE '0'; - - all_pass_m_tready <= m_axis_tready WHEN enable_filter = '0' ELSE '0'; - moving_avg_m_tready <= m_axis_tready WHEN enable_filter = '1' ELSE '0'; - - -- Main AXIS assignments based on enable_filter - s_axis_tready <= all_pass_s_tready WHEN enable_filter = '0' ELSE moving_avg_s_tready; - m_axis_tvalid <= all_pass_m_tvalid WHEN enable_filter = '0' ELSE moving_avg_m_tvalid; - m_axis_tdata <= all_pass_m_tdata WHEN enable_filter = '0' ELSE moving_avg_m_tdata; - m_axis_tlast <= all_pass_m_tlast WHEN enable_filter = '0' ELSE moving_avg_m_tlast; - -END Behavioral; \ No newline at end of file diff --git a/LAB3/src/mute_controller.vhd b/LAB3/src/mute_controller.vhd index 2afdbf0..f46eab0 100644 --- a/LAB3/src/mute_controller.vhd +++ b/LAB3/src/mute_controller.vhd @@ -1,31 +1,68 @@ -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; -use IEEE.NUMERIC_STD.ALL; +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; -entity mute_controller is - Generic ( - TDATA_WIDTH : positive := 24 +ENTITY mute_controller IS + GENERIC ( + TDATA_WIDTH : POSITIVE := 24 ); - Port ( - aclk : in std_logic; - aresetn : in std_logic; + 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; + 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; + 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 + mute : IN STD_LOGIC ); -end mute_controller; +END mute_controller; -architecture Behavioral of mute_controller is +ARCHITECTURE Behavioral OF mute_controller IS +BEGIN -begin + PROCESS (aclk) + BEGIN -end Behavioral; + IF rising_edge(aclk) THEN + + IF aresetn = '0' THEN + m_axis_tvalid <= '0'; + m_axis_tdata <= (OTHERS => '0'); + m_axis_tlast <= '0'; + s_axis_tready <= '0'; + + ELSE + IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN + -- Accept input data + s_axis_tready <= '1'; + m_axis_tvalid <= '1'; + m_axis_tlast <= s_axis_tlast; + + IF mute = '1' THEN + m_axis_tdata <= (OTHERS => '0'); + ELSE + m_axis_tdata <= s_axis_tdata; + END IF; + + ELSE + -- Do not accept new data + s_axis_tready <= '0'; + m_axis_tvalid <= '0'; + m_axis_tlast <= '0'; + + END IF; + + END IF; + + END IF; + + END PROCESS; + +END Behavioral; \ No newline at end of file diff --git a/LAB3/src/volume_controller.vhd b/LAB3/src/volume_controller.vhd index f47429f..f983367 100644 --- a/LAB3/src/volume_controller.vhd +++ b/LAB3/src/volume_controller.vhd @@ -1,35 +1,138 @@ -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; -use IEEE.NUMERIC_STD.ALL; +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 +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; + 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; + 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; + 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) + volume : IN STD_LOGIC_VECTOR(VOLUME_WIDTH - 1 DOWNTO 0) ); -end volume_controller; +END volume_controller; -architecture Behavioral of volume_controller is +ARCHITECTURE Behavioral OF volume_controller IS -begin + -- 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; -end Behavioral; + 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 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; + + 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; + + -- 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; + +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, + + 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, + + 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, + + 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 + ); + +END Behavioral; \ No newline at end of file diff --git a/LAB3/src/volume_multiplier.vhd b/LAB3/src/volume_multiplier.vhd index 34641e2..8aa60fc 100644 --- a/LAB3/src/volume_multiplier.vhd +++ b/LAB3/src/volume_multiplier.vhd @@ -1,33 +1,118 @@ -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; -use IEEE.NUMERIC_STD.ALL; +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 +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; + 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; + 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; + 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) + volume : IN STD_LOGIC_VECTOR(VOLUME_WIDTH - 1 DOWNTO 0) ); -end volume_multiplier; +END volume_multiplier; -architecture Behavioral of volume_multiplier is +ARCHITECTURE Behavioral OF volume_multiplier IS -begin + CONSTANT VOLUME_STEPS : INTEGER := (2 ** VOLUME_WIDTH) / (2 ** (VOLUME_STEP_2 + 1)); -end Behavioral; + SIGNAL volume_exp_mult : INTEGER RANGE -VOLUME_STEPS TO VOLUME_STEPS := 0; + signal volume_centered : SIGNED(VOLUME_WIDTH - 1 DOWNTO 0); + + SIGNAL s_axis_tready_int : STD_LOGIC; + SIGNAL m_axis_tvalid_int : STD_LOGIC; + +BEGIN + -- Assigning the output signals + s_axis_tready <= s_axis_tready_int; + m_axis_tvalid <= m_axis_tvalid_int; + + -- Volume to signed and centered + volume_centered <= signed(unsigned(volume) - to_unsigned(511, VOLUME_WIDTH)); + + -- Volume to exp + PROCESS (aclk) + BEGIN + + IF rising_edge(aclk) THEN + + IF aresetn = '0' THEN + volume_exp_mult <= 0; + + ELSE + volume_exp_mult <= to_integer(volume_centered(VOLUME_WIDTH - 1 DOWNTO VOLUME_STEP_2)); + + END IF; + + END IF; + + END PROCESS; + + -- Handle AXIS stream + PROCESS (aclk) + BEGIN + + IF rising_edge(aclk) THEN + + IF aresetn = '0' THEN + s_axis_tready_int <= '0'; + m_axis_tvalid_int <= '0'; + m_axis_tlast <= '0'; + + ELSE + -- Clear valid flag when master interface is ready + IF m_axis_tready = '1' THEN + m_axis_tvalid_int <= '0'; + END IF; + + IF s_axis_tvalid = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + IF volume_exp_mult >= 0 THEN + m_axis_tdata <= STD_LOGIC_VECTOR( + shift_left( + resize( + signed(s_axis_tdata), + m_axis_tdata'LENGTH + ), + volume_exp_mult + ) + ); + ELSE + m_axis_tdata <= STD_LOGIC_VECTOR( + shift_right( + resize( + signed(s_axis_tdata), + m_axis_tdata'LENGTH + ), + -volume_exp_mult + ) + ); + END IF; + s_axis_tready_int <= '1'; + m_axis_tvalid_int <= '1'; + m_axis_tlast <= s_axis_tlast; + + ELSE + s_axis_tready_int <= '0'; + END IF; + + END IF; + + END IF; + + END PROCESS; + +END Behavioral; \ No newline at end of file diff --git a/LAB3/src/volume_saturator.vhd b/LAB3/src/volume_saturator.vhd index ae69f9f..10744c0 100644 --- a/LAB3/src/volume_saturator.vhd +++ b/LAB3/src/volume_saturator.vhd @@ -1,33 +1,81 @@ -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; -use IEEE.NUMERIC_STD.ALL; +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 +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; + 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; + 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 + 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; +END volume_saturator; -architecture Behavioral of volume_saturator is +ARCHITECTURE Behavioral OF volume_saturator IS -begin + SIGNAL s_axis_tready_int : STD_LOGIC; + SIGNAL m_axis_tvalid_int : STD_LOGIC; -end Behavioral; +BEGIN + -- Output assignments + s_axis_tready <= s_axis_tready_int; + m_axis_tvalid <= m_axis_tvalid_int; + + PROCESS (aclk) + BEGIN + + IF rising_edge(aclk) THEN + + IF aresetn = '0' THEN + s_axis_tready_int <= '0'; + m_axis_tvalid_int <= '0'; + m_axis_tlast <= '0'; + m_axis_tdata <= (OTHERS => '0'); + + ELSE + -- Clear valid flag when master interface is ready + IF m_axis_tready = '1' THEN + m_axis_tvalid_int <= '0'; + END IF; + + IF s_axis_tvalid = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + -- Check if the input data is within the bounds else saturate + IF signed(s_axis_tdata) > to_signed(HIGHER_BOUND, s_axis_tdata'length) THEN + m_axis_tdata <= STD_LOGIC_VECTOR(to_signed(HIGHER_BOUND, TDATA_WIDTH)); + ELSIF signed(s_axis_tdata) < to_signed(LOWER_BOUND, s_axis_tdata'length) THEN + m_axis_tdata <= STD_LOGIC_VECTOR(to_signed(LOWER_BOUND, TDATA_WIDTH)); + ELSE + m_axis_tdata <= STD_LOGIC_VECTOR(resize(signed(s_axis_tdata), TDATA_WIDTH)); + END IF; + + s_axis_tready_int <= '1'; + m_axis_tvalid_int <= '1'; + m_axis_tlast <= s_axis_tlast; + + ELSE + s_axis_tready_int <= '0'; + + END IF; + + END IF; + + END IF; + + END PROCESS; + +END Behavioral; \ No newline at end of file diff --git a/LAB3/vivado/diligent_jstk/diligent_jstk.xpr b/LAB3/vivado/diligent_jstk/diligent_jstk.xpr index 66fb777..f06df87 100644 --- a/LAB3/vivado/diligent_jstk/diligent_jstk.xpr +++ b/LAB3/vivado/diligent_jstk/diligent_jstk.xpr @@ -95,27 +95,27 @@ - + - - - - + - - - - + - + - + + + + + + + @@ -164,6 +164,18 @@