diff --git a/LAB3/design/diligent_jstk/diligent_jstk.bd b/LAB3/design/diligent_jstk/diligent_jstk.bd index ced2b7f..45a1dc3 100644 --- a/LAB3/design/diligent_jstk/diligent_jstk.bd +++ b/LAB3/design/diligent_jstk/diligent_jstk.bd @@ -13,9 +13,9 @@ "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": "", + "digilent_jstk2_0": "" }, "interface_ports": { "usb_uart": { @@ -101,6 +101,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 +112,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,22 +330,242 @@ "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" + } + } + }, + "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" ] }, + "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", @@ -565,17 +578,17 @@ "AXI4Stream_UART_0/UART" ] }, - "AXI4Stream_UART_0_M00_AXIS_RX": { - "interface_ports": [ - "AXI4Stream_UART_0/M00_AXIS_RX", - "jstk_uart_bridge_0/s_axis" - ] - }, "axi4stream_spi_master_0_SPI_M": { "interface_ports": [ "SPI_M_0", "axi4stream_spi_master_0/SPI_M" ] + }, + "AXI4Stream_UART_0_M00_AXIS_RX": { + "interface_ports": [ + "AXI4Stream_UART_0/M00_AXIS_RX", + "jstk_uart_bridge_0/s_axis" + ] } }, "nets": { @@ -603,11 +616,11 @@ "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", + "digilent_jstk2_0/aclk" ] }, "digilent_jstk2_0_btn_trigger": { @@ -655,11 +668,11 @@ "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", + "digilent_jstk2_0/aresetn" ] }, "proc_sys_reset_0_peripheral_reset": { diff --git a/LAB3/design/diligent_jstk/hdl/diligent_jstk_wrapper.vhd b/LAB3/design/diligent_jstk/hdl/diligent_jstk_wrapper.vhd index 9c30c60..7fff9d5 100644 --- a/LAB3/design/diligent_jstk/hdl/diligent_jstk_wrapper.vhd +++ b/LAB3/design/diligent_jstk/hdl/diligent_jstk_wrapper.vhd @@ -1,7 +1,7 @@ --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 +--Date : Wed May 14 13:59:17 2025 --Host : Davide-Samsung running 64-bit major release (build 9200) --Command : generate_target diligent_jstk_wrapper.bd --Design : diligent_jstk_wrapper @@ -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/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_digilent_jstk2.vhd b/LAB3/sim/tb_digilent_jstk2.vhd new file mode 100644 index 0000000..f5ae1fa --- /dev/null +++ b/LAB3/sim/tb_digilent_jstk2.vhd @@ -0,0 +1,154 @@ +---------------------------------------------------------------------------------- +-- 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 := 66_666; + 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); + IF m_axis_tvalid = '1' THEN + IF m_axis_tdata = CMDSETLEDRGB THEN + send_data := TRUE; + mem_idx := 0; + END IF; + + IF send_data THEN + IF mem_idx <= 4 THEN + s_axis_tdata <= spi_mem(mem_idx); + s_axis_tvalid <= '1'; + mem_idx := mem_idx + 1; + ELSE + send_data := FALSE; + END IF; + END IF; + ELSE + s_axis_tvalid <= '0'; + END IF; + END LOOP; + END PROCESS; + +END sim; \ No newline at end of file diff --git a/LAB3/src/digilent_jstk2.vhd b/LAB3/src/digilent_jstk2.vhd index 9194ef3..356632e 100644 --- a/LAB3/src/digilent_jstk2.vhd +++ b/LAB3/src/digilent_jstk2.vhd @@ -1,49 +1,193 @@ -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) +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; + PORT ( + aclk : IN STD_LOGIC; + aresetn : IN STD_LOGIC; -- Data going TO the SPI IP-Core (and so, to the JSTK2 module) - m_axis_tvalid : out STD_LOGIC; - m_axis_tdata : out STD_LOGIC_VECTOR(7 downto 0); - m_axis_tready : in STD_LOGIC; + m_axis_tvalid : OUT STD_LOGIC; + m_axis_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); + m_axis_tready : IN STD_LOGIC; -- Data coming FROM the SPI IP-Core (and so, from the JSTK2 module) -- There is no tready signal, so you must be always ready to accept and use the incoming data, or it will be lost! - s_axis_tvalid : in STD_LOGIC; - s_axis_tdata : in STD_LOGIC_VECTOR(7 downto 0); + s_axis_tvalid : IN STD_LOGIC; + s_axis_tdata : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Joystick and button values read from the module - jstk_x : out std_logic_vector(9 downto 0); - jstk_y : out std_logic_vector(9 downto 0); - btn_jstk : out std_logic; - btn_trigger : out std_logic; + jstk_x : OUT STD_LOGIC_VECTOR(9 DOWNTO 0); + jstk_y : OUT STD_LOGIC_VECTOR(9 DOWNTO 0); + btn_jstk : OUT STD_LOGIC; + btn_trigger : OUT STD_LOGIC; -- LED color to send to the module - led_r : in std_logic_vector(7 downto 0); - led_g : in std_logic_vector(7 downto 0); - led_b : in std_logic_vector(7 downto 0) + 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; +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"; + CONSTANT CMDSETLEDRGB : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"84"; -- Do not forget that you MUST wait a bit between two packets. See the JSTK2 datasheet (and the SPI IP-Core README). ------------------------------------------------------------ -begin + CONSTANT DELAY_CLK_CYCLES : INTEGER := DELAY_US * (CLKFREQ / 1_000_000) - 1; - -- ... + -- State machine states + 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); -end architecture; + SIGNAL tx_state : tx_state_type; + SIGNAL rx_state : rx_state_type; + + SIGNAL rx_cache : STD_LOGIC_VECTOR(7 DOWNTO 0); + SIGNAL tx_delay_counter : INTEGER := 0; + + SIGNAL m_axis_tvalid_int : STD_LOGIC := '0'; + +BEGIN + + m_axis_tvalid <= m_axis_tvalid_int; + + -- Send the data to the SPI IP-Core + TX : PROCESS (aclk) + BEGIN + IF rising_edge(aclk) THEN + IF aresetn = '0' THEN + -- Reset the state machine + tx_state <= DELAY; + + m_axis_tvalid_int <= '0'; + m_axis_tdata <= (OTHERS => '0'); + + tx_delay_counter <= 0; + + ELSE + -- Clear valid flag when master interface is ready + IF m_axis_tready = '1' THEN + m_axis_tvalid_int <= '0'; + END IF; + + -- State machine for sending data to the SPI IP-Core + CASE tx_state IS + + WHEN DELAY => + m_axis_tvalid_int <= '0'; + m_axis_tdata <= (OTHERS => '0'); + + IF tx_delay_counter >= DELAY_CLK_CYCLES THEN + tx_delay_counter <= 0; + tx_state <= SEND_CMD; + ELSE + tx_delay_counter <= tx_delay_counter + 1; + END IF; + + WHEN SEND_CMD => + IF (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + m_axis_tdata <= CMDSETLEDRGB; + m_axis_tvalid_int <= '1'; + tx_state <= SEND_RED; + END IF; + + WHEN SEND_RED => + IF (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + m_axis_tdata <= led_r; + m_axis_tvalid_int <= '1'; + tx_state <= SEND_GREEN; + END IF; + + WHEN SEND_GREEN => + IF (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + m_axis_tdata <= led_g; + m_axis_tvalid_int <= '1'; + tx_state <= SEND_BLUE; + END IF; + + WHEN SEND_BLUE => + IF (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + m_axis_tdata <= led_b; + m_axis_tvalid_int <= '1'; + tx_state <= SEND_DUMMY; + END IF; + + WHEN SEND_DUMMY => + IF (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN + m_axis_tdata <= (OTHERS => '0'); + m_axis_tvalid_int <= '1'; + tx_state <= DELAY; + END IF; + + END CASE; + + END IF; + END IF; + + END PROCESS TX; + + -- Receive the data from the SPI IP-Core + RX : PROCESS (aclk) + BEGIN + IF rising_edge(aclk) THEN + IF aresetn = '0' THEN + -- Reset the state machine + rx_state <= JSTK_X_LOW; + + -- jstk_x <= (others => '0'); + -- jstk_y <= (others => '0'); + btn_jstk <= '0'; + btn_trigger <= '0'; + + rx_cache <= (OTHERS => '0'); + ELSE + -- State machine for receiving data from the SPI IP-Core + CASE rx_state IS + + WHEN JSTK_X_LOW => + IF s_axis_tvalid = '1' THEN + rx_cache(7 DOWNTO 0) <= s_axis_tdata; + rx_state <= JSTK_X_HIGH; + END IF; + + WHEN JSTK_X_HIGH => + IF s_axis_tvalid = '1' THEN + jstk_x(9 DOWNTO 0) <= s_axis_tdata(1 DOWNTO 0) & rx_cache(7 DOWNTO 0); + rx_state <= JSTK_Y_LOW; + END IF; + + WHEN JSTK_Y_LOW => + IF s_axis_tvalid = '1' THEN + rx_cache(7 DOWNTO 0) <= s_axis_tdata; + rx_state <= JSTK_Y_HIGH; + END IF; + + WHEN JSTK_Y_HIGH => + IF s_axis_tvalid = '1' THEN + jstk_y(9 DOWNTO 0) <= s_axis_tdata(1 DOWNTO 0) & rx_cache(7 DOWNTO 0); + rx_state <= BUTTONS; + END IF; + + WHEN BUTTONS => + IF s_axis_tvalid = '1' THEN + btn_jstk <= s_axis_tdata(0); + btn_trigger <= s_axis_tdata(1); + rx_state <= JSTK_X_LOW; + END IF; + + END CASE; + END IF; + END IF; + + END PROCESS RX; + +END ARCHITECTURE; \ No newline at end of file diff --git a/LAB3/test/uart_viewer.py b/LAB3/test/uart_viewer.py new file mode 100644 index 0000000..07b2d2d --- /dev/null +++ b/LAB3/test/uart_viewer.py @@ -0,0 +1,61 @@ +import serial +import time + +# CONFIGURAZIONE +PORT = 'COM4' # Cambia con la tua porta: es. 'COM3' su Windows o '/dev/ttyUSB0' su Linux +BAUDRATE = 115200 # Imposta la tua velocità +CHUNK_SIZE = 4 # 4 byte per riga + +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 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 + +try: + mode = "" + while mode not in ["r", "s"]: + mode = input("Vuoi ricevere (r) o inviare (s) dati? [r/s]: ").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) + else: + send_mode(ser) + +except KeyboardInterrupt: + print("\nChiusura programma...") +except serial.SerialException as e: + print(f"Errore nella connessione seriale: {e}") +finally: + if 'ser' in locals() and ser.is_open: + ser.close() diff --git a/LAB3/vivado/diligent_jstk/diligent_jstk.xpr b/LAB3/vivado/diligent_jstk/diligent_jstk.xpr index 68f7553..b670b84 100644 --- a/LAB3/vivado/diligent_jstk/diligent_jstk.xpr +++ b/LAB3/vivado/diligent_jstk/diligent_jstk.xpr @@ -48,20 +48,20 @@