From be099a88a7bffcbf13dc95a1d3a6c1bb20dd31fa Mon Sep 17 00:00:00 2001 From: pfaure Date: Fri, 9 Apr 2021 23:32:03 +0200 Subject: [PATCH] Screen OK --- .gitignore | 72 +- .../digilent-xdc-master/Basys-3-Master.xdc | 299 ----- .../sim_1/new/test_Compteur.vhd | 53 - .../sources_1/new/ClockDivider10.vhd | 54 - .../sources_1/new/ClockDivider1000.vhd | 50 - .../sources_1/new/Compteur.vhd | 64 - .../sources_1/new/System.vhd | 66 - Compteur8BitsBasys3.xpr | 166 --- README.md | 5 + hw_handoff/.keep | 0 proj/cleanup.cmd | 22 + proj/cleanup.sh | 16 + proj/create_project.tcl | 160 +++ repo/cache/.keep | 0 repo/local/.keep | 0 sdk/.keep | 0 src/bd/.keep | 0 src/constraints/.keep | 0 src/constraints/Basys3_Master.xdc | 361 +++++ src/hdl/.keep | 0 src/hdl/GPIO_Demo.vhd | 476 +++++++ src/hdl/MouseCtl.vhd | 1169 +++++++++++++++++ src/hdl/MouseDisplay.vhd | 269 ++++ src/hdl/Ps2Interface.vhd | 807 ++++++++++++ src/hdl/UART_TX_CTRL.vhd | 157 +++ src/hdl/clk_wiz_0.vhd | 108 ++ src/hdl/clk_wiz_0_clk_wiz.vhd | 201 +++ src/hdl/debouncer.vhd | 95 ++ src/hdl/vga_ctrl.vhd | 415 ++++++ src/ip/.keep | 0 src/others/.keep | 0 31 files changed, 4328 insertions(+), 757 deletions(-) delete mode 100644 Compteur8BitsBasys3.srcs/constrs_1/imports/digilent-xdc-master/Basys-3-Master.xdc delete mode 100644 Compteur8BitsBasys3.srcs/sim_1/new/test_Compteur.vhd delete mode 100644 Compteur8BitsBasys3.srcs/sources_1/new/ClockDivider10.vhd delete mode 100644 Compteur8BitsBasys3.srcs/sources_1/new/ClockDivider1000.vhd delete mode 100644 Compteur8BitsBasys3.srcs/sources_1/new/Compteur.vhd delete mode 100644 Compteur8BitsBasys3.srcs/sources_1/new/System.vhd delete mode 100644 Compteur8BitsBasys3.xpr create mode 100644 README.md create mode 100644 hw_handoff/.keep create mode 100644 proj/cleanup.cmd create mode 100644 proj/cleanup.sh create mode 100644 proj/create_project.tcl create mode 100644 repo/cache/.keep create mode 100644 repo/local/.keep create mode 100644 sdk/.keep create mode 100644 src/bd/.keep create mode 100644 src/constraints/.keep create mode 100644 src/constraints/Basys3_Master.xdc create mode 100644 src/hdl/.keep create mode 100644 src/hdl/GPIO_Demo.vhd create mode 100644 src/hdl/MouseCtl.vhd create mode 100644 src/hdl/MouseDisplay.vhd create mode 100644 src/hdl/Ps2Interface.vhd create mode 100644 src/hdl/UART_TX_CTRL.vhd create mode 100644 src/hdl/clk_wiz_0.vhd create mode 100644 src/hdl/clk_wiz_0_clk_wiz.vhd create mode 100644 src/hdl/debouncer.vhd create mode 100644 src/hdl/vga_ctrl.vhd create mode 100644 src/ip/.keep create mode 100644 src/others/.keep diff --git a/.gitignore b/.gitignore index 7ffc11d..e6448f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,67 @@ -Compteur8BitsBasys3.ip_user_files/* -Compteur8BitsBasys3.cache/* -Compteur8BitsBasys3.hw/* -Compteur8BitsBasys3.runs/* -Compteur8BitsBasys3.sim/* +# Blacklist everything +/* + +# whitelist the necessary files and folders, this gets everything from inside them too +!.gitignore +!.gitmodules +!README.md +!hw_handoff/ +!proj/ +!repo/ +!sdk/ +!src/ + +#Digilent Added ignore rules for Vivado projects + +# sdk exclusions +sdk/.metadata +sdk/**/*RemoteSystemsTempFiles +sdk/**/*Debug/* +sdk/**/*Release +sdk/**/*webtalk +sdk/.sdk +sdk/*.log +# ignore everything in the hw_platform +sdk/*hw_platform*/* +# except +!sdk/*hw_platform*/*.hdf +!sdk/*hw_platform*/.*project +# ignore everything in the BSP +sdk/*_bsp*/* +# except +!sdk/*_bsp*/system.mss +!sdk/*_bsp*/Makefile +!sdk/*_bsp*/.*project +# include the relevant elf files +!sdk/**/*Debug/*.elf +!sdk/**/*Debug/*.elf.size + +repo/** +# whitelist vivado-library if it exists +!repo/vivado-library +#do not white-list submodule contents +!repo/local +!repo/local/** +!repo/cache +repo/cache/** + +# Make sure we keep only xci files in ip src subfolder +src/ip/*/** +!src/ip/*/*.xci +!src/ip/*/*.prj +# Do not ignore anything in src/others +!src/others/* +# Do not ignore block diagram files +!src/bd/** + + +# ignore everything in project folder +proj/* +# except this file and project generators +!proj/create_project.tcl +!proj/cleanup.cmd +!proj/cleanup.sh +!proj/release.py + +# keep the empty folders +!**/.keep \ No newline at end of file diff --git a/Compteur8BitsBasys3.srcs/constrs_1/imports/digilent-xdc-master/Basys-3-Master.xdc b/Compteur8BitsBasys3.srcs/constrs_1/imports/digilent-xdc-master/Basys-3-Master.xdc deleted file mode 100644 index 27543c5..0000000 --- a/Compteur8BitsBasys3.srcs/constrs_1/imports/digilent-xdc-master/Basys-3-Master.xdc +++ /dev/null @@ -1,299 +0,0 @@ -## This file is a general .xdc for the Basys3 rev B board -## To use it in a project: -## - uncomment the lines corresponding to used pins -## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project - -## Clock signal -set_property PACKAGE_PIN W5 [get_ports CLK] -set_property IOSTANDARD LVCMOS33 [get_ports CLK] -create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports CLK] - -## Switches -set_property PACKAGE_PIN V17 [get_ports {SW[0]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SW[0]}] -set_property PACKAGE_PIN V16 [get_ports {SW[1]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SW[1]}] -set_property PACKAGE_PIN W16 [get_ports {SW[2]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SW[2]}] -set_property PACKAGE_PIN W17 [get_ports {SW[3]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SW[3]}] -set_property PACKAGE_PIN W15 [get_ports {SW[4]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SW[4]}] -set_property PACKAGE_PIN V15 [get_ports {SW[5]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SW[5]}] -set_property PACKAGE_PIN W14 [get_ports {SW[6]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SW[6]}] -set_property PACKAGE_PIN W13 [get_ports {SW[7]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SW[7]}] -#set_property PACKAGE_PIN V2 [get_ports {sw[8]}] -#set_property IOSTANDARD LVCMOS33 [get_ports {sw[8]}] -#set_property PACKAGE_PIN T3 [get_ports {sw[9]}] -#set_property IOSTANDARD LVCMOS33 [get_ports {sw[9]}] -#set_property PACKAGE_PIN T2 [get_ports {sw[10]}] -#set_property IOSTANDARD LVCMOS33 [get_ports {sw[10]}] -#set_property PACKAGE_PIN R3 [get_ports {sw[11]}] -#set_property IOSTANDARD LVCMOS33 [get_ports {sw[11]}] -#set_property PACKAGE_PIN W2 [get_ports {sw[12]}] -#set_property IOSTANDARD LVCMOS33 [get_ports {sw[12]}] -#set_property PACKAGE_PIN U1 [get_ports {sw[13]}] -#set_property IOSTANDARD LVCMOS33 [get_ports {sw[13]}] -#set_property PACKAGE_PIN T1 [get_ports {sw[14]}] -#set_property IOSTANDARD LVCMOS33 [get_ports {sw[14]}] -#set_property PACKAGE_PIN R2 [get_ports {sw[15]}] -#set_property IOSTANDARD LVCMOS33 [get_ports {sw[15]}] - - -## 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]}] - - -##7 segment display -#set_property PACKAGE_PIN W7 [get_ports {seg[0]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {seg[0]}] -#set_property PACKAGE_PIN W6 [get_ports {seg[1]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {seg[1]}] -#set_property PACKAGE_PIN U8 [get_ports {seg[2]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {seg[2]}] -#set_property PACKAGE_PIN V8 [get_ports {seg[3]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {seg[3]}] -#set_property PACKAGE_PIN U5 [get_ports {seg[4]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {seg[4]}] -#set_property PACKAGE_PIN V5 [get_ports {seg[5]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {seg[5]}] -#set_property PACKAGE_PIN U7 [get_ports {seg[6]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {seg[6]}] - -#set_property PACKAGE_PIN V7 [get_ports dp] - #set_property IOSTANDARD LVCMOS33 [get_ports dp] - -#set_property PACKAGE_PIN U2 [get_ports {an[0]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {an[0]}] -#set_property PACKAGE_PIN U4 [get_ports {an[1]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {an[1]}] -#set_property PACKAGE_PIN V4 [get_ports {an[2]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {an[2]}] -#set_property PACKAGE_PIN W4 [get_ports {an[3]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {an[3]}] - - -##Buttons -set_property PACKAGE_PIN U18 [get_ports btnC] -set_property IOSTANDARD LVCMOS33 [get_ports btnC] -#set_property PACKAGE_PIN T18 [get_ports btnU] - #set_property IOSTANDARD LVCMOS33 [get_ports btnU] -set_property PACKAGE_PIN W19 [get_ports btnL] -set_property IOSTANDARD LVCMOS33 [get_ports btnL] -set_property PACKAGE_PIN T17 [get_ports btnR] -set_property IOSTANDARD LVCMOS33 [get_ports btnR] -set_property PACKAGE_PIN U17 [get_ports btnD] -set_property IOSTANDARD LVCMOS33 [get_ports btnD] - - - -##Pmod Header JA -##Sch name = JA1 -#set_property PACKAGE_PIN J1 [get_ports {JA[0]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JA[0]}] -##Sch name = JA2 -#set_property PACKAGE_PIN L2 [get_ports {JA[1]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JA[1]}] -##Sch name = JA3 -#set_property PACKAGE_PIN J2 [get_ports {JA[2]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JA[2]}] -##Sch name = JA4 -#set_property PACKAGE_PIN G2 [get_ports {JA[3]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JA[3]}] -##Sch name = JA7 -#set_property PACKAGE_PIN H1 [get_ports {JA[4]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JA[4]}] -##Sch name = JA8 -#set_property PACKAGE_PIN K2 [get_ports {JA[5]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JA[5]}] -##Sch name = JA9 -#set_property PACKAGE_PIN H2 [get_ports {JA[6]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JA[6]}] -##Sch name = JA10 -#set_property PACKAGE_PIN G3 [get_ports {JA[7]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JA[7]}] - - - -##Pmod Header JB -##Sch name = JB1 -#set_property PACKAGE_PIN A14 [get_ports {JB[0]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JB[0]}] -##Sch name = JB2 -#set_property PACKAGE_PIN A16 [get_ports {JB[1]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JB[1]}] -##Sch name = JB3 -#set_property PACKAGE_PIN B15 [get_ports {JB[2]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JB[2]}] -##Sch name = JB4 -#set_property PACKAGE_PIN B16 [get_ports {JB[3]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JB[3]}] -##Sch name = JB7 -#set_property PACKAGE_PIN A15 [get_ports {JB[4]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JB[4]}] -##Sch name = JB8 -#set_property PACKAGE_PIN A17 [get_ports {JB[5]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JB[5]}] -##Sch name = JB9 -#set_property PACKAGE_PIN C15 [get_ports {JB[6]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JB[6]}] -##Sch name = JB10 -#set_property PACKAGE_PIN C16 [get_ports {JB[7]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JB[7]}] - - - -##Pmod Header JC -##Sch name = JC1 -#set_property PACKAGE_PIN K17 [get_ports {JC[0]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JC[0]}] -##Sch name = JC2 -#set_property PACKAGE_PIN M18 [get_ports {JC[1]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JC[1]}] -##Sch name = JC3 -#set_property PACKAGE_PIN N17 [get_ports {JC[2]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JC[2]}] -##Sch name = JC4 -#set_property PACKAGE_PIN P18 [get_ports {JC[3]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JC[3]}] -##Sch name = JC7 -#set_property PACKAGE_PIN L17 [get_ports {JC[4]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JC[4]}] -##Sch name = JC8 -#set_property PACKAGE_PIN M19 [get_ports {JC[5]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JC[5]}] -##Sch name = JC9 -#set_property PACKAGE_PIN P17 [get_ports {JC[6]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JC[6]}] -##Sch name = JC10 -#set_property PACKAGE_PIN R18 [get_ports {JC[7]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JC[7]}] - - -##Pmod Header JXADC -##Sch name = XA1_P -#set_property PACKAGE_PIN J3 [get_ports {JXADC[0]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[0]}] -##Sch name = XA2_P -#set_property PACKAGE_PIN L3 [get_ports {JXADC[1]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[1]}] -##Sch name = XA3_P -#set_property PACKAGE_PIN M2 [get_ports {JXADC[2]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[2]}] -##Sch name = XA4_P -#set_property PACKAGE_PIN N2 [get_ports {JXADC[3]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[3]}] -##Sch name = XA1_N -#set_property PACKAGE_PIN K3 [get_ports {JXADC[4]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[4]}] -##Sch name = XA2_N -#set_property PACKAGE_PIN M3 [get_ports {JXADC[5]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[5]}] -##Sch name = XA3_N -#set_property PACKAGE_PIN M1 [get_ports {JXADC[6]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[6]}] -##Sch name = XA4_N -#set_property PACKAGE_PIN N1 [get_ports {JXADC[7]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[7]}] - - - -##VGA Connector -#set_property PACKAGE_PIN G19 [get_ports {vgaRed[0]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaRed[0]}] -#set_property PACKAGE_PIN H19 [get_ports {vgaRed[1]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaRed[1]}] -#set_property PACKAGE_PIN J19 [get_ports {vgaRed[2]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaRed[2]}] -#set_property PACKAGE_PIN N19 [get_ports {vgaRed[3]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaRed[3]}] -#set_property PACKAGE_PIN N18 [get_ports {vgaBlue[0]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaBlue[0]}] -#set_property PACKAGE_PIN L18 [get_ports {vgaBlue[1]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaBlue[1]}] -#set_property PACKAGE_PIN K18 [get_ports {vgaBlue[2]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaBlue[2]}] -#set_property PACKAGE_PIN J18 [get_ports {vgaBlue[3]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaBlue[3]}] -#set_property PACKAGE_PIN J17 [get_ports {vgaGreen[0]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaGreen[0]}] -#set_property PACKAGE_PIN H17 [get_ports {vgaGreen[1]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaGreen[1]}] -#set_property PACKAGE_PIN G17 [get_ports {vgaGreen[2]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaGreen[2]}] -#set_property PACKAGE_PIN D17 [get_ports {vgaGreen[3]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {vgaGreen[3]}] -#set_property PACKAGE_PIN P19 [get_ports Hsync] - #set_property IOSTANDARD LVCMOS33 [get_ports Hsync] -#set_property PACKAGE_PIN R19 [get_ports Vsync] - #set_property IOSTANDARD LVCMOS33 [get_ports Vsync] - - -##USB-RS232 Interface -#set_property PACKAGE_PIN B18 [get_ports RsRx] - #set_property IOSTANDARD LVCMOS33 [get_ports RsRx] -#set_property PACKAGE_PIN A18 [get_ports RsTx] - #set_property IOSTANDARD LVCMOS33 [get_ports RsTx] - - -##USB HID (PS/2) -#set_property PACKAGE_PIN C17 [get_ports PS2Clk] - #set_property IOSTANDARD LVCMOS33 [get_ports PS2Clk] - #set_property PULLUP true [get_ports PS2Clk] -#set_property PACKAGE_PIN B17 [get_ports PS2Data] - #set_property IOSTANDARD LVCMOS33 [get_ports PS2Data] - #set_property PULLUP true [get_ports PS2Data] - - -##Quad SPI Flash -##Note that CCLK_0 cannot be placed in 7 series devices. You can access it using the -##STARTUPE2 primitive. -#set_property PACKAGE_PIN D18 [get_ports {QspiDB[0]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[0]}] -#set_property PACKAGE_PIN D19 [get_ports {QspiDB[1]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[1]}] -#set_property PACKAGE_PIN G18 [get_ports {QspiDB[2]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[2]}] -#set_property PACKAGE_PIN F18 [get_ports {QspiDB[3]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[3]}] -#set_property PACKAGE_PIN K19 [get_ports QspiCSn] - #set_property IOSTANDARD LVCMOS33 [get_ports QspiCSn] - - -## Configuration options, can be used for all designs -set_property CONFIG_VOLTAGE 3.3 [current_design] -set_property CFGBVS VCCO [current_design] diff --git a/Compteur8BitsBasys3.srcs/sim_1/new/test_Compteur.vhd b/Compteur8BitsBasys3.srcs/sim_1/new/test_Compteur.vhd deleted file mode 100644 index 88d42fb..0000000 --- a/Compteur8BitsBasys3.srcs/sim_1/new/test_Compteur.vhd +++ /dev/null @@ -1,53 +0,0 @@ ----------------------------------------------------------------------------------- --- Company: --- Engineer: --- --- Create Date: 09.04.2021 22:51:31 --- Design Name: --- Module Name: test_Compteur - Behavioral --- Project Name: --- Target Devices: --- Tool Versions: --- Description: --- --- Dependencies: --- --- Revision: --- Revision 0.01 - File Created --- Additional Comments: --- ----------------------------------------------------------------------------------- - - -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; - --- Uncomment the following library declaration if using --- arithmetic functions with Signed or Unsigned values ---use IEEE.NUMERIC_STD.ALL; - --- Uncomment the following library declaration if instantiating --- any Xilinx leaf cells in this code. ---library UNISIM; ---use UNISIM.VComponents.all; - -entity test_Compteur is --- Port ( ); -end test_Compteur; - -architecture Behavioral of test_Compteur is - component Compteur is - Port ( CK : in STD_LOGIC; - RST : in STD_LOGIC; - SENS : in STD_LOGIC; - LOAD : in STD_LOGIC; - EN : in STD_LOGIC; - Din : in STD_LOGIC_VECTOR (7 downto 0); - Dout : out STD_LOGIC_VECTOR (7 downto 0)); - end component; - - signal CK -begin - - -end Behavioral; diff --git a/Compteur8BitsBasys3.srcs/sources_1/new/ClockDivider10.vhd b/Compteur8BitsBasys3.srcs/sources_1/new/ClockDivider10.vhd deleted file mode 100644 index d09c2ec..0000000 --- a/Compteur8BitsBasys3.srcs/sources_1/new/ClockDivider10.vhd +++ /dev/null @@ -1,54 +0,0 @@ ----------------------------------------------------------------------------------- --- Company: --- Engineer: --- --- Create Date: 09.04.2021 21:42:26 --- Design Name: --- Module Name: ClockDivider10 - Behavioral --- Project Name: --- Target Devices: --- Tool Versions: --- Description: --- --- Dependencies: --- --- Revision: --- Revision 0.01 - File Created --- Additional Comments: --- ----------------------------------------------------------------------------------- - - -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; - --- Uncomment the following library declaration if using --- arithmetic functions with Signed or Unsigned values ---use IEEE.NUMERIC_STD.ALL; - --- Uncomment the following library declaration if instantiating --- any Xilinx leaf cells in this code. ---library UNISIM; ---use UNISIM.VComponents.all; - -entity ClockDivider10 is - Port ( clk_in : in STD_LOGIC; - clk_out : out STD_LOGIC); -end ClockDivider10; - -architecture Behavioral of ClockDivider10 is - subtype int10 is INTEGER range 0 to 10; - signal N : int10 := 0; - signal aux : STD_LOGIC; -begin - process - begin - wait until clk_in'event and clk_in = '1'; - N <= N + 1; - if N = 10 then - aux <= not aux; - N <= 0; - end if; - end process; - clk_out <= aux; -end Behavioral; diff --git a/Compteur8BitsBasys3.srcs/sources_1/new/ClockDivider1000.vhd b/Compteur8BitsBasys3.srcs/sources_1/new/ClockDivider1000.vhd deleted file mode 100644 index cf026ad..0000000 --- a/Compteur8BitsBasys3.srcs/sources_1/new/ClockDivider1000.vhd +++ /dev/null @@ -1,50 +0,0 @@ ----------------------------------------------------------------------------------- --- Company: --- Engineer: --- --- Create Date: 09.04.2021 21:44:36 --- Design Name: --- Module Name: ClockDivider1000 - Structural --- Project Name: --- Target Devices: --- Tool Versions: --- Description: --- --- Dependencies: --- --- Revision: --- Revision 0.01 - File Created --- Additional Comments: --- ----------------------------------------------------------------------------------- - - -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; - --- Uncomment the following library declaration if using --- arithmetic functions with Signed or Unsigned values ---use IEEE.NUMERIC_STD.ALL; - --- Uncomment the following library declaration if instantiating --- any Xilinx leaf cells in this code. ---library UNISIM; ---use UNISIM.VComponents.all; - -entity ClockDivider1000 is - Port ( clk_in : in STD_LOGIC; - clk_out : out STD_LOGIC); -end ClockDivider1000; - -architecture Structural of ClockDivider1000 is - component ClockDivider10 - Port ( clk_in : in STD_LOGIC; - clk_out : out STD_LOGIC); - end component; - - signal aux1, aux2 : STD_LOGIC; -begin - U1: ClockDivider10 port map(clk_in, aux1); - U2: ClockDivider10 port map(aux1, aux2); - U3: ClockDivider10 port map(aux2, clk_out); -end Structural; diff --git a/Compteur8BitsBasys3.srcs/sources_1/new/Compteur.vhd b/Compteur8BitsBasys3.srcs/sources_1/new/Compteur.vhd deleted file mode 100644 index eb8a5ce..0000000 --- a/Compteur8BitsBasys3.srcs/sources_1/new/Compteur.vhd +++ /dev/null @@ -1,64 +0,0 @@ ----------------------------------------------------------------------------------- --- Company: --- Engineer: --- --- Create Date: 09.04.2021 21:20:39 --- Design Name: --- Module Name: Compteur - 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.STD_LOGIC_UNSIGNED.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 Compteur is - Port ( CK : in STD_LOGIC; - RST : in STD_LOGIC; - SENS : in STD_LOGIC; - LOAD : in STD_LOGIC; - EN : in STD_LOGIC; - Din : in STD_LOGIC_VECTOR (7 downto 0); - Dout : out STD_LOGIC_VECTOR (7 downto 0)); -end Compteur; - -architecture Behavioral of Compteur is - signal aux: STD_LOGIC_VECTOR (7 downto 0) := (others => '0'); -begin - Dout <= aux; - process - begin - wait until CK'event and CK='1'; - if RST = '0' then - aux <= (others => '0'); - elsif LOAD = '1' then - aux <= Din; - elsif EN = '0' then - if SENS = '1' then - aux <= aux + 1; - else - aux <= aux - 1; - end if; - end if; - end process; -end Behavioral; diff --git a/Compteur8BitsBasys3.srcs/sources_1/new/System.vhd b/Compteur8BitsBasys3.srcs/sources_1/new/System.vhd deleted file mode 100644 index 52fded3..0000000 --- a/Compteur8BitsBasys3.srcs/sources_1/new/System.vhd +++ /dev/null @@ -1,66 +0,0 @@ ----------------------------------------------------------------------------------- --- Company: --- Engineer: --- --- Create Date: 09.04.2021 22:03:10 --- Design Name: --- Module Name: System - Behavioral --- Project Name: --- Target Devices: --- Tool Versions: --- Description: --- --- Dependencies: --- --- Revision: --- Revision 0.01 - File Created --- Additional Comments: --- ----------------------------------------------------------------------------------- - - -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; - --- Uncomment the following library declaration if using --- arithmetic functions with Signed or Unsigned values ---use IEEE.NUMERIC_STD.ALL; - --- Uncomment the following library declaration if instantiating --- any Xilinx leaf cells in this code. ---library UNISIM; ---use UNISIM.VComponents.all; - -entity System is - Port ( SW : in STD_LOGIC_VECTOR (0 to 7); - btnL : in STD_LOGIC; - btnC : in STD_LOGIC; - btnR : in STD_LOGIC; - btnD : in STD_LOGIC; - LED : out STD_LOGIC_VECTOR (0 to 7); - CLK : in STD_LOGIC); -end System; - -architecture Structural of System is - - component ClockDivider1000 - Port ( clk_in : in STD_LOGIC; - clk_out : out STD_LOGIC); - end component; - - component Compteur - Port ( CK : in STD_LOGIC; - RST : in STD_LOGIC; - SENS : in STD_LOGIC; - LOAD : in STD_LOGIC; - EN : in STD_LOGIC; - Din : in STD_LOGIC_VECTOR (7 downto 0); - Dout : out STD_LOGIC_VECTOR (7 downto 0)); - end component; - - signal CLK_DIV_1000, CLK_DIV_1000000 : STD_LOGIC; -begin - DIV1: ClockDivider1000 port map(CLK, CLK_DIV_1000); - DIV2: ClockDivider1000 port map(CLK_DIV_1000, CLK_DIV_1000000); - CMPT: Compteur port map(CLK_DIV_1000000, btnC, btnR, btnL, btnD, SW, LED); -end Structural; diff --git a/Compteur8BitsBasys3.xpr b/Compteur8BitsBasys3.xpr deleted file mode 100644 index 1fb19bf..0000000 --- a/Compteur8BitsBasys3.xpr +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/README.md b/README.md new file mode 100644 index 0000000..3b2d56c --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Basys 3 GPIO +Created for Vivado 2016.4 + +[Link to the project wiki](https://reference.digilentinc.com/learn/programmable-logic/tutorials/basys-3-general-io/start) + diff --git a/hw_handoff/.keep b/hw_handoff/.keep new file mode 100644 index 0000000..e69de29 diff --git a/proj/cleanup.cmd b/proj/cleanup.cmd new file mode 100644 index 0000000..e63b694 --- /dev/null +++ b/proj/cleanup.cmd @@ -0,0 +1,22 @@ +@echo off +rem delete all files from subfolders +for /d /r %%i in (*) do del /f /q %%i\* +rem delete all subfolders +for /d %%i in (*) do rd /S /Q %%i + +rem unmark read only from all files +attrib -R .\* /S + +rem mark read only those we wish to keep +attrib +R .\create_project.tcl +attrib +R .\cleanup.sh +attrib +R .\cleanup.cmd +attrib +R .\release.py +attrib +R .\.gitignore +attrib +R .\_READ_ME_.txt + +rem delete all non read-only +del /Q /A:-R .\* + +rem unmark read-only +attrib -R .\* diff --git a/proj/cleanup.sh b/proj/cleanup.sh new file mode 100644 index 0000000..5ee40d9 --- /dev/null +++ b/proj/cleanup.sh @@ -0,0 +1,16 @@ +# This script is useful for cleaning up the 'project' +# directory of a Digilent Vivado-project git repository +### +# Run the following command to change permissions of +# this 'cleanup' file if needed: +# chmod u+x cleanup.sh +### +# Remove directories/subdirectories +find . -mindepth 1 -type d -exec rm -rf {} + +# Remove any other files than: +find . -type f ! -name 'cleanup.sh' \ + ! -name 'cleanup.cmd' \ + ! -name 'create_project.tcl' \ + ! -name 'release.py' \ + ! -name '.gitignore' \ + -exec rm -rf {} + diff --git a/proj/create_project.tcl b/proj/create_project.tcl new file mode 100644 index 0000000..8fb2232 --- /dev/null +++ b/proj/create_project.tcl @@ -0,0 +1,160 @@ +# Run this script to create the Vivado project files NEXT TO THIS script +# If ::create_path global variable is set, the project is created under that path instead of the working dir + +# Project specific settings. These must be updated for each project. +set proj_name "GPIO" + +if {[info exists ::create_path]} { + set dest_dir $::create_path +} else { + set dest_dir [file normalize [file dirname [info script]]] +} +puts "INFO: Creating new project in $dest_dir" +cd $dest_dir + + + +set part "xc7a35tcpg236-1" +set brd_part "digilentinc.com:basys3:part0:1.1" + +# Set the reference directory for source file relative paths (by default the value is script directory path) +set origin_dir ".." + +# Set the directory path for the original project from where this script was exported +set orig_proj_dir "[file normalize "$origin_dir/proj"]" + +set src_dir $origin_dir/src +set repo_dir $origin_dir/repo + +# # Set the board repo +# # Uncomment if distributing board files with project in the "repo/board_files" folder. +# # This is currently untested. It intends to also keep any existing board repo paths, since this is a global Vivado setting (not project specific. +# # Ideally, if the project is closed, and then a new project is created (without closing Vivado), this should still be able to see a board repo specified in init.tcl. +#set_param board.repoPaths "[file normalize "$repo_dir/board_files"]" + +# Create project +create_project $proj_name $dest_dir + +# Set the directory path for the new project +set proj_dir [get_property directory [current_project]] + +# Set project properties +set obj [get_projects $proj_name] +set_property "default_lib" "xil_defaultlib" $obj +set_property "part" $part $obj +set_property "board_part" $brd_part $obj +set_property "simulator_language" "Mixed" $obj +set_property "target_language" "VHDL" $obj + +# Uncomment the following 3 lines to greatly increase build speed while working with IP cores (and/or block diagrams) +set_property "corecontainer.enable" "0" $obj +set_property "ip_cache_permissions" "read write" $obj +set_property "ip_output_repo" "[file normalize "$origin_dir/repo/cache"]" $obj + +# Create 'sources_1' fileset (if not found) +if {[string equal [get_filesets -quiet sources_1] ""]} { + create_fileset -srcset sources_1 +} + +# Create 'constrs_1' fileset (if not found) +if {[string equal [get_filesets -quiet constrs_1] ""]} { + create_fileset -constrset constrs_1 +} + +# Set IP repository paths +set obj [get_filesets sources_1] +set_property "ip_repo_paths" "[file normalize $repo_dir]" $obj + +# Refresh IP Repositories +update_ip_catalog -rebuild + +# Add conventional sources +add_files -quiet $src_dir/hdl + +# Add IPs +# TODO: handle IP containers files +add_files -quiet [glob -nocomplain ../src/ip/*/*.xci] + +# Add constraints +add_files -fileset constrs_1 -quiet $src_dir/constraints + +# Create 'synth_1' run (if not found) +if {[string equal [get_runs -quiet synth_1] ""]} { + create_run -name synth_1 -part $part -flow {Vivado Synthesis 2015} -strategy "Vivado Synthesis Defaults" -constrset constrs_1 +} else { + set_property strategy "Vivado Synthesis Defaults" [get_runs synth_1] + set_property flow "Vivado Synthesis 2015" [get_runs synth_1] +} +set obj [get_runs synth_1] +set_property "part" $part $obj +set_property "steps.synth_design.args.flatten_hierarchy" "none" $obj +set_property "steps.synth_design.args.directive" "RuntimeOptimized" $obj +set_property "steps.synth_design.args.fsm_extraction" "off" $obj + +# set the current synth run +current_run -synthesis [get_runs synth_1] + +# Create 'impl_1' run (if not found) +if {[string equal [get_runs -quiet impl_1] ""]} { + create_run -name impl_1 -part $part -flow {Vivado Implementation 2015} -strategy "Vivado Implementation Defaults" -constrset constrs_1 -parent_run synth_1 +} else { + set_property strategy "Vivado Implementation Defaults" [get_runs impl_1] + set_property flow "Vivado Implementation 2015" [get_runs impl_1] +} +set obj [get_runs impl_1] +set_property "part" $part $obj +set_property "steps.opt_design.args.directive" "RuntimeOptimized" $obj +set_property "steps.place_design.args.directive" "RuntimeOptimized" $obj +set_property "steps.route_design.args.directive" "RuntimeOptimized" $obj + +# set the current impl run +current_run -implementation [get_runs impl_1] + +puts "INFO: Project created:$proj_name" + +# Comment the rest of this script if there is no block design +# Note that this script currently only supports a single block diagram + +# Uncomment this if building the block diagram from a tcl +# Create block design +# source $origin_dir/src/bd/system.tcl + +# Uncomment this block if importing an existing block diagram project +# Import block design if it exists +set bd_list [glob -nocomplain $src_dir/bd/*/*.bd] +if {[llength $bd_list] != 0} { + add_files -norecurse -quiet -fileset sources_1 [glob -nocomplain $src_dir/bd/*/*.bd] + open_bd_design [glob -nocomplain $src_dir/bd/*/*.bd] + set design_name [get_bd_designs] + set file "$origin_dir/src/bd/$design_name/$design_name.bd" + set file [file normalize $file] + set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] + if { ![get_property "is_locked" $file_obj] } { + set_property "synth_checkpoint_mode" "Hierarchical" $file_obj + } + + # Generate the wrapper + set design_name [get_bd_designs] + add_files -norecurse [make_wrapper -files [get_files $design_name.bd] -top -force] + + set obj [get_filesets sources_1] + set_property "top" "${design_name}_wrapper" $obj +} + +set sdk_dir $origin_dir/sdk + +set hw_list [glob -nocomplain $sdk_dir/*hw_platform*] +if {[llength $hw_list] != 0} { + foreach hw_plat $hw_list { + file delete -force $hw_plat + } +} + +set sdk_list [glob -nocomplain $sdk_dir/*] +set sdk_list [lsearch -inline -all -not -exact $sdk_list "../sdk/.keep"] +if {[llength $sdk_list] != 0} { + exec xsct -eval "setws -switch ../sdk; importproject ../sdk" +} +# +# +# puts "INFO: Block design ready: $design_name.bd" \ No newline at end of file diff --git a/repo/cache/.keep b/repo/cache/.keep new file mode 100644 index 0000000..e69de29 diff --git a/repo/local/.keep b/repo/local/.keep new file mode 100644 index 0000000..e69de29 diff --git a/sdk/.keep b/sdk/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/bd/.keep b/src/bd/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/constraints/.keep b/src/constraints/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/constraints/Basys3_Master.xdc b/src/constraints/Basys3_Master.xdc new file mode 100644 index 0000000..7858c59 --- /dev/null +++ b/src/constraints/Basys3_Master.xdc @@ -0,0 +1,361 @@ +## This file is a general .xdc for the Basys3 rev B board +## To use it in a project: +## - uncomment the lines corresponding to used pins +## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project + +# Clock signal +#Bank = 34, Pin name = , Sch name = CLK100MHZ +set_property PACKAGE_PIN W5 [get_ports CLK] +set_property IOSTANDARD LVCMOS33 [get_ports CLK] +create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports CLK] + +# Switches +set_property PACKAGE_PIN V17 [get_ports {SW[0]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[0]}] +set_property PACKAGE_PIN V16 [get_ports {SW[1]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[1]}] +set_property PACKAGE_PIN W16 [get_ports {SW[2]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[2]}] +set_property PACKAGE_PIN W17 [get_ports {SW[3]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[3]}] +set_property PACKAGE_PIN W15 [get_ports {SW[4]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[4]}] +set_property PACKAGE_PIN V15 [get_ports {SW[5]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[5]}] +set_property PACKAGE_PIN W14 [get_ports {SW[6]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[6]}] +set_property PACKAGE_PIN W13 [get_ports {SW[7]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[7]}] +set_property PACKAGE_PIN V2 [get_ports {SW[8]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[8]}] +set_property PACKAGE_PIN T3 [get_ports {SW[9]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[9]}] +set_property PACKAGE_PIN T2 [get_ports {SW[10]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[10]}] +set_property PACKAGE_PIN R3 [get_ports {SW[11]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[11]}] +set_property PACKAGE_PIN W2 [get_ports {SW[12]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[12]}] +set_property PACKAGE_PIN U1 [get_ports {SW[13]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[13]}] +set_property PACKAGE_PIN T1 [get_ports {SW[14]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[14]}] +set_property PACKAGE_PIN R2 [get_ports {SW[15]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SW[15]}] + + +# 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]}] + + +#7 segment display +#Bank = 34, Pin name = , Sch name = CA +set_property PACKAGE_PIN W7 [get_ports {SSEG_CA[0]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_CA[0]}] +#Bank = 34, Pin name = , Sch name = CB +set_property PACKAGE_PIN W6 [get_ports {SSEG_CA[1]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_CA[1]}] +#Bank = 34, Pin name = , Sch name = CC +set_property PACKAGE_PIN U8 [get_ports {SSEG_CA[2]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_CA[2]}] +#Bank = 34, Pin name = , Sch name = CD +set_property PACKAGE_PIN V8 [get_ports {SSEG_CA[3]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_CA[3]}] +#Bank = 34, Pin name = , Sch name = CE +set_property PACKAGE_PIN U5 [get_ports {SSEG_CA[4]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_CA[4]}] +#Bank = 34, Pin name = , Sch name = CF +set_property PACKAGE_PIN V5 [get_ports {SSEG_CA[5]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_CA[5]}] +#Bank = 34, Pin name = , Sch name = CG +set_property PACKAGE_PIN U7 [get_ports {SSEG_CA[6]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_CA[6]}] + +#Bank = 34, Pin name = , Sch name = DP +set_property PACKAGE_PIN V7 [get_ports {SSEG_CA[7]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_CA[7]}] + +#Bank = 34, Pin name = , Sch name = AN0 +set_property PACKAGE_PIN U2 [get_ports {SSEG_AN[0]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_AN[0]}] +#Bank = 34, Pin name = , Sch name = AN1 +set_property PACKAGE_PIN U4 [get_ports {SSEG_AN[1]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_AN[1]}] +#Bank = 34, Pin name = , Sch name = AN2 +set_property PACKAGE_PIN V4 [get_ports {SSEG_AN[2]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_AN[2]}] +#Bank = 34, Pin name = , Sch name = AN3 +set_property PACKAGE_PIN W4 [get_ports {SSEG_AN[3]}] +set_property IOSTANDARD LVCMOS33 [get_ports {SSEG_AN[3]}] + + +#Buttons +#Bank = 14, Pin name = , Sch name = BTNC +set_property PACKAGE_PIN U18 [get_ports {BTN[4]}] +set_property IOSTANDARD LVCMOS33 [get_ports {BTN[4]}] +#Bank = 14, Pin name = , Sch name = BTNU +set_property PACKAGE_PIN T18 [get_ports {BTN[0]}] +set_property IOSTANDARD LVCMOS33 [get_ports {BTN[0]}] +#Bank = 14, Pin name = , Sch name = BTNL +set_property PACKAGE_PIN W19 [get_ports {BTN[1]}] +set_property IOSTANDARD LVCMOS33 [get_ports {BTN[1]}] +#Bank = 14, Pin name = , Sch name = BTNR +set_property PACKAGE_PIN T17 [get_ports {BTN[2]}] +set_property IOSTANDARD LVCMOS33 [get_ports {BTN[2]}] +#Bank = 14, Pin name = , Sch name = BTND +set_property PACKAGE_PIN U17 [get_ports {BTN[3]}] +set_property IOSTANDARD LVCMOS33 [get_ports {BTN[3]}] + + + +##Pmod Header JA +##Bank = 15, Pin name = IO_L1N_T0_AD0N_15, Sch name = JA1 +#set_property PACKAGE_PIN B13 [get_ports {JA[0]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JA[0]}] +##Bank = 15, Pin name = IO_L5N_T0_AD9N_15, Sch name = JA2 +#set_property PACKAGE_PIN F14 [get_ports {JA[1]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JA[1]}] +##Bank = 15, Pin name = IO_L16N_T2_A27_15, Sch name = JA3 +#set_property PACKAGE_PIN D17 [get_ports {JA[2]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JA[2]}] +##Bank = 15, Pin name = IO_L16P_T2_A28_15, Sch name = JA4 +#set_property PACKAGE_PIN E17 [get_ports {JA[3]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JA[3]}] +##Bank = 15, Pin name = IO_0_15, Sch name = JA7 +#set_property PACKAGE_PIN G13 [get_ports {JA[4]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JA[4]}] +##Bank = 15, Pin name = IO_L20N_T3_A19_15, Sch name = JA8 +#set_property PACKAGE_PIN C17 [get_ports {JA[5]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JA[5]}] +##Bank = 15, Pin name = IO_L21N_T3_A17_15, Sch name = JA9 +#set_property PACKAGE_PIN D18 [get_ports {JA[6]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JA[6]}] +##Bank = 15, Pin name = IO_L21P_T3_DQS_15, Sch name = JA10 +#set_property PACKAGE_PIN E18 [get_ports {JA[7]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JA[7]}] + + + +##Pmod Header JB +##Bank = 15, Pin name = IO_L15N_T2_DQS_ADV_B_15, Sch name = JB1 +#set_property PACKAGE_PIN G14 [get_ports {JB[0]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JB[0]}] +##Bank = 14, Pin name = IO_L13P_T2_MRCC_14, Sch name = JB2 +#set_property PACKAGE_PIN P15 [get_ports {JB[1]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JB[1]}] +##Bank = 14, Pin name = IO_L21N_T3_DQS_A06_D22_14, Sch name = JB3 +#set_property PACKAGE_PIN V11 [get_ports {JB[2]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JB[2]}] +##Bank = CONFIG, Pin name = IO_L16P_T2_CSI_B_14, Sch name = JB4 +#set_property PACKAGE_PIN V15 [get_ports {JB[3]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JB[3]}] +##Bank = 15, Pin name = IO_25_15, Sch name = JB7 +#set_property PACKAGE_PIN K16 [get_ports {JB[4]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JB[4]}] +##Bank = CONFIG, Pin name = IO_L15P_T2_DQS_RWR_B_14, Sch name = JB8 +#set_property PACKAGE_PIN R16 [get_ports {JB[5]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JB[5]}] +##Bank = 14, Pin name = IO_L24P_T3_A01_D17_14, Sch name = JB9 +#set_property PACKAGE_PIN T9 [get_ports {JB[6]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JB[6]}] +##Bank = 14, Pin name = IO_L19N_T3_A09_D25_VREF_14, Sch name = JB10 +#set_property PACKAGE_PIN U11 [get_ports {JB[7]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JB[7]}] + + + +##Pmod Header JC +##Bank = 35, Pin name = IO_L23P_T3_35, Sch name = JC1 +#set_property PACKAGE_PIN K2 [get_ports {JC[0]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JC[0]}] +##Bank = 35, Pin name = IO_L6P_T0_35, Sch name = JC2 +#set_property PACKAGE_PIN E7 [get_ports {JC[1]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JC[1]}] +##Bank = 35, Pin name = IO_L22P_T3_35, Sch name = JC3 +#set_property PACKAGE_PIN J3 [get_ports {JC[2]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JC[2]}] +##Bank = 35, Pin name = IO_L21P_T3_DQS_35, Sch name = JC4 +#set_property PACKAGE_PIN J4 [get_ports {JC[3]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JC[3]}] +##Bank = 35, Pin name = IO_L23N_T3_35, Sch name = JC7 +#set_property PACKAGE_PIN K1 [get_ports {JC[4]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JC[4]}] +##Bank = 35, Pin name = IO_L5P_T0_AD13P_35, Sch name = JC8 +#set_property PACKAGE_PIN E6 [get_ports {JC[5]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JC[5]}] +##Bank = 35, Pin name = IO_L22N_T3_35, Sch name = JC9 +#set_property PACKAGE_PIN J2 [get_ports {JC[6]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JC[6]}] +##Bank = 35, Pin name = IO_L19P_T3_35, Sch name = JC10 +#set_property PACKAGE_PIN G6 [get_ports {JC[7]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JC[7]}] + + +##Pmod Header JXADC +##Bank = 15, Pin name = IO_L9P_T1_DQS_AD3P_15, Sch name = XADC1_P -> XA1_P +#set_property PACKAGE_PIN A13 [get_ports {JXADC[0]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[0]}] +##Bank = 15, Pin name = IO_L8P_T1_AD10P_15, Sch name = XADC2_P -> XA2_P +#set_property PACKAGE_PIN A15 [get_ports {JXADC[1]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[1]}] +##Bank = 15, Pin name = IO_L7P_T1_AD2P_15, Sch name = XADC3_P -> XA3_P +#set_property PACKAGE_PIN B16 [get_ports {JXADC[2]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[2]}] +##Bank = 15, Pin name = IO_L10P_T1_AD11P_15, Sch name = XADC4_P -> XA4_P +#set_property PACKAGE_PIN B18 [get_ports {JXADC[3]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[3]}] +##Bank = 15, Pin name = IO_L9N_T1_DQS_AD3N_15, Sch name = XADC1_N -> XA1_N +#set_property PACKAGE_PIN A14 [get_ports {JXADC[4]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[4]}] +##Bank = 15, Pin name = IO_L8N_T1_AD10N_15, Sch name = XADC2_N -> XA2_N +#set_property PACKAGE_PIN A16 [get_ports {JXADC[5]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[5]}] +##Bank = 15, Pin name = IO_L7N_T1_AD2N_15, Sch name = XADC3_N -> XA3_N +#set_property PACKAGE_PIN B17 [get_ports {JXADC[6]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[6]}] +##Bank = 15, Pin name = IO_L10N_T1_AD11N_15, Sch name = XADC4_N -> XA4_N +#set_property PACKAGE_PIN A18 [get_ports {JXADC[7]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[7]}] + + + +#VGA Connector +#Bank = 14, Pin name = , Sch name = VGA_R0 +set_property PACKAGE_PIN G19 [get_ports {VGA_RED[0]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_RED[0]}] +#Bank = 14, Pin name = , Sch name = VGA_R1 +set_property PACKAGE_PIN H19 [get_ports {VGA_RED[1]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_RED[1]}] +#Bank = 14, Pin name = , Sch name = VGA_R2 +set_property PACKAGE_PIN J19 [get_ports {VGA_RED[2]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_RED[2]}] +#Bank = 14, Pin name = , Sch name = VGA_R3 +set_property PACKAGE_PIN N19 [get_ports {VGA_RED[3]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_RED[3]}] +#Bank = 14, Pin name = , Sch name = VGA_B0 +set_property PACKAGE_PIN N18 [get_ports {VGA_BLUE[0]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_BLUE[0]}] +#Bank = 14, Pin name = , Sch name = VGA_B1 +set_property PACKAGE_PIN L18 [get_ports {VGA_BLUE[1]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_BLUE[1]}] +#Bank = 14, Pin name = , Sch name = VGA_B2 +set_property PACKAGE_PIN K18 [get_ports {VGA_BLUE[2]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_BLUE[2]}] +#Bank = 14, Pin name = , Sch name = VGA_B3 +set_property PACKAGE_PIN J18 [get_ports {VGA_BLUE[3]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_BLUE[3]}] +#Bank = 14, Pin name = , Sch name = VGA_G0 +set_property PACKAGE_PIN J17 [get_ports {VGA_GREEN[0]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_GREEN[0]}] +#Bank = 14, Pin name = , Sch name = VGA_G1 +set_property PACKAGE_PIN H17 [get_ports {VGA_GREEN[1]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_GREEN[1]}] +#Bank = 14, Pin name = , Sch name = VGA_G2 +set_property PACKAGE_PIN G17 [get_ports {VGA_GREEN[2]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_GREEN[2]}] +#Bank = 14, Pin name = , Sch name = VGA_G3 +set_property PACKAGE_PIN D17 [get_ports {VGA_GREEN[3]}] +set_property IOSTANDARD LVCMOS33 [get_ports {VGA_GREEN[3]}] +#Bank = 14, Pin name = , Sch name = VGA_HS +set_property PACKAGE_PIN P19 [get_ports VGA_HS] +set_property IOSTANDARD LVCMOS33 [get_ports VGA_HS] +#Bank = 14, Pin name = , Sch name = VGA_VS +set_property PACKAGE_PIN R19 [get_ports VGA_VS] +set_property IOSTANDARD LVCMOS33 [get_ports VGA_VS] + + +##USB-RS232 Interface +##Bank = 16, Pin name = , Sch name = UART_TXD_IN +#set_property PACKAGE_PIN B18 [get_ports RsRx] +#set_property IOSTANDARD LVCMOS33 [get_ports RsRx] +#Bank = 16, Pin name = , Sch name = UART_RXD_OUT +set_property PACKAGE_PIN A18 [get_ports UART_TXD] +set_property IOSTANDARD LVCMOS33 [get_ports UART_TXD] + + + +#USB HID (PS/2) +#Bank = 16, Pin name = , Sch name = PS2_CLK +set_property PACKAGE_PIN C17 [get_ports PS2_CLK] +set_property IOSTANDARD LVCMOS33 [get_ports PS2_CLK] +set_property PULLUP true [get_ports PS2_CLK] +#Bank = 16, Pin name = , Sch name = PS2_DATA +set_property PACKAGE_PIN B17 [get_ports PS2_DATA] +set_property IOSTANDARD LVCMOS33 [get_ports PS2_DATA] +set_property PULLUP true [get_ports PS2_DATA] + + + +##Quad SPI Flash +##Bank = CONFIG, Pin name = CCLK_0, Sch name = QSPI_SCK +#set_property PACKAGE_PIN C11 [get_ports {QspiSCK}] +#set_property IOSTANDARD LVCMOS33 [get_ports {QspiSCK}] +##Bank = CONFIG, Pin name = IO_L1P_T0_D00_MOSI_14, Sch name = QSPI_DQ0 +#set_property PACKAGE_PIN D18 [get_ports {QspiDB[0]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[0]}] +##Bank = CONFIG, Pin name = IO_L1N_T0_D01_DIN_14, Sch name = QSPI_DQ1 +#set_property PACKAGE_PIN D19 [get_ports {QspiDB[1]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[1]}] +##Bank = CONFIG, Pin name = IO_L20_T0_D02_14, Sch name = QSPI_DQ2 +#set_property PACKAGE_PIN G18 [get_ports {QspiDB[2]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[2]}] +##Bank = CONFIG, Pin name = IO_L2P_T0_D03_14, Sch name = QSPI_DQ3 +#set_property PACKAGE_PIN F18 [get_ports {QspiDB[3]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[3]}] +##Bank = CONFIG, Pin name = IO_L6P_T0_FCS_B_14, Sch name = QSPI_CS +#set_property PACKAGE_PIN K19 [get_ports QspiCSn] +#set_property IOSTANDARD LVCMOS33 [get_ports QspiCSn] + + + +set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] +set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] +set_property CONFIG_MODE SPIx4 [current_design] + +set_property BITSTREAM.CONFIG.CONFIGRATE 33 [current_design] + +set_property CONFIG_VOLTAGE 3.3 [current_design] +set_property CFGBVS VCCO [current_design] + + + + + + + + + + + + diff --git a/src/hdl/.keep b/src/hdl/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/hdl/GPIO_Demo.vhd b/src/hdl/GPIO_Demo.vhd new file mode 100644 index 0000000..5b71733 --- /dev/null +++ b/src/hdl/GPIO_Demo.vhd @@ -0,0 +1,476 @@ +---------------------------------------------------------------------------- +-- GPIO_Demo.vhd -- Basys3 GPIO/UART Demonstration Project +---------------------------------------------------------------------------- +-- Author: Marshall Wingerson Adapted from Sam Bobrowicz +-- Copyright 2013 Digilent, Inc. +---------------------------------------------------------------------------- +-- +---------------------------------------------------------------------------- +-- The GPIO/UART Demo project demonstrates a simple usage of the Basys3's +-- GPIO and UART. The behavior is as follows: +-- +-- *The 16 User LEDs are tied to the 16 User Switches. While the center +-- User button is pressed, the LEDs are instead tied to GND +-- *The 7-Segment display counts from 0 to 9 on each of its 8 +-- digits. This count is reset when the center button is pressed. +-- Also, single anodes of the 7-Segment display are blanked by +-- holding BTNU, BTNL, BTND, or BTNR. Holding the center button +-- blanks all the 7-Segment anodes. +-- *An introduction message is sent across the UART when the device +-- is finished being configured, and after the center User button +-- is pressed. +-- *A message is sent over UART whenever BTNU, BTNL, BTND, or BTNR is +-- pressed. +-- *Note that the center user button behaves as a user reset button +-- and is referred to as such in the code comments below +-- *A test pattern is displayed on the VGA port at 1280x1024 resolution. +-- If a mouse is attached to the USB-HID port, a cursor can be moved +-- around the pattern. +-- +-- All UART communication can be captured by attaching the UART port to a +-- computer running a Terminal program with 9600 Baud Rate, 8 data bits, no +-- parity, and 1 stop bit. +---------------------------------------------------------------------------- +-- +---------------------------------------------------------------------------- +-- Revision History: +-- 08/08/2011(SamB): Created using Xilinx Tools 13.2 +-- 08/27/2013(MarshallW): Modified for the Nexys4 with Xilinx ISE 14.4\ +-- --added RGB and microphone +-- 7/22/2014(SamB): Modified for the Basys3 with Vivado 2014.2\ +-- --Removed RGB and microphone +---------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; + +--The IEEE.std_logic_unsigned contains definitions that allow +--std_logic_vector types to be used with the + operator to instantiate a +--counter. +use IEEE.std_logic_unsigned.all; + +entity GPIO_demo is + Port ( SW : in STD_LOGIC_VECTOR (15 downto 0); + BTN : in STD_LOGIC_VECTOR (4 downto 0); + CLK : in STD_LOGIC; + LED : out STD_LOGIC_VECTOR (15 downto 0); + SSEG_CA : out STD_LOGIC_VECTOR (7 downto 0); + SSEG_AN : out STD_LOGIC_VECTOR (3 downto 0); + UART_TXD : out STD_LOGIC; + VGA_RED : out STD_LOGIC_VECTOR (3 downto 0); + VGA_BLUE : out STD_LOGIC_VECTOR (3 downto 0); + VGA_GREEN : out STD_LOGIC_VECTOR (3 downto 0); + VGA_VS : out STD_LOGIC; + VGA_HS : out STD_LOGIC; + PS2_CLK : inout STD_LOGIC; + PS2_DATA : inout STD_LOGIC + ); +end GPIO_demo; + +architecture Behavioral of GPIO_demo is + +component UART_TX_CTRL +Port( + SEND : in std_logic; + DATA : in std_logic_vector(7 downto 0); + CLK : in std_logic; + READY : out std_logic; + UART_TX : out std_logic + ); +end component; + +component debouncer +Generic( + DEBNC_CLOCKS : integer; + PORT_WIDTH : integer); +Port( + SIGNAL_I : in std_logic_vector(4 downto 0); + CLK_I : in std_logic; + SIGNAL_O : out std_logic_vector(4 downto 0) + ); +end component; + +component vga_ctrl + Port ( CLK_I : in STD_LOGIC; + VGA_HS_O : out STD_LOGIC; + VGA_VS_O : out STD_LOGIC; + VGA_RED_O : out STD_LOGIC_VECTOR (3 downto 0); + VGA_BLUE_O : out STD_LOGIC_VECTOR (3 downto 0); + VGA_GREEN_O : out STD_LOGIC_VECTOR (3 downto 0); + PS2_CLK : inout STD_LOGIC; + PS2_DATA : inout STD_LOGIC + ); +end component; + + +--The type definition for the UART state machine type. Here is a description of what +--occurs during each state: +-- RST_REG -- Do Nothing. This state is entered after configuration or a user reset. +-- The state is set to LD_INIT_STR. +-- LD_INIT_STR -- The Welcome String is loaded into the sendStr variable and the strIndex +-- variable is set to zero. The welcome string length is stored in the StrEnd +-- variable. The state is set to SEND_CHAR. +-- SEND_CHAR -- uartSend is set high for a single clock cycle, signaling the character +-- data at sendStr(strIndex) to be registered by the UART_TX_CTRL at the next +-- cycle. Also, strIndex is incremented (behaves as if it were post +-- incremented after reading the sendStr data). The state is set to RDY_LOW. +-- RDY_LOW -- Do nothing. Wait for the READY signal from the UART_TX_CTRL to go low, +-- indicating a send operation has begun. State is set to WAIT_RDY. +-- WAIT_RDY -- Do nothing. Wait for the READY signal from the UART_TX_CTRL to go high, +-- indicating a send operation has finished. If READY is high and strEnd = +-- StrIndex then state is set to WAIT_BTN, else if READY is high and strEnd /= +-- StrIndex then state is set to SEND_CHAR. +-- WAIT_BTN -- Do nothing. Wait for a button press on BTNU, BTNL, BTND, or BTNR. If a +-- button press is detected, set the state to LD_BTN_STR. +-- LD_BTN_STR -- The Button String is loaded into the sendStr variable and the strIndex +-- variable is set to zero. The button string length is stored in the StrEnd +-- variable. The state is set to SEND_CHAR. +type UART_STATE_TYPE is (RST_REG, LD_INIT_STR, SEND_CHAR, RDY_LOW, WAIT_RDY, WAIT_BTN, LD_BTN_STR); + +--The CHAR_ARRAY type is a variable length array of 8 bit std_logic_vectors. +--Each std_logic_vector contains an ASCII value and represents a character in +--a string. The character at index 0 is meant to represent the first +--character of the string, the character at index 1 is meant to represent the +--second character of the string, and so on. +type CHAR_ARRAY is array (integer range<>) of std_logic_vector(7 downto 0); + +constant TMR_CNTR_MAX : std_logic_vector(26 downto 0) := "101111101011110000100000000"; --100,000,000 = clk cycles per second +constant TMR_VAL_MAX : std_logic_vector(3 downto 0) := "1001"; --9 + +constant RESET_CNTR_MAX : std_logic_vector(17 downto 0) := "110000110101000000";-- 100,000,000 * 0.002 = 200,000 = clk cycles per 2 ms + +constant MAX_STR_LEN : integer := 27; + +constant WELCOME_STR_LEN : natural := 27; +constant BTN_STR_LEN : natural := 24; + +--Welcome string definition. Note that the values stored at each index +--are the ASCII values of the indicated character. +constant WELCOME_STR : CHAR_ARRAY(0 to 26) := (X"0A", --\n + X"0D", --\r + X"42", --B + X"41", --A + X"53", --S + X"59", --Y + X"53", --S + X"33", --3 + X"20", -- + X"47", --G + X"50", --P + X"49", --I + X"4F", --O + X"2F", --/ + X"55", --U + X"41", --A + X"52", --R + X"54", --T + X"20", -- + X"44", --D + X"45", --E + X"4D", --M + X"4F", --O + X"21", --! + X"0A", --\n + X"0A", --\n + X"0D"); --\r + +--Button press string definition. +constant BTN_STR : CHAR_ARRAY(0 to 23) := (X"42", --B + X"75", --u + X"74", --t + X"74", --t + X"6F", --o + X"6E", --n + X"20", -- + X"70", --p + X"72", --r + X"65", --e + X"73", --s + X"73", --s + X"20", -- + X"64", --d + X"65", --e + X"74", --t + X"65", --e + X"63", --c + X"74", --t + X"65", --e + X"64", --d + X"21", --! + X"0A", --\n + X"0D"); --\r + +--This is used to determine when the 7-segment display should be +--incremented +signal tmrCntr : std_logic_vector(26 downto 0) := (others => '0'); + +--This counter keeps track of which number is currently being displayed +--on the 7-segment. +signal tmrVal : std_logic_vector(3 downto 0) := (others => '0'); + +--Contains the current string being sent over uart. +signal sendStr : CHAR_ARRAY(0 to (MAX_STR_LEN - 1)); + +--Contains the length of the current string being sent over uart. +signal strEnd : natural; + +--Contains the index of the next character to be sent over uart +--within the sendStr variable. +signal strIndex : natural; + +--Used to determine when a button press has occured +signal btnReg : std_logic_vector (3 downto 0) := "0000"; +signal btnDetect : std_logic; + +--UART_TX_CTRL control signals +signal uartRdy : std_logic; +signal uartSend : std_logic := '0'; +signal uartData : std_logic_vector (7 downto 0):= "00000000"; +signal uartTX : std_logic; + +--Current uart state signal +signal uartState : UART_STATE_TYPE := RST_REG; + +--Debounced btn signals used to prevent single button presses +--from being interpreted as multiple button presses. +signal btnDeBnc : std_logic_vector(4 downto 0); + +signal clk_cntr_reg : std_logic_vector (4 downto 0) := (others=>'0'); + +signal pwm_val_reg : std_logic := '0'; + +--this counter counts the amount of time paused in the UART reset state +signal reset_cntr : std_logic_vector (17 downto 0) := (others=>'0'); + +begin + +---------------------------------------------------------- +------ LED Control ------- +---------------------------------------------------------- + +with BTN(4) select + LED <= SW when '0', + "0000000000000000" when others; + +---------------------------------------------------------- +------ 7-Seg Display Control ------- +---------------------------------------------------------- +--Digits are incremented every second, and are blanked in +--response to button presses. + +--Individual and reset blanking of Anodes +with BTN(4) select + SSEG_AN(3 downto 0) <= btnDeBnc(3 downto 0) when '0', + "1111" when others; + +--This process controls the counter that triggers the 7-segment +--to be incremented. It counts 100,000,000 and then resets. +timer_counter_process : process (CLK) +begin + if (rising_edge(CLK)) then + if ((tmrCntr = TMR_CNTR_MAX) or (BTN(4) = '1')) then + tmrCntr <= (others => '0'); + else + tmrCntr <= tmrCntr + 1; + end if; + end if; +end process; + +--This process increments the digit being displayed on the +--7-segment display every second. +timer_inc_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (BTN(4) = '1') then + tmrVal <= (others => '0'); + elsif (tmrCntr = TMR_CNTR_MAX) then + if (tmrVal = TMR_VAL_MAX) then + tmrVal <= (others => '0'); + else + tmrVal <= tmrVal + 1; + end if; + end if; + end if; +end process; + +--This select statement encodes the value of tmrVal to the necessary +--cathode signals to display it on the 7-segment +with tmrVal select + SSEG_CA <= "01000000" when "0000", + "01111001" when "0001", + "00100100" when "0010", + "00110000" when "0011", + "00011001" when "0100", + "00010010" when "0101", + "00000010" when "0110", + "01111000" when "0111", + "00000000" when "1000", + "00010000" when "1001", + "11111111" when others; + + +---------------------------------------------------------- +------ Button Control ------- +---------------------------------------------------------- +--Buttons are debounced and their rising edges are detected +--to trigger UART messages + + +--Debounces btn signals +Inst_btn_debounce: debouncer + generic map( + DEBNC_CLOCKS => (2**16), + PORT_WIDTH => 5) + port map( + SIGNAL_I => BTN, + CLK_I => CLK, + SIGNAL_O => btnDeBnc + ); + +--Registers the debounced button signals, for edge detection. +btn_reg_process : process (CLK) +begin + if (rising_edge(CLK)) then + btnReg <= btnDeBnc(3 downto 0); + end if; +end process; + +--btnDetect goes high for a single clock cycle when a btn press is +--detected. This triggers a UART message to begin being sent. +btnDetect <= '1' when ((btnReg(0)='0' and btnDeBnc(0)='1') or + (btnReg(1)='0' and btnDeBnc(1)='1') or + (btnReg(2)='0' and btnDeBnc(2)='1') or + (btnReg(3)='0' and btnDeBnc(3)='1') ) else + '0'; + + + + +---------------------------------------------------------- +------ UART Control ------- +---------------------------------------------------------- +--Messages are sent on reset and when a button is pressed. + +--This counter holds the UART state machine in reset for ~2 milliseconds. This +--will complete transmission of any byte that may have been initiated during +--FPGA configuration due to the UART_TX line being pulled low, preventing a +--frame shift error from occuring during the first message. +process(CLK) +begin + if (rising_edge(CLK)) then + if ((reset_cntr = RESET_CNTR_MAX) or (uartState /= RST_REG)) then + reset_cntr <= (others=>'0'); + else + reset_cntr <= reset_cntr + 1; + end if; + end if; +end process; + +--Next Uart state logic (states described above) +next_uartState_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (btnDeBnc(4) = '1') then + uartState <= RST_REG; + else + case uartState is + when RST_REG => + if (reset_cntr = RESET_CNTR_MAX) then + uartState <= LD_INIT_STR; + end if; + when LD_INIT_STR => + uartState <= SEND_CHAR; + when SEND_CHAR => + uartState <= RDY_LOW; + when RDY_LOW => + uartState <= WAIT_RDY; + when WAIT_RDY => + if (uartRdy = '1') then + if (strEnd = strIndex) then + uartState <= WAIT_BTN; + else + uartState <= SEND_CHAR; + end if; + end if; + when WAIT_BTN => + if (btnDetect = '1') then + uartState <= LD_BTN_STR; + end if; + when LD_BTN_STR => + uartState <= SEND_CHAR; + when others=> --should never be reached + uartState <= RST_REG; + end case; + end if ; + end if; +end process; + +--Loads the sendStr and strEnd signals when a LD state is +--is reached. +string_load_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (uartState = LD_INIT_STR) then + sendStr <= WELCOME_STR; + strEnd <= WELCOME_STR_LEN; + elsif (uartState = LD_BTN_STR) then + sendStr(0 to 23) <= BTN_STR; + strEnd <= BTN_STR_LEN; + end if; + end if; +end process; + +--Conrols the strIndex signal so that it contains the index +--of the next character that needs to be sent over uart +char_count_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (uartState = LD_INIT_STR or uartState = LD_BTN_STR) then + strIndex <= 0; + elsif (uartState = SEND_CHAR) then + strIndex <= strIndex + 1; + end if; + end if; +end process; + +--Controls the UART_TX_CTRL signals +char_load_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (uartState = SEND_CHAR) then + uartSend <= '1'; + uartData <= sendStr(strIndex); + else + uartSend <= '0'; + end if; + end if; +end process; + +--Component used to send a byte of data over a UART line. +Inst_UART_TX_CTRL: UART_TX_CTRL port map( + SEND => uartSend, + DATA => uartData, + CLK => CLK, + READY => uartRdy, + UART_TX => uartTX + ); + +UART_TXD <= uartTX; + + +---------------------------------------------------------- +------ VGA Control ------- +---------------------------------------------------------- + +Inst_vga_ctrl: vga_ctrl port map( + CLK_I => CLK, + VGA_HS_O => VGA_HS, + VGA_VS_O => VGA_VS, + VGA_RED_O => VGA_RED, + VGA_BLUE_O => VGA_BLUE, + VGA_GREEN_O => VGA_GREEN, + PS2_CLK => PS2_CLK, + PS2_DATA => PS2_DATA + ); + +end Behavioral; diff --git a/src/hdl/MouseCtl.vhd b/src/hdl/MouseCtl.vhd new file mode 100644 index 0000000..a03d9e3 --- /dev/null +++ b/src/hdl/MouseCtl.vhd @@ -0,0 +1,1169 @@ +------------------------------------------------------------------------ +-- mouse_controller.vhd +------------------------------------------------------------------------ +-- Author : Ulrich Zoltán +-- Copyright 2006 Digilent, Inc. +------------------------------------------------------------------------ +-- This file contains a controller for a ps/2 compatible mouse device. +-- This controller uses the ps2interface module. +------------------------------------------------------------------------ +-- Behavioral description +------------------------------------------------------------------------ +-- Please read the following article on the web for understanding how +-- to interface a ps/2 mouse: +-- http://www.computer-engineering.org/ps2mouse/ + +-- This controller is implemented as described in the above article. +-- The mouse controller receives bytes from the ps2interface which, in +-- turn, receives them from the mouse device. Data is received on the +-- rx_data input port, and is validated by the read signal. read is +-- active for one clock period when new byte available on rx_data. Data +-- is sent to the ps2interface on the tx_data output port and validated +-- by the write output signal. 'write' should be active for one clock +-- period when tx_data contains the command or data to be sent to the +-- mouse. ps2interface wraps the byte in a 11 bits packet that is sent +-- through the ps/2 port using the ps/2 protocol. Similarly, when the +-- mouse sends data, the ps2interface receives 11 bits for every byte, +-- extracts the byte from the ps/2 frame, puts it on rx_data and +-- activates read for one clock period. If an error occurs when sending +-- or receiving a frame from the mouse, the err input goes high for one +-- clock period. When this occurs, the controller enters reset state. + +-- When in reset state, the controller resets the mouse and begins an +-- initialization procedure that consists of tring to put mouse in +-- scroll mode (enables wheel if the mouse has one), setting the +-- resolution of the mouse, the sample rate and finally enables +-- reporting. Implicitly the mouse, after a reset or imediately after a +-- reset, does not send data packets on its own. When reset(or power-up) +-- the mouse enters reset state, where it performs a test, called the +-- bat test (basic assurance test), when this test is done, it sends +-- the result: AAh for test ok, FCh for error. After this it sends its +-- ID which is 00h. When this is done, the mouse enters stream mode, +-- but with reporting disabled (movement data packets are not sent). +-- To enable reporting the enable data reporting command (F4h) must be +-- sent to the mouse. After this command is sent, the mouse will send +-- movement data packets when the mouse is moved or the status of the +-- button changes. + +-- After sending a command or a byte following a command, the mouse +-- must respond with ack (FAh). For managing the intialization +-- procedure and receiving the movement data packets, a FSM is used. +-- When the fpga is powered up or the logic is reset using the global +-- reset, the FSM enters reset state. From this state, the FSM will +-- transition to a series of states used to initialize the mouse. When +-- initialization is complete, the FSM remains in state read_byte_1, +-- waiting for a movement data packet to be sent. This is the idle +-- state if the FSM. When a byte is received in this state, this is +-- the first byte of the 3 bytes sent in a movement data packet (4 bytes +-- if mouse in scrolling mode). After reading the last byte from the +-- packet, the FSM enters mark_new_event state and sets new_event high. +-- After that FSM enterss read_byte_1 state, resets new_event and waits +-- for a new packet. +-- After a packet is received, new_event is set high for one clock +-- period to "inform" the clients of this controller a new packet was +-- received and processed. + +-- During the initialization procedure, the controller tries to put the +-- mouse in scroll mode (activates wheel, if mouse has one). This is +-- done by successively setting the sample rate to 200, then to 100, and +-- lastly to 80. After this is done, the mouse ID is requested by +-- sending get device ID command (F2h). If the received ID is 00h than +-- the mouse does not have a wheel. If the received ID is 03h than the +-- mouse is in scroll mode, and when sending movement data packets +-- (after enabling data reporting) it will include z movement data. +-- If the mouse is in normal, non-scroll mode, the movement data packet +-- consists of 3 successive bytes. This is their format: +-- +-- +-- +-- bits 7 6 5 4 3 2 1 0 +-- ------------------------------------------------- +-- byte 1 | YOVF| XOVF|YSIGN|XSIGN| 1 | MBTN| RBTN| LBTN| +-- ------------------------------------------------- +-- ------------------------------------------------- +-- byte 2 | X MOVEMENT | +-- ------------------------------------------------- +-- ------------------------------------------------- +-- byte 3 | Y MOVEMENT | +-- ------------------------------------------------- +-- OVF = overflow +-- BTN = button +-- M = middle +-- R = right +-- L = left +-- +-- When scroll mode is enabled, the mouse send 4 byte movement packets. +-- bits 7 6 5 4 3 2 1 0 +-- ------------------------------------------------- +-- byte 1 | YOVF| XOVF|YSIGN|XSIGN| 1 | MBTN| RBTN| LBTN| +-- ------------------------------------------------- +-- ------------------------------------------------- +-- byte 2 | X MOVEMENT | +-- ------------------------------------------------- +-- ------------------------------------------------- +-- byte 3 | Y MOVEMENT | +-- ------------------------------------------------- +-- ------------------------------------------------- +-- byte 4 | Z MOVEMENT | +-- ------------------------------------------------- +-- x and y movement counters are represented on 8 bits, 2's complement +-- encoding. The first bit (sign bit) of the counters are the xsign and +-- ysign bit from the first packet, the rest of the bits are the second +-- byte for the x movement and the third byte for y movement. For the +-- z movement the range is -8 -> +7 and only the 4 least significant +-- bits from z movement are valid, the rest are sign extensions. +-- The x and y movements are in range: -256 -> +255 + +-- The mouse uses as axes origin the lower-left corner. For the purpose +-- of displaying a mouse cursor on the screen, the controller inverts +-- the y axis to move the axes origin in the upper-left corner. This +-- is done by negating the y movement value (following the 2s complement +-- encoding). The movement data received from the mouse are delta +-- movements, the data represents the movement of the mouse relative +-- to the last position. The controller keeps track of the position of +-- the mouse relative to the upper-left corner. This is done by keeping +-- the mouse position in two registers x_pos and y_pos and adding the +-- delta movements to their value. The addition uses saturation. That +-- means the value of the mouse position will not exceed certain bounds +-- and will not rollover the a margin. For example, if the mouse is at +-- the left margin and is moved left, the x position remains at the left +-- margin(0). The lower bound is always 0 for both x and y movement. +-- The upper margin can be set using input pins: value, setmax_x, +-- setmax_y. To set the upper bound of the x movement counter, the new +-- value is placed on the value input pins and setmax_x is activated +-- for at least one clock period. Similarly for y movement counter, but +-- setmax_y is activated instead. Notice that value has 10 bits, and so +-- the maximum value for a bound is 1023. + +-- The position of the mouse (x_pos and y_pos) can be set at any time, +-- by placing the x or y position on the value input pins and activating +-- the setx, or sety respectively, for at least one clock period. This +-- is useful for setting an original position of the mouse different +-- from (0,0). +------------------------------------------------------------------------ +-- Port definitions +------------------------------------------------------------------------ +-- clk - global clock signal (100MHz) +-- rst - global reset signal +-- xpos - output pin, 10 bits +-- - the x position of the mouse relative to the upper +-- - left corner +-- ypos - output pin, 10 bits +-- - the y position of the mouse relative to the upper +-- - left corner +-- zpos - output pin, 4 bits +-- - last delta movement on z axis +-- left - output pin, high if the left mouse button is pressed +-- middle - output pin, high if the middle mouse button is +-- - pressed +-- right - output pin, high if the right mouse button is +-- - pressed +-- new_event - output pin, active one clock period after receiving +-- - and processing one movement data packet. +------------------------------------------------------------------------ +-- Revision History: +-- 09/18/2006(UlrichZ): created +------------------------------------------------------------------------ + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +-- simulation library +library UNISIM; +use UNISIM.VComponents.all; + +-- the mouse_controller entity declaration +-- read above for behavioral description and port definitions. +entity MouseCtl is +generic +( + SYSCLK_FREQUENCY_HZ : integer := 100000000; + CHECK_PERIOD_MS : integer := 500; -- Period in miliseconds to check if the mouse is present + TIMEOUT_PERIOD_MS : integer := 100 -- Timeout period in miliseconds when the mouse presence is checked +); +port( + clk : in std_logic; + rst : in std_logic; + xpos : out std_logic_vector(11 downto 0); + ypos : out std_logic_vector(11 downto 0); + zpos : out std_logic_vector(3 downto 0); + left : out std_logic; + middle : out std_logic; + right : out std_logic; + new_event : out std_logic; + value : in std_logic_vector(11 downto 0); + setx : in std_logic; + sety : in std_logic; + setmax_x : in std_logic; + setmax_y : in std_logic; + + ps2_clk : inout std_logic; + ps2_data : inout std_logic + +); +end MouseCtl; + +architecture Behavioral of MouseCtl is + +------------------------------------------------------------------------ +-- Ps2 Interface component declaration +------------------------------------------------------------------------ +COMPONENT Ps2Interface +PORT( + ps2_clk : inout std_logic; + ps2_data : inout std_logic; + clk : in std_logic; + rst : in std_logic; + tx_data : in std_logic_vector(7 downto 0); + write_data : in std_logic; + rx_data : out std_logic_vector(7 downto 0); + read_data : out std_logic; + busy : out std_logic; + err : out std_logic +); +END COMPONENT; + +------------------------------------------------------------------------ +-- CONSTANTS +------------------------------------------------------------------------ +-- constants defining commands to send or received from the mouse +constant FA: std_logic_vector(7 downto 0) := "11111010"; -- 0xFA(ACK) +constant FF: std_logic_vector(7 downto 0) := "11111111"; -- 0xFF(RESET) +constant AA: std_logic_vector(7 downto 0) := "10101010"; -- 0xAA(BAT_OK) +constant OO: std_logic_vector(7 downto 0) := "00000000"; -- 0x00(ID) + -- (atention: name is 2 letters O not zero) + +-- command to read id +constant READ_ID : std_logic_vector(7 downto 0) := x"F2"; +-- command to enable mouse reporting +-- after this command is sent, the mouse begins sending data packets +constant ENABLE_REPORTING : std_logic_vector(7 downto 0) := x"F4"; +-- command to set the mouse resolution +constant SET_RESOLUTION : std_logic_vector(7 downto 0) := x"E8"; +-- the value of the resolution to send after sending SET_RESOLUTION +constant RESOLUTION : std_logic_vector(7 downto 0) := x"03"; + -- (8 counts/mm) +-- command to set the mouse sample rate +constant SET_SAMPLE_RATE : std_logic_vector(7 downto 0) := x"F3"; + +-- the value of the sample rate to send after sending SET_SAMPLE_RATE +constant SAMPLE_RATE : std_logic_vector(7 downto 0) := x"28"; + -- (40 samples/s) + +-- default maximum value for the horizontal mouse position +constant DEFAULT_MAX_X : std_logic_vector(11 downto 0) := x"4FF"; + -- 1279 +-- default maximum value for the vertical mouse position +constant DEFAULT_MAX_Y : std_logic_vector(11 downto 0) := x"3FF"; + -- 1023 + +-- Mouse check tick constants +constant CHECK_PERIOD_CLOCKS : integer := ((CHECK_PERIOD_MS*1000000)/(1000000000/SYSCLK_FREQUENCY_HZ)); +constant TIMEOUT_PERIOD_CLOCKS : integer := ((TIMEOUT_PERIOD_MS*1000000)/(1000000000/SYSCLK_FREQUENCY_HZ)); + +------------------------------------------------------------------------ +-- SIGNALS +------------------------------------------------------------------------ + +-- after doing the enable scroll mouse procedure, if the ID returned by +-- the mouse is 03 (scroll mouse enabled) then this register will be set +-- If '1' then the mouse is in scroll mode, else mouse is in simple +-- mouse mode. +signal haswheel: std_logic := '0'; + +-- horizontal and veritcal mouse position +-- origin of axes is upper-left corner +-- the origin of axes the mouse uses is the lower-left corner +-- The y-axis is inverted, by making negative the y movement received +-- from the mouse (if it was positive it becomes negative +-- and vice versa) +signal x_pos,y_pos: std_logic_vector(11 downto 0) := (others => '0'); + +-- active when an overflow occurred on the x and y axis +-- bits 6 and 7 from the first byte received from the mouse +signal x_overflow,y_overflow: std_logic := '0'; + +-- active when the x,y movement is negative +-- bits 4 and 5 from the first byte received from the mouse +signal x_sign,y_sign: std_logic := '0'; + +-- 2's complement value for incrementing the x_pos,y_pos +-- y_inc is the negated value from the mouse in the third byte +signal x_inc,y_inc: std_logic_vector(7 downto 0) := (others => '0'); + +-- active for one clock period, indicates new delta movement received +-- on x,y axis +signal x_new,y_new: std_logic := '0'; + +-- maximum value for x and y position registers(x_pos,y_pos) +signal x_max: std_logic_vector(11 downto 0) := DEFAULT_MAX_X; +signal y_max: std_logic_vector(11 downto 0) := DEFAULT_MAX_Y; + +-- active when left,middle,right mouse button is down +signal left_down,middle_down,right_down: std_logic := '0'; + +-- the FSM states +-- states that begin with "reset" are part of the reset procedure. +-- states that end in "_wait_ack" are states in which ack is waited +-- as response to sending a byte to the mouse. +-- read behavioral description above for details. +type fsm_state is +( + reset,reset_wait_ack,reset_wait_bat_completion,reset_wait_id, + reset_set_sample_rate_200,reset_set_sample_rate_200_wait_ack, + reset_send_sample_rate_200,reset_send_sample_rate_200_wait_ack, + reset_set_sample_rate_100,reset_set_sample_rate_100_wait_ack, + reset_send_sample_rate_100,reset_send_sample_rate_100_wait_ack, + reset_set_sample_rate_80,reset_set_sample_rate_80_wait_ack, + reset_send_sample_rate_80,reset_send_sample_rate_80_wait_ack, + reset_read_id,reset_read_id_wait_ack,reset_read_id_wait_id, + reset_set_resolution,reset_set_resolution_wait_ack, + reset_send_resolution,reset_send_resolution_wait_ack, + reset_set_sample_rate_40,reset_set_sample_rate_40_wait_ack, + reset_send_sample_rate_40,reset_send_sample_rate_40_wait_ack, + reset_enable_reporting,reset_enable_reporting_wait_ack, + read_byte_1,read_byte_2,read_byte_3,read_byte_4, + check_read_id,check_read_id_wait_ack,check_read_id_wait_id, + mark_new_event +); +-- holds current state of the FSM +signal state: fsm_state := reset; + +-- PS2 Interface and Mouse Controller interconnection signals +-- read_data - from ps2interface +-- - active one clock period when new data received +-- - and available on rx_data +-- err - from ps2interface +-- - active one clock period when error occurred when +-- - receiving or sending data. +-- rx_data - 8 bits, from ps2interface +-- - the byte received from the mouse. +-- tx_data - 8 bits, to ps2interface +-- - byte to be sent to the mouse +-- write_data - to ps2interface +-- - active one clock period when sending a byte to the +-- - ps2interface. +signal read_data : std_logic; +signal err : std_logic; +signal rx_data: std_logic_vector (7 downto 0); +signal tx_data: std_logic_vector (7 downto 0); +signal write_data : std_logic; + +-- Periodic checking counter, reset and tick signal +-- The periodic checking counter acts as a watchdog, periodically +-- reading the Mouse ID, therefore checking if the mouse is present +-- If there is no answer, after the timeout period passed, then the +-- state machine is reinitialized +signal periodic_check_cnt : integer range 0 to (CHECK_PERIOD_CLOCKS - 1) := 0; +signal reset_periodic_check_cnt : STD_LOGIC := '0'; +signal periodic_check_tick : STD_LOGIC := '0'; + +-- Self-blocking Timeout checking counter, reset and timeout indication signal +signal timeout_cnt : integer range 0 to (TIMEOUT_PERIOD_CLOCKS - 1) := 0; +signal reset_timeout_cnt : STD_LOGIC := '0'; +signal timeout : STD_LOGIC := '0'; + +begin + + Inst_Ps2Interface: Ps2Interface + PORT MAP + ( + ps2_clk => ps2_clk, + ps2_data => ps2_data, + clk => clk, + rst => rst, + tx_data => tx_data, + write_data => write_data, + rx_data => rx_data, + read_data => read_data, + busy => open, + err => err + ); + + +-- Create the periodic_check_cnt counter +Count_periodic_check: process (clk, periodic_check_cnt, reset_periodic_check_cnt) +begin + if clk'EVENT AND clk = '1' then + if reset_periodic_check_cnt = '1' then + periodic_check_cnt <= 0; + elsif periodic_check_cnt = (CHECK_PERIOD_CLOCKS - 1) then + periodic_check_cnt <= 0; + else + periodic_check_cnt <= periodic_check_cnt + 1; + end if; + end if; +end process Count_periodic_check; + +periodic_check_tick <= '1' when periodic_check_cnt = (CHECK_PERIOD_CLOCKS - 1) else '0'; + +-- Create the timeout counter +Count_timeout: process (clk, timeout_cnt, reset_timeout_cnt) +begin + if clk'EVENT AND clk = '1' then + if reset_timeout_cnt = '1' then + timeout_cnt <= 0; + elsif timeout_cnt = (TIMEOUT_PERIOD_CLOCKS - 1) then + timeout_cnt <= (TIMEOUT_PERIOD_CLOCKS - 1); + else + timeout_cnt <= timeout_cnt + 1; + end if; + end if; +end process Count_timeout; + +timeout <= '1' when timeout_cnt = (TIMEOUT_PERIOD_CLOCKS - 1) else '0'; + + -- left output the state of the left_down register + left <= left_down when rising_edge(clk); + -- middle output the state of the middle_down register + middle <= middle_down when rising_edge(clk); + -- right output the state of the right_down register + right <= right_down when rising_edge(clk); + + -- xpos output is the horizontal position of the mouse + -- it has the range: 0-x_max + xpos <= x_pos(11 downto 0) when rising_edge(clk); + -- ypos output is the vertical position of the mouse + -- it has the range: 0-y_max + ypos <= y_pos(11 downto 0) when rising_edge(clk); + + -- sets the value of x_pos from another module when setx is active + -- else, computes the new x_pos from the old position when new x + -- movement detected by adding the delta movement in x_inc, or by + -- adding 256 or -256 when overflow occurs. + set_x: process(clk) + variable x_inter: std_logic_vector(11 downto 0); + variable inc: std_logic_vector(11 downto 0); + begin + if(rising_edge(clk)) then + -- if setx active, set new x_pos value + if(setx = '1') then + x_pos <= value; + -- if delta movement received from mouse + elsif(x_new = '1') then + -- if negative movement on x axis + if(x_sign = '1') then + -- if overflow occurred + if(x_overflow = '1') then + -- inc is -256 + inc := "111000000000"; + else + -- inc is sign extended x_inc + inc := "1111" & x_inc; + end if; + -- intermediary horizontal position + x_inter := x_pos + inc; + -- if first bit of x_inter is 1 + -- then negative overflow occurred and + -- new x position is 0. + -- Note: x_pos and x_inter have 11 bits, + -- and because xpos has only 10, when + -- first bit becomes 1, this is considered + -- a negative number when moving left + if(x_inter(11) = '1') then + x_pos <= (others => '0'); + else + x_pos <= x_inter; + end if; + -- if positive movement on x axis + else + -- if overflow occurred + if(x_overflow = '1') then + -- inc is 256 + inc := "000100000000"; + else + -- inc is sign extended x_inc + inc := "0000" & x_inc; + end if; + -- intermediary horizontal position + x_inter := x_pos + inc; + -- if x_inter is greater than x_max + -- then positive overflow occurred and + -- new x position is x_max. + if(x_inter > ('0' & x_max)) then + x_pos <= x_max; + else + x_pos <= x_inter; + end if; + end if; + end if; + end if; + end process set_x; + + -- sets the value of y_pos from another module when sety is active + -- else, computes the new y_pos from the old position when new y + -- movement detected by adding the delta movement in y_inc, or by + -- adding 256 or -256 when overflow occurs. + set_y: process(clk) + variable y_inter: std_logic_vector(11 downto 0); + variable inc: std_logic_vector(11 downto 0); + begin + if(rising_edge(clk)) then + -- if sety active, set new y_pos value + if(sety = '1') then + y_pos <= value; + -- if delta movement received from mouse + elsif(y_new = '1') then + -- if negative movement on y axis + -- Note: axes origin is upper-left corner + if(y_sign = '1') then + -- if overflow occurred + if(y_overflow = '1') then + -- inc is -256 + inc := "111100000000"; + else + -- inc is sign extended y_inc + inc := "1111" & y_inc; + end if; + -- intermediary vertical position + y_inter := y_pos + inc; + -- if first bit of y_inter is 1 + -- then negative overflow occurred and + -- new y position is 0. + -- Note: y_pos and y_inter have 11 bits, + -- and because ypos has only 10, when + -- first bit becomes 1, this is considered + -- a negative number when moving upward + if(y_inter(11) = '1') then + y_pos <= (others => '0'); + else + y_pos <= y_inter; + end if; + -- if positive movement on y axis + else + -- if overflow occurred + if(y_overflow = '1') then + -- inc is 256 + inc := "000100000000"; + else + -- inc is sign extended y_inc + inc := "0000" & y_inc; + end if; + -- intermediary vertical position + y_inter := y_pos + inc; + -- if y_inter is greater than y_max + -- then positive overflow occurred and + -- new y position is y_max. + if(y_inter > (y_max)) then + y_pos <= y_max; + else + y_pos <= y_inter; + end if; + end if; + end if; + end if; + end process set_y; + + -- sets the maximum value of the x movement register, stored in x_max + -- when setmax_x is active, max value should be on value input pin + set_max_x: process(clk,rst) + begin + if(rising_edge(clk)) then + if(rst = '1') then + x_max <= DEFAULT_MAX_X; + elsif(setmax_x = '1') then + x_max <= value; + end if; + end if; + end process set_max_x; + + -- sets the maximum value of the y movement register, stored in y_max + -- when setmax_y is active, max value should be on value input pin + set_max_y: process(clk,rst) + begin + if(rising_edge(clk)) then + if(rst = '1') then + y_max <= DEFAULT_MAX_Y; + elsif(setmax_y = '1') then + y_max <= value; + end if; + end if; + end process set_max_y; + + -- Synchronous one process fsm to handle the communication + -- with the mouse. + -- When reset and at start-up it enters reset state + -- where it begins the procedure of initializing the mouse. + -- After initialization is complete, it waits packets from + -- the mouse. + -- Read at Behavioral decription for details. + manage_fsm: process(clk,rst) + begin + -- when reset occurs, give signals default values. + if(rst = '1') then + state <= reset; + haswheel <= '0'; + x_overflow <= '0'; + y_overflow <= '0'; + x_sign <= '0'; + y_sign <= '0'; + x_inc <= (others => '0'); + y_inc <= (others => '0'); + x_new <= '0'; + y_new <= '0'; + new_event <= '0'; + left_down <= '0'; + middle_down <= '0'; + right_down <= '0'; + reset_periodic_check_cnt <= '1'; + reset_timeout_cnt <= '1'; + + + elsif(rising_edge(clk)) then + + -- at every rising edge of the clock, this signals + -- are reset, thus assuring that they are active + -- for one clock period only if a state sets then + -- because the fsm will transition from the state + -- that set them on the next rising edge of clock. + write_data <= '0'; + x_new <= '0'; + y_new <= '0'; + + case state is + + -- if just powered-up, reset occurred or some error in + -- transmision encountered, then fsm will transition to + -- this state. Here the RESET command (FF) is sent to the + -- mouse, and various signals receive their default values + -- From here the FSM transitions to a series of states that + -- perform the mouse initialization procedure. All this + -- state are prefixed by "reset_". After sending a byte + -- to the mouse, it respondes by sending ack (FA). All + -- states that wait ack from the mouse are postfixed by + -- "_wait_ack". + -- Read at Behavioral decription for details. + when reset => + haswheel <= '0'; + x_overflow <= '0'; + y_overflow <= '0'; + x_sign <= '0'; + y_sign <= '0'; + x_inc <= (others => '0'); + y_inc <= (others => '0'); + x_new <= '0'; + y_new <= '0'; + left_down <= '0'; + middle_down <= '0'; + right_down <= '0'; + tx_data <= FF; + write_data <= '1'; + reset_periodic_check_cnt <= '1'; + reset_timeout_cnt <= '1'; + state <= reset_wait_ack; + + -- wait ack for the reset command. + -- when received transition to reset_wait_bat_completion. + -- if error occurs go to reset state. + when reset_wait_ack => + if(read_data = '1') then + -- if received ack + if(rx_data = FA) then + state <= reset_wait_bat_completion; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_wait_ack; + end if; + + -- wait for bat completion test + -- mouse should send AA if test is successful + when reset_wait_bat_completion => + if(read_data = '1') then + if(rx_data = AA) then + state <= reset_wait_id; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_wait_bat_completion; + end if; + + -- the mouse sends its id after performing bat test + -- the mouse id should be 00 + when reset_wait_id => + if(read_data = '1') then + if(rx_data = OO) then + state <= reset_set_sample_rate_200; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_wait_id; + end if; + + -- with this state begins the enable wheel mouse + -- procedure. The procedure consists of setting + -- the sample rate of the mouse first 200, then 100 + -- then 80. After this is done, the mouse id is + -- requested and if the mouse id is 03, then + -- mouse is in wheel mode and will send 4 byte packets + -- when reporting is enabled. + -- If the id is 00, the mouse does not have a wheel + -- and will send 3 byte packets when reporting is enabled. + -- This state issues the set_sample_rate command to the + -- mouse. + when reset_set_sample_rate_200 => + tx_data <= SET_SAMPLE_RATE; + write_data <= '1'; + state <= reset_set_sample_rate_200_wait_ack; + + -- wait ack for set sample rate command + when reset_set_sample_rate_200_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= reset_send_sample_rate_200; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_set_sample_rate_200_wait_ack; + end if; + + -- send the desired sample rate (200 = 0xC8) + when reset_send_sample_rate_200 => + tx_data <= "11001000"; -- 0xC8 + write_data <= '1'; + state <= reset_send_sample_rate_200_wait_ack; + + -- wait ack for sending the sample rate + when reset_send_sample_rate_200_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= reset_set_sample_rate_100; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_send_sample_rate_200_wait_ack; + end if; + + -- send the sample rate command + when reset_set_sample_rate_100 => + tx_data <= SET_SAMPLE_RATE; + write_data <= '1'; + state <= reset_set_sample_rate_100_wait_ack; + + -- wait ack for sending the sample rate command + when reset_set_sample_rate_100_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= reset_send_sample_rate_100; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_set_sample_rate_100_wait_ack; + end if; + + -- send the desired sample rate (100 = 0x64) + when reset_send_sample_rate_100 => + tx_data <= "01100100"; -- 0x64 + write_data <= '1'; + state <= reset_send_sample_rate_100_wait_ack; + + -- wait ack for sending the sample rate + when reset_send_sample_rate_100_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= reset_set_sample_rate_80; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_send_sample_rate_100_wait_ack; + end if; + + -- send set sample rate command + when reset_set_sample_rate_80 => + tx_data <= SET_SAMPLE_RATE; + write_data <= '1'; + state <= reset_set_sample_rate_80_wait_ack; + + -- wait ack for sending the sample rate command + when reset_set_sample_rate_80_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= reset_send_sample_rate_80; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_set_sample_rate_80_wait_ack; + end if; + + -- send desired sample rate (80 = 0x50) + when reset_send_sample_rate_80 => + tx_data <= "01010000"; -- 0x50 + write_data <= '1'; + state <= reset_send_sample_rate_80_wait_ack; + + -- wait ack for sending the sample rate + when reset_send_sample_rate_80_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= reset_read_id; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_send_sample_rate_80_wait_ack; + end if; + + -- now the procedure for enabling wheel mode is done + -- the mouse id is read to determine is mouse is in + -- wheel mode. + -- Read ID command is sent to the mouse. + when reset_read_id => + tx_data <= READ_ID; + write_data <= '1'; + state <= reset_read_id_wait_ack; + + -- wait ack for sending the read id command + when reset_read_id_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= reset_read_id_wait_id; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_read_id_wait_ack; + end if; + + -- received the mouse id + -- if the id is 00, then the mouse does not have + -- a wheel and haswheel is reset + -- if the id is 03, then the mouse is in scroll mode + -- and haswheel is set. + -- if anything else is received or an error occurred + -- then the FSM transitions to reset state. + when reset_read_id_wait_id => + if(read_data = '1') then + if(rx_data = "000000000") then + -- the mouse does not have a wheel + haswheel <= '0'; + state <= reset_set_resolution; + elsif(rx_data = "00000011") then -- 0x03 + -- the mouse is in scroll mode + haswheel <= '1'; + state <= reset_set_resolution; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_read_id_wait_id; + end if; + + -- send the set resolution command to the mouse + when reset_set_resolution => + tx_data <= SET_RESOLUTION; + write_data <= '1'; + state <= reset_set_resolution_wait_ack; + + -- wait ack for sending the set resolution command + when reset_set_resolution_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= reset_send_resolution; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_set_resolution_wait_ack; + end if; + + -- send the desired resolution (0x03 = 8 counts/mm) + when reset_send_resolution => + tx_data <= RESOLUTION; + write_data <= '1'; + state <= reset_send_resolution_wait_ack; + + + -- wait ack for sending the resolution + when reset_send_resolution_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= reset_set_sample_rate_40; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_send_resolution_wait_ack; + end if; + + -- send the set sample rate command + when reset_set_sample_rate_40 => + tx_data <= SET_SAMPLE_RATE; + write_data <= '1'; + state <= reset_set_sample_rate_40_wait_ack; + + -- wait ack for sending the set sample rate command + when reset_set_sample_rate_40_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= reset_send_sample_rate_40; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_set_sample_rate_40_wait_ack; + end if; + + -- send the desired sampele rate. + -- 40 samples per second is sent. + when reset_send_sample_rate_40 => + tx_data <= SAMPLE_RATE; + write_data <= '1'; + state <= reset_send_sample_rate_40_wait_ack; + + -- wait ack for sending the sample rate + when reset_send_sample_rate_40_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= reset_enable_reporting; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_send_sample_rate_40_wait_ack; + end if; + + -- in this state enable reporting command is sent + -- to the mouse. Before this point, the mouse + -- does not send packets. Only after issuing this + -- command, the mouse begins sending data packets, + -- 3 byte packets if it doesn't have a wheel and + -- 4 byte packets if it is in scroll mode. + when reset_enable_reporting => + tx_data <= ENABLE_REPORTING; + write_data <= '1'; + state <= reset_enable_reporting_wait_ack; + + -- wait ack for sending the enable reporting command + when reset_enable_reporting_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= read_byte_1; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + else + state <= reset_enable_reporting_wait_ack; + end if; + + -- this is idle state of the FSM after the + -- initialization is complete. + -- Here the first byte of a packet is waited. + -- The first byte contains the state of the + -- buttons, the sign of the x and y movement + -- and overflow information about these movements + -- First byte looks like this: + -- 7 6 5 4 3 2 1 0 + ------------------------------------------------------ + -- | Y OVF | X OVF | Y SIGN | X SIGN | 1 | M | R | L | + ------------------------------------------------------ + when read_byte_1 => + -- Start periodic check counter + reset_periodic_check_cnt <= '0'; + -- reset new_event when back in idle state. + new_event <= '0'; + -- reset last z delta movement + zpos <= (others => '0'); + if(read_data = '1') then + -- mouse button states + left_down <= rx_data(0); + middle_down <= rx_data(2); + right_down <= rx_data(1); + -- sign of the movement data + x_sign <= rx_data(4); + -- y sign is changed to invert the y axis + -- because the mouse uses the lower-left corner + -- as axes origin and it is placed in the upper-left + -- corner by this inversion (suitable for displaying + -- a mouse cursor on the screen). + -- y movement data from the third packet must be + -- also negated. + y_sign <= not rx_data(5); + + -- overflow status of the x and y movement + x_overflow <= rx_data(6); + y_overflow <= rx_data(7); + + -- transition to state read_byte_2 + state <= read_byte_2; + elsif periodic_check_tick = '1' then -- Check periodically if the mouse is present + state <= check_read_id; + else + -- no byte received yet. + state <= read_byte_1; + end if; + + -- wait the second byte of the packet + -- this byte contains the x movement counter. + when read_byte_2 => + if(read_data = '1') then + -- put the delta movement in x_inc + x_inc <= rx_data; + -- signal the arrival of new x movement data. + x_new <= '1'; + -- go to state read_byte_3. + state <= read_byte_3; + elsif periodic_check_tick = '1' then -- Check periodically if the mouse is present + state <= check_read_id; + elsif(err = '1') then + state <= reset; + else + -- byte not received yet. + state <= read_byte_2; + end if; + + -- wait the third byte of the data, that + -- contains the y data movement counter. + -- negate its value, for the axis to be + -- inverted. + -- If mouse is in scroll mode, transition + -- to read_byte_4, else go to mark_new_event + when read_byte_3 => + if(read_data = '1') then + -- when y movement is 0, then ignore + if(rx_data /= "00000000") then + -- 2's complement positive numbers + -- become negative and vice versa + y_inc <= (not rx_data) + "00000001"; + y_new <= '1'; + end if; + -- if the mouse has a wheel then transition + -- to read_byte_4, else go to mark_new_event + if(haswheel = '1') then + state <= read_byte_4; + else + state <= mark_new_event; + end if; + elsif periodic_check_tick = '1' then -- Check periodically if the mouse is present + state <= check_read_id; + elsif(err = '1') then + state <= reset; + else + state <= read_byte_3; + end if; + + -- only reached when mouse is in scroll mode + -- wait for the fourth byte to arrive + -- fourth byte contains the z movement counter + -- only least significant 4 bits are relevant + -- the rest are sign extension. + when read_byte_4 => + if(read_data = '1') then + -- zpos is the delta movement on z + zpos <= rx_data(3 downto 0); + -- packet completly received, + -- go to mark_new_event + state <= mark_new_event; + elsif periodic_check_tick = '1' then -- Check periodically if the mouse is present + state <= check_read_id; + elsif(err = '1') then + state <= reset; + else + state <= read_byte_4; + end if; + -- From timer to time determined by the CHECK_TICK_PERIOD_MS, + -- Read ID command is sent to the mouse. + when check_read_id => + -- Start the timeout counter + reset_timeout_cnt <= '0'; + + tx_data <= READ_ID; + write_data <= '1'; + state <= check_read_id_wait_ack; + + -- wait ack for sending the read id command + when check_read_id_wait_ack => + if(read_data = '1') then + if(rx_data = FA) then + state <= check_read_id_wait_id; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + elsif (timeout = '1') then -- Timeout ocurred, so the mouse is not present, go to the reset state + state <= reset; + else + state <= check_read_id_wait_ack; + end if; + + -- received the mouse id + -- It means that the mouse is present and reading data + -- can continue + -- if anything else is received or timeout or an error occurred + -- then the FSM transitions to reset state. + when check_read_id_wait_id => + if(read_data = '1') then + if(rx_data = "000000000") or (rx_data = "00000011") then + -- The mouse is present, so reset the timeout counter + reset_timeout_cnt <= '1'; + state <= read_byte_1; + else + state <= reset; + end if; + elsif(err = '1') then + state <= reset; + elsif (timeout = '1') then-- Timeout ocurred, so the mouse is not present, go to the reset state + state <= reset; + else + state <= check_read_id_wait_id; + end if; + + -- set new_event high + -- it will be reset in next state + -- informs client new packet received and processed + when mark_new_event => + new_event <= '1'; + state <= read_byte_1; + + -- if invalid transition occurred, reset + when others => + state <= reset; + + end case; + end if; + end process manage_fsm; + + +end Behavioral; \ No newline at end of file diff --git a/src/hdl/MouseDisplay.vhd b/src/hdl/MouseDisplay.vhd new file mode 100644 index 0000000..6bd6bcc --- /dev/null +++ b/src/hdl/MouseDisplay.vhd @@ -0,0 +1,269 @@ +------------------------------------------------------------------------ +-- mouse_displayer.vhd +------------------------------------------------------------------------ +-- Author : Ulrich Zoltán +-- Copyright 2006 Digilent, Inc. +------------------------------------------------------------------------ +-- Software version : Xilinx ISE 7.1.04i +-- WebPack +-- Device : 3s200ft256-4 +------------------------------------------------------------------------ +-- This file contains the implementation of a mouse cursor. +------------------------------------------------------------------------ +-- Behavioral description +------------------------------------------------------------------------ +-- Mouse position is received from the mouse_controller, horizontal and +-- vertical counters are received from vga_module and if the counters +-- are inside the mouse cursor bounds, then the mouse is sent to the +-- screen. +-- The mouse display module can be also used as an overlay of the VGA +-- signal, also blanking the VGA screen, if the red_in, green_in, blue_in +-- and the blank_in signals are used. +-- In this application the signals mentioned and their corresponding code +-- lines are commented, therefore the mouse display module only generates +-- the RGB signals to display the cursor, and the VGA controller decides +-- whether or not to display the cursor. +-- The mouse cursor is 16x16 pixels and uses 2 colors: white and black. +-- For the color encoding 2 bits are used to be able to use transparency. +-- The cursor is stored in a 256X2 bit distributed ram memory. If the current +-- pixel of the mouse is "00" then output color is black, if "01" then is +-- white and if "10" or "11" then the pixel is transparent and the input +-- R, G and B signals are passed to the output. +-- In this way, the mouse cursor will not be a 16x16 square, instead will +-- have an arrow shape. +-- The memory address is composed from the difference of the vga counters +-- and mouse position: xdiff is the difference on 4 bits (because cursor +-- is 16 pixels width) between the horizontal vga counter and the xpos +-- of the mouse. ydiff is the difference on 4 bits (because cursor +-- has 16 pixels in height) between the vertical vga counter and the +-- ypos of the mouse. By concatenating ydiff and xidff (in this order) +-- the memory address of the current pixel is obtained. +-- A distributed memory implementation is forced by the attributes, to save +-- BRAM resources. +-- If the blank input from the vga_module is active, this means that current +-- pixel is not inside visible screen and color outputs are set to black +------------------------------------------------------------------------ +-- Port definitions +------------------------------------------------------------------------ +-- pixel_clk - input pin, representing the pixel clock, used +-- - by the vga_controller for the currently used +-- - resolution, generated by a dcm. 25MHz for 640x480, +-- - 40MHz for 800x600 and 108 MHz for 1280x1024. +-- - This clock is used to read pixels from memory +-- - and output data on color outputs. +-- xpos - input pin, 10 bits, from mouse_controller +-- - the x position of the mouse relative to the upper +-- - left corner +-- ypos - input pin, 10 bits, from mouse_controller +-- - the y position of the mouse relative to the upper +-- - left corner +-- hcount - input pin, 11 bits, from vga_module +-- - the horizontal counter from the vga_controller +-- - tells the horizontal position of the current pixel +-- - on the screen from left to right. +-- vcount - input pin, 11 bits, from vga_module +-- - the vertical counter from the vga_controller +-- - tells the vertical position of the currentl pixel +-- - on the screen from top to bottom. +-- red_out - output pin, 4 bits, to vga hardware module. +-- - red output channel +-- green_out - output pin, 4 bits, to vga hardware module. +-- - green output channel +-- blue_out - output pin, 4 bits, to vga hardware module. +-- - blue output channel + +------------------- Signals used when the mouse display is in overlay mode + +-- blank - input pin, from vga_module +-- - if active, current pixel is not in visible area, +-- - and color outputs should be set on 0. +-- red_in - input pin, 4 bits, from effects_layer +-- - red channel input of the image to be displayed +-- green_in - input pin, 4 bits, from effects_layer +-- - green channel input of the image to be displayed +-- blue_in - input pin, 4 bits, from effects_layer +-- - blue channel input of the image to be displayed +------------------------------------------------------------------------ + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +-- simulation library +--library UNISIM; +--use UNISIM.VComponents.all; + +-- the mouse_displayer entity declaration +-- read above for behavioral description and port definitions. +entity MouseDisplay is +port ( + pixel_clk: in std_logic; + xpos : in std_logic_vector(11 downto 0); + ypos : in std_logic_vector(11 downto 0); + + hcount : in std_logic_vector(11 downto 0); + vcount : in std_logic_vector(11 downto 0); + --blank : in std_logic; -- if VGA blank is used + + --red_in : in std_logic_vector(3 downto 0); -- if VGA signal pass-through is used + --green_in : in std_logic_vector(3 downto 0); + --blue_in : in std_logic_vector(3 downto 0); + + enable_mouse_display_out : out std_logic; + + red_out : out std_logic_vector(3 downto 0); + green_out: out std_logic_vector(3 downto 0); + blue_out : out std_logic_vector(3 downto 0) +); + +-- force synthesizer to extract distributed ram for the +-- displayrom signal, and not a block ram, to save BRAM resources. +attribute rom_extract : string; +attribute rom_extract of MouseDisplay: entity is "yes"; +attribute rom_style : string; +attribute rom_style of MouseDisplay: entity is "distributed"; + +end MouseDisplay; + +architecture Behavioral of MouseDisplay is + +------------------------------------------------------------------------ +-- CONSTANTS +------------------------------------------------------------------------ + +type displayrom is array(0 to 255) of std_logic_vector(1 downto 0); +-- the memory that holds the cursor. +-- 00 - black +-- 01 - white +-- 1x - transparent + +constant mouserom: displayrom := ( +"00","00","11","11","11","11","11","11","11","11","11","11","11","11","11","11", +"00","01","00","11","11","11","11","11","11","11","11","11","11","11","11","11", +"00","01","01","00","11","11","11","11","11","11","11","11","11","11","11","11", +"00","01","01","01","00","11","11","11","11","11","11","11","11","11","11","11", +"00","01","01","01","01","00","11","11","11","11","11","11","11","11","11","11", +"00","01","01","01","01","01","00","11","11","11","11","11","11","11","11","11", +"00","01","01","01","01","01","01","00","11","11","11","11","11","11","11","11", +"00","01","01","01","01","01","01","01","00","11","11","11","11","11","11","11", +"00","01","01","01","01","01","00","00","00","00","11","11","11","11","11","11", +"00","01","01","01","01","01","00","11","11","11","11","11","11","11","11","11", +"00","01","00","00","01","01","00","11","11","11","11","11","11","11","11","11", +"00","00","11","11","00","01","01","00","11","11","11","11","11","11","11","11", +"00","11","11","11","00","01","01","00","11","11","11","11","11","11","11","11", +"11","11","11","11","11","00","01","01","00","11","11","11","11","11","11","11", +"11","11","11","11","11","00","01","01","00","11","11","11","11","11","11","11", +"11","11","11","11","11","11","00","00","11","11","11","11","11","11","11","11" +); + +-- width and height of cursor. +constant OFFSET: std_logic_vector(4 downto 0) := "10000"; -- 16 + +------------------------------------------------------------------------ +-- SIGNALS +------------------------------------------------------------------------ + +-- pixel from the display memory, representing currently displayed +-- pixel of the cursor, if the cursor is being display at this point +signal mousepixel: std_logic_vector(1 downto 0) := (others => '0'); +-- when high, enables displaying of the cursor, and reading the +-- cursor memory. +signal enable_mouse_display: std_logic := '0'; + +-- difference in range 0-15 between the vga counters and mouse position +signal xdiff: std_logic_vector(3 downto 0) := (others => '0'); +signal ydiff: std_logic_vector(3 downto 0) := (others => '0'); + +signal red_int : std_logic_vector(3 downto 0); +signal green_int: std_logic_vector(3 downto 0); +signal blue_int : std_logic_vector(3 downto 0); + +signal red_int1 : std_logic_vector(3 downto 0); +signal green_int1: std_logic_vector(3 downto 0); +signal blue_int1 : std_logic_vector(3 downto 0); + +begin + + -- compute xdiff + x_diff: process(hcount, xpos) + variable temp_diff: std_logic_vector(11 downto 0) := (others => '0'); + begin + temp_diff := hcount - xpos; + xdiff <= temp_diff(3 downto 0); + end process x_diff; + + -- compute ydiff + y_diff: process(vcount, xpos) + variable temp_diff: std_logic_vector(11 downto 0) := (others => '0'); + begin + temp_diff := vcount - ypos; + ydiff <= temp_diff(3 downto 0); + end process y_diff; + + -- read pixel from memory at address obtained by concatenation of + -- ydiff and xdiff + mousepixel <= mouserom(conv_integer(ydiff & xdiff)) + when rising_edge(pixel_clk); + + -- set enable_mouse_display high if vga counters inside cursor block + enable_mouse: process(pixel_clk, hcount, vcount, xpos, ypos) + begin + if(rising_edge(pixel_clk)) then + if(hcount >= xpos +X"001" and hcount < (xpos + OFFSET - X"001") and + vcount >= ypos and vcount < (ypos + OFFSET)) and + (mousepixel = "00" or mousepixel = "01") + then + enable_mouse_display <= '1'; + else + enable_mouse_display <= '0'; + end if; + end if; + end process enable_mouse; + +enable_mouse_display_out <= enable_mouse_display; + + -- if cursor display is enabled, then, according to pixel + -- value, set the output color channels. + process(pixel_clk) + begin + if(rising_edge(pixel_clk)) then + -- if in visible screen +-- if(blank = '0') then + -- in display is enabled + if(enable_mouse_display = '1') then + -- white pixel of cursor + if(mousepixel = "01") then + red_out <= (others => '1'); + green_out <= (others => '1'); + blue_out <= (others => '1'); + -- black pixel of cursor + elsif(mousepixel = "00") then + red_out <= (others => '0'); + green_out <= (others => '0'); + blue_out <= (others => '0'); + -- transparent pixel of cursor + -- let input pass to output +-- else +-- red_out <= red_in; +-- green_out <= green_in; +-- blue_out <= blue_in; + end if; + -- cursor display is not enabled + -- let input pass to output. +-- else +-- red_out <= red_in; +-- green_out <= green_in; +-- blue_out <= blue_in; + end if; + -- not in visible screen, black outputs. +-- else +-- red_out <= (others => '0'); +-- green_out <= (others => '0'); +-- blue_out <= (others => '0'); +-- end if; + end if; + end process; + + +end Behavioral; diff --git a/src/hdl/Ps2Interface.vhd b/src/hdl/Ps2Interface.vhd new file mode 100644 index 0000000..213029c --- /dev/null +++ b/src/hdl/Ps2Interface.vhd @@ -0,0 +1,807 @@ +------------------------------------------------------------------------ +-- ps2interface.vhd +------------------------------------------------------------------------ +-- Author : Ulrich Zoltán +-- Copyright 2006 Digilent, Inc. +------------------------------------------------------------------------ +-- This file contains the implementation of a generic bidirectional +-- ps/2 interface. +------------------------------------------------------------------------ +-- Behavioral description +------------------------------------------------------------------------ +-- Please read the following article on the web for understanding how +-- the ps/2 protocol works. +-- http://www.computer-engineering.org/ps2protocol/ + +-- This module implements a generic bidirectional ps/2 interface. It can +-- be used with any ps/2 compatible device. It offers its clients a +-- convenient way to exchange data with the device. The interface +-- transparently wraps the byte to be sent into a ps/2 frame, generates +-- parity for byte and sends the frame one bit at a time to the device. +-- Similarly, when receiving data from the ps2 device, the interface +-- receives the frame, checks for parity, and extract the usefull data +-- and forwards it to the client. If an error occurs during receiving +-- or sending a byte, the client is informed by settings the err output +-- line high. This way, the client can resend the data or can issue +-- a resend command to the device. + +-- The physical ps/2 interface uses 4 lines +-- For the 6-pin connector pins are assigned as follows: +-- 1 - Data +-- 2 - Not Implemented +-- 3 - Ground +-- 4 - Vcc (+5V) +-- 5 - Clock +-- 6 - Not Implemented + +-- The clock line carries the device generated clock which has a +-- frequency in range 10 - 16.7 kHz (30 to 50us). When line is idle +-- it is placed in high impedance. The clock is only generated when +-- device is sending or receiving data. +-- The Data and Clock lines are both open-collector with pullup +-- resistors to Vcc. An "open-collector" interface has two possible +-- states: low('0') or high impedance('Z'). + +-- When device wants to send a byte, it pulls the clock line low and the +-- host(i.e. this interfaces) recognizes that the device is sending data +-- When the host wants to send data, it maeks a request to send. This +-- is done by holding the clock line low for at least 100us, then with +-- the clock line low, the data line is brought low. Next the clock line +-- is released (placed in high impedance). The devices begins generating +-- clock signal on clock line. +-- When receiving data, bits are read from the data line (ps2_data) on +-- the falling edge of the clock (ps2_clk). When sending data, the +-- device reads the bits from the data line on the rising edge of the +-- clock. +-- A frame for sending a byte is comprised of 11 bits as shown bellow: +-- bits 10 9 8 7 6 5 4 3 2 1 0 +-- ------------------------------------------------------------- +-- | STOP| PAR | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | START | +-- ------------------------------------------------------------- +-- STOP - stop bit, always '1' +-- PAR - parity bit, odd parity for the 8 data bits. +-- - select in such way that the number of bits of '1' in the data +-- - bits together with parity bit is odd. +-- D0-7 - data bits. +-- START - start bit, always '0' +-- +-- Frame is sent bit by bit starting with the least significant bit +-- (starting bit) and is received the same way. This is done, when +-- receiving, by shifting the frame register to the left when a bit +-- is available and placing the bit on data line on the most significant +-- bit. This way the first bit sent will reach the least significant bit +-- of the frame when all the bits have been received. When sending data +-- the least significant bit of the frame is placed on the data line +-- and the frame is shifted to the right when another bit needs to be +-- sent. During the request to send, when releasing the clock line, +-- the device reads the data line and interprets the data on it as the +-- first bit of the frame. Data line is low at that time, at this is the +-- way the start bit('0') is sent. Because of this, when sending, only +-- 10 shifts of the frame will be made. +-- While the interface is sending or receiving data, the busy output +-- signal goes high. When interface is idle, busy is low. +-- After sending all the bits in the frame, the device must acknowledge +-- the data sent. This is done by the host releasing and data line +-- (clock line is already released) after the last bit is sent. The +-- devices brings the data line and the clock line low, in this order, +-- to acknowledge the data. If data line is high when clock line goes +-- low after last bit, the device did not acknowledge the data and +-- err output is set. +-- A FSM is used to manage the transitions the set all the command +-- signals. States that begin with "rx_" are used to receive data +-- from device and states begining with "tx_" are used to send data +-- to the device. +-- For the parity bit, a ROM holds the parity bit for all possible +-- data (256 possible values, since 8 bits of data). The ROM has +-- dimensions 256x1bit. For obtaining the parity bit of a value, +-- the bit at the data value address is read. Ex: to find the parity +-- bit of 174, the bit at address 174 is read. +-- For generating the necessary delay, counters are used. For example, +-- to generate the 100us delay a 14 bit counter is used that has the +-- upper limit for counting 10000. The interface is designed to run +-- at 100MHz. Thus, 10000x10ns = 100us. + +----------------------------------------------------------------------- +-- If using the interface at different frequency than 100MHz, adjusting +-- the delay counters is necessary!!! +----------------------------------------------------------------------- + +-- Clock line(ps2_clk) and data line(ps2_data) are passed through a +-- debouncer for the transitions of the clock and data to be clean. +-- Also, ps2_clk_s and ps2_data_s hold the debounced and synchronized +-- value of the clock and data line to the system clock(clk). +------------------------------------------------------------------------ +-- Port definitions +------------------------------------------------------------------------ +-- ps2_clk - inout pin, clock line of the ps/2 interface +-- ps2_data - inout pin, data line of the ps/2 interface +-- clk - input pin, system clock signal +-- rst - input pin, system reset signal +-- tx_data - input pin, 8 bits, from client +-- - data to be sent to the device +-- write_data - input pin, from client +-- - should be active for one clock period when then +-- - client wants to send data to the device and +-- - data to be sent is valid on tx_data +-- rx_data - output pin, 8 bits, to client +-- - data received from device +-- read - output pin, to client +-- - active for one clock period when new data is +-- - available from device +-- busy - output pin, to client +-- - active while sending or receiving data. +-- err - output pin, to client +-- - active for one clock period when an error occurred +-- - during sending or receiving. +------------------------------------------------------------------------ +-- Revision History: +-- 09/18/2006(UlrichZ): created +------------------------------------------------------------------------ + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +-- simulation library +library UNISIM; +use UNISIM.VComponents.all; + +-- the ps2interface entity declaration +-- read above for behavioral description and port definitions. +entity Ps2Interface is +port( + ps2_clk : inout std_logic; + ps2_data : inout std_logic; + + clk : in std_logic; + rst : in std_logic; + + tx_data : in std_logic_vector(7 downto 0); + write_data : in std_logic; + + rx_data : out std_logic_vector(7 downto 0); + read_data : out std_logic; + busy : out std_logic; + err : out std_logic + +); + +-- forces the extraction of distributed ram for +-- the parity rom memory. +-- please remove if block ram is preffered. +attribute rom_extract : string; +attribute rom_extract of Ps2Interface: entity is "yes"; +attribute rom_style : string; +attribute rom_style of Ps2Interface: entity is "distributed"; + +end Ps2Interface; + +architecture Behavioral of Ps2Interface is + +------------------------------------------------------------------------ +-- CONSTANTS +------------------------------------------------------------------------ + +-- Values are valid for a 100MHz clk. Please adjust for other +-- frequencies if necessary! + +-- upper limit for 100us delay counter. +-- 10000 * 10ns = 100us +constant DELAY_100US : std_logic_vector(13 downto 0):= "10011100010000"; + -- 10000 clock periods +-- upper limit for 20us delay counter. +-- 2000 * 10ns = 20us +constant DELAY_20US : std_logic_vector(10 downto 0) := "11111010000"; + -- 2000 clock periods +-- upper limit for 63clk delay counter. +constant DELAY_63CLK : std_logic_vector(6 downto 0) := "1111111"; + -- 63 clock periods +-- delay from debouncing ps2_clk and ps2_data signals +constant DEBOUNCE_DELAY : std_logic_vector(3 downto 0) := "1111"; + +-- number of bits in a frame +constant NUMBITS: std_logic_vector(3 downto 0) := "1011"; -- 11 + +-- parity bit position in frame +constant PARITY_BIT: positive := 9; + +-- (odd) parity bit ROM +-- Used instead of logic because this way speed is far greater +-- 256x1bit rom +-- If the odd parity bit for a 8 bits number, x, is needed +-- the bit at address x is the parity bit. +type ROM is array(0 to 255) of std_logic; +constant parityrom : ROM := ( +'1','0','0','1','0','1','1','0', +'0','1','1','0','1','0','0','1', +'0','1','1','0','1','0','0','1', +'1','0','0','1','0','1','1','0', +'0','1','1','0','1','0','0','1', +'1','0','0','1','0','1','1','0', +'1','0','0','1','0','1','1','0', +'0','1','1','0','1','0','0','1', +'0','1','1','0','1','0','0','1', +'1','0','0','1','0','1','1','0', +'1','0','0','1','0','1','1','0', +'0','1','1','0','1','0','0','1', +'1','0','0','1','0','1','1','0', +'0','1','1','0','1','0','0','1', +'0','1','1','0','1','0','0','1', +'1','0','0','1','0','1','1','0', +'0','1','1','0','1','0','0','1', +'1','0','0','1','0','1','1','0', +'1','0','0','1','0','1','1','0', +'0','1','1','0','1','0','0','1', +'1','0','0','1','0','1','1','0', +'0','1','1','0','1','0','0','1', +'0','1','1','0','1','0','0','1', +'1','0','0','1','0','1','1','0', +'1','0','0','1','0','1','1','0', +'0','1','1','0','1','0','0','1', +'0','1','1','0','1','0','0','1', +'1','0','0','1','0','1','1','0', +'0','1','1','0','1','0','0','1', +'1','0','0','1','0','1','1','0', +'1','0','0','1','0','1','1','0', +'0','1','1','0','1','0','0','1' +); + +------------------------------------------------------------------------ +-- SIGNALS +------------------------------------------------------------------------ + +-- 14 bits counter +-- max value DELAY_100US +-- used to wait 100us +signal delay_100us_count: std_logic_vector(13 downto 0) := + (others => '0'); + +-- 11 bits counter +-- max value DELAY_20US +-- used to wait 20us +signal delay_20us_count: std_logic_vector(10 downto 0) := + (others => '0'); +-- 11 bits counter +-- max value DELAY_63CLK +-- used to wait 63 clock periods +signal delay_63clk_count: std_logic_vector(6 downto 0) := + (others => '0'); + +-- done signal for the couters above +-- when a counter reaches max value,the corresponding done signal is set +signal delay_100us_done, delay_20us_done, delay_63clk_done: std_logic; + +-- enable signal for 100us delay counter +signal delay_100us_counter_enable: std_logic := '0'; +-- enable signal for 20us delay counter +signal delay_20us_counter_enable : std_logic := '0'; +-- enable signal for 63clk delay counter +signal delay_63clk_counter_enable: std_logic := '0'; + +-- synchronzed input for ps2_clk and ps2_data +signal ps2_clk_s,ps2_data_s: std_logic := '1'; + +-- control the output of ps2_clk and ps2_data +-- if 1 then corresponding signal (ps2_clk or ps2_data) is +-- put in high impedance ('Z'). +signal ps2_clk_h,ps2_data_h: std_logic := '1'; + +-- states of the FSM for controlling the communcation with the device +-- states that begin with "rx_" are used when receiving data +-- states that begin with "tx_" are used when transmiting data +type fsm_state is +( + idle,rx_clk_h,rx_clk_l,rx_down_edge,rx_error_parity,rx_data_ready, + tx_force_clk_l,tx_bring_data_down,tx_release_clk, + tx_first_wait_down_edge,tx_clk_l,tx_wait_up_edge,tx_clk_h, + tx_wait_up_edge_before_ack,tx_wait_ack,tx_received_ack, + tx_error_no_ack +); + +-- the signal that holds the current state of the FSM +-- implicitly state is idle. +signal state: fsm_state := idle; + +-- register that holds the frame received or the one to be sent. +-- Its contents are shifted in from the bus one bit at a time +-- from left to right when receiving data and are shifted on the +-- bus (ps2_data) one bit at a time to the right when sending data +signal frame: std_logic_vector(10 downto 0) := (others => '0'); + +-- how many bits have been sent or received. +signal bit_count: std_logic_vector(3 downto 0) := (others => '0'); + +-- when active the bit counter is reset. +signal reset_bit_count: std_logic := '0'; + +-- when active the contents of the frame is shifted to the right +-- and the most significant bit of frame is loaded with ps2_data. +signal shift_frame: std_logic := '0'; + +-- parity of the byte that was received from the device. +-- must match the parity bit received, else error occurred. +signal rx_parity: std_logic := '0'; +-- parity bit that is sent with the frame, representing the +-- odd parity of the byte currently being sent +signal tx_parity: std_logic := '0'; + +-- when active, frame is loaded with the start bit, data on +-- tx_data, parity bit (tx_parity) and stop bit +-- this frame will be sent to the device. +signal load_tx_data: std_logic := '0'; + +-- when active bits 8 downto 1 from frame are loaded into +-- rx_data register. This is the byte received from the device. +signal load_rx_data: std_logic := '0'; + +-- intermediary signals used to debounce the inputs ps2_clk and ps2_data +signal ps2_clk_clean,ps2_data_clean: std_logic := '1'; +-- debounce counter for the ps2_clk input and the ps2_data input. +signal clk_count,data_count: std_logic_vector(3 downto 0); +-- last value on ps2_clk and ps2_data. +signal clk_inter,data_inter: std_logic := '1'; + +begin + + --------------------------------------------------------------------- + -- FLAGS and PS2 CLOCK AND DATA LINES + --------------------------------------------------------------------- + + -- clean ps2_clk signal (debounce) + -- note that this introduces a delay in ps2_clk of + -- DEBOUNCE_DELAY clocks + process(clk) + begin + if(rising_edge(clk)) then + -- if the current bit on ps2_clk is different + -- from the last value, then reset counter + -- and retain value + if(ps2_clk /= clk_inter) then + clk_inter <= ps2_clk; + clk_count <= (others => '0'); + -- if counter reached upper limit, then + -- the signal is clean + elsif(clk_count = DEBOUNCE_DELAY) then + ps2_clk_clean <= clk_inter; + -- ps2_clk did not change, but counter did not + -- reach limit. Increment counter + else + clk_count <= clk_count + 1; + end if; + end if; + end process; + + -- clean ps2_data signal (debounce) + -- note that this introduces a delay in ps2_data of + -- DEBOUNCE_DELAY clocks + process(clk) + begin + if(rising_edge(clk)) then + -- if the current bit on ps2_data is different + -- from the last value, then reset counter + -- and retain value + if(ps2_data /= data_inter) then + data_inter <= ps2_data; + data_count <= (others => '0'); + -- if counter reached upper limit, then + -- the signal is clean + elsif(data_count = DEBOUNCE_DELAY) then + ps2_data_clean <= data_inter; + -- ps2_data did not change, but counter did not + -- reach limit. Increment counter + else + data_count <= data_count + 1; + end if; + end if; + end process; + + -- Synchronize ps2 entries + ps2_clk_s <= ps2_clk_clean when rising_edge(clk); + ps2_data_s <= ps2_data_clean when rising_edge(clk); + + -- Assign parity from frame bits 8 downto 1, this is the parity + -- that should be received inside the frame on PARITY_BIT position + rx_parity <= parityrom(conv_integer(frame(8 downto 1))) + when rising_edge(clk); + -- The parity for the data to be sent + tx_parity <= parityrom(conv_integer(tx_data)) when rising_edge(clk); + + -- Force ps2_clk to '0' if ps2_clk_h = '0', else release the line + -- ('Z' = +5Vcc because of pull-ups) + ps2_clk <= 'Z' when ps2_clk_h = '1' else '0'; + + -- Force ps2_data to '0' if ps2_data_h = '0', else release the line + -- ('Z' = +5Vcc because of pull-ups) + ps2_data <= 'Z' when ps2_data_h = '1' else '0'; + + -- Control busy flag. Interface is not busy while in idle state. + busy <= '0' when state = idle else '1'; + + -- reset the bit counter when in idle state. + reset_bit_count <= '1' when state = idle else '0'; + + -- Control shifting of the frame + -- When receiving from device, data is read + -- on the falling edge of ps2_clk + -- When sending to device, data is read by device + -- on the rising edge of ps2_clk + shift_frame <= '1' when state = rx_down_edge or + state = tx_clk_l else + '0'; + + --------------------------------------------------------------------- + -- FINITE STATE MACHINE + --------------------------------------------------------------------- + + -- For the current state establish next state + -- and give necessary commands + manage_fsm: process(clk,rst,state,ps2_clk_s,ps2_data_s,write_data,tx_data, + bit_count,rx_parity,frame,delay_100us_done, + delay_20us_done,delay_63clk_done) + begin + -- if reset occurs, go to idle state. + if(rst = '1') then + state <= idle; + elsif(rising_edge(clk)) then + + -- default values for these signals + -- ensures signals are reset to default value + -- when coditions for their activation are no + -- longer applied (transition to other state, + -- where signal should not be active) + -- Idle value for ps2_clk and ps2_data is 'Z' + ps2_clk_h <= '1'; + ps2_data_h <= '1'; + load_tx_data <= '0'; + load_rx_data <= '0'; + read_data <= '0'; + err <= '0'; + + case state is + + -- wait for the device to begin a transmission + -- by pulling the clock line low and go to state + -- rx_down_edge or, if write is high, the + -- client of this interface wants to send a byte + -- to the device and a transition is made to state + -- tx_force_clk_l + when idle => + if(ps2_clk_s = '0') then + state <= rx_down_edge; + elsif(write_data = '1') then + state <= tx_force_clk_l; + else + state <= idle; + end if; + + -- ps2_clk is high, check if all the bits have been read + -- if, last bit read, check parity, and if parity ok + -- load received data into rx_data. + -- else if more bits left, then wait for the ps2_clk to + -- go low + when rx_clk_h => + if(bit_count = NUMBITS) then + if(not (rx_parity = frame(PARITY_BIT))) then + state <= rx_error_parity; + else + load_rx_data <= '1'; + state <= rx_data_ready; + end if; + elsif(ps2_clk_s = '0') then + state <= rx_down_edge; + else + state <= rx_clk_h; + end if; + + -- data must be read into frame in this state + -- the ps2_clk just transitioned from high to low + when rx_down_edge => + state <= rx_clk_l; + + -- ps2_clk line is low, wait for it to go high + when rx_clk_l => + if(ps2_clk_s = '1') then + state <= rx_clk_h; + else + state <= rx_clk_l; + end if; + + -- parity bit received is invalid + -- signal error and go back to idle. + when rx_error_parity => + err <= '1'; + state <= idle; + + -- parity bit received was good + -- set read signal for the client to know + -- a new byte was received and is available on rx_data + when rx_data_ready => + read_data <= '1'; + state <= idle; + + -- the client wishes to transmit a byte to the device + -- this is done by holding ps2_clk down for at least 100us + -- bringing down ps2_data, wait 20us and then releasing + -- the ps2_clk. + -- This constitutes a request to send command. + -- In this state, the ps2_clk line is held down and + -- the counter for waiting 100us is eanbled. + -- when the counter reached upper limit, transition + -- to tx_bring_data_down + when tx_force_clk_l => + load_tx_data <= '1'; + ps2_clk_h <= '0'; + if(delay_100us_done = '1') then + state <= tx_bring_data_down; + else + state <= tx_force_clk_l; + end if; + + -- with the ps2_clk line low bring ps2_data low + -- wait for 20us and then go to tx_release_clk + when tx_bring_data_down => + -- keep clock line low + ps2_clk_h <= '0'; + -- set data line low + -- when clock is released in the next state + -- the device will read bit 0 on data line + -- and this bit represents the start bit. + ps2_data_h <= '0'; -- start bit = '0' + if(delay_20us_done = '1') then + state <= tx_release_clk; + else + state <= tx_bring_data_down; + end if; + + -- release the ps2_clk line + -- keep holding data line low + when tx_release_clk => + ps2_clk_h <= '1'; + -- must maintain data low, + -- otherwise will be released by default value + ps2_data_h <= '0'; + state <= tx_first_wait_down_edge; + + -- state is necessary because the clock signal + -- is not released instantaneously and, because of debounce, + -- delay is even greater. + -- Wait 63 clock periods for the clock line to release + -- then if clock is low then go to tx_clk_l + -- else wait until ps2_clk goes low. + when tx_first_wait_down_edge => + ps2_data_h <= '0'; + if(delay_63clk_done = '1') then + if(ps2_clk_s = '0') then + state <= tx_clk_l; + else + state <= tx_first_wait_down_edge; + end if; + else + state <= tx_first_wait_down_edge; + end if; + + -- place the least significant bit from frame + -- on the data line + -- During this state the frame is shifted one + -- bit to the right + when tx_clk_l => + ps2_data_h <= frame(0); + state <= tx_wait_up_edge; + + -- wait for the clock to go high + -- this is the edge on which the device reads the data + -- on ps2_data. + -- keep holding ps2_data on frame(0) because else + -- will be released by default value. + -- Check if sent the last bit and if so, release data line + -- and go to state that wait for acknowledge + when tx_wait_up_edge => + ps2_data_h <= frame(0); + -- NUMBITS - 1 because first (start bit = 0) bit was read + -- when the clock line was released in the request to + -- send command (see tx_bring_data_down state). + if(bit_count = NUMBITS-1) then + ps2_data_h <= '1'; + state <= tx_wait_up_edge_before_ack; + -- if more bits to send, wait for the up edge + -- of ps2_clk + elsif(ps2_clk_s = '1') then + state <= tx_clk_h; + else + state <= tx_wait_up_edge; + end if; + + -- ps2_clk is released, wait for down edge + -- and go to tx_clk_l when arrived + when tx_clk_h => + ps2_data_h <= frame(0); + if(ps2_clk_s = '0') then + state <= tx_clk_l; + else + state <= tx_clk_h; + end if; + + -- release ps2_data and wait for rising edge of ps2_clk + -- once this occurs, transition to tx_wait_ack + when tx_wait_up_edge_before_ack => + ps2_data_h <= '1'; + if(ps2_clk_s = '1') then + state <= tx_wait_ack; + else + state <= tx_wait_up_edge_before_ack; + end if; + + -- wait for the falling edge of the clock line + -- if data line is low when this occurs, the + -- ack is received + -- else if data line is high, the device did not + -- acknowledge the transimission + when tx_wait_ack => + if(ps2_clk_s = '0') then + if(ps2_data_s = '0') then + -- acknowledge received + state <= tx_received_ack; + else + -- acknowledge not received + state <= tx_error_no_ack; + end if; + else + state <= tx_wait_ack; + end if; + + -- wait for ps2_clk to be released together with ps2_data + -- (bus to be idle) and go back to idle state + when tx_received_ack => + if(ps2_clk_s = '1' and ps2_data_s = '1') then + state <= idle; + else + state <= tx_received_ack; + end if; + + -- wait for ps2_clk to be released together with ps2_data + -- (bus to be idle) and go back to idle state + -- signal error for not receiving ack + when tx_error_no_ack => + if(ps2_clk_s = '1' and ps2_data_s = '1') then + err <= '1'; + state <= idle; + else + state <= tx_error_no_ack; + end if; + + -- if invalid transition occurred, signal error and + -- go back to idle state + when others => + err <= '1'; + state <= idle; + + end case; + end if; + end process manage_fsm; + + --------------------------------------------------------------------- + -- DELAY COUNTERS + --------------------------------------------------------------------- + + -- Enable the 100us counter only when state is tx_force_clk_l + delay_100us_counter_enable <= '1' when state = tx_force_clk_l else '0'; + + -- Counter for a 100us delay + -- after done counting, done signal remains active until + -- enable counter is reset. + delay_100us_counter: process(clk) + begin + if(rising_edge(clk)) then + if(delay_100us_counter_enable = '1') then + if(delay_100us_count = (DELAY_100US)) then + delay_100us_count <= delay_100us_count; + delay_100us_done <= '1'; + else + delay_100us_count <= delay_100us_count + 1; + delay_100us_done <= '0'; + end if; + else + delay_100us_count <= (others => '0'); + delay_100us_done <= '0'; + end if; + end if; + end process delay_100us_counter; + + -- Enable the 20us counter only when state is tx_bring_data_down + delay_20us_counter_enable <= '1' when state = tx_bring_data_down else '0'; + + -- Counter for a 20us delay + -- after done counting, done signal remains active until + -- enable counter is reset. + delay_20us_counter: process(clk) + begin + if(rising_edge(clk)) then + if(delay_20us_counter_enable = '1') then + if(delay_20us_count = (DELAY_20US)) then + delay_20us_count <= delay_20us_count; + delay_20us_done <= '1'; + else + delay_20us_count <= delay_20us_count + 1; + delay_20us_done <= '0'; + end if; + else + delay_20us_count <= (others => '0'); + delay_20us_done <= '0'; + end if; + end if; + end process delay_20us_counter; + + -- Enable the 63clk counter only when state is tx_first_wait_down_edge + delay_63clk_counter_enable <= '1' when state = tx_first_wait_down_edge else '0'; + + -- Counter for a 63 clock periods delay + -- after done counting, done signal remains active until + -- enable counter is reset. + delay_63clk_counter: process(clk) + begin + if(rising_edge(clk)) then + if(delay_63clk_counter_enable = '1') then + if(delay_63clk_count = (DELAY_63CLK)) then + delay_63clk_count <= delay_63clk_count; + delay_63clk_done <= '1'; + else + delay_63clk_count <= delay_63clk_count + 1; + delay_63clk_done <= '0'; + end if; + else + delay_63clk_count <= (others => '0'); + delay_63clk_done <= '0'; + end if; + end if; + end process delay_63clk_counter; + + --------------------------------------------------------------------- + -- BIT COUNTER AND FRAME SHIFTING LOGIC + --------------------------------------------------------------------- + + -- counts the number of bits shifted into the frame + -- or out of the frame. + bit_counter: process(clk) + begin + if(rising_edge(clk)) then + if(reset_bit_count = '1') then + bit_count <= (others => '0'); + elsif(shift_frame = '1') then + bit_count <= bit_count + 1; + end if; + end if; + end process bit_counter; + + -- shifts frame with one bit to right when shift_frame is acitve + -- and loads data into frame from tx_data then load_tx_data is high + load_tx_data_into_frame: process(clk) + begin + if(rising_edge(clk)) then + if(load_tx_data = '1') then + frame(8 downto 1) <= tx_data; -- byte to send + frame(0) <= '0'; -- start bit + frame(10) <= '1'; -- stop bit + frame(9) <= tx_parity; -- parity bit + elsif(shift_frame = '1') then + -- shift right 1 bit + frame(9 downto 0) <= frame(10 downto 1); + -- shift in from the ps2_data line + frame(10) <= ps2_data_s; + end if; + end if; + end process load_tx_data_into_frame; + + -- Loads data from frame into rx_data output when data is ready + do_load_rx_data: process(clk) + begin + if(rising_edge(clk)) then + if(load_rx_data = '1') then + rx_data <= frame(8 downto 1); + end if; + end if; + end process do_load_rx_data; + +end Behavioral; + + diff --git a/src/hdl/UART_TX_CTRL.vhd b/src/hdl/UART_TX_CTRL.vhd new file mode 100644 index 0000000..82e33f3 --- /dev/null +++ b/src/hdl/UART_TX_CTRL.vhd @@ -0,0 +1,157 @@ +---------------------------------------------------------------------------- +-- UART_TX_CTRL.vhd -- UART Data Transfer Component +---------------------------------------------------------------------------- +-- Author: Sam Bobrowicz +-- Copyright 2011 Digilent, Inc. +---------------------------------------------------------------------------- +-- +---------------------------------------------------------------------------- +-- This component may be used to transfer data over a UART device. It will +-- serialize a byte of data and transmit it over a TXD line. The serialized +-- data has the following characteristics: +-- *9600 Baud Rate +-- *8 data bits, LSB first +-- *1 stop bit +-- *no parity +-- +-- Port Descriptions: +-- +-- SEND - Used to trigger a send operation. The upper layer logic should +-- set this signal high for a single clock cycle to trigger a +-- send. When this signal is set high DATA must be valid . Should +-- not be asserted unless READY is high. +-- DATA - The parallel data to be sent. Must be valid the clock cycle +-- that SEND has gone high. +-- CLK - A 100 MHz clock is expected +-- READY - This signal goes low once a send operation has begun and +-- remains low until it has completed and the module is ready to +-- send another byte. +-- UART_TX - This signal should be routed to the appropriate TX pin of the +-- external UART device. +-- +---------------------------------------------------------------------------- +-- +---------------------------------------------------------------------------- +-- Revision History: +-- 08/08/2011(SamB): Created using Xilinx Tools 13.2 +---------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.std_logic_unsigned.all; + +entity UART_TX_CTRL is + Port ( SEND : in STD_LOGIC; + DATA : in STD_LOGIC_VECTOR (7 downto 0); + CLK : in STD_LOGIC; + READY : out STD_LOGIC; + UART_TX : out STD_LOGIC); +end UART_TX_CTRL; + +architecture Behavioral of UART_TX_CTRL is + +type TX_STATE_TYPE is (RDY, LOAD_BIT, SEND_BIT); + +constant BIT_TMR_MAX : std_logic_vector(13 downto 0) := "10100010110000"; --10416 = (round(100MHz / 9600)) - 1 +constant BIT_INDEX_MAX : natural := 10; + +--Counter that keeps track of the number of clock cycles the current bit has been held stable over the +--UART TX line. It is used to signal when the ne +signal bitTmr : std_logic_vector(13 downto 0) := (others => '0'); + +--combinatorial logic that goes high when bitTmr has counted to the proper value to ensure +--a 9600 baud rate +signal bitDone : std_logic; + +--Contains the index of the next bit in txData that needs to be transferred +signal bitIndex : natural; + +--a register that holds the current data being sent over the UART TX line +signal txBit : std_logic := '1'; + +--A register that contains the whole data packet to be sent, including start and stop bits. +signal txData : std_logic_vector(9 downto 0); + +signal txState : TX_STATE_TYPE := RDY; + +begin + +--Next state logic +next_txState_process : process (CLK) +begin + if (rising_edge(CLK)) then + case txState is + when RDY => + if (SEND = '1') then + txState <= LOAD_BIT; + end if; + when LOAD_BIT => + txState <= SEND_BIT; + when SEND_BIT => + if (bitDone = '1') then + if (bitIndex = BIT_INDEX_MAX) then + txState <= RDY; + else + txState <= LOAD_BIT; + end if; + end if; + when others=> --should never be reached + txState <= RDY; + end case; + end if; +end process; + +bit_timing_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (txState = RDY) then + bitTmr <= (others => '0'); + else + if (bitDone = '1') then + bitTmr <= (others => '0'); + else + bitTmr <= bitTmr + 1; + end if; + end if; + end if; +end process; + +bitDone <= '1' when (bitTmr = BIT_TMR_MAX) else + '0'; + +bit_counting_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (txState = RDY) then + bitIndex <= 0; + elsif (txState = LOAD_BIT) then + bitIndex <= bitIndex + 1; + end if; + end if; +end process; + +tx_data_latch_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (SEND = '1') then + txData <= '1' & DATA & '0'; + end if; + end if; +end process; + +tx_bit_process : process (CLK) +begin + if (rising_edge(CLK)) then + if (txState = RDY) then + txBit <= '1'; + elsif (txState = LOAD_BIT) then + txBit <= txData(bitIndex); + end if; + end if; +end process; + +UART_TX <= txBit; +READY <= '1' when (txState = RDY) else + '0'; + +end Behavioral; + diff --git a/src/hdl/clk_wiz_0.vhd b/src/hdl/clk_wiz_0.vhd new file mode 100644 index 0000000..b9a93f1 --- /dev/null +++ b/src/hdl/clk_wiz_0.vhd @@ -0,0 +1,108 @@ +-- file: clk_wiz_0.vhd +-- +-- (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved. +-- +-- This file contains confidential and proprietary information +-- of Xilinx, Inc. and is protected under U.S. and +-- international copyright and other intellectual property +-- laws. +-- +-- DISCLAIMER +-- This disclaimer is not a license and does not grant any +-- rights to the materials distributed herewith. Except as +-- otherwise provided in a valid license issued to you by +-- Xilinx, and to the maximum extent permitted by applicable +-- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND +-- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES +-- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING +-- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- +-- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and +-- (2) Xilinx shall not be liable (whether in contract or tort, +-- including negligence, or under any other theory of +-- liability) for any loss or damage of any kind or nature +-- related to, arising under or in connection with these +-- materials, including for any direct, or any indirect, +-- special, incidental, or consequential loss or damage +-- (including loss of data, profits, goodwill, or any type of +-- loss or damage suffered as a result of any action brought +-- by a third party) even if such damage or loss was +-- reasonably foreseeable or Xilinx had been advised of the +-- possibility of the same. +-- +-- CRITICAL APPLICATIONS +-- Xilinx products are not designed or intended to be fail- +-- safe, or for use in any application requiring fail-safe +-- performance, such as life-support or safety devices or +-- systems, Class III medical devices, nuclear facilities, +-- applications related to the deployment of airbags, or any +-- other applications that could lead to death, personal +-- injury, or severe property or environmental damage +-- (individually and collectively, "Critical +-- Applications"). Customer assumes the sole risk and +-- liability of any use of Xilinx products in Critical +-- Applications, subject only to applicable laws and +-- regulations governing limitations on product liability. +-- +-- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS +-- PART OF THIS FILE AT ALL TIMES. +-- +------------------------------------------------------------------------------ +-- User entered comments +------------------------------------------------------------------------------ +-- None +-- +------------------------------------------------------------------------------ +-- Output Output Phase Duty Cycle Pk-to-Pk Phase +-- Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps) +------------------------------------------------------------------------------ +-- CLK_OUT1___108.000______0.000______50.0______127.691_____97.646 +-- +------------------------------------------------------------------------------ +-- Input Clock Freq (MHz) Input Jitter (UI) +------------------------------------------------------------------------------ +-- __primary_________100.000____________0.010 + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity clk_wiz_0 is +port + (-- Clock in ports + clk_in1 : in std_logic; + -- Clock out ports + clk_out1 : out std_logic + ); +end clk_wiz_0; + +architecture xilinx of clk_wiz_0 is + attribute CORE_GENERATION_INFO : string; + attribute CORE_GENERATION_INFO of xilinx : architecture is "clk_wiz_0,clk_wiz_v5_1,{component_name=clk_wiz_0,use_phase_alignment=true,use_min_o_jitter=false,use_max_i_jitter=false,use_dyn_phase_shift=false,use_inclk_switchover=false,use_dyn_reconfig=false,enable_axi=0,feedback_source=FDBK_AUTO,PRIMITIVE=MMCM,num_out_clk=1,clkin1_period=10.0,clkin2_period=10.0,use_power_down=false,use_reset=false,use_locked=false,use_inclk_stopped=false,feedback_type=SINGLE,CLOCK_MGR_TYPE=NA,manual_override=false}"; + +component clk_wiz_0_clk_wiz +port + (-- Clock in ports + clk_in1 : in std_logic; + -- Clock out ports + clk_out1 : out std_logic + ); +end component; + +begin + + U0: clk_wiz_0_clk_wiz + port map ( + + -- Clock in ports + clk_in1 => clk_in1, + -- Clock out ports + clk_out1 => clk_out1 + ); + +end xilinx; + diff --git a/src/hdl/clk_wiz_0_clk_wiz.vhd b/src/hdl/clk_wiz_0_clk_wiz.vhd new file mode 100644 index 0000000..7cac3e6 --- /dev/null +++ b/src/hdl/clk_wiz_0_clk_wiz.vhd @@ -0,0 +1,201 @@ +-- file: clk_wiz_0_clk_wiz.vhd +-- +-- (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved. +-- +-- This file contains confidential and proprietary information +-- of Xilinx, Inc. and is protected under U.S. and +-- international copyright and other intellectual property +-- laws. +-- +-- DISCLAIMER +-- This disclaimer is not a license and does not grant any +-- rights to the materials distributed herewith. Except as +-- otherwise provided in a valid license issued to you by +-- Xilinx, and to the maximum extent permitted by applicable +-- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND +-- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES +-- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING +-- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- +-- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and +-- (2) Xilinx shall not be liable (whether in contract or tort, +-- including negligence, or under any other theory of +-- liability) for any loss or damage of any kind or nature +-- related to, arising under or in connection with these +-- materials, including for any direct, or any indirect, +-- special, incidental, or consequential loss or damage +-- (including loss of data, profits, goodwill, or any type of +-- loss or damage suffered as a result of any action brought +-- by a third party) even if such damage or loss was +-- reasonably foreseeable or Xilinx had been advised of the +-- possibility of the same. +-- +-- CRITICAL APPLICATIONS +-- Xilinx products are not designed or intended to be fail- +-- safe, or for use in any application requiring fail-safe +-- performance, such as life-support or safety devices or +-- systems, Class III medical devices, nuclear facilities, +-- applications related to the deployment of airbags, or any +-- other applications that could lead to death, personal +-- injury, or severe property or environmental damage +-- (individually and collectively, "Critical +-- Applications"). Customer assumes the sole risk and +-- liability of any use of Xilinx products in Critical +-- Applications, subject only to applicable laws and +-- regulations governing limitations on product liability. +-- +-- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS +-- PART OF THIS FILE AT ALL TIMES. +-- +------------------------------------------------------------------------------ +-- User entered comments +------------------------------------------------------------------------------ +-- None +-- +------------------------------------------------------------------------------ +-- Output Output Phase Duty Cycle Pk-to-Pk Phase +-- Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps) +------------------------------------------------------------------------------ +-- CLK_OUT1___108.000______0.000______50.0______127.691_____97.646 +-- +------------------------------------------------------------------------------ +-- Input Clock Freq (MHz) Input Jitter (UI) +------------------------------------------------------------------------------ +-- __primary_________100.000____________0.010 + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity clk_wiz_0_clk_wiz is +port + (-- Clock in ports + clk_in1 : in std_logic; + -- Clock out ports + clk_out1 : out std_logic + ); +end clk_wiz_0_clk_wiz; + +architecture xilinx of clk_wiz_0_clk_wiz is + -- Input clock buffering / unused connectors + signal clk_in1_clk_wiz_0 : std_logic; + -- Output clock buffering / unused connectors + signal clkfbout_clk_wiz_0 : std_logic; + signal clkfbout_buf_clk_wiz_0 : std_logic; + signal clkfboutb_unused : std_logic; + signal clk_out1_clk_wiz_0 : std_logic; + signal clkout0b_unused : std_logic; + signal clkout1_unused : std_logic; + signal clkout1b_unused : std_logic; + signal clkout2_unused : std_logic; + signal clkout2b_unused : std_logic; + signal clkout3_unused : std_logic; + signal clkout3b_unused : std_logic; + signal clkout4_unused : std_logic; + signal clkout5_unused : std_logic; + signal clkout6_unused : std_logic; + -- Dynamic programming unused signals + signal do_unused : std_logic_vector(15 downto 0); + signal drdy_unused : std_logic; + -- Dynamic phase shift unused signals + signal psdone_unused : std_logic; + signal locked_int : std_logic; + -- Unused status signals + signal clkfbstopped_unused : std_logic; + signal clkinstopped_unused : std_logic; + +begin + + + -- Input buffering + -------------------------------------- +clk_in1_clk_wiz_0 <= clk_in1; + + + + -- Clocking PRIMITIVE + -------------------------------------- + -- Instantiation of the MMCM PRIMITIVE + -- * Unused inputs are tied off + -- * Unused outputs are labeled unused + mmcm_adv_inst : MMCME2_ADV + generic map + (BANDWIDTH => "OPTIMIZED", + CLKOUT4_CASCADE => FALSE, + COMPENSATION => "ZHOLD", + STARTUP_WAIT => FALSE, + DIVCLK_DIVIDE => 1, + CLKFBOUT_MULT_F => 10.125, + CLKFBOUT_PHASE => 0.000, + CLKFBOUT_USE_FINE_PS => FALSE, + CLKOUT0_DIVIDE_F => 9.375, + CLKOUT0_PHASE => 0.000, + CLKOUT0_DUTY_CYCLE => 0.500, + CLKOUT0_USE_FINE_PS => FALSE, + CLKIN1_PERIOD => 10.0, + REF_JITTER1 => 0.010) + port map + -- Output clocks + ( + CLKFBOUT => clkfbout_clk_wiz_0, + CLKFBOUTB => clkfboutb_unused, + CLKOUT0 => clk_out1_clk_wiz_0, + CLKOUT0B => clkout0b_unused, + CLKOUT1 => clkout1_unused, + CLKOUT1B => clkout1b_unused, + CLKOUT2 => clkout2_unused, + CLKOUT2B => clkout2b_unused, + CLKOUT3 => clkout3_unused, + CLKOUT3B => clkout3b_unused, + CLKOUT4 => clkout4_unused, + CLKOUT5 => clkout5_unused, + CLKOUT6 => clkout6_unused, + -- Input clock control + CLKFBIN => clkfbout_buf_clk_wiz_0, + CLKIN1 => clk_in1_clk_wiz_0, + CLKIN2 => '0', + -- Tied to always select the primary input clock + CLKINSEL => '1', + -- Ports for dynamic reconfiguration + DADDR => (others => '0'), + DCLK => '0', + DEN => '0', + DI => (others => '0'), + DO => do_unused, + DRDY => drdy_unused, + DWE => '0', + -- Ports for dynamic phase shift + PSCLK => '0', + PSEN => '0', + PSINCDEC => '0', + PSDONE => psdone_unused, + -- Other control and status signals + LOCKED => locked_int, + CLKINSTOPPED => clkinstopped_unused, + CLKFBSTOPPED => clkfbstopped_unused, + PWRDWN => '0', + RST => '0'); + + + -- Output buffering + ------------------------------------- + + clkf_buf : BUFG + port map + (O => clkfbout_buf_clk_wiz_0, + I => clkfbout_clk_wiz_0); + + + + clkout1_buf : BUFG + port map + (O => clk_out1, + I => clk_out1_clk_wiz_0); + + + +end xilinx; diff --git a/src/hdl/debouncer.vhd b/src/hdl/debouncer.vhd new file mode 100644 index 0000000..2e71d9a --- /dev/null +++ b/src/hdl/debouncer.vhd @@ -0,0 +1,95 @@ +---------------------------------------------------------------------------- +-- debouncer.vhd -- Signal Debouncer +---------------------------------------------------------------------------- +-- Author: Sam Bobrowicz +-- Copyright 2011 Digilent, Inc. +---------------------------------------------------------------------------- +-- +---------------------------------------------------------------------------- +-- This component is used to debounce signals. It is designed to +-- independently debounce a variable number of signals, the number of which +-- are set using the PORT_WIDTH generic. Debouncing is done by only +-- registering a change in a button state if it remains constant for +-- the number of clocks determined by the DEBNC_CLOCKS generic. +-- +-- Generic Descriptions: +-- +-- PORT_WIDTH - The number of signals to debounce. determines the width +-- of the SIGNAL_I and SIGNAL_O std_logic_vectors +-- DEBNC_CLOCKS - The number of clocks (CLK_I) to wait before registering +-- a change. +-- +-- Port Descriptions: +-- +-- SIGNAL_I - The input signals. A vector of width equal to PORT_WIDTH +-- CLK_I - Input clock +-- SIGNAL_O - The debounced signals. A vector of width equal to PORT_WIDTH +-- +---------------------------------------------------------------------------- +-- +---------------------------------------------------------------------------- +-- Revision History: +-- 08/08/2011(SamB): Created using Xilinx Tools 13.2 +-- 08/29/2013(SamB): Improved reuseability by using generics +---------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.std_logic_unsigned.all; +USE IEEE.NUMERIC_STD.ALL; +use IEEE.math_real.all; + +entity debouncer is + Generic ( DEBNC_CLOCKS : INTEGER range 2 to (INTEGER'high) := 2**16; + PORT_WIDTH : INTEGER range 1 to (INTEGER'high) := 5); + Port ( SIGNAL_I : in STD_LOGIC_VECTOR ((PORT_WIDTH - 1) downto 0); + CLK_I : in STD_LOGIC; + SIGNAL_O : out STD_LOGIC_VECTOR ((PORT_WIDTH - 1) downto 0)); +end debouncer; + +architecture Behavioral of debouncer is + +constant CNTR_WIDTH : integer := natural(ceil(LOG2(real(DEBNC_CLOCKS)))); +constant CNTR_MAX : std_logic_vector((CNTR_WIDTH - 1) downto 0) := std_logic_vector(to_unsigned((DEBNC_CLOCKS - 1), CNTR_WIDTH)); +type VECTOR_ARRAY_TYPE is array (integer range <>) of std_logic_vector((CNTR_WIDTH - 1) downto 0); + +signal sig_cntrs_ary : VECTOR_ARRAY_TYPE (0 to (PORT_WIDTH - 1)) := (others=>(others=>'0')); + +signal sig_out_reg : std_logic_vector((PORT_WIDTH - 1) downto 0) := (others => '0'); + +begin + +debounce_process : process (CLK_I) +begin + if (rising_edge(CLK_I)) then + for index in 0 to (PORT_WIDTH - 1) loop + if (sig_cntrs_ary(index) = CNTR_MAX) then + sig_out_reg(index) <= not(sig_out_reg(index)); + end if; + end loop; + end if; +end process; + +counter_process : process (CLK_I) +begin + if (rising_edge(CLK_I)) then + for index in 0 to (PORT_WIDTH - 1) loop + + if ((sig_out_reg(index) = '1') xor (SIGNAL_I(index) = '1')) then + if (sig_cntrs_ary(index) = CNTR_MAX) then + sig_cntrs_ary(index) <= (others => '0'); + else + sig_cntrs_ary(index) <= sig_cntrs_ary(index) + 1; + end if; + else + sig_cntrs_ary(index) <= (others => '0'); + end if; + + end loop; + end if; +end process; + +SIGNAL_O <= sig_out_reg; + +end Behavioral; + diff --git a/src/hdl/vga_ctrl.vhd b/src/hdl/vga_ctrl.vhd new file mode 100644 index 0000000..51d518c --- /dev/null +++ b/src/hdl/vga_ctrl.vhd @@ -0,0 +1,415 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 04/25/2014 02:10:40 PM +-- Design Name: +-- Module Name: vga_ctrl - 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.STD_LOGIC_ARITH.ALL; +use IEEE.std_logic_unsigned.all; +use ieee.math_real.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 vga_ctrl is + Port ( CLK_I : in STD_LOGIC; + VGA_HS_O : out STD_LOGIC; + VGA_VS_O : out STD_LOGIC; + VGA_RED_O : out STD_LOGIC_VECTOR (3 downto 0); + VGA_BLUE_O : out STD_LOGIC_VECTOR (3 downto 0); + VGA_GREEN_O : out STD_LOGIC_VECTOR (3 downto 0); + PS2_CLK : inout STD_LOGIC; + PS2_DATA : inout STD_LOGIC + ); +end vga_ctrl; + +architecture Behavioral of vga_ctrl is + + COMPONENT MouseCtl + GENERIC + ( + SYSCLK_FREQUENCY_HZ : integer := 100000000; + CHECK_PERIOD_MS : integer := 500; + TIMEOUT_PERIOD_MS : integer := 100 + ); + PORT( + clk : IN std_logic; + rst : IN std_logic; + value : IN std_logic_vector(11 downto 0); + setx : IN std_logic; + sety : IN std_logic; + setmax_x : IN std_logic; + setmax_y : IN std_logic; + ps2_clk : INOUT std_logic; + ps2_data : INOUT std_logic; + xpos : OUT std_logic_vector(11 downto 0); + ypos : OUT std_logic_vector(11 downto 0); + zpos : OUT std_logic_vector(3 downto 0); + left : OUT std_logic; + middle : OUT std_logic; + right : OUT std_logic; + new_event : OUT std_logic + ); + END COMPONENT; + + COMPONENT MouseDisplay + PORT( + pixel_clk : IN std_logic; + xpos : IN std_logic_vector(11 downto 0); + ypos : IN std_logic_vector(11 downto 0); + hcount : IN std_logic_vector(11 downto 0); + vcount : IN std_logic_vector(11 downto 0); + enable_mouse_display_out : OUT std_logic; + red_out : OUT std_logic_vector(3 downto 0); + green_out : OUT std_logic_vector(3 downto 0); + blue_out : OUT std_logic_vector(3 downto 0) + ); + END COMPONENT; + +component clk_wiz_0 +port + (-- Clock in ports + clk_in1 : in std_logic; + -- Clock out ports + clk_out1 : out std_logic + ); +end component; + + --***1280x1024@60Hz***-- + constant FRAME_WIDTH : natural := 1280; + constant FRAME_HEIGHT : natural := 1024; + + constant H_FP : natural := 48; --H front porch width (pixels) + constant H_PW : natural := 112; --H sync pulse width (pixels) + constant H_MAX : natural := 1688; --H total period (pixels) + + constant V_FP : natural := 1; --V front porch width (lines) + constant V_PW : natural := 3; --V sync pulse width (lines) + constant V_MAX : natural := 1066; --V total period (lines) + + constant H_POL : std_logic := '1'; + constant V_POL : std_logic := '1'; + + ------------------------------------------------------------------------- + + -- VGA Controller specific signals: Counters, Sync, R, G, B + + ------------------------------------------------------------------------- + -- Pixel clock, in this case 108 MHz + signal pxl_clk : std_logic; + -- The active signal is used to signal the active region of the screen (when not blank) + signal active : std_logic; + + -- Horizontal and Vertical counters + signal h_cntr_reg : std_logic_vector(11 downto 0) := (others =>'0'); + signal v_cntr_reg : std_logic_vector(11 downto 0) := (others =>'0'); + + -- Pipe Horizontal and Vertical Counters + signal h_cntr_reg_dly : std_logic_vector(11 downto 0) := (others => '0'); + signal v_cntr_reg_dly : std_logic_vector(11 downto 0) := (others => '0'); + + -- Horizontal and Vertical Sync + signal h_sync_reg : std_logic := not(H_POL); + signal v_sync_reg : std_logic := not(V_POL); + -- Pipe Horizontal and Vertical Sync + signal h_sync_reg_dly : std_logic := not(H_POL); + signal v_sync_reg_dly : std_logic := not(V_POL); + + -- VGA R, G and B signals coming from the main multiplexers + signal vga_red_cmb : std_logic_vector(3 downto 0); + signal vga_green_cmb : std_logic_vector(3 downto 0); + signal vga_blue_cmb : std_logic_vector(3 downto 0); + --The main VGA R, G and B signals, validated by active + signal vga_red : std_logic_vector(3 downto 0); + signal vga_green : std_logic_vector(3 downto 0); + signal vga_blue : std_logic_vector(3 downto 0); + -- Register VGA R, G and B signals + signal vga_red_reg : std_logic_vector(3 downto 0) := (others =>'0'); + signal vga_green_reg : std_logic_vector(3 downto 0) := (others =>'0'); + signal vga_blue_reg : std_logic_vector(3 downto 0) := (others =>'0'); + + ------------------------------------------------------------------------- + --Mouse pointer signals + ------------------------------------------------------------------------- + + -- Mouse data signals + signal MOUSE_X_POS: std_logic_vector (11 downto 0); + signal MOUSE_Y_POS: std_logic_vector (11 downto 0); + signal MOUSE_X_POS_REG: std_logic_vector (11 downto 0); + signal MOUSE_Y_POS_REG: std_logic_vector (11 downto 0); + + -- Mouse cursor display signals + signal mouse_cursor_red : std_logic_vector (3 downto 0) := (others => '0'); + signal mouse_cursor_blue : std_logic_vector (3 downto 0) := (others => '0'); + signal mouse_cursor_green : std_logic_vector (3 downto 0) := (others => '0'); + -- Mouse cursor enable display signals + signal enable_mouse_display: std_logic; + -- Registered Mouse cursor display signals + signal mouse_cursor_red_dly : std_logic_vector (3 downto 0) := (others => '0'); + signal mouse_cursor_blue_dly : std_logic_vector (3 downto 0) := (others => '0'); + signal mouse_cursor_green_dly : std_logic_vector (3 downto 0) := (others => '0'); + -- Registered Mouse cursor enable display signals + signal enable_mouse_display_dly : std_logic; + + ----------------------------------------------------------- + -- Signals for generating the background (moving colorbar) + ----------------------------------------------------------- + signal cntDyn : integer range 0 to 2**28-1; -- counter for generating the colorbar + signal intHcnt : integer range 0 to H_MAX - 1; + signal intVcnt : integer range 0 to V_MAX - 1; + -- Colorbar red, greeen and blue signals + signal bg_red : std_logic_vector(3 downto 0); + signal bg_blue : std_logic_vector(3 downto 0); + signal bg_green : std_logic_vector(3 downto 0); + -- Pipe the colorbar red, green and blue signals + signal bg_red_dly : std_logic_vector(3 downto 0) := (others => '0'); + signal bg_green_dly : std_logic_vector(3 downto 0) := (others => '0'); + signal bg_blue_dly : std_logic_vector(3 downto 0) := (others => '0'); + + +begin + + + clk_wiz_0_inst : clk_wiz_0 + port map + ( + clk_in1 => CLK_I, + clk_out1 => pxl_clk); + + + ---------------------------------------------------------------------------------- + -- Mouse Controller + ---------------------------------------------------------------------------------- + Inst_MouseCtl: MouseCtl + GENERIC MAP + ( + SYSCLK_FREQUENCY_HZ => 108000000, + CHECK_PERIOD_MS => 500, + TIMEOUT_PERIOD_MS => 100 + ) + PORT MAP + ( + clk => pxl_clk, + rst => '0', + xpos => MOUSE_X_POS, + ypos => MOUSE_Y_POS, + zpos => open, + left => open, + middle => open, + right => open, + new_event => open, + value => x"000", + setx => '0', + sety => '0', + setmax_x => '0', + setmax_y => '0', + ps2_clk => PS2_CLK, + ps2_data => PS2_DATA + ); + + --------------------------------------------------------------- + + -- Generate Horizontal, Vertical counters and the Sync signals + + --------------------------------------------------------------- + -- Horizontal counter + process (pxl_clk) + begin + if (rising_edge(pxl_clk)) then + if (h_cntr_reg = (H_MAX - 1)) then + h_cntr_reg <= (others =>'0'); + else + h_cntr_reg <= h_cntr_reg + 1; + end if; + end if; + end process; + -- Vertical counter + process (pxl_clk) + begin + if (rising_edge(pxl_clk)) then + if ((h_cntr_reg = (H_MAX - 1)) and (v_cntr_reg = (V_MAX - 1))) then + v_cntr_reg <= (others =>'0'); + elsif (h_cntr_reg = (H_MAX - 1)) then + v_cntr_reg <= v_cntr_reg + 1; + end if; + end if; + end process; + -- Horizontal sync + process (pxl_clk) + begin + if (rising_edge(pxl_clk)) then + if (h_cntr_reg >= (H_FP + FRAME_WIDTH - 1)) and (h_cntr_reg < (H_FP + FRAME_WIDTH + H_PW - 1)) then + h_sync_reg <= H_POL; + else + h_sync_reg <= not(H_POL); + end if; + end if; + end process; + -- Vertical sync + process (pxl_clk) + begin + if (rising_edge(pxl_clk)) then + if (v_cntr_reg >= (V_FP + FRAME_HEIGHT - 1)) and (v_cntr_reg < (V_FP + FRAME_HEIGHT + V_PW - 1)) then + v_sync_reg <= V_POL; + else + v_sync_reg <= not(V_POL); + end if; + end if; + end process; + + -------------------- + + -- The active + + -------------------- + -- active signal + active <= '1' when h_cntr_reg_dly < FRAME_WIDTH and v_cntr_reg_dly < FRAME_HEIGHT + else '0'; + + + -------------------- + + -- Register Inputs + + -------------------- + register_inputs: process (pxl_clk) + begin + if (rising_edge(pxl_clk)) then + if v_sync_reg = V_POL then + MOUSE_X_POS_REG <= MOUSE_X_POS; + MOUSE_Y_POS_REG <= MOUSE_Y_POS; + end if; + end if; + end process register_inputs; + --------------------------------------- + + -- Generate moving colorbar background + + --------------------------------------- + + process(pxl_clk) + begin + if(rising_edge(pxl_clk)) then + cntdyn <= cntdyn + 1; + end if; + end process; + + intHcnt <= conv_integer(h_cntr_reg); + intVcnt <= conv_integer(v_cntr_reg); + + bg_red <= conv_std_logic_vector((-intvcnt - inthcnt - cntDyn/2**20),8)(7 downto 4); + bg_green <= conv_std_logic_vector((inthcnt - cntDyn/2**20),8)(7 downto 4); + bg_blue <= conv_std_logic_vector((intvcnt - cntDyn/2**20),8)(7 downto 4); + + + ---------------------------------- + + -- Mouse Cursor display instance + + ---------------------------------- + Inst_MouseDisplay: MouseDisplay + PORT MAP + ( + pixel_clk => pxl_clk, + xpos => MOUSE_X_POS_REG, + ypos => MOUSE_Y_POS_REG, + hcount => h_cntr_reg, + vcount => v_cntr_reg, + enable_mouse_display_out => enable_mouse_display, + red_out => mouse_cursor_red, + green_out => mouse_cursor_green, + blue_out => mouse_cursor_blue + ); + + --------------------------------------------------------------------------------------------------- + + -- Register Outputs coming from the displaying components and the horizontal and vertical counters + + --------------------------------------------------------------------------------------------------- + process (pxl_clk) + begin + if (rising_edge(pxl_clk)) then + + bg_red_dly <= bg_red; + bg_green_dly <= bg_green; + bg_blue_dly <= bg_blue; + + mouse_cursor_red_dly <= mouse_cursor_red; + mouse_cursor_blue_dly <= mouse_cursor_blue; + mouse_cursor_green_dly <= mouse_cursor_green; + + enable_mouse_display_dly <= enable_mouse_display; + + h_cntr_reg_dly <= h_cntr_reg; + v_cntr_reg_dly <= v_cntr_reg; + + end if; + end process; + + ---------------------------------- + + -- VGA Output Muxing + + ---------------------------------- + + vga_red <= mouse_cursor_red_dly when enable_mouse_display_dly = '1' else + bg_red_dly; + vga_green <= mouse_cursor_green_dly when enable_mouse_display_dly = '1' else + bg_green_dly; + vga_blue <= mouse_cursor_blue_dly when enable_mouse_display_dly = '1' else + bg_blue_dly; + + ------------------------------------------------------------ + -- Turn Off VGA RBG Signals if outside of the active screen + -- Make a 4-bit AND logic with the R, G and B signals + ------------------------------------------------------------ + vga_red_cmb <= (active & active & active & active) and vga_red; + vga_green_cmb <= (active & active & active & active) and vga_green; + vga_blue_cmb <= (active & active & active & active) and vga_blue; + + + -- Register Outputs + process (pxl_clk) + begin + if (rising_edge(pxl_clk)) then + + v_sync_reg_dly <= v_sync_reg; + h_sync_reg_dly <= h_sync_reg; + vga_red_reg <= vga_red_cmb; + vga_green_reg <= vga_green_cmb; + vga_blue_reg <= vga_blue_cmb; + end if; + end process; + + -- Assign outputs + VGA_HS_O <= h_sync_reg_dly; + VGA_VS_O <= v_sync_reg_dly; + VGA_RED_O <= vga_red_reg; + VGA_GREEN_O <= vga_green_reg; + VGA_BLUE_O <= vga_blue_reg; + +end Behavioral; diff --git a/src/ip/.keep b/src/ip/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/others/.keep b/src/others/.keep new file mode 100644 index 0000000..e69de29