diff --git a/.gitignore b/.gitignore
index 7747d92..73b2a23 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,7 +43,7 @@
*.wdf
*.lpr
*.bxml
-
+*.zip
# Vivado project directories
*.sim/
@@ -64,6 +64,8 @@ vivado_pid*.str
vivado*.backup.jou
vivado*.backup.log
+# Directories to ignore
+.venv
# SDK workspace
.sdk/
@@ -78,4 +80,8 @@ vivado*.backup.log
**/design/**/*.xdc
# Other files
-**/test/*.zip
\ No newline at end of file
+**/test/*.zip
+**/test/*.exe
+*.spec
+**/dist/
+**/build/
\ No newline at end of file
diff --git a/LAB3/cons/io.xdc b/LAB3/cons/io.xdc
index ee4f8ea..262649a 100644
--- a/LAB3/cons/io.xdc
+++ b/LAB3/cons/io.xdc
@@ -1,3 +1,21 @@
+# pmod I2S2 connected to JB
+set_property IOSTANDARD LVCMOS33 [get_ports rx_lrck_0]
+set_property IOSTANDARD LVCMOS33 [get_ports rx_mclk_0]
+set_property IOSTANDARD LVCMOS33 [get_ports rx_sclk_0]
+set_property IOSTANDARD LVCMOS33 [get_ports rx_sdin_0]
+set_property IOSTANDARD LVCMOS33 [get_ports tx_lrck_0]
+set_property IOSTANDARD LVCMOS33 [get_ports tx_mclk_0]
+set_property IOSTANDARD LVCMOS33 [get_ports tx_sclk_0]
+set_property IOSTANDARD LVCMOS33 [get_ports tx_sdout_0]
+set_property PACKAGE_PIN A14 [get_ports tx_mclk_0]
+set_property PACKAGE_PIN A16 [get_ports tx_lrck_0]
+set_property PACKAGE_PIN B15 [get_ports tx_sclk_0]
+set_property PACKAGE_PIN B16 [get_ports tx_sdout_0]
+set_property PACKAGE_PIN A15 [get_ports rx_mclk_0]
+set_property PACKAGE_PIN A17 [get_ports rx_lrck_0]
+set_property PACKAGE_PIN C15 [get_ports rx_sclk_0]
+set_property PACKAGE_PIN C16 [get_ports rx_sdin_0]
+
# SPI connected to JA, top row
set_property PACKAGE_PIN J1 [get_ports SPI_M_0_ss_io]
set_property PACKAGE_PIN G2 [get_ports SPI_M_0_sck_io]
@@ -7,7 +25,45 @@ set_property IOSTANDARD LVCMOS33 [get_ports SPI_M_0_io0_io]
set_property IOSTANDARD LVCMOS33 [get_ports SPI_M_0_io1_io]
set_property IOSTANDARD LVCMOS33 [get_ports SPI_M_0_sck_io]
set_property IOSTANDARD LVCMOS33 [get_ports SPI_M_0_ss_io]
-set_property OFFCHIP_TERM NONE [get_ports SPI_M_0_io0_io]
-set_property OFFCHIP_TERM NONE [get_ports SPI_M_0_io1_io]
-set_property OFFCHIP_TERM NONE [get_ports SPI_M_0_sck_io]
-set_property OFFCHIP_TERM NONE [get_ports SPI_M_0_ss_io]
+
+# Button
+set_property IOSTANDARD LVCMOS33 [get_ports effect]
+set_property PACKAGE_PIN T18 [get_ports effect]
+
+# Switch
+set_property IOSTANDARD LVCMOS33 [get_ports {lfo_enable}]
+set_property PACKAGE_PIN V17 [get_ports {lfo_enable}]
+
+# LEDs
+set_property PACKAGE_PIN U16 [get_ports {LED[0]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[0]}]
+set_property PACKAGE_PIN E19 [get_ports {LED[1]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[1]}]
+set_property PACKAGE_PIN U19 [get_ports {LED[2]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[2]}]
+set_property PACKAGE_PIN V19 [get_ports {LED[3]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[3]}]
+set_property PACKAGE_PIN W18 [get_ports {LED[4]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[4]}]
+set_property PACKAGE_PIN U15 [get_ports {LED[5]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[5]}]
+set_property PACKAGE_PIN U14 [get_ports {LED[6]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[6]}]
+set_property PACKAGE_PIN V14 [get_ports {LED[7]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[7]}]
+set_property PACKAGE_PIN V13 [get_ports {LED[8]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[8]}]
+set_property PACKAGE_PIN V3 [get_ports {LED[9]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[9]}]
+set_property PACKAGE_PIN W3 [get_ports {LED[10]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[10]}]
+set_property PACKAGE_PIN U3 [get_ports {LED[11]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[11]}]
+set_property PACKAGE_PIN P3 [get_ports {LED[12]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[12]}]
+set_property PACKAGE_PIN N3 [get_ports {LED[13]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[13]}]
+set_property PACKAGE_PIN P1 [get_ports {LED[14]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[14]}]
+set_property PACKAGE_PIN L1 [get_ports {LED[15]}]
+ set_property IOSTANDARD LVCMOS33 [get_ports {LED[15]}]
\ No newline at end of file
diff --git a/LAB3/design/diligent_jstk/diligent_jstk.bd b/LAB3/design/diligent_jstk/diligent_jstk.bd
index ced2b7f..1570bb4 100644
--- a/LAB3/design/diligent_jstk/diligent_jstk.bd
+++ b/LAB3/design/diligent_jstk/diligent_jstk.bd
@@ -5,7 +5,7 @@
"device": "xc7a35tcpg236-1",
"name": "diligent_jstk",
"rev_ctrl_bd_flag": "RevCtrlBdOff",
- "synth_flow_mode": "None",
+ "synth_flow_mode": "Hierarchical",
"tool_version": "2020.2",
"validated": "true"
},
@@ -13,9 +13,10 @@
"proc_sys_reset_0": "",
"clk_wiz_0": "",
"AXI4Stream_UART_0": "",
- "digilent_jstk2_0": "",
"jstk_uart_bridge_0": "",
- "axi4stream_spi_master_0": ""
+ "axi4stream_spi_master_0": "",
+ "system_ila_0": "",
+ "digilent_jstk2_0": ""
},
"interface_ports": {
"usb_uart": {
@@ -83,8 +84,8 @@
},
"clk_wiz_0": {
"vlnv": "xilinx.com:ip:clk_wiz:6.0",
- "xci_name": "diligent_jstk_clk_wiz_0_1",
- "xci_path": "ip\\diligent_jstk_clk_wiz_0_1\\diligent_jstk_clk_wiz_0_1.xci",
+ "xci_name": "diligent_jstk_clk_wiz_0_0",
+ "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": {
@@ -101,6 +102,9 @@
"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": {
+ "value": "115200"
+ },
"UART_BOARD_INTERFACE": {
"value": "usb_uart"
},
@@ -109,216 +113,6 @@
}
}
},
- "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\\diligent_jstk_digilent_jstk2_0_0.xci",
- "inst_hier_path": "digilent_jstk2_0",
- "reference_info": {
- "ref_type": "hdl",
- "ref_name": "digilent_jstk2",
- "boundary_crc": "0x0"
- },
- "interface_ports": {
- "m_axis": {
- "mode": "Master",
- "vlnv": "xilinx.com:interface:axis_rtl:1.0",
- "parameters": {
- "TDATA_NUM_BYTES": {
- "value": "1",
- "value_src": "constant"
- },
- "TDEST_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TID_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TUSER_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TREADY": {
- "value": "1",
- "value_src": "constant"
- },
- "HAS_TSTRB": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TKEEP": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TLAST": {
- "value": "0",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- },
- "port_maps": {
- "TDATA": {
- "physical_name": "m_axis_tdata",
- "direction": "O",
- "left": "7",
- "right": "0"
- },
- "TVALID": {
- "physical_name": "m_axis_tvalid",
- "direction": "O"
- },
- "TREADY": {
- "physical_name": "m_axis_tready",
- "direction": "I"
- }
- }
- },
- "s_axis": {
- "mode": "Slave",
- "vlnv": "xilinx.com:interface:axis_rtl:1.0",
- "parameters": {
- "TDATA_NUM_BYTES": {
- "value": "1",
- "value_src": "constant"
- },
- "TDEST_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TID_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TUSER_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TREADY": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TSTRB": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TKEEP": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TLAST": {
- "value": "0",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- },
- "port_maps": {
- "TDATA": {
- "physical_name": "s_axis_tdata",
- "direction": "I",
- "left": "7",
- "right": "0"
- },
- "TVALID": {
- "physical_name": "s_axis_tvalid",
- "direction": "I"
- }
- }
- }
- },
- "ports": {
- "aclk": {
- "type": "clk",
- "direction": "I",
- "parameters": {
- "ASSOCIATED_BUSIF": {
- "value": "m_axis:s_axis",
- "value_src": "constant"
- },
- "ASSOCIATED_RESET": {
- "value": "aresetn",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- }
- },
- "aresetn": {
- "type": "rst",
- "direction": "I",
- "parameters": {
- "POLARITY": {
- "value": "ACTIVE_LOW",
- "value_src": "constant"
- }
- }
- },
- "jstk_x": {
- "direction": "O",
- "left": "9",
- "right": "0"
- },
- "jstk_y": {
- "direction": "O",
- "left": "9",
- "right": "0"
- },
- "btn_jstk": {
- "direction": "O"
- },
- "btn_trigger": {
- "direction": "O"
- },
- "led_r": {
- "direction": "I",
- "left": "7",
- "right": "0"
- },
- "led_g": {
- "direction": "I",
- "left": "7",
- "right": "0"
- },
- "led_b": {
- "direction": "I",
- "left": "7",
- "right": "0"
- }
- }
- },
"jstk_uart_bridge_0": {
"vlnv": "xilinx.com:module_ref:jstk_uart_bridge:1.0",
"xci_name": "diligent_jstk_jstk_uart_bridge_0_0",
@@ -537,34 +331,266 @@
"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\\diligent_jstk_axi4stream_spi_master_0_0.xci",
- "inst_hier_path": "axi4stream_spi_master_0"
+ "inst_hier_path": "axi4stream_spi_master_0",
+ "parameters": {
+ "c_sclkfreq": {
+ "value": "5000"
+ }
+ }
+ },
+ "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\\diligent_jstk_system_ila_0_0.xci",
+ "inst_hier_path": "system_ila_0",
+ "parameters": {
+ "C_MON_TYPE": {
+ "value": "MIX"
+ },
+ "C_NUM_MONITOR_SLOTS": {
+ "value": "2"
+ },
+ "C_NUM_OF_PROBES": {
+ "value": "7"
+ },
+ "C_SLOT": {
+ "value": "1"
+ },
+ "C_SLOT_0_INTF_TYPE": {
+ "value": "xilinx.com:interface:axis_rtl:1.0"
+ },
+ "C_SLOT_1_INTF_TYPE": {
+ "value": "xilinx.com:interface:axis_rtl:1.0"
+ }
+ },
+ "interface_ports": {
+ "SLOT_0_AXIS": {
+ "mode": "Monitor",
+ "vlnv": "xilinx.com:interface:axis_rtl:1.0"
+ },
+ "SLOT_1_AXIS": {
+ "mode": "Monitor",
+ "vlnv": "xilinx.com:interface:axis_rtl:1.0"
+ }
+ }
+ },
+ "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\\diligent_jstk_digilent_jstk2_0_0.xci",
+ "inst_hier_path": "digilent_jstk2_0",
+ "parameters": {
+ "SPI_SCLKFREQ": {
+ "value": "5000"
+ }
+ },
+ "reference_info": {
+ "ref_type": "hdl",
+ "ref_name": "digilent_jstk2",
+ "boundary_crc": "0x0"
+ },
+ "interface_ports": {
+ "m_axis": {
+ "mode": "Master",
+ "vlnv": "xilinx.com:interface:axis_rtl:1.0",
+ "parameters": {
+ "TDATA_NUM_BYTES": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "TDEST_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TID_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TUSER_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TREADY": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "HAS_TSTRB": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TKEEP": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TLAST": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ },
+ "port_maps": {
+ "TDATA": {
+ "physical_name": "m_axis_tdata",
+ "direction": "O",
+ "left": "7",
+ "right": "0"
+ },
+ "TVALID": {
+ "physical_name": "m_axis_tvalid",
+ "direction": "O"
+ },
+ "TREADY": {
+ "physical_name": "m_axis_tready",
+ "direction": "I"
+ }
+ }
+ },
+ "s_axis": {
+ "mode": "Slave",
+ "vlnv": "xilinx.com:interface:axis_rtl:1.0",
+ "parameters": {
+ "TDATA_NUM_BYTES": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "TDEST_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TID_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TUSER_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TREADY": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TSTRB": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TKEEP": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TLAST": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ },
+ "port_maps": {
+ "TDATA": {
+ "physical_name": "s_axis_tdata",
+ "direction": "I",
+ "left": "7",
+ "right": "0"
+ },
+ "TVALID": {
+ "physical_name": "s_axis_tvalid",
+ "direction": "I"
+ }
+ }
+ }
+ },
+ "ports": {
+ "aclk": {
+ "type": "clk",
+ "direction": "I",
+ "parameters": {
+ "ASSOCIATED_BUSIF": {
+ "value": "m_axis:s_axis",
+ "value_src": "constant"
+ },
+ "ASSOCIATED_RESET": {
+ "value": "aresetn",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ }
+ },
+ "aresetn": {
+ "type": "rst",
+ "direction": "I",
+ "parameters": {
+ "POLARITY": {
+ "value": "ACTIVE_LOW",
+ "value_src": "constant"
+ }
+ }
+ },
+ "jstk_x": {
+ "direction": "O",
+ "left": "9",
+ "right": "0"
+ },
+ "jstk_y": {
+ "direction": "O",
+ "left": "9",
+ "right": "0"
+ },
+ "btn_jstk": {
+ "direction": "O"
+ },
+ "btn_trigger": {
+ "direction": "O"
+ },
+ "led_r": {
+ "direction": "I",
+ "left": "7",
+ "right": "0"
+ },
+ "led_g": {
+ "direction": "I",
+ "left": "7",
+ "right": "0"
+ },
+ "led_b": {
+ "direction": "I",
+ "left": "7",
+ "right": "0"
+ }
+ }
}
},
"interface_nets": {
- "jstk_uart_bridge_0_m_axis": {
- "interface_ports": [
- "AXI4Stream_UART_0/S00_AXIS_TX",
- "jstk_uart_bridge_0/m_axis"
- ]
- },
- "axi4stream_spi_master_0_M_AXIS": {
- "interface_ports": [
- "axi4stream_spi_master_0/M_AXIS",
- "digilent_jstk2_0/s_axis"
- ]
- },
- "digilent_jstk2_0_m_axis": {
- "interface_ports": [
- "digilent_jstk2_0/m_axis",
- "axi4stream_spi_master_0/S_AXIS"
- ]
- },
- "AXI4Stream_UART_0_UART": {
- "interface_ports": [
- "usb_uart",
- "AXI4Stream_UART_0/UART"
- ]
- },
"AXI4Stream_UART_0_M00_AXIS_RX": {
"interface_ports": [
"AXI4Stream_UART_0/M00_AXIS_RX",
@@ -576,6 +602,32 @@
"SPI_M_0",
"axi4stream_spi_master_0/SPI_M"
]
+ },
+ "axi4stream_spi_master_0_M_AXIS": {
+ "interface_ports": [
+ "axi4stream_spi_master_0/M_AXIS",
+ "digilent_jstk2_0/s_axis",
+ "system_ila_0/SLOT_1_AXIS"
+ ]
+ },
+ "jstk_uart_bridge_0_m_axis": {
+ "interface_ports": [
+ "AXI4Stream_UART_0/S00_AXIS_TX",
+ "jstk_uart_bridge_0/m_axis"
+ ]
+ },
+ "digilent_jstk2_0_m_axis": {
+ "interface_ports": [
+ "digilent_jstk2_0/m_axis",
+ "axi4stream_spi_master_0/S_AXIS",
+ "system_ila_0/SLOT_0_AXIS"
+ ]
+ },
+ "AXI4Stream_UART_0_UART": {
+ "interface_ports": [
+ "usb_uart",
+ "AXI4Stream_UART_0/UART"
+ ]
}
},
"nets": {
@@ -603,63 +655,72 @@
"clk_wiz_0/clk_out1",
"proc_sys_reset_0/slowest_sync_clk",
"axi4stream_spi_master_0/aclk",
- "digilent_jstk2_0/aclk",
"AXI4Stream_UART_0/clk_uart",
"AXI4Stream_UART_0/m00_axis_rx_aclk",
"jstk_uart_bridge_0/aclk",
- "AXI4Stream_UART_0/s00_axis_tx_aclk"
+ "AXI4Stream_UART_0/s00_axis_tx_aclk",
+ "system_ila_0/clk",
+ "digilent_jstk2_0/aclk"
]
},
"digilent_jstk2_0_btn_trigger": {
"ports": [
"digilent_jstk2_0/btn_trigger",
- "jstk_uart_bridge_0/btn_trigger"
+ "jstk_uart_bridge_0/btn_trigger",
+ "system_ila_0/probe6"
]
},
"digilent_jstk2_0_btn_jstk": {
"ports": [
"digilent_jstk2_0/btn_jstk",
- "jstk_uart_bridge_0/btn_jstk"
+ "jstk_uart_bridge_0/btn_jstk",
+ "system_ila_0/probe5"
]
},
"digilent_jstk2_0_jstk_y": {
"ports": [
"digilent_jstk2_0/jstk_y",
- "jstk_uart_bridge_0/jstk_y"
+ "jstk_uart_bridge_0/jstk_y",
+ "system_ila_0/probe4"
]
},
"digilent_jstk2_0_jstk_x": {
"ports": [
"digilent_jstk2_0/jstk_x",
- "jstk_uart_bridge_0/jstk_x"
+ "jstk_uart_bridge_0/jstk_x",
+ "system_ila_0/probe3"
]
},
"jstk_uart_bridge_0_led_r": {
"ports": [
"jstk_uart_bridge_0/led_r",
+ "system_ila_0/probe0",
"digilent_jstk2_0/led_r"
]
},
"jstk_uart_bridge_0_led_g": {
"ports": [
"jstk_uart_bridge_0/led_g",
+ "system_ila_0/probe1",
"digilent_jstk2_0/led_g"
]
},
"jstk_uart_bridge_0_led_b": {
"ports": [
"jstk_uart_bridge_0/led_b",
+ "system_ila_0/probe2",
"digilent_jstk2_0/led_b"
]
},
"proc_sys_reset_0_peripheral_aresetn": {
"ports": [
"proc_sys_reset_0/peripheral_aresetn",
- "digilent_jstk2_0/aresetn",
"AXI4Stream_UART_0/m00_axis_rx_aresetn",
"jstk_uart_bridge_0/aresetn",
"AXI4Stream_UART_0/s00_axis_tx_aresetn",
- "axi4stream_spi_master_0/aresetn"
+ "axi4stream_spi_master_0/aresetn",
+ "system_ila_0/resetn",
+ "digilent_jstk2_0/aresetn"
]
},
"proc_sys_reset_0_peripheral_reset": {
diff --git a/LAB3/design/diligent_jstk/diligent_jstk.bda b/LAB3/design/diligent_jstk/diligent_jstk.bda
index 0f3d98f..aafae03 100644
--- a/LAB3/design/diligent_jstk/diligent_jstk.bda
+++ b/LAB3/design/diligent_jstk/diligent_jstk.bda
@@ -26,17 +26,17 @@
VR
+ diligent_jstk
+ BC
+
+
active
2
PM
-
- diligent_jstk
- BC
-
-
+
-
+
diff --git a/LAB3/design/diligent_jstk/hdl/diligent_jstk_wrapper.vhd b/LAB3/design/diligent_jstk/hdl/diligent_jstk_wrapper.vhd
index 9c30c60..9d1328b 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 : Mon May 12 15:44:44 2025
---Host : Davide-Samsung running 64-bit major release (build 9200)
+--Date : Fri May 30 13:56:20 2025
+--Host : DavideASUS running 64-bit major release (build 9200)
--Command : generate_target diligent_jstk_wrapper.bd
--Design : diligent_jstk_wrapper
--Purpose : IP block netlist
@@ -29,8 +29,6 @@ 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;
@@ -42,7 +40,9 @@ 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
+ SPI_M_0_io0_i : in STD_LOGIC;
+ usb_uart_txd : out STD_LOGIC;
+ usb_uart_rxd : in STD_LOGIC
);
end component diligent_jstk;
component IOBUF is
diff --git a/LAB3/design/lab_3/hdl/lab_3_wrapper.vhd b/LAB3/design/lab_3/hdl/lab_3_wrapper.vhd
index 1709770..726d18d 100644
--- a/LAB3/design/lab_3/hdl/lab_3_wrapper.vhd
+++ b/LAB3/design/lab_3/hdl/lab_3_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 : Mon May 12 14:54:08 2025
---Host : Davide-Samsung running 64-bit major release (build 9200)
+--Date : Fri May 30 14:28:09 2025
+--Host : DavideASUS running 64-bit major release (build 9200)
--Command : generate_target lab_3_wrapper.bd
--Design : lab_3_wrapper
--Purpose : IP block netlist
diff --git a/LAB3/design/lab_3/lab_3.bd b/LAB3/design/lab_3/lab_3.bd
index a2d9475..9863b6c 100644
--- a/LAB3/design/lab_3/lab_3.bd
+++ b/LAB3/design/lab_3/lab_3.bd
@@ -13,21 +13,21 @@
"clk_wiz_0": "",
"proc_sys_reset_0": "",
"proc_sys_reset_1": "",
- "digilent_jstk2_0": "",
"edge_detector_toggle_0": "",
"edge_detector_toggle_1": "",
"debouncer_0": "",
"axis_broadcaster_0": "",
- "moving_average_filte_0": "",
+ "axi4stream_spi_master_0": "",
+ "axis_dual_i2s_0": "",
"volume_controller_0": "",
- "LFO_0": "",
"balance_controller_0": "",
"effect_selector_0": "",
- "led_controller_0": "",
"led_level_controller_0": "",
+ "led_controller_0": "",
"mute_controller_0": "",
- "axi4stream_spi_master_0": "",
- "axis_dual_i2s_0": ""
+ "moving_average_filte_0": "",
+ "LFO_0": "",
+ "digilent_jstk2_0": ""
},
"interface_ports": {
"SPI_M_0": {
@@ -178,221 +178,6 @@
"xci_path": "ip\\lab_3_proc_sys_reset_1_0\\lab_3_proc_sys_reset_1_0.xci",
"inst_hier_path": "proc_sys_reset_1"
},
- "digilent_jstk2_0": {
- "vlnv": "xilinx.com:module_ref:digilent_jstk2:1.0",
- "xci_name": "lab_3_digilent_jstk2_0_0",
- "xci_path": "ip\\lab_3_digilent_jstk2_0_0\\lab_3_digilent_jstk2_0_0.xci",
- "inst_hier_path": "digilent_jstk2_0",
- "parameters": {
- "CLKFREQ": {
- "value": "215000000"
- }
- },
- "reference_info": {
- "ref_type": "hdl",
- "ref_name": "digilent_jstk2",
- "boundary_crc": "0x0"
- },
- "interface_ports": {
- "m_axis": {
- "mode": "Master",
- "vlnv": "xilinx.com:interface:axis_rtl:1.0",
- "parameters": {
- "TDATA_NUM_BYTES": {
- "value": "1",
- "value_src": "constant"
- },
- "TDEST_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TID_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TUSER_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TREADY": {
- "value": "1",
- "value_src": "constant"
- },
- "HAS_TSTRB": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TKEEP": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TLAST": {
- "value": "0",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- },
- "port_maps": {
- "TDATA": {
- "physical_name": "m_axis_tdata",
- "direction": "O",
- "left": "7",
- "right": "0"
- },
- "TVALID": {
- "physical_name": "m_axis_tvalid",
- "direction": "O"
- },
- "TREADY": {
- "physical_name": "m_axis_tready",
- "direction": "I"
- }
- }
- },
- "s_axis": {
- "mode": "Slave",
- "vlnv": "xilinx.com:interface:axis_rtl:1.0",
- "parameters": {
- "TDATA_NUM_BYTES": {
- "value": "1",
- "value_src": "constant"
- },
- "TDEST_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TID_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TUSER_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TREADY": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TSTRB": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TKEEP": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TLAST": {
- "value": "0",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- },
- "port_maps": {
- "TDATA": {
- "physical_name": "s_axis_tdata",
- "direction": "I",
- "left": "7",
- "right": "0"
- },
- "TVALID": {
- "physical_name": "s_axis_tvalid",
- "direction": "I"
- }
- }
- }
- },
- "ports": {
- "aclk": {
- "type": "clk",
- "direction": "I",
- "parameters": {
- "ASSOCIATED_BUSIF": {
- "value": "m_axis:s_axis",
- "value_src": "constant"
- },
- "ASSOCIATED_RESET": {
- "value": "aresetn",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- }
- },
- "aresetn": {
- "type": "rst",
- "direction": "I",
- "parameters": {
- "POLARITY": {
- "value": "ACTIVE_LOW",
- "value_src": "constant"
- }
- }
- },
- "jstk_x": {
- "direction": "O",
- "left": "9",
- "right": "0"
- },
- "jstk_y": {
- "direction": "O",
- "left": "9",
- "right": "0"
- },
- "btn_jstk": {
- "direction": "O"
- },
- "btn_trigger": {
- "direction": "O"
- },
- "led_r": {
- "direction": "I",
- "left": "7",
- "right": "0"
- },
- "led_g": {
- "direction": "I",
- "left": "7",
- "right": "0"
- },
- "led_b": {
- "direction": "I",
- "left": "7",
- "right": "0"
- }
- }
- },
"edge_detector_toggle_0": {
"vlnv": "xilinx.com:module_ref:edge_detector_toggle:1.0",
"xci_name": "lab_3_edge_detector_toggle_0_0",
@@ -502,7 +287,7 @@
"inst_hier_path": "debouncer_0",
"parameters": {
"CLOCK_FREQ": {
- "value": "200000000"
+ "value": "100000000"
}
},
"reference_info": {
@@ -557,200 +342,26 @@
"xci_path": "ip\\lab_3_axis_broadcaster_0_0\\lab_3_axis_broadcaster_0_0.xci",
"inst_hier_path": "axis_broadcaster_0"
},
- "moving_average_filte_0": {
- "vlnv": "xilinx.com:module_ref:moving_average_filter_en:1.0",
- "xci_name": "lab_3_moving_average_filte_0_0",
- "xci_path": "ip\\lab_3_moving_average_filte_0_0\\lab_3_moving_average_filte_0_0.xci",
- "inst_hier_path": "moving_average_filte_0",
- "reference_info": {
- "ref_type": "hdl",
- "ref_name": "moving_average_filter_en",
- "boundary_crc": "0x0"
- },
- "interface_ports": {
- "m_axis": {
- "mode": "Master",
- "vlnv": "xilinx.com:interface:axis_rtl:1.0",
- "parameters": {
- "TDATA_NUM_BYTES": {
- "value": "3",
- "value_src": "auto"
- },
- "TDEST_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TID_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TUSER_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TREADY": {
- "value": "1",
- "value_src": "constant"
- },
- "HAS_TSTRB": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TKEEP": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TLAST": {
- "value": "1",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- },
- "port_maps": {
- "TDATA": {
- "physical_name": "m_axis_tdata",
- "direction": "O",
- "left": "23",
- "right": "0"
- },
- "TLAST": {
- "physical_name": "m_axis_tlast",
- "direction": "O"
- },
- "TVALID": {
- "physical_name": "m_axis_tvalid",
- "direction": "O"
- },
- "TREADY": {
- "physical_name": "m_axis_tready",
- "direction": "I"
- }
- }
+ "axi4stream_spi_master_0": {
+ "vlnv": "DigiLAB:ip:axi4stream_spi_master:1.0",
+ "xci_name": "lab_3_axi4stream_spi_master_0_0",
+ "xci_path": "ip\\lab_3_axi4stream_spi_master_0_0\\lab_3_axi4stream_spi_master_0_0.xci",
+ "inst_hier_path": "axi4stream_spi_master_0",
+ "parameters": {
+ "c_clkfreq": {
+ "value": "100000000"
},
- "s_axis": {
- "mode": "Slave",
- "vlnv": "xilinx.com:interface:axis_rtl:1.0",
- "parameters": {
- "TDATA_NUM_BYTES": {
- "value": "3",
- "value_src": "auto"
- },
- "TDEST_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TID_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TUSER_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TREADY": {
- "value": "1",
- "value_src": "constant"
- },
- "HAS_TSTRB": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TKEEP": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TLAST": {
- "value": "1",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- },
- "port_maps": {
- "TDATA": {
- "physical_name": "s_axis_tdata",
- "direction": "I",
- "left": "23",
- "right": "0"
- },
- "TLAST": {
- "physical_name": "s_axis_tlast",
- "direction": "I"
- },
- "TVALID": {
- "physical_name": "s_axis_tvalid",
- "direction": "I"
- },
- "TREADY": {
- "physical_name": "s_axis_tready",
- "direction": "O"
- }
- }
- }
- },
- "ports": {
- "aclk": {
- "type": "clk",
- "direction": "I",
- "parameters": {
- "ASSOCIATED_BUSIF": {
- "value": "m_axis:s_axis",
- "value_src": "constant"
- },
- "ASSOCIATED_RESET": {
- "value": "aresetn",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- }
- },
- "aresetn": {
- "type": "rst",
- "direction": "I",
- "parameters": {
- "POLARITY": {
- "value": "ACTIVE_LOW",
- "value_src": "constant"
- }
- }
- },
- "enable_filter": {
- "direction": "I"
+ "c_sclkfreq": {
+ "value": "5000"
}
}
},
+ "axis_dual_i2s_0": {
+ "vlnv": "DigiLAB:ip:axis_dual_i2s:1.0",
+ "xci_name": "lab_3_axis_dual_i2s_0_0",
+ "xci_path": "ip\\lab_3_axis_dual_i2s_0_0\\lab_3_axis_dual_i2s_0_0.xci",
+ "inst_hier_path": "axis_dual_i2s_0"
+ },
"volume_controller_0": {
"vlnv": "xilinx.com:module_ref:volume_controller:1.0",
"xci_name": "lab_3_volume_controller_0_0",
@@ -952,210 +563,6 @@
}
}
},
- "LFO_0": {
- "vlnv": "xilinx.com:module_ref:LFO:1.0",
- "xci_name": "lab_3_LFO_0_0",
- "xci_path": "ip\\lab_3_LFO_0_0\\lab_3_LFO_0_0.xci",
- "inst_hier_path": "LFO_0",
- "parameters": {
- "CLK_PERIOD_NS": {
- "value": "10"
- }
- },
- "reference_info": {
- "ref_type": "hdl",
- "ref_name": "LFO",
- "boundary_crc": "0x0"
- },
- "interface_ports": {
- "m_axis": {
- "mode": "Master",
- "vlnv": "xilinx.com:interface:axis_rtl:1.0",
- "parameters": {
- "TDATA_NUM_BYTES": {
- "value": "3",
- "value_src": "auto"
- },
- "TDEST_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TID_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TUSER_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TREADY": {
- "value": "1",
- "value_src": "constant"
- },
- "HAS_TSTRB": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TKEEP": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TLAST": {
- "value": "1",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- },
- "port_maps": {
- "TDATA": {
- "physical_name": "m_axis_tdata",
- "direction": "O",
- "left": "23",
- "right": "0"
- },
- "TLAST": {
- "physical_name": "m_axis_tlast",
- "direction": "O"
- },
- "TVALID": {
- "physical_name": "m_axis_tvalid",
- "direction": "O"
- },
- "TREADY": {
- "physical_name": "m_axis_tready",
- "direction": "I"
- }
- }
- },
- "s_axis": {
- "mode": "Slave",
- "vlnv": "xilinx.com:interface:axis_rtl:1.0",
- "parameters": {
- "TDATA_NUM_BYTES": {
- "value": "3",
- "value_src": "auto"
- },
- "TDEST_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TID_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "TUSER_WIDTH": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TREADY": {
- "value": "1",
- "value_src": "constant"
- },
- "HAS_TSTRB": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TKEEP": {
- "value": "0",
- "value_src": "constant"
- },
- "HAS_TLAST": {
- "value": "1",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- },
- "port_maps": {
- "TDATA": {
- "physical_name": "s_axis_tdata",
- "direction": "I",
- "left": "23",
- "right": "0"
- },
- "TLAST": {
- "physical_name": "s_axis_tlast",
- "direction": "I"
- },
- "TVALID": {
- "physical_name": "s_axis_tvalid",
- "direction": "I"
- },
- "TREADY": {
- "physical_name": "s_axis_tready",
- "direction": "O"
- }
- }
- }
- },
- "ports": {
- "aclk": {
- "type": "clk",
- "direction": "I",
- "parameters": {
- "ASSOCIATED_BUSIF": {
- "value": "m_axis:s_axis",
- "value_src": "constant"
- },
- "ASSOCIATED_RESET": {
- "value": "aresetn",
- "value_src": "constant"
- },
- "FREQ_HZ": {
- "value": "100000000",
- "value_src": "ip_prop"
- },
- "PHASE": {
- "value": "0.0",
- "value_src": "ip_prop"
- },
- "CLK_DOMAIN": {
- "value": "/clk_wiz_0_clk_out1",
- "value_src": "ip_prop"
- }
- }
- },
- "aresetn": {
- "type": "rst",
- "direction": "I",
- "parameters": {
- "POLARITY": {
- "value": "ACTIVE_LOW",
- "value_src": "constant"
- }
- }
- },
- "lfo_period": {
- "direction": "I",
- "left": "9",
- "right": "0"
- },
- "lfo_enable": {
- "direction": "I"
- }
- }
- },
"balance_controller_0": {
"vlnv": "xilinx.com:module_ref:balance_controller:1.0",
"xci_name": "lab_3_balance_controller_0_0",
@@ -1425,40 +832,6 @@
}
}
},
- "led_controller_0": {
- "vlnv": "xilinx.com:module_ref:led_controller:1.0",
- "xci_name": "lab_3_led_controller_0_0",
- "xci_path": "ip\\lab_3_led_controller_0_0\\lab_3_led_controller_0_0.xci",
- "inst_hier_path": "led_controller_0",
- "reference_info": {
- "ref_type": "hdl",
- "ref_name": "led_controller",
- "boundary_crc": "0x0"
- },
- "ports": {
- "mute_enable": {
- "direction": "I"
- },
- "filter_enable": {
- "direction": "I"
- },
- "led_r": {
- "direction": "O",
- "left": "7",
- "right": "0"
- },
- "led_g": {
- "direction": "O",
- "left": "7",
- "right": "0"
- },
- "led_b": {
- "direction": "O",
- "left": "7",
- "right": "0"
- }
- }
- },
"led_level_controller_0": {
"vlnv": "xilinx.com:module_ref:led_level_controller:1.0",
"xci_name": "lab_3_led_level_controller_0_0",
@@ -1590,6 +963,40 @@
}
}
},
+ "led_controller_0": {
+ "vlnv": "xilinx.com:module_ref:led_controller:1.0",
+ "xci_name": "lab_3_led_controller_0_0",
+ "xci_path": "ip\\lab_3_led_controller_0_0\\lab_3_led_controller_0_0.xci",
+ "inst_hier_path": "led_controller_0",
+ "reference_info": {
+ "ref_type": "hdl",
+ "ref_name": "led_controller",
+ "boundary_crc": "0x0"
+ },
+ "ports": {
+ "mute_enable": {
+ "direction": "I"
+ },
+ "filter_enable": {
+ "direction": "I"
+ },
+ "led_r": {
+ "direction": "O",
+ "left": "7",
+ "right": "0"
+ },
+ "led_g": {
+ "direction": "O",
+ "left": "7",
+ "right": "0"
+ },
+ "led_b": {
+ "direction": "O",
+ "left": "7",
+ "right": "0"
+ }
+ }
+ },
"mute_controller_0": {
"vlnv": "xilinx.com:module_ref:mute_controller:1.0",
"xci_name": "lab_3_mute_controller_0_0",
@@ -1784,52 +1191,621 @@
}
}
},
- "axi4stream_spi_master_0": {
- "vlnv": "DigiLAB:ip:axi4stream_spi_master:1.0",
- "xci_name": "lab_3_axi4stream_spi_master_0_0",
- "xci_path": "ip\\lab_3_axi4stream_spi_master_0_0\\lab_3_axi4stream_spi_master_0_0.xci",
- "inst_hier_path": "axi4stream_spi_master_0",
- "parameters": {
- "c_clkfreq": {
- "value": "215000000"
+ "moving_average_filte_0": {
+ "vlnv": "xilinx.com:module_ref:moving_average_filter_en:1.0",
+ "xci_name": "lab_3_moving_average_filte_0_0",
+ "xci_path": "ip\\lab_3_moving_average_filte_0_0\\lab_3_moving_average_filte_0_0.xci",
+ "inst_hier_path": "moving_average_filte_0",
+ "reference_info": {
+ "ref_type": "hdl",
+ "ref_name": "moving_average_filter_en",
+ "boundary_crc": "0x0"
+ },
+ "interface_ports": {
+ "m_axis": {
+ "mode": "Master",
+ "vlnv": "xilinx.com:interface:axis_rtl:1.0",
+ "parameters": {
+ "TDATA_NUM_BYTES": {
+ "value": "3",
+ "value_src": "auto"
+ },
+ "TDEST_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TID_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TUSER_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TREADY": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "HAS_TSTRB": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TKEEP": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TLAST": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ },
+ "port_maps": {
+ "TDATA": {
+ "physical_name": "m_axis_tdata",
+ "direction": "O",
+ "left": "23",
+ "right": "0"
+ },
+ "TLAST": {
+ "physical_name": "m_axis_tlast",
+ "direction": "O"
+ },
+ "TVALID": {
+ "physical_name": "m_axis_tvalid",
+ "direction": "O"
+ },
+ "TREADY": {
+ "physical_name": "m_axis_tready",
+ "direction": "I"
+ }
+ }
},
- "c_sclkfreq": {
- "value": "5000"
+ "s_axis": {
+ "mode": "Slave",
+ "vlnv": "xilinx.com:interface:axis_rtl:1.0",
+ "parameters": {
+ "TDATA_NUM_BYTES": {
+ "value": "3",
+ "value_src": "auto"
+ },
+ "TDEST_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TID_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TUSER_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TREADY": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "HAS_TSTRB": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TKEEP": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TLAST": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ },
+ "port_maps": {
+ "TDATA": {
+ "physical_name": "s_axis_tdata",
+ "direction": "I",
+ "left": "23",
+ "right": "0"
+ },
+ "TLAST": {
+ "physical_name": "s_axis_tlast",
+ "direction": "I"
+ },
+ "TVALID": {
+ "physical_name": "s_axis_tvalid",
+ "direction": "I"
+ },
+ "TREADY": {
+ "physical_name": "s_axis_tready",
+ "direction": "O"
+ }
+ }
+ }
+ },
+ "ports": {
+ "aclk": {
+ "type": "clk",
+ "direction": "I",
+ "parameters": {
+ "ASSOCIATED_BUSIF": {
+ "value": "m_axis:s_axis",
+ "value_src": "constant"
+ },
+ "ASSOCIATED_RESET": {
+ "value": "aresetn",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ }
+ },
+ "aresetn": {
+ "type": "rst",
+ "direction": "I",
+ "parameters": {
+ "POLARITY": {
+ "value": "ACTIVE_LOW",
+ "value_src": "constant"
+ }
+ }
+ },
+ "enable_filter": {
+ "direction": "I"
}
}
},
- "axis_dual_i2s_0": {
- "vlnv": "DigiLAB:ip:axis_dual_i2s:1.0",
- "xci_name": "lab_3_axis_dual_i2s_0_0",
- "xci_path": "ip\\lab_3_axis_dual_i2s_0_0\\lab_3_axis_dual_i2s_0_0.xci",
- "inst_hier_path": "axis_dual_i2s_0"
+ "LFO_0": {
+ "vlnv": "xilinx.com:module_ref:LFO:1.0",
+ "xci_name": "lab_3_LFO_0_0",
+ "xci_path": "ip\\lab_3_LFO_0_0\\lab_3_LFO_0_0.xci",
+ "inst_hier_path": "LFO_0",
+ "parameters": {
+ "CLK_PERIOD_NS": {
+ "value": "10"
+ }
+ },
+ "reference_info": {
+ "ref_type": "hdl",
+ "ref_name": "LFO",
+ "boundary_crc": "0x0"
+ },
+ "interface_ports": {
+ "m_axis": {
+ "mode": "Master",
+ "vlnv": "xilinx.com:interface:axis_rtl:1.0",
+ "parameters": {
+ "TDATA_NUM_BYTES": {
+ "value": "3",
+ "value_src": "auto"
+ },
+ "TDEST_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TID_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TUSER_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TREADY": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "HAS_TSTRB": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TKEEP": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TLAST": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ },
+ "port_maps": {
+ "TDATA": {
+ "physical_name": "m_axis_tdata",
+ "direction": "O",
+ "left": "23",
+ "right": "0"
+ },
+ "TLAST": {
+ "physical_name": "m_axis_tlast",
+ "direction": "O"
+ },
+ "TVALID": {
+ "physical_name": "m_axis_tvalid",
+ "direction": "O"
+ },
+ "TREADY": {
+ "physical_name": "m_axis_tready",
+ "direction": "I"
+ }
+ }
+ },
+ "s_axis": {
+ "mode": "Slave",
+ "vlnv": "xilinx.com:interface:axis_rtl:1.0",
+ "parameters": {
+ "TDATA_NUM_BYTES": {
+ "value": "3",
+ "value_src": "auto"
+ },
+ "TDEST_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TID_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TUSER_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TREADY": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "HAS_TSTRB": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TKEEP": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TLAST": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ },
+ "port_maps": {
+ "TDATA": {
+ "physical_name": "s_axis_tdata",
+ "direction": "I",
+ "left": "23",
+ "right": "0"
+ },
+ "TLAST": {
+ "physical_name": "s_axis_tlast",
+ "direction": "I"
+ },
+ "TVALID": {
+ "physical_name": "s_axis_tvalid",
+ "direction": "I"
+ },
+ "TREADY": {
+ "physical_name": "s_axis_tready",
+ "direction": "O"
+ }
+ }
+ }
+ },
+ "ports": {
+ "aclk": {
+ "type": "clk",
+ "direction": "I",
+ "parameters": {
+ "ASSOCIATED_BUSIF": {
+ "value": "m_axis:s_axis",
+ "value_src": "constant"
+ },
+ "ASSOCIATED_RESET": {
+ "value": "aresetn",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ }
+ },
+ "aresetn": {
+ "type": "rst",
+ "direction": "I",
+ "parameters": {
+ "POLARITY": {
+ "value": "ACTIVE_LOW",
+ "value_src": "constant"
+ }
+ }
+ },
+ "lfo_period": {
+ "direction": "I",
+ "left": "9",
+ "right": "0"
+ },
+ "lfo_enable": {
+ "direction": "I"
+ }
+ }
+ },
+ "digilent_jstk2_0": {
+ "vlnv": "xilinx.com:module_ref:digilent_jstk2:1.0",
+ "xci_name": "lab_3_digilent_jstk2_0_0",
+ "xci_path": "ip\\lab_3_digilent_jstk2_0_0\\lab_3_digilent_jstk2_0_0.xci",
+ "inst_hier_path": "digilent_jstk2_0",
+ "parameters": {
+ "CLKFREQ": {
+ "value": "215000000"
+ }
+ },
+ "reference_info": {
+ "ref_type": "hdl",
+ "ref_name": "digilent_jstk2",
+ "boundary_crc": "0x0"
+ },
+ "interface_ports": {
+ "m_axis": {
+ "mode": "Master",
+ "vlnv": "xilinx.com:interface:axis_rtl:1.0",
+ "parameters": {
+ "TDATA_NUM_BYTES": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "TDEST_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TID_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TUSER_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TREADY": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "HAS_TSTRB": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TKEEP": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TLAST": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ },
+ "port_maps": {
+ "TDATA": {
+ "physical_name": "m_axis_tdata",
+ "direction": "O",
+ "left": "7",
+ "right": "0"
+ },
+ "TVALID": {
+ "physical_name": "m_axis_tvalid",
+ "direction": "O"
+ },
+ "TREADY": {
+ "physical_name": "m_axis_tready",
+ "direction": "I"
+ }
+ }
+ },
+ "s_axis": {
+ "mode": "Slave",
+ "vlnv": "xilinx.com:interface:axis_rtl:1.0",
+ "parameters": {
+ "TDATA_NUM_BYTES": {
+ "value": "1",
+ "value_src": "constant"
+ },
+ "TDEST_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TID_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "TUSER_WIDTH": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TREADY": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TSTRB": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TKEEP": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "HAS_TLAST": {
+ "value": "0",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ },
+ "port_maps": {
+ "TDATA": {
+ "physical_name": "s_axis_tdata",
+ "direction": "I",
+ "left": "7",
+ "right": "0"
+ },
+ "TVALID": {
+ "physical_name": "s_axis_tvalid",
+ "direction": "I"
+ }
+ }
+ }
+ },
+ "ports": {
+ "aclk": {
+ "type": "clk",
+ "direction": "I",
+ "parameters": {
+ "ASSOCIATED_BUSIF": {
+ "value": "m_axis:s_axis",
+ "value_src": "constant"
+ },
+ "ASSOCIATED_RESET": {
+ "value": "aresetn",
+ "value_src": "constant"
+ },
+ "FREQ_HZ": {
+ "value": "100000000",
+ "value_src": "ip_prop"
+ },
+ "PHASE": {
+ "value": "0.0",
+ "value_src": "ip_prop"
+ },
+ "CLK_DOMAIN": {
+ "value": "/clk_wiz_0_clk_out1",
+ "value_src": "ip_prop"
+ }
+ }
+ },
+ "aresetn": {
+ "type": "rst",
+ "direction": "I",
+ "parameters": {
+ "POLARITY": {
+ "value": "ACTIVE_LOW",
+ "value_src": "constant"
+ }
+ }
+ },
+ "jstk_x": {
+ "direction": "O",
+ "left": "9",
+ "right": "0"
+ },
+ "jstk_y": {
+ "direction": "O",
+ "left": "9",
+ "right": "0"
+ },
+ "btn_jstk": {
+ "direction": "O"
+ },
+ "btn_trigger": {
+ "direction": "O"
+ },
+ "led_r": {
+ "direction": "I",
+ "left": "7",
+ "right": "0"
+ },
+ "led_g": {
+ "direction": "I",
+ "left": "7",
+ "right": "0"
+ },
+ "led_b": {
+ "direction": "I",
+ "left": "7",
+ "right": "0"
+ }
+ }
}
},
"interface_nets": {
- "axis_dual_i2s_0_m_axis": {
- "interface_ports": [
- "axis_dual_i2s_0/m_axis",
- "moving_average_filte_0/s_axis"
- ]
- },
- "LFO_0_m_axis": {
- "interface_ports": [
- "LFO_0/m_axis",
- "mute_controller_0/s_axis"
- ]
- },
- "digilent_jstk2_0_m_axis": {
- "interface_ports": [
- "digilent_jstk2_0/m_axis",
- "axi4stream_spi_master_0/S_AXIS"
- ]
- },
- "axi4stream_spi_master_0_SPI_M": {
- "interface_ports": [
- "SPI_M_0",
- "axi4stream_spi_master_0/SPI_M"
- ]
- },
"volume_controller_0_m_axis": {
"interface_ports": [
"volume_controller_0/m_axis",
@@ -1842,10 +1818,34 @@
"axis_broadcaster_0/S_AXIS"
]
},
- "axis_broadcaster_0_M01_AXIS": {
+ "moving_average_filte_0_m_axis": {
"interface_ports": [
- "axis_broadcaster_0/M01_AXIS",
- "led_level_controller_0/s_axis"
+ "balance_controller_0/s_axis",
+ "moving_average_filte_0/m_axis"
+ ]
+ },
+ "axis_dual_i2s_0_m_axis": {
+ "interface_ports": [
+ "axis_dual_i2s_0/m_axis",
+ "moving_average_filte_0/s_axis"
+ ]
+ },
+ "digilent_jstk2_0_m_axis": {
+ "interface_ports": [
+ "digilent_jstk2_0/m_axis",
+ "axi4stream_spi_master_0/S_AXIS"
+ ]
+ },
+ "LFO_0_m_axis": {
+ "interface_ports": [
+ "LFO_0/m_axis",
+ "mute_controller_0/s_axis"
+ ]
+ },
+ "axi4stream_spi_master_0_SPI_M": {
+ "interface_ports": [
+ "SPI_M_0",
+ "axi4stream_spi_master_0/SPI_M"
]
},
"axis_broadcaster_0_M00_AXIS": {
@@ -1854,18 +1854,18 @@
"axis_dual_i2s_0/s_axis"
]
},
+ "axis_broadcaster_0_M01_AXIS": {
+ "interface_ports": [
+ "axis_broadcaster_0/M01_AXIS",
+ "led_level_controller_0/s_axis"
+ ]
+ },
"balance_controller_0_m_axis": {
"interface_ports": [
"balance_controller_0/m_axis",
"volume_controller_0/s_axis"
]
},
- "moving_average_filte_0_m_axis": {
- "interface_ports": [
- "balance_controller_0/s_axis",
- "moving_average_filte_0/m_axis"
- ]
- },
"axi4stream_spi_master_0_M_AXIS": {
"interface_ports": [
"axi4stream_spi_master_0/M_AXIS",
@@ -1884,20 +1884,20 @@
"ports": [
"clk_wiz_0/clk_out1",
"proc_sys_reset_0/slowest_sync_clk",
- "digilent_jstk2_0/aclk",
"edge_detector_toggle_0/clk",
"edge_detector_toggle_1/clk",
"debouncer_0/clk",
"axis_broadcaster_0/aclk",
- "moving_average_filte_0/aclk",
+ "axi4stream_spi_master_0/aclk",
+ "axis_dual_i2s_0/aclk",
"volume_controller_0/aclk",
- "LFO_0/aclk",
"balance_controller_0/aclk",
"effect_selector_0/aclk",
"led_level_controller_0/aclk",
"mute_controller_0/aclk",
- "axi4stream_spi_master_0/aclk",
- "axis_dual_i2s_0/aclk"
+ "moving_average_filte_0/aclk",
+ "LFO_0/aclk",
+ "digilent_jstk2_0/aclk"
]
},
"reset_1": {
@@ -1925,18 +1925,18 @@
"proc_sys_reset_0_peripheral_aresetn": {
"ports": [
"proc_sys_reset_0/peripheral_aresetn",
- "digilent_jstk2_0/aresetn",
"debouncer_0/reset",
"axis_broadcaster_0/aresetn",
- "moving_average_filte_0/aresetn",
+ "axi4stream_spi_master_0/aresetn",
+ "axis_dual_i2s_0/aresetn",
"volume_controller_0/aresetn",
- "LFO_0/aresetn",
"balance_controller_0/aresetn",
"effect_selector_0/aresetn",
"led_level_controller_0/aresetn",
"mute_controller_0/aresetn",
- "axi4stream_spi_master_0/aresetn",
- "axis_dual_i2s_0/aresetn"
+ "moving_average_filte_0/aresetn",
+ "LFO_0/aresetn",
+ "digilent_jstk2_0/aresetn"
]
},
"proc_sys_reset_1_peripheral_aresetn": {
@@ -2015,8 +2015,8 @@
"edge_detector_toggle_1_output_signal": {
"ports": [
"edge_detector_toggle_1/output_signal",
- "moving_average_filte_0/enable_filter",
- "led_controller_0/filter_enable"
+ "led_controller_0/filter_enable",
+ "moving_average_filte_0/enable_filter"
]
},
"led_controller_0_led_r": {
@@ -2086,17 +2086,17 @@
"debouncer_0/input_signal"
]
},
- "led_level_controller_0_led": {
- "ports": [
- "led_level_controller_0/led",
- "LED"
- ]
- },
"debouncer_0_debounced": {
"ports": [
"debouncer_0/debounced",
"effect_selector_0/effect"
]
+ },
+ "led_level_controller_0_led": {
+ "ports": [
+ "led_level_controller_0/led",
+ "LED"
+ ]
}
}
}
diff --git a/LAB3/design/lab_3/lab_3.bda b/LAB3/design/lab_3/lab_3.bda
index 3fa1797..c595aff 100644
--- a/LAB3/design/lab_3/lab_3.bda
+++ b/LAB3/design/lab_3/lab_3.bda
@@ -26,17 +26,17 @@
VR
+ lab_3
+ BC
+
+
active
2
PM
-
- lab_3
- BC
-
-
+
-
+
diff --git a/LAB3/sim/ReadMe.md b/LAB3/sim/ReadMe.md
deleted file mode 100644
index 0f8aee3..0000000
--- a/LAB3/sim/ReadMe.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Placeholder
-
-This is a placeholder.
\ No newline at end of file
diff --git a/LAB3/sim/tb_LFO.vhd b/LAB3/sim/tb_LFO.vhd
new file mode 100644
index 0000000..50fe8e1
--- /dev/null
+++ b/LAB3/sim/tb_LFO.vhd
@@ -0,0 +1,146 @@
+-- filepath: c:\DESD\LAB3\sim\tb_LFO.vhd
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY tb_LFO IS
+END tb_LFO;
+
+ARCHITECTURE sim OF tb_LFO IS
+
+ CONSTANT CHANNEL_LENGHT : INTEGER := 24;
+ CONSTANT JOYSTICK_LENGHT : INTEGER := 10;
+ CONSTANT TRIANGULAR_COUNTER_LENGHT: INTEGER := 10;
+ CONSTANT CLK_PERIOD_NS : INTEGER := 10;
+
+ SIGNAL aclk : STD_LOGIC := '0';
+ SIGNAL aresetn : STD_LOGIC := '0';
+
+ SIGNAL lfo_period : STD_LOGIC_VECTOR(JOYSTICK_LENGHT-1 DOWNTO 0) := (OTHERS => '0');
+ SIGNAL lfo_enable : STD_LOGIC := '0';
+
+ SIGNAL s_axis_tvalid : STD_LOGIC := '0';
+ SIGNAL s_axis_tdata : STD_LOGIC_VECTOR(CHANNEL_LENGHT-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(CHANNEL_LENGHT-1 DOWNTO 0);
+ SIGNAL m_axis_tlast : STD_LOGIC;
+ SIGNAL m_axis_tready : STD_LOGIC := '1';
+
+ -- DUT
+ COMPONENT LFO
+ GENERIC (
+ CHANNEL_LENGHT : INTEGER := 24;
+ JOYSTICK_LENGHT : INTEGER := 10;
+ CLK_PERIOD_NS : INTEGER := 10;
+ TRIANGULAR_COUNTER_LENGHT : INTEGER := 10
+ );
+ 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 COMPONENT;
+
+BEGIN
+
+ -- Clock generation
+ clk_proc : PROCESS
+ BEGIN
+ aclk <= '0';
+ WAIT FOR 5 ns;
+ aclk <= '1';
+ WAIT FOR 5 ns;
+ END PROCESS;
+
+ -- DUT instantiation
+ dut: LFO
+ GENERIC MAP (
+ CHANNEL_LENGHT => CHANNEL_LENGHT,
+ JOYSTICK_LENGHT => JOYSTICK_LENGHT,
+ CLK_PERIOD_NS => CLK_PERIOD_NS,
+ TRIANGULAR_COUNTER_LENGHT => TRIANGULAR_COUNTER_LENGHT
+ )
+ PORT MAP (
+ aclk => aclk,
+ aresetn => aresetn,
+ lfo_period => lfo_period,
+ lfo_enable => lfo_enable,
+ 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 => m_axis_tvalid,
+ m_axis_tdata => m_axis_tdata,
+ m_axis_tlast => m_axis_tlast,
+ m_axis_tready => m_axis_tready
+ );
+
+ -- Stimulus process
+ stim_proc : PROCESS
+ VARIABLE data_cnt : INTEGER := 0;
+ VARIABLE lr_flag : STD_LOGIC := '0'; -- '0' = SX, '1' = DX
+ BEGIN
+ -- Reset
+ aresetn <= '0';
+ WAIT FOR 20 ns;
+ aresetn <= '1';
+ WAIT FOR 10 ns;
+
+ -- Imposta parametri iniziali
+ lfo_enable <= '1';
+ lfo_period <= std_logic_vector(to_unsigned(1023, JOYSTICK_LENGHT));
+
+ WHILE TRUE LOOP
+ -- Prepara il dato
+ IF lr_flag = '0' THEN
+ -- SX: aggiungi +100
+ s_axis_tdata <= std_logic_vector(to_signed(data_cnt + 100, CHANNEL_LENGHT));
+ s_axis_tlast <= '0';
+ ELSE
+ -- DX: valore normale
+ s_axis_tdata <= std_logic_vector(to_signed(data_cnt, CHANNEL_LENGHT));
+ s_axis_tlast <= '1';
+ END IF;
+ s_axis_tvalid <= '1';
+
+ -- Attendi handshake
+ WAIT UNTIL rising_edge(aclk);
+ WHILE s_axis_tready = '0' LOOP
+ WAIT UNTIL rising_edge(aclk);
+ END LOOP;
+
+ -- Dopo handshake, aggiorna flag/counter
+ IF lr_flag = '0' THEN
+ lr_flag := '1'; -- prossimo sarà DX
+ ELSE
+ lr_flag := '0'; -- prossimo sarà SX
+ data_cnt := data_cnt + 1; -- passa al prossimo campione solo dopo DX
+ END IF;
+ END LOOP;
+ END PROCESS;
+
+ -- Simula backpressure abbassando m_axis_tready ogni tanto
+ backpressure_proc : PROCESS
+ BEGIN
+ WAIT FOR 200 ns;
+ WAIT UNTIL rising_edge(aclk);
+ m_axis_tready <= '0';
+ WAIT FOR 500 ns;
+ WAIT UNTIL rising_edge(aclk);
+ m_axis_tready <= '1';
+ WAIT;
+ END PROCESS;
+
+END sim;
\ No newline at end of file
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/sim/tb_digilent_jstk2.vhd b/LAB3/sim/tb_digilent_jstk2.vhd
new file mode 100644
index 0000000..fde276e
--- /dev/null
+++ b/LAB3/sim/tb_digilent_jstk2.vhd
@@ -0,0 +1,160 @@
+----------------------------------------------------------------------------------
+-- Company:
+-- Engineer:
+--
+-- Create Date: 05/13/2025
+-- Design Name:
+-- Module Name: tb_digilent_jstk2 - sim
+-- Project Name:
+-- Target Devices:
+-- Tool Versions:
+-- Description: Testbench for digilent_jstk2, sends data only after CMDSETLEDRGB is received
+--
+-- Dependencies:
+--
+-- Revision:
+-- Revision 0.01 - File Created
+-- Additional Comments:
+--
+----------------------------------------------------------------------------------
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY tb_digilent_jstk2 IS
+END tb_digilent_jstk2;
+
+ARCHITECTURE sim OF tb_digilent_jstk2 IS
+
+ -- Testbench constants
+ CONSTANT CLKFREQ : INTEGER := 100_000_000;
+ CONSTANT DELAY_US : INTEGER := 25;
+ CONSTANT SPI_SCLKFREQ : INTEGER := 5_000;
+ CONSTANT CMDSETLEDRGB : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"84";
+
+ -- Component declaration for digilent_jstk2
+ COMPONENT digilent_jstk2 IS
+ GENERIC (
+ DELAY_US : INTEGER;
+ CLKFREQ : INTEGER;
+ SPI_SCLKFREQ : INTEGER
+ );
+ 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);
+ 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_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 COMPONENT;
+
+ -- Signals for DUT
+ SIGNAL aclk : STD_LOGIC := '0';
+ SIGNAL aresetn : STD_LOGIC := '0';
+ SIGNAL m_axis_tvalid : STD_LOGIC;
+ SIGNAL m_axis_tdata : STD_LOGIC_VECTOR(7 DOWNTO 0);
+ SIGNAL m_axis_tready : STD_LOGIC := '1'; -- Always ready in TB
+ SIGNAL s_axis_tvalid : STD_LOGIC := '0';
+ SIGNAL s_axis_tdata : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '0');
+ SIGNAL jstk_x : STD_LOGIC_VECTOR(9 DOWNTO 0);
+ SIGNAL jstk_y : STD_LOGIC_VECTOR(9 DOWNTO 0);
+ SIGNAL btn_jstk : STD_LOGIC;
+ SIGNAL btn_trigger : STD_LOGIC;
+ SIGNAL led_r : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"AA";
+ SIGNAL led_g : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"55";
+ SIGNAL led_b : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"FF";
+
+ -- Stimulus memory for SPI responses (simulate JSTK2 module)
+ TYPE spi_mem_type IS ARRAY(0 TO 4) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
+ SIGNAL spi_mem : spi_mem_type := (
+ 0 => x"34", -- JSTK_X_LOW
+ 1 => x"02", -- JSTK_X_HIGH (2 LSBs used)
+ 2 => x"56", -- JSTK_Y_LOW
+ 3 => x"01", -- JSTK_Y_HIGH (2 LSBs used)
+ 4 => "00000011" -- BUTTONS: btn_jstk='1', btn_trigger='1'
+ );
+
+BEGIN
+
+ -- Clock generation
+ aclk <= NOT aclk AFTER 5 ns;
+
+ -- DUT instantiation
+ uut : digilent_jstk2
+ GENERIC MAP(
+ DELAY_US => DELAY_US,
+ CLKFREQ => CLKFREQ,
+ SPI_SCLKFREQ => SPI_SCLKFREQ
+ )
+ PORT MAP(
+ aclk => aclk,
+ aresetn => aresetn,
+ m_axis_tvalid => m_axis_tvalid,
+ m_axis_tdata => m_axis_tdata,
+ m_axis_tready => m_axis_tready,
+ s_axis_tvalid => s_axis_tvalid,
+ s_axis_tdata => s_axis_tdata,
+ jstk_x => jstk_x,
+ jstk_y => jstk_y,
+ btn_jstk => btn_jstk,
+ btn_trigger => btn_trigger,
+ led_r => led_r,
+ led_g => led_g,
+ led_b => led_b
+ );
+
+ -- Stimulus process
+ stimulus : PROCESS
+ VARIABLE send_data : BOOLEAN := FALSE;
+ VARIABLE mem_idx : INTEGER := 0;
+ BEGIN
+ -- Reset
+ aresetn <= '0';
+ WAIT FOR 20 ns;
+ aresetn <= '1';
+ WAIT UNTIL rising_edge(aclk);
+
+ -- Wait for the DUT to start sending SPI packets
+ WAIT FOR 1000 ns;
+
+ -- Main loop: wait for CMDSETLEDRGB, then send mem bytes for each byte received
+ WHILE TRUE LOOP
+ WAIT UNTIL rising_edge(aclk);
+
+ -- Default: s_axis_tvalid low unless sending
+ s_axis_tvalid <= '0';
+
+ IF m_axis_tvalid = '1' THEN
+ IF m_axis_tdata = CMDSETLEDRGB THEN
+ send_data := TRUE;
+ mem_idx := 0;
+ END IF;
+
+ IF send_data AND mem_idx <= 4 THEN
+ -- Present data for one cycle when master is ready
+ s_axis_tdata <= spi_mem(mem_idx);
+ s_axis_tvalid <= '1';
+ WAIT UNTIL rising_edge(aclk); -- handshake
+ s_axis_tvalid <= '0';
+ mem_idx := mem_idx + 1;
+ -- Simula il tempo di risposta reale del JSTK2 (1,6 ms per byte)
+ WAIT FOR 1600 us;
+ IF mem_idx > 4 THEN
+ send_data := FALSE;
+ END IF;
+ END IF;
+ END IF;
+ END LOOP;
+ END PROCESS;
+
+END sim;
\ No newline at end of file
diff --git a/LAB3/sim/tb_moving_average.vhd b/LAB3/sim/tb_moving_average.vhd
new file mode 100644
index 0000000..d8a0bd2
--- /dev/null
+++ b/LAB3/sim/tb_moving_average.vhd
@@ -0,0 +1,142 @@
+-- filepath: c:\DESD\LAB3\sim\tb_moving_average.vhd
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY tb_moving_average IS
+END tb_moving_average;
+
+ARCHITECTURE sim OF tb_moving_average IS
+
+ CONSTANT TDATA_WIDTH : INTEGER := 24;
+ CONSTANT FILTER_ORDER_PWR : INTEGER := 5;
+
+ 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 enable_filter : STD_LOGIC := '0';
+
+ -- DUT
+ COMPONENT moving_average_filter_en
+ 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;
+ enable_filter : IN STD_LOGIC
+ );
+ END COMPONENT;
+
+BEGIN
+
+ -- Clock generation
+ clk_proc : PROCESS
+ BEGIN
+ aclk <= '0';
+ WAIT FOR 5 ns;
+ aclk <= '1';
+ WAIT FOR 5 ns;
+ END PROCESS;
+
+ -- DUT instantiation
+ dut: moving_average_filter_en
+ GENERIC MAP (
+ FILTER_ORDER_POWER => FILTER_ORDER_PWR,
+ TDATA_WIDTH => TDATA_WIDTH
+ )
+ 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 => m_axis_tvalid,
+ m_axis_tdata => m_axis_tdata,
+ m_axis_tlast => m_axis_tlast,
+ m_axis_tready => m_axis_tready,
+ enable_filter => enable_filter
+ );
+
+ -- Stimulus process
+ stim_proc : PROCESS
+ BEGIN
+ -- Reset
+ aresetn <= '0';
+ WAIT FOR 20 ns;
+ aresetn <= '1';
+ WAIT FOR 10 ns;
+
+ -- Test All Pass (enable_filter = '0')
+ enable_filter <= '0';
+ FOR i IN 0 TO 7 LOOP
+ -- SX sample
+ s_axis_tdata <= std_logic_vector(to_signed(i*100, TDATA_WIDTH));
+ s_axis_tvalid <= '1';
+ s_axis_tlast <= '0';
+ WAIT UNTIL rising_edge(aclk);
+ WHILE s_axis_tready /= '1' LOOP
+ WAIT UNTIL rising_edge(aclk);
+ END LOOP;
+ s_axis_tvalid <= '0';
+
+ -- DX sample (tlast high)
+ s_axis_tdata <= std_logic_vector(to_signed(i*100+50, TDATA_WIDTH));
+ s_axis_tvalid <= '1';
+ s_axis_tlast <= '1';
+ WAIT UNTIL rising_edge(aclk);
+ WHILE s_axis_tready /= '1' LOOP
+ WAIT UNTIL rising_edge(aclk);
+ END LOOP;
+ s_axis_tvalid <= '0';
+ END LOOP;
+
+ -- Test Moving Average (enable_filter = '1')
+ enable_filter <= '1';
+ FOR i IN 0 TO 7 LOOP
+ -- SX sample
+ s_axis_tdata <= std_logic_vector(to_signed(i*100, TDATA_WIDTH));
+ s_axis_tvalid <= '1';
+ s_axis_tlast <= '0';
+ WAIT UNTIL rising_edge(aclk);
+ WHILE s_axis_tready /= '1' LOOP
+ WAIT UNTIL rising_edge(aclk);
+ END LOOP;
+ s_axis_tvalid <= '0';
+
+ -- DX sample (tlast high)
+ s_axis_tdata <= std_logic_vector(to_signed(i*100+50, TDATA_WIDTH));
+ s_axis_tvalid <= '1';
+ s_axis_tlast <= '1';
+ WAIT UNTIL rising_edge(aclk);
+ WHILE s_axis_tready /= '1' LOOP
+ WAIT UNTIL rising_edge(aclk);
+ END LOOP;
+ s_axis_tvalid <= '0';
+ END LOOP;
+
+ -- End simulation
+ WAIT FOR 50 ns;
+ END PROCESS;
+
+END sim;
\ No newline at end of file
diff --git a/LAB3/sim/tb_volume_multiplier.vhd b/LAB3/sim/tb_volume_multiplier.vhd
new file mode 100644
index 0000000..b91b495
--- /dev/null
+++ b/LAB3/sim/tb_volume_multiplier.vhd
@@ -0,0 +1,178 @@
+----------------------------------------------------------------------------------
+-- Testbench for volume_multiplier
+----------------------------------------------------------------------------------
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+
+ENTITY tb_volume_multiplier IS
+END tb_volume_multiplier;
+
+ARCHITECTURE Behavioral OF tb_volume_multiplier IS
+
+ CONSTANT TDATA_WIDTH : POSITIVE := 24;
+ CONSTANT VOLUME_WIDTH : POSITIVE := 10;
+ CONSTANT VOLUME_STEP_2 : POSITIVE := 6;
+ CONSTANT N_SAMPLES : INTEGER := 8;
+ CONSTANT N_VOLUMES : INTEGER := 10;
+
+ -- Output width calculation (as in DUT)
+ CONSTANT TDATA_OUT_WIDTH : INTEGER := TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) + 1;
+
+ COMPONENT volume_multiplier IS
+ GENERIC (
+ TDATA_WIDTH : POSITIVE := 24;
+ VOLUME_WIDTH : POSITIVE := 10;
+ VOLUME_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_tlast : IN STD_LOGIC;
+ s_axis_tready : OUT STD_LOGIC;
+ m_axis_tvalid : OUT STD_LOGIC;
+ m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_OUT_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 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_OUT_WIDTH - 1 DOWNTO 0);
+ SIGNAL m_axis_tlast : STD_LOGIC;
+ SIGNAL m_axis_tready : STD_LOGIC := '1';
+ SIGNAL volume : STD_LOGIC_VECTOR(VOLUME_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
+ );
+
+ -- Vettore di memoria per i valori di volume
+ TYPE volume_mem_type IS ARRAY(0 TO N_VOLUMES-1) OF STD_LOGIC_VECTOR(VOLUME_WIDTH-1 DOWNTO 0);
+ SIGNAL volume_mem : volume_mem_type := (
+ std_logic_vector(to_unsigned(0, VOLUME_WIDTH)), -- 0.25x (forte attenuazione)
+ std_logic_vector(to_unsigned(64, VOLUME_WIDTH)), -- 0.375x (attenuazione media)
+ std_logic_vector(to_unsigned(479, VOLUME_WIDTH)), -- 0.4375x (leggera attenuazione)
+ std_logic_vector(to_unsigned(480, VOLUME_WIDTH)), -- 0.5x (volume neutro)
+ std_logic_vector(to_unsigned(513, VOLUME_WIDTH)), -- Circa 0.5x (volume neutro)
+ std_logic_vector(to_unsigned(576, VOLUME_WIDTH)), -- 0.5625x (leggero aumento)
+ std_logic_vector(to_unsigned(640, VOLUME_WIDTH)), -- 0.625x (aumento medio)
+ std_logic_vector(to_unsigned(768, VOLUME_WIDTH)), -- 0.75x (aumento forte)
+ std_logic_vector(to_unsigned(896, VOLUME_WIDTH)), -- 0.875x (aumento molto forte)
+ std_logic_vector(to_unsigned(1023, VOLUME_WIDTH)) -- 1x (massimo volume)
+ );
+
+BEGIN
+
+ -- Clock generation
+ aclk <= NOT aclk AFTER 5 ns;
+
+ -- DUT instantiation
+ uut: 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 => m_axis_tvalid,
+ m_axis_tdata => m_axis_tdata,
+ m_axis_tlast => m_axis_tlast,
+ m_axis_tready => m_axis_tready,
+ volume => volume
+ );
+
+ -- Stimulus process
+ stimulus : PROCESS
+ BEGIN
+ -- Reset
+ WAIT FOR 10 ns;
+ aresetn <= '1';
+ WAIT UNTIL rising_edge(aclk);
+
+ -- Set volume to mid (no gain/loss)
+ volume <= volume_mem(7);
+ WAIT UNTIL rising_edge(aclk);
+
+ -- Send all samples
+ 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 for handshake
+ 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 volume (attenuate)
+ WAIT FOR 20 ns;
+ volume <= volume_mem(1);
+
+ -- Send one more sample
+ 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';
+
+ FOR i IN 2 TO N_VOLUMES-1 LOOP
+ WAIT FOR 20 ns;
+ volume <= volume_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/sim/tb_volume_saturator.vhd b/LAB3/sim/tb_volume_saturator.vhd
new file mode 100644
index 0000000..4782913
--- /dev/null
+++ b/LAB3/sim/tb_volume_saturator.vhd
@@ -0,0 +1,157 @@
+----------------------------------------------------------------------------------
+-- Company:
+-- Engineer:
+--
+-- Create Date: 05/20/2025
+-- Design Name:
+-- Module Name: tb_volume_saturator - Behavioral
+-- Project Name:
+-- Target Devices:
+-- Tool Versions: Vivado 2020.2
+-- Description: Testbench for volume_saturator (stereo, L->R, tlast on R)
+--
+----------------------------------------------------------------------------------
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+
+ENTITY tb_volume_saturator IS
+END tb_volume_saturator;
+
+ARCHITECTURE Behavioral OF tb_volume_saturator IS
+
+ CONSTANT TDATA_WIDTH : POSITIVE := 24;
+ CONSTANT VOLUME_WIDTH : POSITIVE := 10;
+ CONSTANT VOLUME_STEP_2 : POSITIVE := 6;
+ CONSTANT STEREO_SAMPLES : INTEGER := 8;
+
+ -- Calculate s_axis_tdata width
+ CONSTANT TDATA_IN_WIDTH : INTEGER := TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) + 1;
+
+ 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;
+
+ 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 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 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';
+
+ -- Example stereo audio: L, R, L, R, ... (tlast on R)
+ TYPE stereo_mem_type IS ARRAY(0 TO 2 * STEREO_SAMPLES - 1) OF STD_LOGIC_VECTOR(TDATA_IN_WIDTH - 1 DOWNTO 0);
+ SIGNAL stereo_mem : stereo_mem_type := (
+ x"00009C40", -- +40000 (clipping positivo)
+ x"00007FFF", -- +32767 (HIGHER_BOUND)
+ x"00007FFE", -- +32766 (appena sotto HIGHER_BOUND)
+ x"00000000", -- 0
+ x"FFFF8001", -- -32767 (appena sopra LOWER_BOUND)
+ x"FFFF8000", -- -32768 (LOWER_BOUND)
+ x"FFFF63C0", -- -40000 (clipping negativo)
+ x"00003039", -- +12345 (valore positivo intermedio)
+ x"FFFFCFC7", -- -12345 (valore negativo intermedio)
+ x"00007FFF", -- +32767 (HIGHER_BOUND, ripetuto)
+ x"FFFF8000", -- -32768 (LOWER_BOUND, ripetuto)
+ x"00009C40", -- +40000 (clipping positivo, ripetuto)
+ x"FFFF63C0", -- -40000 (clipping negativo, ripetuto)
+ x"00000001", -- +1
+ x"FFFFFFFF", -- -1
+ x"00000000" -- 0 (ripetuto)
+ );
+
+BEGIN
+
+ -- Clock generation
+ aclk <= NOT aclk AFTER 5 ns;
+
+ -- DUT instantiation
+ uut : volume_saturator
+ GENERIC MAP(
+ TDATA_WIDTH => TDATA_WIDTH,
+ VOLUME_WIDTH => VOLUME_WIDTH,
+ VOLUME_STEP_2 => VOLUME_STEP_2,
+ HIGHER_BOUND => 2 ** 15 - 1,
+ LOWER_BOUND => - 2 ** 15
+ )
+ 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 => m_axis_tvalid,
+ m_axis_tdata => m_axis_tdata,
+ m_axis_tlast => m_axis_tlast,
+ m_axis_tready => m_axis_tready
+ );
+
+ -- Stimulus process: send stereo samples, tlast on R
+ stimulus : PROCESS
+ BEGIN
+ -- Reset
+ WAIT FOR 10 ns;
+ aresetn <= '1';
+ WAIT UNTIL rising_edge(aclk);
+
+ FOR i IN 0 TO stereo_mem'high LOOP
+ s_axis_tdata <= stereo_mem(i);
+ s_axis_tvalid <= '1';
+ -- tlast asserted on every R channel (odd index)
+ IF (i MOD 2) = 1 THEN
+ s_axis_tlast <= '1';
+ ELSE
+ s_axis_tlast <= '0';
+ END IF;
+ -- Wait for handshake
+ 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';
+
+ -- Wait and finish
+ WAIT FOR 100 ns;
+ WAIT;
+ END PROCESS;
+
+ -- Optionally, block m_axis_tready for a few cycles to test backpressure
+ PROCESS
+ BEGIN
+ WAIT FOR 80 ns;
+ WAIT UNTIL rising_edge(aclk);
+ m_axis_tready <= '0';
+ WAIT FOR 30 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/LFO.vhd b/LAB3/src/LFO.vhd
index b596bb8..5279f36 100644
--- a/LAB3/src/LFO.vhd
+++ b/LAB3/src/LFO.vhd
@@ -1,40 +1,225 @@
- library IEEE;
-use IEEE.STD_LOGIC_1164.ALL;
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.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
+-- Entity: LFO (Low Frequency Oscillator) - Alternative Implementation
+-- 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
+ GENERIC (
+ CHANNEL_LENGHT : INTEGER := 24; -- Bit width of audio samples (24-bit signed)
+ JOYSTICK_LENGHT : INTEGER := 10; -- Bit width of joystick input (10-bit = 0-1023 range)
+ CLK_PERIOD_NS : INTEGER := 10; -- Clock period in nanoseconds (10ns = 100MHz)
+ TRIANGULAR_COUNTER_LENGHT : INTEGER := 10 -- Triangular wave counter length (affects modulation depth)
);
- 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;
+ PORT (
+ -- Clock and Reset
+ aclk : IN STD_LOGIC; -- Main system clock
+ aresetn : IN STD_LOGIC; -- Active-low asynchronous reset
-architecture Behavioral of LFO is
+ -- LFO Control inputs
+ lfo_period : IN STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0); -- Controls LFO frequency (joystick Y-axis)
+ lfo_enable : IN STD_LOGIC; -- Enable/bypass LFO effect
-begin
+ -- Slave AXI Stream interface (audio input)
+ s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal
+ s_axis_tdata : IN STD_LOGIC_VECTOR(CHANNEL_LENGHT - 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
-end architecture;
\ No newline at end of file
+ -- Master AXI Stream interface (audio output)
+ m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal
+ m_axis_tdata : OUT STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0); -- Modulated audio sample output
+ m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough
+ m_axis_tready : IN STD_LOGIC -- Downstream ready signal
+ );
+END ENTITY LFO;
+
+ARCHITECTURE Behavioral OF LFO IS
+
+ -- LFO timing configuration constants
+ CONSTANT LFO_COUNTER_BASE_PERIOD_US : INTEGER := 1000; -- Base period: 1ms (1kHz base frequency)
+ CONSTANT ADJUSTMENT_FACTOR : INTEGER := 90; -- Frequency adjustment sensitivity (clock cycles per joystick unit)
+ CONSTANT JSTK_CENTER_VALUE : INTEGER := 2 ** (JOYSTICK_LENGHT - 1); -- Joystick center position (512 for 10-bit)
+
+ -- Calculate base clock cycles for 1ms period at current clock frequency
+ CONSTANT LFO_COUNTER_BASE_CLK_CYCLES : INTEGER := LFO_COUNTER_BASE_PERIOD_US * 1000 / CLK_PERIOD_NS; -- 1ms = 100,000 clk cycles
+
+ -- Calculate frequency range limits based on joystick range
+ CONSTANT LFO_CLK_CYCLES_MIN : INTEGER := LFO_COUNTER_BASE_CLK_CYCLES - ADJUSTMENT_FACTOR * (2 ** (JOYSTICK_LENGHT - 1)); -- 53,920 clk cycles (faster)
+ CONSTANT LFO_CLK_CYCLES_MAX : INTEGER := LFO_COUNTER_BASE_CLK_CYCLES + ADJUSTMENT_FACTOR * (2 ** (JOYSTICK_LENGHT - 1) - 1); -- 145,990 clk cycles (slower)
+
+ -- LFO timing control signals
+ SIGNAL step_clk_cycles_delta : INTEGER RANGE - 2 ** (JOYSTICK_LENGHT - 1) * ADJUSTMENT_FACTOR TO (2 ** (JOYSTICK_LENGHT - 1) - 1) * ADJUSTMENT_FACTOR := 0;
+ SIGNAL step_clk_cycles : INTEGER RANGE LFO_CLK_CYCLES_MIN TO LFO_CLK_CYCLES_MAX := LFO_COUNTER_BASE_CLK_CYCLES;
+ SIGNAL step_counter : NATURAL RANGE 0 TO LFO_CLK_CYCLES_MAX := 0;
+
+ -- Triangular wave generation signals
+ -- Note: Using signed counter with extra bit to handle full range calculations
+ SIGNAL tri_counter : SIGNED(TRIANGULAR_COUNTER_LENGHT DOWNTO 0) := (OTHERS => '0'); -- Triangular wave amplitude
+ SIGNAL direction_up : STD_LOGIC := '1'; -- Wave direction: '1' = ascending, '0' = descending
+
+ -- AXI4-Stream control signals
+ SIGNAL trigger : STD_LOGIC := '0'; -- Trigger to indicate new processed data is ready
+ SIGNAL s_axis_tlast_reg : STD_LOGIC := '0'; -- Registered version of tlast for output synchronization
+ SIGNAL m_axis_tvalid_int : STD_LOGIC := '0'; -- Internal output valid signal
+
+ -- Audio processing signal with extended width for multiplication
+ -- Width accommodates: audio sample + triangular counter to prevent overflow
+ SIGNAL m_axis_tdata_temp : SIGNED(CHANNEL_LENGHT + TRIANGULAR_COUNTER_LENGHT DOWNTO 0) := (OTHERS => '0');
+
+BEGIN
+
+ -- Output signal assignments with proper AXI4-Stream flow control
+ m_axis_tvalid <= m_axis_tvalid_int;
+ -- Input ready logic: Ready when downstream is ready OR no valid data pending, AND not in reset
+ s_axis_tready <= (m_axis_tready OR NOT m_axis_tvalid_int) AND aresetn;
+
+ -- Optimized single process for LFO timing and triangular waveform generation
+ -- This process handles both the frequency control and wave shape generation
+ triangular_wave_lfo_generator : PROCESS (aclk)
+ BEGIN
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset LFO generator to initial state
+ step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES; -- Set to base frequency
+ step_counter <= 0; -- Clear timing counter
+ tri_counter <= (OTHERS => '0'); -- Start triangular wave at zero
+ direction_up <= '1'; -- Start counting up
+
+ ELSE
+ -- Calculate LFO period based on joystick input
+ -- Joystick mapping:
+ -- 0-511: Slower than base frequency (longer period, lower frequency)
+ -- 512: Base frequency (1kHz)
+ -- 513-1023: Faster than base frequency (shorter period, higher frequency)
+ step_clk_cycles_delta <= (to_integer(unsigned(lfo_period)) - JSTK_CENTER_VALUE);
+ step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES - step_clk_cycles_delta * ADJUSTMENT_FACTOR;
+
+ -- Generate triangular wave when LFO is enabled
+ IF lfo_enable = '1' THEN
+
+ -- Clock divider: Update triangular wave at calculated rate
+ IF step_counter >= step_clk_cycles THEN
+ 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 due to process signal assignment
+ IF tri_counter = (2 ** TRIANGULAR_COUNTER_LENGHT) - 2 THEN
+ direction_up <= '0'; -- Switch to descending at near-maximum
+
+ ELSIF tri_counter = 1 THEN
+ direction_up <= '1'; -- Switch to ascending at near-minimum
+
+ END IF;
+
+ -- Update triangular wave value based on current direction
+ -- This creates the classic triangular waveform shape
+ IF direction_up = '1' THEN
+ tri_counter <= tri_counter + 1; -- Ascending: increment
+ ELSE
+ tri_counter <= tri_counter - 1; -- Descending: decrement
+ END IF;
+
+ ELSE
+ step_counter <= step_counter + 1; -- Continue counting towards next update
+
+ END IF;
+
+ END IF;
+
+ END IF;
+
+ END IF;
+
+ END PROCESS triangular_wave_lfo_generator;
+
+ -- AXI4-Stream handshake logic and audio processing
+ -- This process handles input/output data flow and applies the LFO modulation
+ AXIS : PROCESS (aclk)
+ BEGIN
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset AXI4-Stream interface and audio processing
+ s_axis_tlast_reg <= '0'; -- Clear registered channel indicator
+ m_axis_tdata_temp <= (OTHERS => '0'); -- Clear temporary audio data
+ m_axis_tvalid_int <= '0'; -- No valid output data
+ m_axis_tlast <= '0'; -- Clear output channel indicator
+
+ ELSE
+ -- Output handshake management:
+ -- Clear valid flag when downstream accepts data
+ IF m_axis_tready = '1' THEN
+ m_axis_tvalid_int <= '0';
+ END IF;
+
+ -- Data output logic: Send processed audio when trigger is active and output is available
+ IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
+ -- Scale down the multiplication result to original audio bit width
+ -- Right shift by TRIANGULAR_COUNTER_LENGHT effectively divides by 2^TRIANGULAR_COUNTER_LENGHT
+ -- This maintains proper audio amplitude after modulation
+ m_axis_tdata <= STD_LOGIC_VECTOR(
+ resize(
+ shift_right(
+ m_axis_tdata_temp, -- Wide multiplication result
+ TRIANGULAR_COUNTER_LENGHT -- Scale factor
+ ),
+ CHANNEL_LENGHT -- Final audio sample width
+ )
+ );
+ m_axis_tlast <= s_axis_tlast_reg; -- Output registered channel indicator
+
+ m_axis_tvalid_int <= '1'; -- Mark output as valid
+ trigger <= '0'; -- Clear trigger - data has been output
+
+ END IF;
+
+ -- 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 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
+
+ ELSE
+ -- LFO disabled: pass audio through unchanged but maintain bit width
+ -- Left shift compensates for the right shift that occurs during output
+ -- This ensures unity gain when LFO is bypassed
+ m_axis_tdata_temp <= shift_left(
+ resize(
+ signed(s_axis_tdata), -- Convert input to signed
+ m_axis_tdata_temp'length -- Extend to full processing width
+ ),
+ TRIANGULAR_COUNTER_LENGHT -- Compensate for output scaling
+ );
+ s_axis_tlast_reg <= s_axis_tlast; -- Register channel indicator
+
+ END IF;
+
+ trigger <= '1'; -- Set trigger to indicate new processed data is ready
+
+ END IF;
+
+ END IF;
+
+ END IF;
+
+ END PROCESS AXIS;
+
+ -- LFO Implementation Summary:
+ -- 1. Generates triangular wave at frequency controlled by joystick input
+ -- 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
+ --
+ -- 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)
+ -- - Bypass capability: Clean audio passthrough when disabled
+
+END ARCHITECTURE Behavioral;
\ No newline at end of file
diff --git a/LAB3/src/LFO_1.vhd b/LAB3/src/LFO_1.vhd
new file mode 100644
index 0000000..d04411f
--- /dev/null
+++ b/LAB3/src/LFO_1.vhd
@@ -0,0 +1,256 @@
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+
+-- Entity: LFO_1 (Low Frequency Oscillator)
+-- Purpose: Applies tremolo effect to audio by modulating amplitude with a triangular wave
+-- Creates classic audio effects like vibrato, tremolo, and amplitude modulation
+-- Implements a 3-stage pipeline for efficient real-time audio processing
+ENTITY LFO_1 IS
+ GENERIC (
+ CHANNEL_LENGHT : INTEGER := 24; -- Bit width of audio samples (24-bit signed)
+ JOYSTICK_LENGHT : INTEGER := 10; -- Bit width of joystick input (10-bit = 0-1023 range)
+ CLK_PERIOD_NS : INTEGER := 10; -- Clock period in nanoseconds (10ns = 100MHz)
+ TRIANGULAR_COUNTER_LENGHT : INTEGER := 10 -- Bit width of triangular wave counter (affects modulation depth)
+ );
+ PORT (
+ -- Clock and Reset
+ aclk : IN STD_LOGIC; -- Main system clock
+ aresetn : IN STD_LOGIC; -- Active-low asynchronous reset
+
+ -- LFO_1 Control inputs
+ lfo_period : IN STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0); -- Controls LFO_1 frequency (joystick Y-axis)
+ lfo_enable : IN STD_LOGIC; -- Enable/bypass LFO_1 effect
+
+ -- Slave AXI Stream interface (audio input)
+ s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal
+ s_axis_tdata : IN STD_LOGIC_VECTOR(CHANNEL_LENGHT - 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
+
+ -- Master AXI Stream interface (audio output)
+ m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal
+ m_axis_tdata : OUT STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0); -- Modulated audio sample output
+ m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough
+ m_axis_tready : IN STD_LOGIC -- Downstream ready signal
+ );
+END ENTITY LFO_1;
+
+ARCHITECTURE Behavioral OF LFO_1 IS
+
+ -- Constants for LFO_1 timing configuration
+ CONSTANT BASE_PERIOD_MICROSECONDS : INTEGER := 1000; -- Base period: 1ms (1kHz base frequency)
+ CONSTANT FREQUENCY_ADJUSTMENT_FACTOR : INTEGER := 90; -- Frequency adjustment sensitivity (clock cycles per joystick unit)
+ CONSTANT JOYSTICK_CENTER_VALUE : INTEGER := 2 ** (JOYSTICK_LENGHT - 1); -- Joystick center position (512 for 10-bit)
+
+ -- Calculate base clock cycles for 1ms period at current clock frequency
+ CONSTANT BASE_CLOCK_CYCLES : INTEGER := BASE_PERIOD_MICROSECONDS * 1000 / CLK_PERIOD_NS;
+
+ -- Calculate frequency range limits based on joystick range
+ -- Minimum frequency (fastest LFO_1): occurs when joystick is at minimum position
+ CONSTANT MIN_CLOCK_CYCLES : INTEGER := BASE_CLOCK_CYCLES - FREQUENCY_ADJUSTMENT_FACTOR * (2 ** (JOYSTICK_LENGHT - 1));
+ -- Maximum frequency (slowest LFO_1): occurs when joystick is at maximum position
+ CONSTANT MAX_CLOCK_CYCLES : INTEGER := BASE_CLOCK_CYCLES + FREQUENCY_ADJUSTMENT_FACTOR * (2 ** (JOYSTICK_LENGHT - 1) - 1);
+
+ -- Internal signals for LFO_1 control
+ -- Period adjustment based on joystick input (positive = slower, negative = faster)
+ SIGNAL period_adjustment_delta : INTEGER RANGE - 2 ** (JOYSTICK_LENGHT - 1) * FREQUENCY_ADJUSTMENT_FACTOR
+ TO (2 ** (JOYSTICK_LENGHT - 1) - 1) * FREQUENCY_ADJUSTMENT_FACTOR := 0;
+ SIGNAL current_period_cycles : INTEGER RANGE MIN_CLOCK_CYCLES TO MAX_CLOCK_CYCLES := BASE_CLOCK_CYCLES;
+
+ -- Pipeline stage 1 registers - Input processing and period calculation
+ SIGNAL audio_data_stage1 : STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0) := (OTHERS => '0'); -- Registered audio input
+ SIGNAL enable_flag_stage1 : STD_LOGIC := '0'; -- Registered LFO_1 enable
+ SIGNAL valid_flag_stage1 : STD_LOGIC := '0'; -- Valid data in stage 1
+ SIGNAL last_flag_stage1 : STD_LOGIC := '0'; -- Registered channel indicator
+
+ -- Pipeline stage 2 registers - Triangular wave generation
+ SIGNAL triangular_wave_value : unsigned(TRIANGULAR_COUNTER_LENGHT - 1 DOWNTO 0) := (OTHERS => '0'); -- Current triangular wave amplitude
+ SIGNAL wave_direction_up : STD_LOGIC := '1'; -- Triangle wave direction: '1' = ascending, '0' = descending
+ SIGNAL timing_counter : NATURAL RANGE 0 TO MAX_CLOCK_CYCLES := 0; -- Clock cycle counter for LFO_1 timing
+ SIGNAL enable_flag_stage2 : STD_LOGIC := '0'; -- LFO_1 enable flag for stage 2
+ SIGNAL valid_flag_stage2 : STD_LOGIC := '0'; -- Valid data in stage 2
+ SIGNAL last_flag_stage2 : STD_LOGIC := '0'; -- Channel indicator for stage 2
+ SIGNAL audio_data_stage2 : STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0) := (OTHERS => '0'); -- Audio data for stage 2
+
+ -- Pipeline stage 3 registers - Modulation and output
+ -- Extended width to accommodate multiplication result before scaling
+ SIGNAL multiplication_result : STD_LOGIC_VECTOR(CHANNEL_LENGHT + TRIANGULAR_COUNTER_LENGHT - 1 DOWNTO 0) := (OTHERS => '0');
+
+ -- Internal AXI4-Stream control signals
+ SIGNAL master_valid_internal : STD_LOGIC := '0'; -- Internal output valid signal
+ SIGNAL slave_ready_internal : STD_LOGIC := '1'; -- Internal input ready signal
+
+BEGIN
+
+ -- Direct connection: tlast passes through unchanged (maintains channel timing)
+ m_axis_tlast <= last_flag_stage1;
+
+ -- Pipeline stage 1: Input registration and LFO_1 period calculation
+ -- This stage captures input data and calculates the LFO_1 period based on joystick position
+ input_processing_stage : PROCESS (aclk)
+ BEGIN
+ IF rising_edge(aclk) THEN
+ IF aresetn = '0' THEN
+ -- Reset all stage 1 registers to safe initial states
+ audio_data_stage1 <= (OTHERS => '0'); -- Clear audio data
+ current_period_cycles <= BASE_CLOCK_CYCLES; -- Set to base frequency
+ enable_flag_stage1 <= '0'; -- Disable LFO_1
+ valid_flag_stage1 <= '0'; -- No valid data
+ last_flag_stage1 <= '0'; -- Clear channel indicator
+ ELSE
+ -- Calculate LFO_1 period based on joystick y-axis input
+ -- Joystick mapping:
+ -- 0-511: Faster than base frequency (shorter period)
+ -- 512: Base frequency (1kHz)
+ -- 513-1023: Slower than base frequency (longer period)
+ period_adjustment_delta <= (to_integer(unsigned(lfo_period)) - JOYSTICK_CENTER_VALUE) * FREQUENCY_ADJUSTMENT_FACTOR;
+ current_period_cycles <= BASE_CLOCK_CYCLES - period_adjustment_delta;
+
+ -- AXI4-Stream handshake: accept new data when both valid and ready
+ IF s_axis_tvalid = '1' AND slave_ready_internal = '1' THEN
+ audio_data_stage1 <= s_axis_tdata; -- Register input audio sample
+ enable_flag_stage1 <= lfo_enable; -- Register enable control
+ valid_flag_stage1 <= '1'; -- Mark data as valid for next stage
+ last_flag_stage1 <= s_axis_tlast; -- Register channel boundary signal
+ ELSE
+ valid_flag_stage1 <= '0'; -- No valid data to pass to next stage
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS input_processing_stage;
+
+ -- Pipeline stage 2: Triangular wave generation
+ -- This stage generates the triangular wave that will modulate the audio amplitude
+ triangular_wave_generator : PROCESS (aclk)
+ BEGIN
+ IF rising_edge(aclk) THEN
+ IF aresetn = '0' THEN
+ -- Reset triangular wave generator to initial state
+ timing_counter <= 0; -- Clear timing counter
+ triangular_wave_value <= (OTHERS => '0'); -- Start at zero amplitude
+ wave_direction_up <= '1'; -- Start counting up
+ enable_flag_stage2 <= '0'; -- Disable LFO_1
+ valid_flag_stage2 <= '0'; -- No valid data
+ last_flag_stage2 <= '0'; -- Clear channel indicator
+ audio_data_stage2 <= (OTHERS => '0'); -- Clear audio data
+ ELSE
+ -- Pass through pipeline registers from stage 1 to stage 2
+ enable_flag_stage2 <= enable_flag_stage1; -- Forward enable flag
+ valid_flag_stage2 <= valid_flag_stage1; -- Forward valid flag
+ last_flag_stage2 <= last_flag_stage1; -- Forward channel indicator
+ audio_data_stage2 <= audio_data_stage1; -- Forward audio data
+
+ -- Generate triangular wave when LFO_1 is enabled
+ IF enable_flag_stage1 = '1' THEN
+ -- Clock divider: update triangular counter based on calculated period
+ IF timing_counter < current_period_cycles THEN
+ timing_counter <= timing_counter + 1; -- Count towards period target
+ ELSE
+ timing_counter <= 0; -- Reset counter for next period
+
+ -- Update triangular wave: count up or down based on current direction
+ -- This creates the classic triangular waveform shape
+ IF wave_direction_up = '1' THEN
+ -- Ascending phase: check if we reached maximum amplitude
+ IF triangular_wave_value = (2 ** TRIANGULAR_COUNTER_LENGHT) - 1 THEN
+ wave_direction_up <= '0'; -- Switch to descending phase
+ triangular_wave_value <= triangular_wave_value - 1; -- Start decreasing
+ ELSE
+ triangular_wave_value <= triangular_wave_value + 1; -- Continue increasing
+ END IF;
+ ELSE
+ -- Descending phase: check if we reached minimum amplitude
+ IF triangular_wave_value = 0 THEN
+ wave_direction_up <= '1'; -- Switch to ascending phase
+ triangular_wave_value <= triangular_wave_value + 1; -- Start increasing
+ ELSE
+ triangular_wave_value <= triangular_wave_value - 1; -- Continue decreasing
+ END IF;
+ END IF;
+ END IF;
+ ELSE
+ -- LFO_1 disabled: reset triangular wave generator to idle state
+ timing_counter <= 0; -- Clear timing counter
+ triangular_wave_value <= (OTHERS => '0'); -- Reset to zero amplitude
+ wave_direction_up <= '1'; -- Reset to ascending direction
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS triangular_wave_generator;
+
+ -- Pipeline stage 3: Audio modulation and output control
+ -- This stage applies the LFO_1 effect by multiplying audio samples with the triangular wave
+ modulation_and_output : PROCESS (aclk)
+ BEGIN
+ IF rising_edge(aclk) THEN
+ IF aresetn = '0' THEN
+ -- Reset output stage to safe initial state
+ m_axis_tdata <= (OTHERS => '0'); -- Clear output data
+ master_valid_internal <= '0'; -- No valid output
+ slave_ready_internal <= '1'; -- Ready to accept input
+ ELSE
+ -- Output flow control: handle backpressure from downstream modules
+ IF master_valid_internal = '1' AND m_axis_tready = '0' THEN
+ -- Downstream not ready: maintain current output valid state
+ -- This implements proper AXI4-Stream backpressure handling
+ master_valid_internal <= '1';
+ ELSIF valid_flag_stage2 = '1' THEN
+ -- New data available from stage 2: apply LFO_1 effect or bypass
+ IF enable_flag_stage2 = '1' THEN
+ -- Apply LFO_1 tremolo effect: multiply audio sample by triangular wave
+ -- This creates amplitude modulation (tremolo effect)
+ multiplication_result <= STD_LOGIC_VECTOR(
+ resize(
+ signed(audio_data_stage2) * signed('0' & triangular_wave_value),
+ multiplication_result'length
+ )
+ );
+ -- Scale down result by removing lower bits (equivalent to division by 2^TRIANGULAR_COUNTER_LENGHT)
+ -- This maintains proper audio amplitude range after multiplication
+ m_axis_tdata <= multiplication_result(multiplication_result'high DOWNTO TRIANGULAR_COUNTER_LENGHT);
+ ELSE
+ -- LFO_1 disabled: pass audio through unchanged (bypass mode)
+ -- This allows seamless switching between effect and clean audio
+ m_axis_tdata <= audio_data_stage2;
+ END IF;
+ master_valid_internal <= '1'; -- Mark output as valid
+ ELSE
+ -- No new data available: clear output valid flag
+ master_valid_internal <= '0';
+ END IF;
+
+ -- AXI4-Stream ready signal management for proper flow control
+ IF master_valid_internal = '1' AND m_axis_tready = '1' THEN
+ -- Successful output handshake: ready for new input data
+ slave_ready_internal <= '1';
+ ELSIF s_axis_tvalid = '1' AND slave_ready_internal = '1' THEN
+ -- Accepted new input: not ready until current output is consumed
+ -- This prevents data loss in the pipeline
+ slave_ready_internal <= '0';
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS modulation_and_output;
+
+ -- Output signal assignments
+ s_axis_tready <= slave_ready_internal; -- Connect internal ready to output port
+ m_axis_tvalid <= master_valid_internal; -- Connect internal valid to output port
+
+ -- LFO_1 Effect Summary:
+ -- 1. Stage 1: Calculates LFO_1 frequency based on joystick position
+ -- 2. Stage 2: Generates triangular wave at calculated frequency
+ -- 3. Stage 3: Multiplies audio samples by triangular wave (tremolo effect)
+ --
+ -- Audio Effect Characteristics:
+ -- - Tremolo: Periodic amplitude modulation creates "shaking" sound
+ -- - Frequency range: Approximately 0.1Hz to 10Hz (typical for audio LFO_1)
+ -- - Modulation depth: Controlled by TRIANGULAR_COUNTER_LENGHT generic
+ -- - Bypass capability: Clean audio passthrough when disabled
+ --
+ -- Pipeline Benefits:
+ -- - Maintains real-time audio processing with no dropouts
+ -- - Allows complex calculations without affecting audio timing
+ -- - Provides proper AXI4-Stream flow control and backpressure handling
+
+END ARCHITECTURE Behavioral;
\ No newline at end of file
diff --git a/LAB3/src/all_pass_filter.vhd b/LAB3/src/all_pass_filter.vhd
index 6d9de3b..4a4a782 100644
--- a/LAB3/src/all_pass_filter.vhd
+++ b/LAB3/src/all_pass_filter.vhd
@@ -1,29 +1,123 @@
-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 all_pass_filter is
- generic (
- TDATA_WIDTH : positive := 24
- );
- Port (
- aclk : in std_logic;
- aresetn : in std_logic;
+-- Entity: all_pass_filter
+-- Purpose: A pass-through filter that maintains the same interface and timing
+-- 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
+ );
+ 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 (Input)
+ s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal
+ s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Input data
+ s_axis_tlast : IN STD_LOGIC; -- Input end-of-packet signal
+ 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
- );
-end all_pass_filter;
+ -- AXI4-Stream Master Interface (Output)
+ m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal
+ m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Output data
+ m_axis_tlast : OUT STD_LOGIC; -- Output end-of-packet signal
+ m_axis_tready : IN STD_LOGIC -- Downstream ready signal
+ );
+END all_pass_filter;
-architecture Behavioral of all_pass_filter is
+ARCHITECTURE Behavioral OF all_pass_filter IS
-begin
+ -- Internal control signal to trigger data output after input processing
+ SIGNAL trigger : STD_LOGIC := '0';
-end Behavioral;
+ -- 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_tvalid_int : STD_LOGIC := '0'; -- Internal valid signal for output
+
+BEGIN
+
+ -- Architecture Overview:
+ -- This design mimics the structure, handshake logic, and timing (clock cycles spent)
+ -- of the moving_average_filter, but does not process or modify the samples.
+ -- It simply passes input data to the output unchanged, ensuring the same latency and interface behavior.
+
+ -- Data Flow:
+ -- 1. Input data is captured when s_axis_tvalid and s_axis_tready are both high
+ -- 2. Data is stored in temporary registers and a trigger is set
+ -- 3. On the next clock cycle, if output interface is ready, data is output
+ -- 4. This creates a 1-clock cycle latency matching the moving average filter
+
+ -- Connect internal signals to output ports
+ m_axis_tvalid <= m_axis_tvalid_int; -- Drive output valid with internal signal
+ s_axis_tready <= s_axis_tready_int; -- Drive input ready with internal signal
+
+ -- Main processing logic - synchronous to clock
+ PROCESS (aclk)
+ BEGIN
+ IF rising_edge(aclk) THEN
+
+ -- Asynchronous reset logic (active low)
+ IF aresetn = '0' THEN
+ -- Reset all internal signals to known states
+ 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
+ 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
+
+ ELSE
+ -- Normal operation logic
+
+ -- Output handshake management:
+ -- Clear the output valid flag when downstream is ready to accept data
+ -- This allows new data to be output on the next cycle
+ IF m_axis_tready = '1' THEN
+ m_axis_tvalid_int <= '0';
+ END IF;
+
+ -- Data output logic:
+ -- Output data when trigger is set AND output interface is available
+ -- (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 <= 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
+ m_axis_tvalid_int <= '1'; -- Mark output data as valid
+ trigger <= '0'; -- Clear trigger - data has been output
+ END IF;
+
+ -- Data input logic:
+ -- Capture input data when both valid and ready are asserted (AXI handshake)
+ 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
+ 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';
+ END IF;
+
+ -- Input ready logic:
+ -- Ready to accept new input when:
+ -- - Downstream is ready (can immediately pass data through), OR
+ -- - No valid data is pending on output (have buffer space)
+ -- This implements backpressure - if output is blocked, input will be blocked
+ s_axis_tready_int <= m_axis_tready OR NOT m_axis_tvalid_int;
+
+ END IF;
+
+ END IF;
+
+ 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 1d5f90c..9abd755 100644
--- a/LAB3/src/balance_controller.vhd
+++ b/LAB3/src/balance_controller.vhd
@@ -1,33 +1,147 @@
-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
- );
- Port (
- aclk : in std_logic;
- aresetn : in std_logic;
+-- Entity: balance_controller
+-- Purpose: Controls the stereo balance (left/right channel volume) of audio data
+-- based on a balance control input. Implements variable attenuation
+-- using bit shifting for efficient hardware implementation.
+ENTITY balance_controller IS
+ GENERIC (
+ TDATA_WIDTH : POSITIVE := 24; -- Width of audio data bus (24-bit audio samples)
+ BALANCE_WIDTH : POSITIVE := 10; -- Width of balance control input (10-bit = 0-1023 range)
+ BALANCE_STEP_2 : POSITIVE := 6 -- Log2 of balance values per step (2^6 = 64 values per step)
+ );
+ PORT (
+ -- Clock and reset
+ aclk : IN STD_LOGIC; -- Main clock
+ 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_tready : out std_logic;
- s_axis_tlast : in std_logic;
+ -- AXI4-Stream Slave Interface (Audio Input)
+ s_axis_tvalid : IN STD_LOGIC; -- Input data valid
+ s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Audio sample data
+ s_axis_tready : OUT STD_LOGIC; -- Ready to accept input
+ s_axis_tlast : IN STD_LOGIC; -- Channel indicator (0=left, 1=right)
- 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;
+ -- AXI4-Stream Master Interface (Audio Output)
+ m_axis_tvalid : OUT STD_LOGIC; -- Output data valid
+ m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Balanced audio sample
+ m_axis_tready : IN STD_LOGIC; -- Downstream ready
+ m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough
- balance : in std_logic_vector(BALANCE_WIDTH-1 downto 0)
- );
-end balance_controller;
+ -- Balance Control Input
+ balance : IN STD_LOGIC_VECTOR(BALANCE_WIDTH - 1 DOWNTO 0) -- Balance position (0=full left, 1023=full right, 512=center)
+ );
+END balance_controller;
-architecture Behavioral of balance_controller is
+ARCHITECTURE Behavioral OF balance_controller IS
-begin
+ -- Balance calculation constants
+ CONSTANT BALANCE_STEPS : INTEGER := (2 ** (BALANCE_WIDTH - 1)) / (2 ** BALANCE_STEP_2) + 1; -- Number of attenuation steps (9 steps for 10-bit balance)
+ CONSTANT BAL_MID : INTEGER := 2 ** (BALANCE_WIDTH - 1); -- Center balance position (512 for 10-bit)
+ CONSTANT DEAD_ZONE : INTEGER := (2 ** BALANCE_STEP_2) / 2; -- Dead zone around center (32 for step size 64)
-end Behavioral;
+ -- Channel attenuation levels (number of bit shifts for volume reduction)
+ SIGNAL left_channel : INTEGER RANGE 0 TO BALANCE_STEPS := 0; -- Left channel attenuation (0 = no attenuation, higher = more attenuation)
+ SIGNAL right_channel : INTEGER RANGE 0 TO BALANCE_STEPS := 0; -- Right channel attenuation (0 = no attenuation, higher = more attenuation)
+
+ -- Internal AXI signals
+ SIGNAL m_axis_tvalid_int : STD_LOGIC; -- Internal valid signal for output
+
+BEGIN
+ -- Connect internal signals to output ports
+ m_axis_tvalid <= m_axis_tvalid_int;
+ -- Input ready logic: Ready when downstream is ready OR no valid data pending, AND not in reset
+ s_axis_tready <= (m_axis_tready OR NOT m_axis_tvalid_int) AND aresetn;
+
+ -- Balance calculation process
+ -- Converts joystick x-axis position to attenuation levels for each channel
+ BALANCE_CALC : PROCESS (aclk)
+ BEGIN
+
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset: No attenuation on either channel
+ left_channel <= 0;
+ right_channel <= 0;
+
+ ELSE
+ -- Balance Mapping:
+ -- balance = 0-479: Left (right channel attenuated)
+ -- balance = 480-543: Center with dead zone (no attenuation)
+ -- balance = 544-1023: Right (left channel attenuated)
+
+ -- Right-leaning balance: Attenuate left channel
+ IF to_integer(unsigned(balance)) > (BAL_MID + DEAD_ZONE) THEN
+ -- Calculate left channel attenuation based on how far right of center
+ -- Subtract center+deadzone, divide by step size, add 1 for rounding
+ left_channel <= to_integer((unsigned(balance) - to_unsigned(BAL_MID + DEAD_ZONE, balance'length)) SRL BALANCE_STEP_2) + 1;
+ ELSE
+ -- Balance not significantly right of center: no left attenuation
+ left_channel <= 0;
+ END IF;
+
+ -- Left-leaning balance: Attenuate right channel
+ IF to_integer(unsigned(balance)) < (BAL_MID - DEAD_ZONE) THEN
+ -- Calculate right channel attenuation based on how far left of center
+ -- Subtract balance from center-deadzone, divide by step size, add 1 for rounding
+ right_channel <= to_integer((to_unsigned(BAL_MID - DEAD_ZONE, balance'length) - unsigned(balance)) SRL BALANCE_STEP_2) + 1;
+ ELSE
+ -- Balance not significantly left of center: no right attenuation
+ right_channel <= 0;
+ END IF;
+
+ END IF;
+
+ END IF;
+
+ END PROCESS BALANCE_CALC;
+
+ -- AXI4-Stream data processing
+ -- Applies calculated attenuation to audio samples based on channel
+ AXIS : PROCESS (aclk)
+ BEGIN
+
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset output interface
+ m_axis_tvalid_int <= '0'; -- No valid output data
+ m_axis_tlast <= '0'; -- Clear channel indicator
+
+ ELSE
+ -- Output handshake: Clear valid flag when downstream accepts data
+ IF m_axis_tready = '1' THEN
+ m_axis_tvalid_int <= '0';
+ END IF;
+
+ -- Data processing: Apply balance when input and output are ready
+ IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN
+ -- Channel identification based on tlast signal:
+ -- tlast = '0': Left channel sample
+ -- tlast = '1': Right channel sample
+
+ IF s_axis_tlast = '0' THEN
+ -- Left channel: Apply left channel attenuation
+ -- Arithmetic right shift preserves sign for signed audio data
+ m_axis_tdata <= STD_LOGIC_VECTOR(shift_right(signed(s_axis_tdata), left_channel));
+ ELSE
+ -- Right channel: Apply right channel attenuation
+ -- Arithmetic right shift preserves sign for signed audio data
+ m_axis_tdata <= STD_LOGIC_VECTOR(shift_right(signed(s_axis_tdata), right_channel));
+ END IF;
+
+ -- Set output control signals
+ m_axis_tvalid_int <= '1'; -- Mark output as valid
+ m_axis_tlast <= s_axis_tlast; -- Pass through channel indicator
+
+ END IF;
+
+ END IF;
+
+ END IF;
+
+ END PROCESS AXIS;
+
+END Behavioral;
\ No newline at end of file
diff --git a/LAB3/src/digilent_jstk2.vhd b/LAB3/src/digilent_jstk2.vhd
index 9194ef3..1872503 100644
--- a/LAB3/src/digilent_jstk2.vhd
+++ b/LAB3/src/digilent_jstk2.vhd
@@ -1,49 +1,199 @@
-library IEEE;
-use IEEE.STD_LOGIC_1164.ALL;
+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;
+-- Entity: digilent_jstk2
+-- Purpose: Interface controller for the Digilent JSTK2 joystick module via SPI
+-- Sends LED color commands and receives joystick/button data
+ENTITY digilent_jstk2 IS
+ GENERIC (
+ DELAY_US : INTEGER := 25; -- Delay (in microseconds) between two SPI packets
+ CLKFREQ : INTEGER := 100_000_000; -- Frequency of the aclk signal (in Hz)
+ SPI_SCLKFREQ : INTEGER := 5_000 -- Frequency of the SPI SCLK clock signal (in Hz)
+ );
+ PORT (
+ aclk : IN STD_LOGIC; -- Main clock input
+ aresetn : IN STD_LOGIC; -- Active-low asynchronous reset
- -- 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;
+ -- AXI4-Stream Master Interface: Data going TO the SPI IP-Core (and so, to the JSTK2 module)
+ m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal
+ m_axis_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8-bit data to send via SPI
+ m_axis_tready : IN STD_LOGIC; -- SPI IP-Core ready to accept data
- -- 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);
+ -- AXI4-Stream Slave Interface: Data coming FROM the SPI IP-Core (and so, from the JSTK2 module)
+ -- Note: There is no tready signal, so you must be always ready to accept incoming data, or it will be lost!
+ s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal
+ s_axis_tdata : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8-bit data received via SPI
- -- 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;
+ -- Joystick and button values read from the JSTK2 module
+ jstk_x : OUT STD_LOGIC_VECTOR(9 DOWNTO 0); -- X-axis joystick position (10-bit, 0-1023)
+ jstk_y : OUT STD_LOGIC_VECTOR(9 DOWNTO 0); -- Y-axis joystick position (10-bit, 0-1023)
+ btn_jstk : OUT STD_LOGIC; -- Joystick button state (1=pressed)
+ btn_trigger : OUT STD_LOGIC; -- Trigger button state (1=pressed)
- -- 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;
+ -- LED color values to send to the JSTK2 module
+ led_r : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Red LED intensity (0-255)
+ led_g : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Green LED intensity (0-255)
+ led_b : IN STD_LOGIC_VECTOR(7 DOWNTO 0) -- Blue LED intensity (0-255)
+ );
+END digilent_jstk2;
-architecture Behavioral of digilent_jstk2 is
+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";
+ -- Command 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).
- ------------------------------------------------------------
+ -- 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) - 1;
-begin
+ -- State machine type definitions
+ TYPE tx_state_type IS (DELAY, SEND_CMD, SEND_RED, SEND_GREEN, SEND_BLUE, SEND_DUMMY);
+ TYPE rx_state_type IS (JSTK_X_LOW, JSTK_X_HIGH, JSTK_Y_LOW, JSTK_Y_HIGH, BUTTONS);
- -- ...
+ -- State machine signals
+ SIGNAL tx_state : tx_state_type := DELAY; -- Transmit state machine current state
+ SIGNAL rx_state : rx_state_type := JSTK_X_LOW; -- Receive state machine current state
-end architecture;
+ -- 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(s_axis_tdata'range); -- Temporary storage for multi-byte data reception
+
+BEGIN
+
+ -- Output valid signal control: Set to '1' when we want to send data to SPI IP-Core
+ -- Only inactive during DELAY state when waiting between packets
+ WITH tx_state SELECT m_axis_tvalid <=
+ '0' WHEN DELAY, -- No transmission during delay
+ '1' WHEN SEND_CMD, -- Send command byte
+ '1' WHEN SEND_RED, -- Send red LED value
+ '1' WHEN SEND_GREEN, -- Send green LED value
+ '1' WHEN SEND_BLUE, -- Send blue LED value
+ '1' WHEN SEND_DUMMY; -- Send dummy byte to complete transaction
+
+ -- Output data multiplexer: Select what data to send based on current TX state
+ WITH tx_state SELECT m_axis_tdata <=
+ (OTHERS => '0') WHEN DELAY, -- No data during delay
+ CMDSETLEDRGB WHEN SEND_CMD, -- SetLEDRGB command (0x84)
+ led_r WHEN SEND_RED, -- Red LED intensity value
+ led_g WHEN SEND_GREEN, -- Green LED intensity value
+ led_b WHEN SEND_BLUE, -- Blue LED intensity value
+ "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 > 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
+ IF aresetn = '0' THEN
+ -- Reset: Start in delay state with counter cleared
+ tx_state <= DELAY;
+ tx_delay_counter <= 0;
+
+ ELSE
+
+ CASE tx_state IS
+
+ WHEN DELAY =>
+ -- Wait for required delay period between SPI transactions
+ IF tx_delay_counter = DELAY_CLK_CYCLES THEN
+ tx_delay_counter <= 0; -- Reset counter
+ tx_state <= SEND_CMD; -- Start new transmission
+ ELSE
+ tx_delay_counter <= tx_delay_counter + 1; -- Continue counting
+ END IF;
+
+ WHEN SEND_CMD =>
+ -- Send SetLEDRGB command byte
+ IF m_axis_tready = '1' THEN
+ tx_state <= SEND_RED; -- Move to red LED transmission
+ END IF;
+
+ WHEN SEND_RED =>
+ -- Send red LED intensity value
+ IF m_axis_tready = '1' THEN
+ tx_state <= SEND_GREEN; -- Move to green LED transmission
+ END IF;
+
+ WHEN SEND_GREEN =>
+ -- Send green LED intensity value
+ IF m_axis_tready = '1' THEN
+ tx_state <= SEND_BLUE; -- Move to blue LED transmission
+ END IF;
+
+ WHEN SEND_BLUE =>
+ -- Send blue LED intensity value
+ IF m_axis_tready = '1' THEN
+ tx_state <= SEND_DUMMY; -- Move to dummy byte transmission
+ END IF;
+
+ WHEN SEND_DUMMY =>
+ -- Send dummy byte to complete 5-byte transaction
+ IF m_axis_tready = '1' THEN
+ tx_state <= DELAY; -- Return to delay state
+ END IF;
+
+ END CASE;
+ END IF;
+ END IF;
+ END PROCESS TX;
+
+ -- RX State Machine: Receives 5 bytes of response data and updates outputs
+ -- Protocol: X_low(1) + X_high(1) + Y_low(1) + Y_high(1) + Buttons(1) = 5 bytes total
+ RX : PROCESS (aclk)
+ BEGIN
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset: Start waiting for X-axis low byte
+ rx_state <= JSTK_X_LOW;
+ rx_cache <= (OTHERS => '0');
+
+ ELSE
+
+ CASE rx_state IS
+
+ WHEN JSTK_X_LOW =>
+ -- Receive X-axis low byte (bits 7:0)
+ IF s_axis_tvalid = '1' THEN
+ rx_cache <= s_axis_tdata; -- Store low byte temporarily
+ rx_state <= JSTK_X_HIGH; -- Wait for high byte
+ END IF;
+
+ WHEN JSTK_X_HIGH =>
+ -- Receive X-axis high byte (bits 9:8) and assemble complete X value
+ IF s_axis_tvalid = '1' THEN
+ -- Combine: high_byte(1:0) & low_byte(7:0) = 10-bit X position
+ jstk_x <= s_axis_tdata(1 DOWNTO 0) & rx_cache;
+ rx_state <= JSTK_Y_LOW; -- Move to Y-axis reception
+ END IF;
+
+ WHEN JSTK_Y_LOW =>
+ -- Receive Y-axis low byte (bits 7:0)
+ IF s_axis_tvalid = '1' THEN
+ rx_cache <= s_axis_tdata; -- Store low byte temporarily
+ rx_state <= JSTK_Y_HIGH; -- Wait for high byte
+ END IF;
+
+ WHEN JSTK_Y_HIGH =>
+ -- Receive Y-axis high byte (bits 9:8) and assemble complete Y value
+ IF s_axis_tvalid = '1' THEN
+ -- Combine: high_byte(1:0) & low_byte(7:0) = 10-bit Y position
+ jstk_y <= s_axis_tdata(1 DOWNTO 0) & rx_cache;
+ rx_state <= BUTTONS; -- Move to button reception
+ END IF;
+
+ WHEN BUTTONS =>
+ -- Receive button states byte
+ IF s_axis_tvalid = '1' THEN
+ btn_jstk <= s_axis_tdata(0); -- Joystick button (bit 0)
+ btn_trigger <= s_axis_tdata(1); -- Trigger button (bit 1)
+ rx_state <= JSTK_X_LOW; -- Return to start for next packet
+ END IF;
+
+ END CASE;
+ END IF;
+ END IF;
+ END PROCESS RX;
+
+END ARCHITECTURE;
\ 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 f8b1184..fee2456 100644
--- a/LAB3/src/effect_selector.vhd
+++ b/LAB3/src/effect_selector.vhd
@@ -1,54 +1,82 @@
-----------------------------------------------------------------------------------
--- 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;
+USE IEEE.NUMERIC_STD.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
+-- Purpose: Routes joystick input to different audio control parameters based on effect mode
+-- Acts as a multiplexer/router for joystick control signals
+ENTITY effect_selector IS
+ GENERIC (
+ JOYSTICK_LENGHT : INTEGER := 10 -- Width of joystick position data (10-bit = 0-1023 range)
);
- 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 (
+ -- Clock and reset signals
+ aclk : IN STD_LOGIC; -- Main clock input
+ aresetn : IN STD_LOGIC; -- Active-low asynchronous reset
+
+ -- Control and input signals
+ effect : IN STD_LOGIC; -- Effect mode selector (0=volume/balance mode, 1=LFO)
+ jstck_x : IN STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0); -- X-axis joystick position
+ jstck_y : IN STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0); -- Y-axis joystick position
+
+ -- Output control parameters
+ volume : OUT STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0); -- Volume control output
+ balance : OUT STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0); -- Balance control output
+ lfo_period : OUT STD_LOGIC_VECTOR(JOYSTICK_LENGHT - 1 DOWNTO 0) -- LFO period control output
);
-end effect_selector;
+END effect_selector;
-architecture Behavioral of effect_selector is
+ARCHITECTURE Behavioral OF effect_selector IS
-begin
+ 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
-end Behavioral;
+ -- Main control logic process
+ -- Routes joystick axes to appropriate audio control parameters based on selected mode
+ PROCESS (aclk)
+ BEGIN
+
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset all outputs to default/center values
+ volume <= JOYSTICK_DEFAULT; -- Default volume (center position)
+ balance <= JOYSTICK_DEFAULT; -- Center balance position
+ lfo_period <= JOYSTICK_DEFAULT; -- Default LFO period (center position)
+
+ ELSE
+ -- Normal operation: Route joystick inputs based on effect mode
+
+ -- Y-axis always controls different parameters based on effect mode
+ -- 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
+ -- 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
+ balance <= JOYSTICK_DEFAULT; -- Reset balance to center position
+
+ ELSE
+ -- Volume/Balance Mode:
+ -- Y-axis controls overall volume level
+ -- X-axis controls left/right audio balance
+ volume <= jstck_y;
+ balance <= jstck_x;
+
+ -- LFO period remains at last set value (preserved from previous LFO mode)
+
+ 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..8c7e198 100644
--- a/LAB3/src/led_controller.vhd
+++ b/LAB3/src/led_controller.vhd
@@ -1,22 +1,64 @@
-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
- );
- Port (
- mute_enable : in std_logic;
- filter_enable : in std_logic;
+-- Entity: led_controller
+-- Purpose: Controls RGB LED indicators based on audio system status
+-- Provides visual feedback for mute and filter enable states
+ENTITY led_controller IS
+ GENERIC (
+ LED_WIDTH : POSITIVE := 8 -- Width of LED intensity control (8-bit = 0-255 intensity levels)
+ );
+ PORT (
+ -- Control input signals
+ mute_enable : IN STD_LOGIC; -- Mute status (1=audio muted, 0=audio active)
+ filter_enable : IN STD_LOGIC; -- Filter status (1=filter active, 0=filter bypassed)
- 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;
+ -- RGB LED output signals (intensity control)
+ led_r : OUT STD_LOGIC_VECTOR(LED_WIDTH - 1 DOWNTO 0); -- Red LED intensity (0-255)
+ led_g : OUT STD_LOGIC_VECTOR(LED_WIDTH - 1 DOWNTO 0); -- Green LED intensity (0-255)
+ led_b : OUT STD_LOGIC_VECTOR(LED_WIDTH - 1 DOWNTO 0) -- Blue LED intensity (0-255)
+ );
+END led_controller;
-architecture Behavioral of led_controller is
+ARCHITECTURE Behavioral OF led_controller IS
-begin
+ -- Constants for LED intensity levels
+ CONSTANT ALL_ON : STD_LOGIC_VECTOR(LED_WIDTH - 1 DOWNTO 0) := (OTHERS => '1'); -- Maximum brightness (255)
+ CONSTANT ALL_OFF : STD_LOGIC_VECTOR(LED_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); -- LED off (0)
-end Behavioral;
+BEGIN
+
+ -- LED Status Indication Logic:
+ -- Priority-based color coding for system status
+ --
+ -- Color Scheme:
+ -- RED = Mute active (highest priority - audio completely off)
+ -- BLUE = Filter active (medium priority - audio processing enabled)
+ -- GREEN = Normal operation (lowest priority - audio pass-through)
+
+ -- Red LED Control: Indicates mute status
+ -- Turn on red LED when audio is muted, regardless of filter state
+ led_r <= ALL_ON WHEN mute_enable = '1' ELSE
+ ALL_OFF;
+
+ -- Blue LED Control: Indicates filter activation
+ -- Turn on blue LED when filter is active AND audio is not muted
+ -- Mute has higher priority than filter indication
+ led_b <= ALL_ON WHEN (mute_enable = '0' AND filter_enable = '1') ELSE
+ ALL_OFF;
+
+ -- Green LED Control: Indicates normal operation
+ -- Turn on green LED when audio is active (not muted) AND filter is disabled
+ -- This represents the default "audio pass-through" state
+ led_g <= ALL_ON WHEN (mute_enable = '0' AND filter_enable = '0') ELSE
+ ALL_OFF;
+
+ -- Truth Table for LED States:
+ -- mute_enable | filter_enable | RED | GREEN | BLUE | Status
+ -- ------------|---------------|-----|-------|------|------------------
+ -- 0 | 0 | 0 | 1 | 0 | Normal (Green)
+ -- 0 | 1 | 0 | 0 | 1 | Filter On (Blue)
+ -- 1 | 0 | 1 | 0 | 0 | Muted (Red)
+ -- 1 | 1 | 1 | 0 | 0 | Muted (Red)
+
+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..4627985 100644
--- a/LAB3/src/led_level_controller.vhd
+++ b/LAB3/src/led_level_controller.vhd
@@ -1,60 +1,165 @@
-----------------------------------------------------------------------------------
--- 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;
+USE IEEE.NUMERIC_STD.ALL;
+USE IEEE.MATH_REAL.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 led_level_controller is
- generic(
- NUM_LEDS : positive := 16;
- CHANNEL_LENGHT : positive := 24;
- refresh_time_ms: positive :=1;
- clock_period_ns: positive :=10
+-- Entity: led_level_controller
+-- Purpose: Audio level meter using LEDs to display real-time audio amplitude
+-- Processes stereo audio samples and drives a bar graph LED display
+ENTITY led_level_controller IS
+ GENERIC (
+ NUM_LEDS : POSITIVE := 16; -- Number of LEDs in the level meter display
+ CHANNEL_LENGHT : POSITIVE := 24; -- Width of audio data (24-bit audio samples)
+ refresh_time_ms : POSITIVE := 1; -- LED refresh rate in milliseconds (1ms = 1kHz update rate)
+ clock_period_ns : POSITIVE := 10 -- System clock period in nanoseconds (10ns = 100MHz)
);
- Port (
-
- aclk : in std_logic;
- aresetn : in std_logic;
-
- led : out std_logic_vector(NUM_LEDS-1 downto 0);
+ 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(CHANNEL_LENGHT-1 downto 0);
- s_axis_tlast : in std_logic;
- s_axis_tready : out std_logic
+ -- LED output array (bar graph display)
+ led : OUT STD_LOGIC_VECTOR(NUM_LEDS - 1 DOWNTO 0); -- LED control signals (1=on, 0=off)
+ -- AXI4-Stream Slave Interface (Audio Input)
+ s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal
+ s_axis_tdata : IN STD_LOGIC_VECTOR(CHANNEL_LENGHT - 1 DOWNTO 0); -- Audio sample input
+ s_axis_tlast : IN STD_LOGIC; -- Channel indicator (0=right, 1=left)
+ s_axis_tready : OUT STD_LOGIC -- Always ready to accept data
);
-end led_level_controller;
+END led_level_controller;
-architecture Behavioral of led_level_controller is
+ARCHITECTURE Behavioral OF led_level_controller IS
-begin
+ -- Calculate clock cycles needed for LED refresh timing
+ CONSTANT REFRESH_CYCLES : INTEGER := (refresh_time_ms * 1_000_000) / clock_period_ns - 1;
-end Behavioral;
+ -- 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
+ SIGNAL refresh_tick : STD_LOGIC := '0'; -- Pulse signal generated every refresh period
+
+ -- Audio amplitude storage for both stereo channels
+ -- Stores absolute values (magnitude) of left and right audio channels
+ SIGNAL abs_l : UNSIGNED(CHANNEL_LENGHT - 1 DOWNTO 0) := (OTHERS => '0'); -- Absolute left channel amplitude registers
+ SIGNAL combined_amp : UNSIGNED(CHANNEL_LENGHT - 1 DOWNTO 0) := (OTHERS => '0'); -- Combined amplitude for LED level calculation
+
+BEGIN
+
+ -- Always ready for AXI4-Stream input
+ s_axis_tready <= '1';
+
+ -- Capture absolute value of input sample for left/right channel
+ PROCESS (aclk)
+ BEGIN
+
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset: Clear both channel amplitude registers
+ abs_l <= (OTHERS => '0');
+ combined_amp <= (OTHERS => '0');
+
+ ELSIF s_axis_tvalid = '1' THEN
+ -- Valid audio data received: Process the sample
+
+ -- Channel routing based on AXI4-Stream tlast signal
+ -- tlast = '1' indicates right channel, tlast = '0' indicates left channel
+ IF s_axis_tlast = '1' THEN
+ -- Right channel: Combine left and right channel amplitudes
+ -- RESIZE ensures the sum fits within the variable's bit width.
+ -- There isn't data loss since both abs_l and abs(s_axis_tdata) are one bit shorter than combined_amp,
+ -- due to the absolute value operation.
+ combined_amp <= RESIZE(abs_l + UNSIGNED(ABS(SIGNED(s_axis_tdata))), combined_amp'LENGTH);
+
+ ELSE
+ -- Left channel: Store absolute value of audio sample
+ abs_l <= UNSIGNED(ABS(SIGNED(s_axis_tdata)));
+
+ END IF;
+
+ END IF;
+
+ END IF;
+
+ END PROCESS;
+
+ -- LED refresh tick generator
+ PROCESS (aclk)
+ BEGIN
+
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset: Initialize counter and tick signal
+ refresh_counter <= 0;
+ refresh_tick <= '0';
+
+ ELSE
+ IF refresh_counter = REFRESH_CYCLES THEN
+ refresh_counter <= 0;
+ refresh_tick <= '1';
+
+ ELSE
+ refresh_counter <= refresh_counter + 1;
+ refresh_tick <= '0';
+
+ END IF;
+
+ END IF;
+
+ END IF;
+
+ END PROCESS;
+
+ -- LED level calculation and bar graph generation process
+ -- Combines left and right channel amplitudes and converts to LED display pattern
+ -- Updates only when refresh_tick is active to maintain stable visual display
+ PROCESS (aclk)
+
+ VARIABLE led_level : INTEGER RANGE 0 TO 2 ** NUMLEDS_BITS := 0;
+
+ BEGIN
+
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset: Turn off all LEDs and reset level counter
+ led <= (OTHERS => '0');
+
+ ELSIF refresh_tick = '1' THEN
+ -- LED update cycle: Calculate new LED pattern based on audio amplitude
+
+ -- Linear scale to LED level conversion to get the best visual effect
+ IF combined_amp = 0 THEN
+ led_level := 0; -- No audio signal, turn off all LEDs
+
+ ELSE
+ led_level := 1 + to_integer(shift_right(combined_amp, CHANNEL_LENGHT - NUMLEDS_BITS));
+
+ END IF;
+
+ -- Saturation protection: Limit LED level to maximum available LEDs
+ -- Prevents overflow and ensures the LED index stays within bounds.
+ IF led_level > NUM_LEDS THEN
+ led_level := NUM_LEDS;
+
+ END IF;
+
+ -- Update LED output based on calculated level
+ led <= (OTHERS => '0');
+
+ IF led_level > 0 THEN
+ led(led_level - 1 DOWNTO 0) <= (OTHERS => '1');
+
+ END IF;
+
+ END IF;
+
+ END IF;
+
+ END PROCESS;
+
+END Behavioral;
\ No newline at end of file
diff --git a/LAB3/src/moving_average_filter.vhd b/LAB3/src/moving_average_filter.vhd
index 73dd17b..bd307a6 100644
--- a/LAB3/src/moving_average_filter.vhd
+++ b/LAB3/src/moving_average_filter.vhd
@@ -1,32 +1,200 @@
-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 moving_average_filter is
- generic (
- -- Filter order expressed as 2^(FILTER_ORDER_POWER)
- FILTER_ORDER_POWER : integer := 5;
+-- Entity: moving_average_filter
+-- 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
+ GENERIC (
+ -- Filter order expressed as 2^(FILTER_ORDER_POWER)
+ -- Example: FILTER_ORDER_POWER = 5 means 32-sample moving average
+ FILTER_ORDER_POWER : INTEGER := 5;
- TDATA_WIDTH : positive := 24
- );
- Port (
- aclk : in std_logic;
- aresetn : in std_logic;
+ TDATA_WIDTH : POSITIVE := 24 -- Width of audio data bus (24-bit audio samples)
+ );
+ 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
- );
-end moving_average_filter;
+ -- 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); -- Filtered audio sample output
+ m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough
+ m_axis_tready : IN STD_LOGIC -- Downstream ready signal
+ );
+END moving_average_filter;
-architecture Behavioral of moving_average_filter is
+ARCHITECTURE Behavioral OF moving_average_filter IS
-begin
+ -- Calculate actual filter order from power-of-2 representation
+ CONSTANT FILTER_ORDER : INTEGER := 2 ** FILTER_ORDER_POWER;
-end Behavioral;
+ -- Array type for storing audio samples in circular buffers
+ TYPE sample_array IS ARRAY (0 TO FILTER_ORDER - 1) OF signed(TDATA_WIDTH - 1 DOWNTO 0);
+
+ -- Right channel (RX) processing signals
+ SIGNAL samples_rx : sample_array := (OTHERS => (OTHERS => '0')); -- Circular buffer for right channel samples
+ SIGNAL sum_rx : signed(TDATA_WIDTH + FILTER_ORDER_POWER - 1 DOWNTO 0) := (OTHERS => '0'); -- Running sum of right channel samples
+ SIGNAL wr_ptr_rx : INTEGER RANGE 0 TO FILTER_ORDER - 1 := 0; -- Write pointer for right channel buffer
+
+ -- Left channel (LX) processing signals
+ SIGNAL samples_lx : sample_array := (OTHERS => (OTHERS => '0')); -- Circular buffer for left channel samples
+ SIGNAL sum_lx : signed(TDATA_WIDTH + FILTER_ORDER_POWER - 1 DOWNTO 0) := (OTHERS => '0'); -- Running sum of left channel samples
+ SIGNAL wr_ptr_lx : INTEGER RANGE 0 TO FILTER_ORDER - 1 := 0; -- Write pointer for left channel buffer
+
+ -- Control and interface signals
+ SIGNAL trigger : STD_LOGIC := '0'; -- Trigger signal to indicate when to output filtered data
+ SIGNAL s_axis_tready_int : STD_LOGIC := '0'; -- Internal ready signal for input interface
+ SIGNAL s_axis_tlast_reg : STD_LOGIC := '0'; -- Registered version of tlast for output synchronization
+ SIGNAL m_axis_tvalid_int : STD_LOGIC := '0'; -- Internal valid signal for output interface
+
+BEGIN
+
+ -- Connect internal signals to output ports
+ m_axis_tvalid <= m_axis_tvalid_int;
+ s_axis_tready <= s_axis_tready_int;
+
+ -- Main processing logic - synchronous to clock
+ PROCESS (aclk)
+ BEGIN
+
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset all filter state and control signals
+ samples_rx <= (OTHERS => (OTHERS => '0')); -- Clear right channel sample buffer
+ samples_lx <= (OTHERS => (OTHERS => '0')); -- Clear left channel sample buffer
+ sum_rx <= (OTHERS => '0'); -- Clear right channel running sum
+ sum_lx <= (OTHERS => '0'); -- Clear left channel running sum
+ wr_ptr_rx <= 0; -- Reset right channel write pointer
+ wr_ptr_lx <= 0; -- Reset left channel write pointer
+
+ -- Reset AXI4-Stream interface signals
+ s_axis_tlast_reg <= '0'; -- Clear registered tlast
+ s_axis_tready_int <= '0'; -- Not ready during reset
+ m_axis_tvalid_int <= '0'; -- No valid output during reset
+ m_axis_tlast <= '0'; -- Clear output tlast
+
+ ELSE
+ -- Normal operation
+
+ -- Output handshake management:
+ -- Clear valid flag when downstream accepts data
+ IF m_axis_tready = '1' THEN
+ m_axis_tvalid_int <= '0';
+ END IF;
+
+ -- Data output logic:
+ -- Output filtered data when trigger is set AND output interface is available
+ IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
+
+ -- Select which channel's filtered data to output based on registered tlast
+ IF s_axis_tlast_reg = '1' THEN
+ -- Right channel: Output averaged right channel data
+ -- Divide sum by filter order using right shift (efficient division by power of 2)
+ m_axis_tdata <= STD_LOGIC_VECTOR(
+ resize(
+ shift_right(
+ sum_rx, -- Right channel running sum
+ FILTER_ORDER_POWER -- Divide by 2^FILTER_ORDER_POWER
+ ),
+ m_axis_tdata'length -- Resize to output width
+ )
+ );
+
+ ELSE
+ -- Left channel: Output averaged left channel data
+ -- Divide sum by filter order using right shift (efficient division by power of 2)
+ m_axis_tdata <= STD_LOGIC_VECTOR(
+ resize(
+ shift_right(
+ sum_lx, -- Left channel running sum
+ FILTER_ORDER_POWER -- Divide by 2^FILTER_ORDER_POWER
+ ),
+ m_axis_tdata'length -- Resize to output width
+ )
+ );
+
+ END IF;
+
+ -- Set output control signals
+ m_axis_tlast <= s_axis_tlast_reg; -- Pass through the registered channel indicator
+ m_axis_tvalid_int <= '1'; -- Mark output as valid
+ trigger <= '0'; -- Clear trigger - data has been output
+
+ END IF;
+
+ -- Data input logic:
+ -- Process new input samples when both valid and ready are asserted
+ IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
+
+ -- Channel identification and processing based on tlast signal
+ IF s_axis_tlast = '1' THEN
+ -- Right channel processing (tlast = '1')
+
+ -- Store new sample in circular buffer, overwriting oldest sample
+ samples_rx(wr_ptr_rx) <= signed(s_axis_tdata);
+
+ -- Update write pointer with wraparound (circular buffer behavior)
+ wr_ptr_rx <= (wr_ptr_rx + 1) MOD FILTER_ORDER;
+
+ -- Update running sum using sliding window technique:
+ -- Remove the oldest sample (about to be overwritten) and add the new sample
+ -- This maintains the sum of the most recent FILTER_ORDER samples
+ sum_rx <= sum_rx - samples_rx(wr_ptr_rx) + signed(s_axis_tdata);
+
+ -- Register tlast for output synchronization
+ s_axis_tlast_reg <= s_axis_tlast;
+
+ ELSE
+ -- Left channel processing (tlast = '0')
+
+ -- Store new sample in circular buffer, overwriting oldest sample
+ samples_lx(wr_ptr_lx) <= signed(s_axis_tdata);
+
+ -- Update write pointer with wraparound (circular buffer behavior)
+ wr_ptr_lx <= (wr_ptr_lx + 1) MOD FILTER_ORDER;
+
+ -- Update running sum using sliding window technique:
+ -- Remove the oldest sample (about to be overwritten) and add the new sample
+ -- This maintains the sum of the most recent FILTER_ORDER samples
+ sum_lx <= sum_lx - samples_lx(wr_ptr_lx) + signed(s_axis_tdata);
+
+ -- Register tlast for output synchronization
+ s_axis_tlast_reg <= s_axis_tlast;
+
+ END IF;
+
+ -- Set trigger to indicate that new filtered data is ready for output
+ trigger <= '1';
+
+ END IF;
+
+ -- Input ready logic:
+ -- Ready to accept new input when downstream is ready OR no valid output pending
+ -- This implements proper AXI4-Stream backpressure handling
+ s_axis_tready_int <= m_axis_tready OR NOT m_axis_tvalid_int;
+
+ END IF;
+
+ END IF;
+
+ END PROCESS;
+
+ -- Filter Operation Summary:
+ -- 1. Maintains separate circular buffers for left and right audio channels
+ -- 2. Uses running sum technique for efficient moving average calculation
+ -- 3. Each new sample: removes oldest from sum, adds newest to sum
+ -- 4. Output = sum / FILTER_ORDER (using efficient bit shift division)
+ -- 5. Provides low-pass filtering with configurable filter order
+
+END Behavioral;
\ No newline at end of file
diff --git a/LAB3/src/moving_average_filter_en.vhd b/LAB3/src/moving_average_filter_en.vhd
index 70c0d4c..5a57442 100644
--- a/LAB3/src/moving_average_filter_en.vhd
+++ b/LAB3/src/moving_average_filter_en.vhd
@@ -1,34 +1,168 @@
-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 moving_average_filter_en is
- generic (
- -- Filter order expressed as 2^(FILTER_ORDER_POWER)
- FILTER_ORDER_POWER : integer := 5;
+-- Entity: moving_average_filter_en
+-- Purpose: Switchable audio filter that can be enabled or disabled at runtime
+-- When enabled: applies moving average low-pass filtering
+-- When disabled: passes audio through unchanged (all-pass filter)
+-- This allows real-time comparison between filtered and unfiltered audio
+ENTITY moving_average_filter_en IS
+ GENERIC (
+ -- Filter order expressed as 2^(FILTER_ORDER_POWER)
+ -- Example: FILTER_ORDER_POWER = 5 means filter order = 32 samples
+ FILTER_ORDER_POWER : INTEGER := 5;
- TDATA_WIDTH : positive := 24
- );
- Port (
- aclk : in std_logic;
- aresetn : in std_logic;
+ TDATA_WIDTH : POSITIVE := 24 -- Width of audio data bus (24-bit audio samples)
+ );
+ 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 (filtered or unfiltered)
+ m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough
+ m_axis_tready : IN STD_LOGIC; -- Downstream ready signal
- enable_filter : in std_logic
- );
-end moving_average_filter_en;
+ -- Filter control input
+ enable_filter : IN STD_LOGIC -- Filter enable control (1=moving average filter, 0=all-pass filter)
+ );
+END moving_average_filter_en;
-architecture Behavioral of moving_average_filter_en is
+ARCHITECTURE Behavioral OF moving_average_filter_en IS
-begin
+ -- Component declaration for all-pass filter
+ -- This filter passes audio unchanged but maintains the same latency as the moving average filter
+ COMPONENT all_pass_filter IS
+ GENERIC (
+ TDATA_WIDTH : POSITIVE := 24
+ );
+ 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 DOWNTO 0);
+ m_axis_tlast : OUT STD_LOGIC;
+ m_axis_tready : IN STD_LOGIC
+ );
+ END COMPONENT;
+
+ -- Component declaration for moving average filter
+ -- This filter applies low-pass filtering by averaging multiple audio samples
+ 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 path
+ -- These signals carry data when filtering is disabled
+ SIGNAL all_pass_m_tvalid : STD_LOGIC; -- All-pass filter output valid
+ SIGNAL all_pass_m_tdata : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- All-pass filter output data
+ SIGNAL all_pass_m_tlast : STD_LOGIC; -- All-pass filter output tlast
+ SIGNAL all_pass_s_tready : STD_LOGIC; -- All-pass filter input ready
+
+ -- Internal signals for the moving average filter path
+ -- These signals carry data when filtering is enabled
+ SIGNAL moving_avg_m_tvalid : STD_LOGIC; -- Moving average filter output valid
+ SIGNAL moving_avg_m_tdata : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Moving average filter output data
+ SIGNAL moving_avg_m_tlast : STD_LOGIC; -- Moving average filter output tlast
+ SIGNAL moving_avg_s_tready : STD_LOGIC; -- Moving average filter input ready
+
+BEGIN
+
+ -- Instantiate the all-pass filter (bypass path)
+ -- This provides unfiltered audio with matched latency for seamless switching
+ all_pass_inst : all_pass_filter
+ GENERIC MAP(
+ TDATA_WIDTH => TDATA_WIDTH
+ )
+ PORT MAP(
+ aclk => aclk,
+ aresetn => aresetn,
+
+ -- Connect input directly to all-pass filter
+ s_axis_tvalid => s_axis_tvalid,
+ s_axis_tdata => s_axis_tdata,
+ s_axis_tlast => s_axis_tlast,
+ s_axis_tready => all_pass_s_tready,
+
+ -- All-pass filter outputs (used when enable_filter = '0')
+ m_axis_tvalid => all_pass_m_tvalid,
+ m_axis_tdata => all_pass_m_tdata,
+ m_axis_tlast => all_pass_m_tlast,
+ m_axis_tready => m_axis_tready
+ );
+
+ -- Instantiate the moving average filter (filtering path)
+ -- This provides low-pass filtered audio for noise reduction
+ moving_avg_inst : moving_average_filter
+ GENERIC MAP(
+ FILTER_ORDER_POWER => FILTER_ORDER_POWER,
+ TDATA_WIDTH => TDATA_WIDTH
+ )
+ PORT MAP(
+ aclk => aclk,
+ aresetn => aresetn,
+
+ -- Connect input directly to moving average filter
+ s_axis_tvalid => s_axis_tvalid,
+ s_axis_tdata => s_axis_tdata,
+ s_axis_tlast => s_axis_tlast,
+ s_axis_tready => moving_avg_s_tready,
+
+ -- Moving average filter outputs (used when enable_filter = '1')
+ m_axis_tvalid => moving_avg_m_tvalid,
+ m_axis_tdata => moving_avg_m_tdata,
+ m_axis_tlast => moving_avg_m_tlast,
+ m_axis_tready => m_axis_tready
+ );
+
+ -- Output multiplexer: Select between filtered and unfiltered audio paths
+ -- This switching is controlled by the enable_filter signal
+
+ -- Input ready selection: Route backpressure to the active filter
+ s_axis_tready <= all_pass_s_tready WHEN enable_filter = '0' ELSE moving_avg_s_tready;
+
+ -- Output data selection: Route output from the active filter
+ 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;
+
+ -- Filter Path Selection Logic:
+ -- enable_filter = '0': All-pass path (unfiltered audio with matched latency)
+ -- enable_filter = '1': Moving average path (low-pass filtered audio)
+ --
+ -- Both filters run continuously but only the selected path is routed to output
+ -- This allows for glitch-free switching between filtered and unfiltered audio
+
+END Behavioral;
\ No newline at end of file
diff --git a/LAB3/src/mute_controller.vhd b/LAB3/src/mute_controller.vhd
index 2afdbf0..32e5fc8 100644
--- a/LAB3/src/mute_controller.vhd
+++ b/LAB3/src/mute_controller.vhd
@@ -1,31 +1,96 @@
-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
- );
- Port (
- aclk : in std_logic;
- aresetn : in std_logic;
+-- Entity: mute_controller
+-- Purpose: Controls audio muting by replacing audio samples with zeros when mute is active
+-- Implements AXI4-Stream interface for seamless integration in audio processing chain
+ENTITY mute_controller IS
+ GENERIC (
+ TDATA_WIDTH : POSITIVE := 24 -- Width of audio data bus (24-bit audio samples)
+ );
+ 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 (muted or passed through)
+ m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough
+ m_axis_tready : IN STD_LOGIC; -- Downstream ready signal
- mute : in std_logic
- );
-end mute_controller;
+ -- Control input
+ mute : IN STD_LOGIC -- Mute control (1=mute audio, 0=pass audio through)
+ );
+END mute_controller;
-architecture Behavioral of mute_controller is
+ARCHITECTURE Behavioral OF mute_controller IS
-begin
+ -- Internal signal for output valid control
+ SIGNAL m_axis_tvalid_int : STD_LOGIC;
-end Behavioral;
+BEGIN
+
+ -- Connect internal signals to output ports
+ m_axis_tvalid <= m_axis_tvalid_int;
+
+ -- Input ready logic: Ready when downstream is ready OR no valid data pending, AND not in reset
+ -- This implements proper AXI4-Stream backpressure handling
+ s_axis_tready <= (m_axis_tready OR NOT m_axis_tvalid_int) AND aresetn;
+
+ -- Main mute control process
+ -- Handles AXI4-Stream protocol and mute functionality
+ PROCESS (aclk)
+ BEGIN
+
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset state: Clear all output control signals
+ m_axis_tvalid_int <= '0'; -- No valid output data during reset
+ m_axis_tlast <= '0'; -- Clear channel indicator
+
+ ELSE
+ -- Normal operation
+
+ -- Output handshake management:
+ -- Clear valid flag when downstream accepts data
+ -- This allows new data to be output on the next cycle
+ IF m_axis_tready = '1' THEN
+ m_axis_tvalid_int <= '0';
+ END IF;
+
+ -- Data processing: Handle mute control when both input and output are ready
+ -- This ensures proper AXI4-Stream handshaking
+ IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN
+ -- Mute control logic:
+ IF mute = '1' THEN
+ -- Mute active: Replace audio data with silence (all zeros)
+ -- This effectively removes all audio content while maintaining data flow
+ m_axis_tdata <= (OTHERS => '0');
+ ELSE
+ -- Mute inactive: Pass audio data through unchanged
+ -- Normal audio processing mode
+ m_axis_tdata <= s_axis_tdata;
+ END IF;
+
+ -- Set output control signals
+ m_axis_tvalid_int <= '1'; -- Mark output data as valid
+ m_axis_tlast <= s_axis_tlast; -- Pass through channel indicator unchanged
+
+ 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..d567757 100644
--- a/LAB3/src/volume_controller.vhd
+++ b/LAB3/src/volume_controller.vhd
@@ -1,35 +1,170 @@
-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
- );
- Port (
- aclk : in std_logic;
- aresetn : in std_logic;
+-- 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; -- 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)
- );
-end volume_controller;
+ -- 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
+ARCHITECTURE Behavioral OF volume_controller IS
-begin
+ -- 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;
-end Behavioral;
+ -- 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;
+
+ -- 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;
+
+ -- 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;
+
+ -- 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;
+
+ -- 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 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 (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,
+
+ -- 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,
+
+ -- 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
+ );
+
+ -- 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,
+
+ -- 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,
+
+ -- 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;
\ No newline at end of file
diff --git a/LAB3/src/volume_multiplier.vhd b/LAB3/src/volume_multiplier.vhd
index 34641e2..26c2d49 100644
--- a/LAB3/src/volume_multiplier.vhd
+++ b/LAB3/src/volume_multiplier.vhd
@@ -1,33 +1,170 @@
-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
- );
- Port (
- aclk : in std_logic;
- aresetn : in std_logic;
+-- Entity: volume_multiplier
+-- Purpose: First stage of volume control pipeline - multiplies audio samples by volume scaling factor
+-- Uses bit-shifting multiplication for efficient hardware implementation
+-- Implements exponential volume scaling for natural-feeling volume control
+ENTITY volume_multiplier IS
+ GENERIC (
+ TDATA_WIDTH : POSITIVE := 24; -- Width of input audio data (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)
+ );
+ 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 + 2**(VOLUME_WIDTH-VOLUME_STEP_2-1) downto 0);
- m_axis_tlast : out std_logic;
- m_axis_tready : in std_logic;
+ -- AXI4-Stream Master Interface (Audio Output with extended width)
+ m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal
+ m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) DOWNTO 0); -- Extended width output data
+ 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)
- );
-end volume_multiplier;
+ -- Volume control input
+ volume : IN STD_LOGIC_VECTOR(VOLUME_WIDTH - 1 DOWNTO 0) -- Volume level (0=minimum, 1023=maximum)
+ );
+END volume_multiplier;
-architecture Behavioral of volume_multiplier is
+ARCHITECTURE Behavioral OF volume_multiplier IS
-begin
+ -- Calculate volume control parameters based on generics
+ CONSTANT VOLUME_STEPS : INTEGER := (2 ** (VOLUME_WIDTH - 1)) / (2 ** VOLUME_STEP_2) + 1; -- Number of volume steps (9 steps for 10-bit)
+ CONSTANT VOL_MID : INTEGER := 2 ** (VOLUME_WIDTH - 1); -- Center volume position (512 for 10-bit)
+ CONSTANT DEAD_ZONE : INTEGER := (2 ** VOLUME_STEP_2) / 2; -- Dead zone around center (32 for step size 64)
-end Behavioral;
+ -- Volume scaling factor as exponential multiplier
+ -- Positive values = amplification (left shift), negative values = attenuation (right shift)
+ SIGNAL volume_exp_mult : INTEGER RANGE -VOLUME_STEPS TO VOLUME_STEPS := 0;
+
+ -- Internal AXI4-Stream signals
+ SIGNAL m_axis_tvalid_int : STD_LOGIC; -- Internal valid signal for output
+
+BEGIN
+ -- Connect internal signals to output ports
+ m_axis_tvalid <= m_axis_tvalid_int;
+
+ -- Input ready logic: Ready when downstream is ready OR no valid data pending, AND not in reset
+ -- This implements proper AXI4-Stream backpressure handling
+ s_axis_tready <= (m_axis_tready OR NOT m_axis_tvalid_int) AND aresetn;
+
+ -- Volume to exponent conversion process
+ -- Converts joystick y-axis position to bit-shift amount for exponential volume scaling
+ VOLUME_CALC : PROCESS (aclk)
+ BEGIN
+
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset: Set to unity gain (no scaling)
+ volume_exp_mult <= 0;
+
+ ELSE
+ -- Volume mapping and conversion to exponential scaling factor:
+ -- 1. Convert volume to signed value
+ -- 2. Center around middle position (VOL_MID)
+ -- 3. Apply dead zone offset for smooth center operation
+ -- 4. Divide by step size to get exponential scaling factor
+ --
+ -- Volume Range Mapping:
+ -- 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),
+ VOLUME_STEP_2
+ )
+ );
+
+ END IF;
+
+ END IF;
+
+ END PROCESS VOLUME_CALC;
+
+ -- AXI4-Stream data processing
+ -- Applies exponential volume scaling using bit-shifting multiplication
+ AXIS : PROCESS (aclk)
+ BEGIN
+
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset output interface
+ m_axis_tvalid_int <= '0'; -- No valid output data
+ m_axis_tlast <= '0'; -- Clear channel indicator
+
+ ELSE
+ -- Output handshake management:
+ -- Clear valid flag when downstream accepts data
+ IF m_axis_tready = '1' THEN
+ m_axis_tvalid_int <= '0';
+ END IF;
+
+ -- Data processing: Apply volume scaling when both input and output are ready
+ IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN
+ -- Volume scaling using bit-shifting for exponential response:
+ --
+ -- Joystick mapping (from datasheet):
+ -- Y-axis: 0 = tilted all the way down (minimum volume)
+ -- 1023 = tilted all the way up (maximum volume)
+ --
+ -- Scaling method:
+ -- Positive exponent: Left shift = amplification (multiply by 2^n)
+ -- Negative exponent: Right shift = attenuation (divide by 2^n)
+ -- Zero exponent: No shift = unity gain (pass through)
+
+ IF volume_exp_mult >= 0 THEN
+ -- Amplification: Left shift for volume boost
+ -- Resize to extended width first to prevent overflow
+ m_axis_tdata <= STD_LOGIC_VECTOR(
+ shift_left(
+ resize(signed(s_axis_tdata), m_axis_tdata'LENGTH),
+ volume_exp_mult
+ )
+ );
+
+ ELSE
+ -- Attenuation: Right shift for volume reduction
+ -- Arithmetic right shift preserves sign for signed audio data
+ m_axis_tdata <= STD_LOGIC_VECTOR(
+ shift_right(
+ resize(signed(s_axis_tdata), m_axis_tdata'LENGTH),
+ - volume_exp_mult -- Convert negative to positive shift amount
+ )
+ );
+
+ END IF;
+
+ -- Set output control signals
+ m_axis_tvalid_int <= '1'; -- Mark output data as valid
+ m_axis_tlast <= s_axis_tlast; -- Pass through channel indicator
+
+ END IF;
+
+ END IF;
+
+ END IF;
+
+ END PROCESS AXIS;
+
+ -- Example scaling factors (VOLUME_STEP_2 = 6, 64 values per step):
+ -- volume_exp_mult = -3: Divide by 8 (>>3)
+ -- volume_exp_mult = -2: Divide by 4 (>>2)
+ -- volume_exp_mult = -1: Divide by 2 (>>1)
+ -- volume_exp_mult = 0: No change (unity)
+ -- volume_exp_mult = +1: Multiply by 2 (<<1)
+ -- volume_exp_mult = +2: Multiply by 4 (<<2)
+ -- volume_exp_mult = +3: Multiply by 8 (<<3)
+
+END Behavioral;
\ No newline at end of file
diff --git a/LAB3/src/volume_saturator.vhd b/LAB3/src/volume_saturator.vhd
index ae69f9f..697e44e 100644
--- a/LAB3/src/volume_saturator.vhd
+++ b/LAB3/src/volume_saturator.vhd
@@ -1,33 +1,110 @@
-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
- );
- Port (
- aclk : in std_logic;
- aresetn : in std_logic;
+-- Entity: volume_saturator
+-- Purpose: Second stage of volume control pipeline - clips multiplication results to prevent overflow
+-- Reduces bit width from extended multiplier output back to original audio format
+-- Implements saturation (clipping) to prevent audio distortion from mathematical overflow
+ENTITY volume_saturator IS
+ GENERIC (
+ TDATA_WIDTH : POSITIVE := 24; -- Width of final audio data output (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 ** 15 - 1; -- Maximum positive value for saturation (inclusive)
+ LOWER_BOUND : INTEGER := - 2 ** 15 -- 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 + 2**(VOLUME_WIDTH-VOLUME_STEP_2-1) downto 0);
- s_axis_tlast : in std_logic;
- s_axis_tready : out std_logic;
+ -- AXI4-Stream Slave Interface (Extended width input from multiplier)
+ s_axis_tvalid : IN STD_LOGIC; -- Input data valid signal
+ s_axis_tdata : IN STD_LOGIC_VECTOR(TDATA_WIDTH - 1 + 2 ** (VOLUME_WIDTH - VOLUME_STEP_2 - 1) DOWNTO 0); -- Wide input data from multiplier
+ 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
- );
-end volume_saturator;
+ -- AXI4-Stream Master Interface (Original width output for audio)
+ m_axis_tvalid : OUT STD_LOGIC; -- Output data valid signal
+ m_axis_tdata : OUT STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0); -- Saturated audio sample output
+ m_axis_tlast : OUT STD_LOGIC; -- Channel indicator passthrough
+ m_axis_tready : IN STD_LOGIC -- Downstream ready signal
+ );
+END volume_saturator;
-architecture Behavioral of volume_saturator is
+ARCHITECTURE Behavioral OF volume_saturator IS
-begin
+ -- Pre-calculated saturation bounds as STD_LOGIC_VECTORS for efficient comparison
+ -- These constants define the valid range for audio samples after volume processing
+ CONSTANT HIGHER_BOUND_VEC : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0) := STD_LOGIC_VECTOR(to_signed(HIGHER_BOUND, TDATA_WIDTH));
+ CONSTANT LOWER_BOUND_VEC : STD_LOGIC_VECTOR(TDATA_WIDTH - 1 DOWNTO 0) := STD_LOGIC_VECTOR(to_signed(LOWER_BOUND, TDATA_WIDTH));
-end Behavioral;
+ -- Internal AXI4-Stream control signal
+ SIGNAL m_axis_tvalid_int : STD_LOGIC;
+
+BEGIN
+
+ -- Connect internal signals to output ports
+ m_axis_tvalid <= m_axis_tvalid_int;
+
+ -- Input ready logic: Ready when downstream is ready OR no valid data pending, AND not in reset
+ -- This implements proper AXI4-Stream backpressure handling
+ s_axis_tready <= (m_axis_tready OR NOT m_axis_tvalid_int) AND aresetn;
+
+ -- Main saturation and data processing logic
+ PROCESS (aclk)
+ BEGIN
+
+ IF rising_edge(aclk) THEN
+
+ IF aresetn = '0' THEN
+ -- Reset output interface
+ m_axis_tvalid_int <= '0'; -- No valid output data during reset
+ m_axis_tlast <= '0'; -- Clear channel indicator
+
+ ELSE
+ -- Normal operation
+
+ -- Output handshake management:
+ -- Clear valid flag when downstream accepts data
+ IF m_axis_tready = '1' THEN
+ m_axis_tvalid_int <= '0';
+ END IF;
+
+ -- Data processing: Apply saturation when both input and output are ready
+ IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN
+
+ -- Saturation Logic:
+ -- Check if the wide input data exceeds the valid audio range
+ -- If so, clip (saturate) to the nearest valid value
+ -- This prevents overflow distortion while preserving audio quality
+
+ IF signed(s_axis_tdata) > signed(HIGHER_BOUND_VEC) THEN
+ -- Positive overflow: Clip to maximum positive value
+ m_axis_tdata <= HIGHER_BOUND_VEC;
+
+ ELSIF signed(s_axis_tdata) < signed(LOWER_BOUND_VEC) THEN
+ -- Negative overflow: Clip to maximum negative value
+ m_axis_tdata <= LOWER_BOUND_VEC;
+
+ ELSE
+ -- Value within valid range: Resize to output width without clipping
+ -- This preserves the original audio quality when no overflow occurs
+ m_axis_tdata <= STD_LOGIC_VECTOR(resize(signed(s_axis_tdata), TDATA_WIDTH));
+
+ END IF;
+
+ -- Set output control signals
+ m_axis_tvalid_int <= '1'; -- Mark output data as valid
+ m_axis_tlast <= s_axis_tlast; -- Pass through channel indicator
+
+ END IF;
+
+ END IF;
+
+ END IF;
+
+ END PROCESS;
+
+END Behavioral;
\ No newline at end of file
diff --git a/LAB3/test/Color_circle_(RGB).png b/LAB3/test/Color_circle_(RGB).png
new file mode 100644
index 0000000..87bd55c
Binary files /dev/null and b/LAB3/test/Color_circle_(RGB).png differ
diff --git a/LAB3/test/uart_viewer.py b/LAB3/test/uart_viewer.py
new file mode 100644
index 0000000..296882a
--- /dev/null
+++ b/LAB3/test/uart_viewer.py
@@ -0,0 +1,175 @@
+import serial
+import serial.tools.list_ports
+import time
+import queue
+import threading
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import io
+from PIL import Image
+import numpy as np
+
+# CONFIGURAZIONE
+BASYS3_PID = 0x6010
+BASYS3_VID = 0x0403
+BAUDRATE = 115200 # Imposta la tua velocitÃ
+CHUNK_SIZE = 4 # 4 byte per riga
+
+# Ricerca automatica della porta Basys3
+dev = ""
+for port in serial.tools.list_ports.comports():
+ if (port.vid == BASYS3_VID and port.pid == BASYS3_PID):
+ dev = port.device
+
+if not dev:
+ raise RuntimeError("Basys 3 Not Found!")
+
+PORT = dev
+
+def receive_mode(ser):
+ print("Modalità ricezione. Premi Ctrl+C per uscire.\n")
+ while True:
+ if ser.in_waiting >= CHUNK_SIZE:
+ data = ser.read(CHUNK_SIZE)
+ hex_bytes = ' '.join(f"{b:02X}" for b in data)
+ print(f"HH | {hex_bytes}")
+
+def receive_graph_mode(ser):
+ print("Modalità ricezione e visualizzazione coordinate in tempo reale. Premi Ctrl+C per uscire.\n")
+ q = queue.Queue()
+
+ def serial_reader():
+ while True:
+ if ser.in_waiting >= CHUNK_SIZE:
+ data = ser.read(CHUNK_SIZE)
+ if len(data) >= 4:
+ x = data[1]
+ y = data[2]
+ flags = data[3]
+ q.put((x, y, flags))
+
+ reader_thread = threading.Thread(target=serial_reader, daemon=True)
+ reader_thread.start()
+
+ point = [64, 64] # Punto iniziale al centro del grafico
+ color = 'blue'
+ size = 100
+
+ release = True
+ rgb = [0, 0, 0]
+
+ fig, ax = plt.subplots()
+
+ # Load PNG directly
+ png_path = r'LAB3\test\Color_circle_(RGB).png'
+ img = Image.open(png_path).convert('RGB')
+ img = img.resize((127, 127), Image.Resampling.LANCZOS) # Ensure image is 127x127
+ img_np = np.array(img)
+
+ # Show the image as background
+ ax.imshow(img, extent=(0, 127, 0, 127), aspect='auto', zorder=0)
+
+ sc = ax.scatter([point[0]], [point[1]], s=[size], zorder=1)
+ ax.set_xlim(0, 127)
+ ax.set_ylim(0, 127)
+ ax.set_xlabel("X")
+ ax.set_ylabel("Y")
+ ax.set_title("Coordinate in tempo reale")
+
+ def send_rgb_over_serial(ser, rgb):
+ """
+ Send RGB values over serial with a fixed first byte (0xC0).
+ """
+ bytes_to_send = [0xC0] # Primo byte fisso
+ for part in rgb:
+ val = int(part)
+ bytes_to_send.append(val)
+ ser.write(bytearray(bytes_to_send))
+ print(f"Inviato: {' '.join(f'{b:02X}' for b in bytes_to_send)}")
+
+ def update(frame):
+ nonlocal point, color, size, release, rgb
+
+ while not q.empty():
+ x, y, flags = q.get()
+ point[0] = x
+ point[1] = y
+
+ if flags & 0b00000001:
+ rgb = [0, 0, 0]
+ size = 50
+ if release:
+ send_rgb_over_serial(ser, rgb)
+ release = False
+
+ elif flags & 0b00000010:
+ flipped_y = 127 - y # Flip y to match image coordinates
+ rgb = img_np[flipped_y, x]
+ size = 300
+ if release:
+ send_rgb_over_serial(ser, rgb)
+ release = False
+
+ else:
+ size = 100
+ release = True # Reset release when no button is pressed
+
+ sc.set_offsets([point])
+ sc.set_sizes([size])
+ return sc,
+
+ ani = animation.FuncAnimation(fig, update, interval=10, blit=True, cache_frame_data=False)
+ plt.show()
+
+def send_mode(ser):
+ print("Modalità invio. Inserisci 3 byte in esadecimale (il primo sarà sempre 'C0').")
+ print("Formato: XX XX XX (dove XX è tra 00 e FF). Premi Ctrl+C per uscire.\n")
+ while True:
+ try:
+ user_input = input("Inserisci 3 byte (es: 12 34 AB): ").strip()
+ parts = user_input.split()
+ if len(parts) != 3:
+ print("Devi inserire esattamente 3 byte.")
+ continue
+ try:
+ bytes_to_send = [0xC0] # Primo byte fisso
+ for part in parts:
+ val = int(part, 16)
+ if not (0x00 <= val <= 0xFF):
+ raise ValueError
+ bytes_to_send.append(val)
+ ser.write(bytearray(bytes_to_send))
+ print(f"Inviato: {' '.join(f'{b:02X}' for b in bytes_to_send)}")
+ except ValueError:
+ print("Valori non validi. Usa solo byte esadecimali tra 00 e FF.")
+ except KeyboardInterrupt:
+ print("\nChiusura modalità invio...")
+ break
+
+ser = None
+try:
+ mode = ""
+ while mode not in ["r", "s", "g"]:
+ mode = input("Vuoi ricevere (r), inviare (s), o ricevere con grafico (g)? [r/s/g]: ").strip().lower()
+
+ ser = serial.Serial(PORT, BAUDRATE, timeout=1)
+ print(f"Aperta porta seriale: {PORT} a {BAUDRATE} baud.\n")
+
+ if mode == "r":
+ receive_mode(ser)
+ elif mode == "s":
+ send_mode(ser)
+ elif mode == "g":
+ receive_graph_mode(ser)
+ else:
+ print("Selezione non valida. Uscita...")
+ ser.close()
+ exit(1)
+
+except KeyboardInterrupt:
+ print("\nChiusura programma...")
+except serial.SerialException as e:
+ print(f"Errore nella connessione seriale: {e}")
+finally:
+ if ser is not None and ser.is_open:
+ ser.close()
diff --git a/LAB3/vivado/LFO/LFO.xpr b/LAB3/vivado/LFO/LFO.xpr
new file mode 100644
index 0000000..7206ae2
--- /dev/null
+++ b/LAB3/vivado/LFO/LFO.xpr
@@ -0,0 +1,391 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ default_dashboard
+
+
+
diff --git a/LAB3/vivado/LFO/tb_LFO_behav.wcfg b/LAB3/vivado/LFO/tb_LFO_behav.wcfg
new file mode 100644
index 0000000..3668c4c
--- /dev/null
+++ b/LAB3/vivado/LFO/tb_LFO_behav.wcfg
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ aclk
+ aclk
+
+
+ aresetn
+ aresetn
+
+
+ step_counter
+ step_counter
+ UNSIGNEDDECRADIX
+
+
+ step_clk_cycles
+ step_clk_cycles
+ UNSIGNEDDECRADIX
+
+
+ tri_counter[10:0]
+ tri_counter[10:0]
+ UNSIGNEDDECRADIX
+
+
+ lfo_period[9:0]
+ lfo_period[9:0]
+ UNSIGNEDDECRADIX
+
+
+ lfo_enable
+ lfo_enable
+
+
+ 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
+
+
diff --git a/LAB3/vivado/balance_controller/balance_controller.xpr b/LAB3/vivado/balance_controller/balance_controller.xpr
new file mode 100644
index 0000000..732795d
--- /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..d0b7ed1
--- /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_channel
+ left_channel
+
+
+ right_channel
+ right_channel
+
+
+ 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
+
+
diff --git a/LAB3/vivado/diligent_jstk/diligent_jstk.xpr b/LAB3/vivado/diligent_jstk/diligent_jstk.xpr
index 68f7553..b3d8a31 100644
--- a/LAB3/vivado/diligent_jstk/diligent_jstk.xpr
+++ b/LAB3/vivado/diligent_jstk/diligent_jstk.xpr
@@ -48,20 +48,20 @@
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -77,13 +77,13 @@
-
+
-
+
@@ -95,6 +95,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -121,6 +142,7 @@
+
@@ -142,6 +164,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -162,18 +226,233 @@
-
+
+
+
+
+
+
+
+
+
+
+
Vivado Synthesis Defaults
+
-
+
+
+
+ Vivado Synthesis Defaults
+
+
+
+
+
+
+
+
+
+
+
+ Vivado Synthesis Defaults
+
+
+
+
+
+
+
+
+
+
+
+ Vivado Synthesis Defaults
+
+
+
+
+
+
+
+
+
+
+
+ Vivado Synthesis Defaults
+
+
+
+
+
+
+
+
+
+
+
+ Vivado Synthesis Defaults
+
+
+
+
+
+
+
+
+
+
+
+ Vivado Synthesis Defaults
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default settings for Implementation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default settings for Implementation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default settings for Implementation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default settings for Implementation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default settings for Implementation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default settings for Implementation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Default settings for Implementation.
diff --git a/LAB3/vivado/lab3/lab3.xpr b/LAB3/vivado/lab3/lab3.xpr
index db3a47d..8bebeb3 100644
--- a/LAB3/vivado/lab3/lab3.xpr
+++ b/LAB3/vivado/lab3/lab3.xpr
@@ -55,13 +55,13 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -77,12 +77,6 @@
-
-
-
-
-
-
@@ -95,7 +89,13 @@
-
+
+
+
+
+
+
+
@@ -107,12 +107,6 @@
-
-
-
-
-
-
@@ -125,24 +119,54 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -156,41 +180,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -251,16 +240,17 @@
-
+
+
-
+
@@ -273,11 +263,192 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LAB3/vivado/moving_average_filter/moving_average_filter.xpr b/LAB3/vivado/moving_average_filter/moving_average_filter.xpr
new file mode 100644
index 0000000..f208da2
--- /dev/null
+++ b/LAB3/vivado/moving_average_filter/moving_average_filter.xpr
@@ -0,0 +1,403 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ default_dashboard
+
+
+
diff --git a/LAB3/vivado/moving_average_filter/tb_moving_average_behav.wcfg b/LAB3/vivado/moving_average_filter/tb_moving_average_behav.wcfg
new file mode 100644
index 0000000..5f3d391
--- /dev/null
+++ b/LAB3/vivado/moving_average_filter/tb_moving_average_behav.wcfg
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ aclk
+ aclk
+
+
+ aresetn
+ aresetn
+
+
+ enable_filter
+ enable_filter
+ #FF00FF
+ true
+
+
+ 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
+
+
+ moving average
+ label
+
+
+ sum_dx[28:0]
+ sum_dx[28:0]
+ SIGNEDDECRADIX
+
+
+ sum_sx[28:0]
+ sum_sx[28:0]
+ SIGNEDDECRADIX
+
+
+ wr_ptr_dx
+ wr_ptr_dx
+
+
+ wr_ptr_sx
+ wr_ptr_sx
+
+
diff --git a/LAB3/vivado/volume_multiplier/tb_volume_multiplier_behav.wcfg b/LAB3/vivado/volume_multiplier/tb_volume_multiplier_behav.wcfg
new file mode 100644
index 0000000..bb1944e
--- /dev/null
+++ b/LAB3/vivado/volume_multiplier/tb_volume_multiplier_behav.wcfg
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ aclk
+ aclk
+
+
+ aresetn
+ aresetn
+
+
+ Volume
+ label
+
+
+ volume[9:0]
+ volume[9:0]
+ UNSIGNEDDECRADIX
+
+
+ volume_exp_mult
+ volume_exp_mult
+
+
+ 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[31:0]
+ m_axis_tdata[31:0]
+ SIGNEDDECRADIX
+
+
+ m_axis_tlast
+ m_axis_tlast
+
+
+ m_axis_tvalid
+ m_axis_tvalid
+ #00FFFF
+ true
+
+
+ m_axis_tready
+ m_axis_tready
+ #FFD700
+ true
+
+
diff --git a/LAB3/vivado/volume_multiplier/volume_multiplier.xpr b/LAB3/vivado/volume_multiplier/volume_multiplier.xpr
new file mode 100644
index 0000000..a4cab43
--- /dev/null
+++ b/LAB3/vivado/volume_multiplier/volume_multiplier.xpr
@@ -0,0 +1,391 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ default_dashboard
+
+
+
diff --git a/LAB3/vivado/volume_saturator/volume_saturator.xpr b/LAB3/vivado/volume_saturator/volume_saturator.xpr
new file mode 100644
index 0000000..605ff8d
--- /dev/null
+++ b/LAB3/vivado/volume_saturator/volume_saturator.xpr
@@ -0,0 +1,391 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ default_dashboard
+
+
+
diff --git a/LAB3/vivado/volume_saturator/volume_saturator_tb_behav.wcfg b/LAB3/vivado/volume_saturator/volume_saturator_tb_behav.wcfg
new file mode 100644
index 0000000..c1a862e
--- /dev/null
+++ b/LAB3/vivado/volume_saturator/volume_saturator_tb_behav.wcfg
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ aclk
+ aclk
+
+
+ aresetn
+ aresetn
+
+
+ s_axis
+ label
+
+
+ s_axis_tdata[31:0]
+ s_axis_tdata[31: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
+
+
+ BOUNDS
+ label
+
+
+ HIGHER_BOUND
+ HIGHER_BOUND
+ SIGNEDDECRADIX
+
+
+ LOWER_BOUND
+ LOWER_BOUND
+ SIGNEDDECRADIX
+
+
+
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..ae328dd
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,6 @@
+pyserial
+matplotlib
+pillow
+numpy
+tqdm
+scipy
\ No newline at end of file