Refactor design files for LAB3: update diligent_jstk and add testbench for digilent_jstk2

This commit is contained in:
2025-05-14 14:34:22 +02:00
parent b11c65043f
commit aa8d8f3c7c
7 changed files with 650 additions and 282 deletions

View File

@@ -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": {

View File

@@ -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

View File

@@ -1,3 +0,0 @@
# Placeholder
This is a placeholder.

View File

@@ -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;

View File

@@ -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;

61
LAB3/test/uart_viewer.py Normal file
View File

@@ -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()

View File

@@ -48,20 +48,20 @@
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
<Option Name="EnableBDX" Val="FALSE"/>
<Option Name="DSABoardId" Val="basys3"/>
<Option Name="WTXSimLaunchSim" Val="0"/>
<Option Name="WTXSimLaunchSim" Val="29"/>
<Option Name="WTModelSimLaunchSim" Val="0"/>
<Option Name="WTQuestaLaunchSim" Val="0"/>
<Option Name="WTIesLaunchSim" Val="0"/>
<Option Name="WTVcsLaunchSim" Val="0"/>
<Option Name="WTRivieraLaunchSim" Val="0"/>
<Option Name="WTActivehdlLaunchSim" Val="0"/>
<Option Name="WTXSimExportSim" Val="1"/>
<Option Name="WTModelSimExportSim" Val="1"/>
<Option Name="WTQuestaExportSim" Val="1"/>
<Option Name="WTIesExportSim" Val="1"/>
<Option Name="WTVcsExportSim" Val="1"/>
<Option Name="WTRivieraExportSim" Val="1"/>
<Option Name="WTActivehdlExportSim" Val="1"/>
<Option Name="WTXSimExportSim" Val="7"/>
<Option Name="WTModelSimExportSim" Val="7"/>
<Option Name="WTQuestaExportSim" Val="7"/>
<Option Name="WTIesExportSim" Val="7"/>
<Option Name="WTVcsExportSim" Val="7"/>
<Option Name="WTRivieraExportSim" Val="7"/>
<Option Name="WTActivehdlExportSim" Val="7"/>
<Option Name="GenerateIPUpgradeLog" Val="TRUE"/>
<Option Name="XSimRadix" Val="hex"/>
<Option Name="XSimTimeUnit" Val="ns"/>
@@ -77,13 +77,13 @@
<FileSets Version="1" Minor="31">
<FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR/sources_1" RelGenDir="$PGENDIR/sources_1">
<Filter Type="Srcs"/>
<File Path="$PPRDIR/../../src/digilent_jstk2.vhd">
<File Path="$PPRDIR/../../src/jstk_uart_bridge.vhd">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/../../src/jstk_uart_bridge.vhd">
<File Path="$PPRDIR/../../src/digilent_jstk2.vhd">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="simulation"/>
@@ -121,6 +121,7 @@
</Config>
</FileSet>
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1" RelGenDir="$PGENDIR/sim_1">
<Filter Type="Srcs"/>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="diligent_jstk_wrapper"/>
@@ -162,22 +163,19 @@
</Simulator>
</Simulators>
<Runs Version="1" Minor="15">
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a35tcpg236-1" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" IncludeInArchive="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/synth_1">
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a35tcpg236-1" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/synth_1" IncludeInArchive="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/synth_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2020">
<Desc>Vivado Synthesis Defaults</Desc>
</StratHandle>
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2020"/>
<Step Id="synth_design"/>
</Strategy>
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2020"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35tcpg236-1" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" SynthRun="synth_1" IncludeInArchive="true" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1">
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35tcpg236-1" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_1" SynthRun="synth_1" IncludeInArchive="true" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2020">
<Desc>Default settings for Implementation.</Desc>
</StratHandle>
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2020"/>
<Step Id="init_design"/>
<Step Id="opt_design"/>
<Step Id="power_opt_design"/>
@@ -188,6 +186,7 @@
<Step Id="post_route_phys_opt_design"/>
<Step Id="write_bitstream"/>
</Strategy>
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
<ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2020"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>