From a22ff94e7271e6c7dc52750683e6a0ffb8361327 Mon Sep 17 00:00:00 2001 From: Samuel Huang Date: Fri, 26 Nov 2021 17:16:16 +0800 Subject: [PATCH] Initial commit --- .DS_Store | Bin 0 -> 8196 bytes Keyboard Sample Code/.DS_Store | Bin 0 -> 8196 bytes Keyboard Sample Code/KeyboardConstraints.xdc | 46 ++ Keyboard Sample Code/KeyboardDecoder.v | 126 ++++ Keyboard Sample Code/OnePulse.v | 17 + Keyboard Sample Code/SampleDisplay.v | 108 ++++ Keyboard Sample Code/SevenSegment.v | 66 ++ Keyboard Sample Code/ip/.DS_Store | Bin 0 -> 8196 bytes .../ip/Keyboard-Controller/.DS_Store | Bin 0 -> 8196 bytes .../keyboard_cntr_1.0/.DS_Store | Bin 0 -> 10244 bytes .../keyboard_cntr_1.0/component.xml | 257 ++++++++ .../keyboard_cntr_1.0/src/KeyboardCtrl.v | 189 ++++++ .../keyboard_cntr_1.0/src/Ps2Interface.v | 562 ++++++++++++++++++ .../xgui/KeyboardCtrl_v1_0.tcl | 25 + 14 files changed, 1396 insertions(+) create mode 100644 .DS_Store create mode 100644 Keyboard Sample Code/.DS_Store create mode 100755 Keyboard Sample Code/KeyboardConstraints.xdc create mode 100755 Keyboard Sample Code/KeyboardDecoder.v create mode 100755 Keyboard Sample Code/OnePulse.v create mode 100755 Keyboard Sample Code/SampleDisplay.v create mode 100755 Keyboard Sample Code/SevenSegment.v create mode 100644 Keyboard Sample Code/ip/.DS_Store create mode 100644 Keyboard Sample Code/ip/Keyboard-Controller/.DS_Store create mode 100644 Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/.DS_Store create mode 100755 Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/component.xml create mode 100755 Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/KeyboardCtrl.v create mode 100755 Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/Ps2Interface.v create mode 100755 Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/xgui/KeyboardCtrl_v1_0.tcl diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d9470d9c9ecccb0c9457c19059334a4c3544c3a2 GIT binary patch literal 8196 zcmeHMUu+ab82`RfV5bzB{)6KxxS`fUb7%{+(4cs24~hbz@!DQns&(&npc}Wl=j~n( zB#kv{G(?RWHSxtr{evNz_@arv7-JyHi$0)%s4u?xWTHOko8Rp0HS}L12~iSuE;GNG z`R1FM`|WRb^4$Rd_7u%_fEWO1lqK>tR4kFCUFJopBJ8OoMDho4!GHpophJ4m=%^!N zAYve5AYve5AY$NVV1VvynY3l@ePxZxh=GWKTap3!e$XjPOolk4FnD!P5rhDQG6V<` z)hP}LeDn~LAVo13!}ko- zE#U0p^$=!zQ~ipt3b#zyl{v!LnpmoS|ABGNi=KE$*oJRSiIm|BZ=A35h{FeRt`mN> zOwP57lMY#Ga)zBN(qPeT+iB|w;SKxZq%Uiuo?GyHgMq^q`O3a=UMs0Nn)fZ&@rFdf zBV_D+bwhk})7I@fcHet>?QQEgt7Y|>DaoBJ21}CG5yQ&~$F!UiqeQmjTgNR?U^Vyy z8*q$Cp}aQ4HZuN+HfGXxj<}{AV+NMkhS(-eJ0|;k3xZ13&Ggt7#tm)2qphhanpq3u z9vgU!p09FkWeJU&Y|u8c!d6}Puy&0fVwowmf7Q8*b!s)3V8c0ga*}rFsqU`WUX6dP zJtEgWYX;(eVeM?OnksjTqDNL;?xm7*)revF{aCt**gaqt^1276X zaG(S)z>Dw_ya}^#9zKT8;R0NQZ{QMq3s>MO{0Kk6ukbtk0e>PO!z!%CwOEUdcsp*! zJMd22j(1}lw&QM0VmJ0;3J>ET4&exnVh(MbL>Ke;BtDNX;~V%kp2b=G5I@3C@e8%9 zin2`mRJ&Z_msI=L=bB_1p6iOtQZkJnsOwApFEYJaEyY<=TUXx@s@0 zm(ow5tFmqa<<1xDdXjLwk!@N|7K0>9aWc>uUwt_kt;e@WfpJYWo8v7SodI4EG+Apr zAr;P7C~Kfxlkt_xN}82w=atIZ#Yn4%7+-g3JIUXzvQ6ZkY9yv~>3y$qN zC&;HP@A=b3tsBC?3N=ei#{c`5|NZ}ltQAcXF%U6ub25OHsdTD`_O{&HR>s;o^_@arv7-QOKU-Y3SCF+ZBKAETw`sOz~dxXEQYTBL4%=gXr zXLsf|zujRL0Kopd)(H>>0EMcMyo#DlitvlNp@e)(IZ32^NSk(=^uNyC@pHR@dJ6%8Og#*T= z4B7yJ0D+ANh{q=c24vF(C%gLm?zkNt%NQyv-&V0*VU<BFzD$oZrH4uQILcw8-kVLJ085{!^7K4u6oZmfX8s=|r- z!J!$>^N#+IZmO;^uP0PjcV_rbhwynIV_W{PQyJUL&spTD$*5)~Pr-VhX(o*)b!WoW z&$~jKa_pQt-~~!}+!O(6xyD&T&#@X@VxyKir^~Fy@NULGRi-r>&M8|HF`DNI zH-?)P<&3Zo!vi_!#Wjy zf~Dr=_@(hM>sD$o#wIfM+#HS2k>;N8F@=AlJR2-B-`9ITr&0B9HA_XA z6d8S*rfW(|e4kv?mUxF$xY${CLkxOh2&Nzd78Kw`cnMyHw_ph_!zb_sT!E|bEnI`| z;07$ikMI-x3ctf2@FxN?ti)>EfwkC#x8okX1MkEGcsF)nCmz8#_Tc~~@Fb4mI8Nde zX3)erv@wfM;S2Z*zKQSPMO?y<@MHW8zm%g2l_)qY`=u7YBF%dqiGu#~7)otM!N^eE zaN<9q;BvJfUQKOXeS^=$zLk|+w|J|0wZ3^+5hrBLpkHiFfd71Qjtkf9aCcVT*!DL=8y*-S0c!Kc? z>Fs54@9E(n`>l}#Q#fuywJnKuk!bcgk?b0L4?n=q@C*C~e-X7RkmD|F#0XKV8Slb2 z+>h-T!!GQ`qu7JTh**O-jK}doOyVdJEJYMc6UB5qi?jGR=Fr7F7O;p<G@eO=?9o3GPNG2s-Dp74dnX^pWI!FByE!Tzyy_*t&GC8ZTIR6iB{r&%@oO>{- z0D%Aji2#--l8JuOw|e`Fvv!o~qf|u^aYZS;6l&Id2%!GTKMYBaQmDv@`?4q{S*ZN$ V9|Gu4i(vm3zz6%kN5EUO`3DsJ(ewZS literal 0 HcmV?d00001 diff --git a/Keyboard Sample Code/KeyboardConstraints.xdc b/Keyboard Sample Code/KeyboardConstraints.xdc new file mode 100755 index 0000000..6f9d5d3 --- /dev/null +++ b/Keyboard Sample Code/KeyboardConstraints.xdc @@ -0,0 +1,46 @@ +# 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] + +#7 segment display +set_property PACKAGE_PIN W7 [get_ports {display[0]}] + set_property IOSTANDARD LVCMOS33 [get_ports {display[0]}] +set_property PACKAGE_PIN W6 [get_ports {display[1]}] + set_property IOSTANDARD LVCMOS33 [get_ports {display[1]}] +set_property PACKAGE_PIN U8 [get_ports {display[2]}] + set_property IOSTANDARD LVCMOS33 [get_ports {display[2]}] +set_property PACKAGE_PIN V8 [get_ports {display[3]}] + set_property IOSTANDARD LVCMOS33 [get_ports {display[3]}] +set_property PACKAGE_PIN U5 [get_ports {display[4]}] + set_property IOSTANDARD LVCMOS33 [get_ports {display[4]}] +set_property PACKAGE_PIN V5 [get_ports {display[5]}] + set_property IOSTANDARD LVCMOS33 [get_ports {display[5]}] +set_property PACKAGE_PIN U7 [get_ports {display[6]}] + set_property IOSTANDARD LVCMOS33 [get_ports {display[6]}] + +#set_property PACKAGE_PIN V7 [get_ports dp] + #set_property IOSTANDARD LVCMOS33 [get_ports dp] + +set_property PACKAGE_PIN U2 [get_ports {digit[0]}] + set_property IOSTANDARD LVCMOS33 [get_ports {digit[0]}] +set_property PACKAGE_PIN U4 [get_ports {digit[1]}] + set_property IOSTANDARD LVCMOS33 [get_ports {digit[1]}] +set_property PACKAGE_PIN V4 [get_ports {digit[2]}] + set_property IOSTANDARD LVCMOS33 [get_ports {digit[2]}] +set_property PACKAGE_PIN W4 [get_ports {digit[3]}] + set_property IOSTANDARD LVCMOS33 [get_ports {digit[3]}] + + +#Buttons +set_property PACKAGE_PIN U18 [get_ports rst] + set_property IOSTANDARD LVCMOS33 [get_ports rst] + +#USB HID (PS/2) +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] +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] + diff --git a/Keyboard Sample Code/KeyboardDecoder.v b/Keyboard Sample Code/KeyboardDecoder.v new file mode 100755 index 0000000..3cde9d5 --- /dev/null +++ b/Keyboard Sample Code/KeyboardDecoder.v @@ -0,0 +1,126 @@ +module KeyboardDecoder( + output reg [511:0] key_down, + output wire [8:0] last_change, + output reg key_valid, + inout wire PS2_DATA, + inout wire PS2_CLK, + input wire rst, + input wire clk + ); + + parameter [1:0] INIT = 2'b00; + parameter [1:0] WAIT_FOR_SIGNAL = 2'b01; + parameter [1:0] GET_SIGNAL_DOWN = 2'b10; + parameter [1:0] WAIT_RELEASE = 2'b11; + + parameter [7:0] IS_INIT = 8'hAA; + parameter [7:0] IS_EXTEND = 8'hE0; + parameter [7:0] IS_BREAK = 8'hF0; + + reg [9:0] key; // key = {been_extend, been_break, key_in} + reg [1:0] state; + reg been_ready, been_extend, been_break; + + wire [7:0] key_in; + wire is_extend; + wire is_break; + wire valid; + wire err; + + wire [511:0] key_decode = 1 << last_change; + assign last_change = {key[9], key[7:0]}; + + KeyboardCtrl_0 inst ( + .key_in(key_in), + .is_extend(is_extend), + .is_break(is_break), + .valid(valid), + .err(err), + .PS2_DATA(PS2_DATA), + .PS2_CLK(PS2_CLK), + .rst(rst), + .clk(clk) + ); + + OnePulse op ( + .signal_single_pulse(pulse_been_ready), + .signal(been_ready), + .clock(clk) + ); + + always @ (posedge clk, posedge rst) begin + if (rst) begin + state <= INIT; + been_ready <= 1'b0; + been_extend <= 1'b0; + been_break <= 1'b0; + key <= 10'b0_0_0000_0000; + end else begin + state <= state; + been_ready <= been_ready; + been_extend <= (is_extend) ? 1'b1 : been_extend; + been_break <= (is_break ) ? 1'b1 : been_break; + key <= key; + case (state) + INIT : begin + if (key_in == IS_INIT) begin + state <= WAIT_FOR_SIGNAL; + been_ready <= 1'b0; + been_extend <= 1'b0; + been_break <= 1'b0; + key <= 10'b0_0_0000_0000; + end else begin + state <= INIT; + end + end + WAIT_FOR_SIGNAL : begin + if (valid == 0) begin + state <= WAIT_FOR_SIGNAL; + been_ready <= 1'b0; + end else begin + state <= GET_SIGNAL_DOWN; + end + end + GET_SIGNAL_DOWN : begin + state <= WAIT_RELEASE; + key <= {been_extend, been_break, key_in}; + been_ready <= 1'b1; + end + WAIT_RELEASE : begin + if (valid == 1) begin + state <= WAIT_RELEASE; + end else begin + state <= WAIT_FOR_SIGNAL; + been_extend <= 1'b0; + been_break <= 1'b0; + end + end + default : begin + state <= INIT; + been_ready <= 1'b0; + been_extend <= 1'b0; + been_break <= 1'b0; + key <= 10'b0_0_0000_0000; + end + endcase + end + end + + always @ (posedge clk, posedge rst) begin + if (rst) begin + key_valid <= 1'b0; + key_down <= 511'b0; + end else if (key_decode[last_change] && pulse_been_ready) begin + key_valid <= 1'b1; + if (key[8] == 0) begin + key_down <= key_down | key_decode; + end else begin + key_down <= key_down & (~key_decode); + end + end else begin + key_valid <= 1'b0; + key_down <= key_down; + end + end + +endmodule diff --git a/Keyboard Sample Code/OnePulse.v b/Keyboard Sample Code/OnePulse.v new file mode 100755 index 0000000..aad4e33 --- /dev/null +++ b/Keyboard Sample Code/OnePulse.v @@ -0,0 +1,17 @@ +module OnePulse ( + output reg signal_single_pulse, + input wire signal, + input wire clock + ); + + reg signal_delay; + + always @(posedge clock) begin + if (signal == 1'b1 & signal_delay == 1'b0) + signal_single_pulse <= 1'b1; + else + signal_single_pulse <= 1'b0; + + signal_delay <= signal; + end +endmodule diff --git a/Keyboard Sample Code/SampleDisplay.v b/Keyboard Sample Code/SampleDisplay.v new file mode 100755 index 0000000..a94418c --- /dev/null +++ b/Keyboard Sample Code/SampleDisplay.v @@ -0,0 +1,108 @@ +module SampleDisplay( + output wire [6:0] display, + output wire [3:0] digit, + inout wire PS2_DATA, + inout wire PS2_CLK, + input wire rst, + input wire clk + ); + + parameter [8:0] LEFT_SHIFT_CODES = 9'b0_0001_0010; + parameter [8:0] RIGHT_SHIFT_CODES = 9'b0_0101_1001; + parameter [8:0] KEY_CODES [0:19] = { + 9'b0_0100_0101, // 0 => 45 + 9'b0_0001_0110, // 1 => 16 + 9'b0_0001_1110, // 2 => 1E + 9'b0_0010_0110, // 3 => 26 + 9'b0_0010_0101, // 4 => 25 + 9'b0_0010_1110, // 5 => 2E + 9'b0_0011_0110, // 6 => 36 + 9'b0_0011_1101, // 7 => 3D + 9'b0_0011_1110, // 8 => 3E + 9'b0_0100_0110, // 9 => 46 + + 9'b0_0111_0000, // right_0 => 70 + 9'b0_0110_1001, // right_1 => 69 + 9'b0_0111_0010, // right_2 => 72 + 9'b0_0111_1010, // right_3 => 7A + 9'b0_0110_1011, // right_4 => 6B + 9'b0_0111_0011, // right_5 => 73 + 9'b0_0111_0100, // right_6 => 74 + 9'b0_0110_1100, // right_7 => 6C + 9'b0_0111_0101, // right_8 => 75 + 9'b0_0111_1101 // right_9 => 7D + }; + + reg [15:0] nums; + reg [3:0] key_num; + reg [9:0] last_key; + + wire shift_down; + wire [511:0] key_down; + wire [8:0] last_change; + wire been_ready; + + assign shift_down = (key_down[LEFT_SHIFT_CODES] == 1'b1 || key_down[RIGHT_SHIFT_CODES] == 1'b1) ? 1'b1 : 1'b0; + + SevenSegment seven_seg ( + .display(display), + .digit(digit), + .nums(nums), + .rst(rst), + .clk(clk) + ); + + KeyboardDecoder key_de ( + .key_down(key_down), + .last_change(last_change), + .key_valid(been_ready), + .PS2_DATA(PS2_DATA), + .PS2_CLK(PS2_CLK), + .rst(rst), + .clk(clk) + ); + + always @ (posedge clk, posedge rst) begin + if (rst) begin + nums <= 16'b0; + end else begin + nums <= nums; + if (been_ready && key_down[last_change] == 1'b1) begin + if (key_num != 4'b1111)begin + if (shift_down == 1'b1) begin + nums <= {key_num, nums[15:4]}; + end else begin + nums <= {nums[11:0], key_num}; + end + end + end + end + end + + always @ (*) begin + case (last_change) + KEY_CODES[00] : key_num = 4'b0000; + KEY_CODES[01] : key_num = 4'b0001; + KEY_CODES[02] : key_num = 4'b0010; + KEY_CODES[03] : key_num = 4'b0011; + KEY_CODES[04] : key_num = 4'b0100; + KEY_CODES[05] : key_num = 4'b0101; + KEY_CODES[06] : key_num = 4'b0110; + KEY_CODES[07] : key_num = 4'b0111; + KEY_CODES[08] : key_num = 4'b1000; + KEY_CODES[09] : key_num = 4'b1001; + KEY_CODES[10] : key_num = 4'b0000; + KEY_CODES[11] : key_num = 4'b0001; + KEY_CODES[12] : key_num = 4'b0010; + KEY_CODES[13] : key_num = 4'b0011; + KEY_CODES[14] : key_num = 4'b0100; + KEY_CODES[15] : key_num = 4'b0101; + KEY_CODES[16] : key_num = 4'b0110; + KEY_CODES[17] : key_num = 4'b0111; + KEY_CODES[18] : key_num = 4'b1000; + KEY_CODES[19] : key_num = 4'b1001; + default : key_num = 4'b1111; + endcase + end + +endmodule diff --git a/Keyboard Sample Code/SevenSegment.v b/Keyboard Sample Code/SevenSegment.v new file mode 100755 index 0000000..5b5287f --- /dev/null +++ b/Keyboard Sample Code/SevenSegment.v @@ -0,0 +1,66 @@ +module SevenSegment( + output reg [6:0] display, + output reg [3:0] digit, + input wire [15:0] nums, + input wire rst, + input wire clk + ); + + reg [15:0] clk_divider; + reg [3:0] display_num; + + always @ (posedge clk, posedge rst) begin + if (rst) begin + clk_divider <= 15'b0; + end else begin + clk_divider <= clk_divider + 15'b1; + end + end + + always @ (posedge clk_divider[15], posedge rst) begin + if (rst) begin + display_num <= 4'b0000; + digit <= 4'b1111; + end else begin + case (digit) + 4'b1110 : begin + display_num <= nums[7:4]; + digit <= 4'b1101; + end + 4'b1101 : begin + display_num <= nums[11:8]; + digit <= 4'b1011; + end + 4'b1011 : begin + display_num <= nums[15:12]; + digit <= 4'b0111; + end + 4'b0111 : begin + display_num <= nums[3:0]; + digit <= 4'b1110; + end + default : begin + display_num <= nums[3:0]; + digit <= 4'b1110; + end + endcase + end + end + + always @ (*) begin + case (display_num) + 0 : display = 7'b1000000; //0000 + 1 : display = 7'b1111001; //0001 + 2 : display = 7'b0100100; //0010 + 3 : display = 7'b0110000; //0011 + 4 : display = 7'b0011001; //0100 + 5 : display = 7'b0010010; //0101 + 6 : display = 7'b0000010; //0110 + 7 : display = 7'b1111000; //0111 + 8 : display = 7'b0000000; //1000 + 9 : display = 7'b0010000; //1001 + default : display = 7'b1111111; + endcase + end + +endmodule diff --git a/Keyboard Sample Code/ip/.DS_Store b/Keyboard Sample Code/ip/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0aa7e696d9409cbe038c5baacd3e25cd59c91767 GIT binary patch literal 8196 zcmeHMU2GIZ9RL5X1$Ow5=?C;U1TSDMkgK*p3k_PY?eU>NXuP&ZOZD8l9q7jG?s>a+ z2R4mo)M$trHEQCEk@|rln)srLz8GU5%8Nc=LZiO;=97u~pl|+XXRo2aB|H!%VP`Y* zo3H=O>~DXwbN@X6z`>Hy4G;wYjiN-pf|Bb5*)HQXArjOy5+d0HIG{rj4CsWRYkG$j zAp;=;Ap;=;Ap;=;w*munX3L<}Irmj-n1&354BVCs$oE5>qQqo?RfYbmgA(5bAe1hE zA1F_LfNv8IFd1M~p>IlKD(?XUQw&@TROZwkm)!}I0ag_%b3kPd7|e`;hl2j>WEc0l z111%QX~;mxz_kp>?b8AWLBJ`+%9!Y(+HHx_4ie^O7qb5tiDX&}k5_J{>mX$W267Eq?ob+UF!gY$?kl*pBNw%^s%bO)JM+%9_ zu@PIJ7RstEx{mSBv`K@ObJ#ItAH#2nwnaB++A&!_R1}n|Y8H=fVqDioTw0nMqMdax z?y`|5=;sOUKS+CZF33fE^Oi$AaT~*x|-J|hu zwa4V#hjiCFQV=#x|3LqPoK`hh?=CfMTv`kmhA_0v$t~)kZ%%fp440?VI!Hi2?1Kr& z)6S^COYkzh0&l|{oP$r{OE?b~;5)bo-@|2?ho9hQ_znJmKjAL~WVjqx;wo&$^>`<4 z#Jlir?8JMq3%hX_CUF3VFolP36vuEJCoqo|PNRbbd>UWGSMe=;7ti1vevF^s=lGRc zRiq};{i<9`@oUQ6xJZLN9m!lzq_KT1`&0jmNat5dX*M;tw5|!XIYF#HR$sRU<4aU4DOPHoH>%b?MoK-%_)^u{&yxQB;-Jdyu@uudUPp{|rFe#f_yx)E zBK!b9!Y}YE{0@JU_?9Bawb+I+65j^A2Rm>pZo>rjU@z{*KHNjn+l%}006vUq93cs2 zNQ5~Op}^xfg->D;JuG1btN08)htJ~+B+1wCb$kQg#CNU|FCHu`-Bbn|)M!!Z|L?8;{r{%U84eaQ5HfIUF@TM!bZU^+RPU`TeeF2K$0^Dn y`&AYCCY1Q@IHB*36E6H=NclK*l{U!$s|u-x!hilDVBx1~c>agyzc0btGWi!eDGNRT literal 0 HcmV?d00001 diff --git a/Keyboard Sample Code/ip/Keyboard-Controller/.DS_Store b/Keyboard Sample Code/ip/Keyboard-Controller/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5d6b7bec8cedc288373ad11ee0478701b1badcab GIT binary patch literal 8196 zcmeI1T}&KR6vxj2+Rg=P@A6T$i_}dKY00)iTWCoY7g(U$HYF~wK+$z}XIds5W^iYg zZ6!pE8cm}{jhgskEPm89n)srLz8GWLXkYZ9CMD{NZ$6o*5Blc0b7x8UN_eR?>DT+q8L$!pbYehlk1^OHSH_q^r7lr$^15@_L4*XZ-e{>P{BhL$+-$wbjgsp%>D; zrq{My)v)y3O`#Jh!_w?RkDa$PXCf)rOBtFwndY^FIemsg2USZSF&rafn1*{^Vd9hK z;n~^!9UZY~Tj$}qSai1Y;DK1Qz3sr<9Di0(>i4vFpBS5-yRh)y`yYIG>7#G1NOjPE z!a(&3wXSYVD$|)6lv0)0MX7EqNyRF{iJHFtH0OCoe^fVB*O<{0s;fI`zRe-^9?sg9 z|D{q{+ssc{G!x3IW;RdGdbepNji+>H)YZ?qqBZW=Ik(qy95pCbjHP*%5ar~wYuJ`E zqURj4j9sp*jqGgPy?6hi2d;0uYa3@(tR^)hR5SJAf)I2}b+Wpp8P=I`lG$>N(}td7 zAzWZXmO7=&sJieD#y?XgG}_JyTN6H-HxsT4Hz>*}G2WZgsg}bm8s5dYsth@_HMv9+ zYi8VGLucvA%Fq@TQ@F;4O*NyNa_D~6rto7dH6!;g2M@9iC4@0Hnzg5X;V%SaSdNvr6|1lw z@5Y^Y58jJ=aUZr~8y>w%LJ%@FPEg&0yNTJJ&?F9fG$=FEJIb*HMKsc-AmVb#ihNO zG7l_Cjz?6H7?0WIm~JO{BlWCdJs^e&Nd25g7~gW;^NvP#3ADH(yG@a1h3MxcUYE5* zVuEd6DrY@rHO4o|S)x^N&dcO%CnHLaF}_*OcCom3Z*h?QrbvP*9M=GGT?{W0gkKPX z*Wd^E5q^PR;dl6(z}t)*w__bf2)qWo51VlhwqOj~u>%idCmtc}`fvb`;v<;EA;K?3 z0A>h49Z%yVK8ZPWF^>hD$7k?4d>&sQ9ACrN@eO@QO vo0rxLp~_3g$$IHH*`+@WsU0O(5fk_AytFhza+ zhmyuKYBWZT8a467Nd1E$n)srLz8GU5%8Nc=0#RRl^T|Yg&^N!?**i+1(HBL`%w^`A z`M&vfXMgkC`EF(b0Q-tY7eE{UG|EEqMk=n6gk9vTQY6#}Ba%OO`K;|`sr5%Te^qa# zPzWdl6aoqXg@8ifzkmS6Y>~7EDOITuPzWdlY6yt+Ax>GyWGE|A21^GO!4`mIJ*k64 zbuKC-W1Wy=fq@3!Unot>93Qdhrh`3jA#Y!E-*wDSJ+j9X6ox?lAA z^un>AWf^8RtPkn_Otn7jx^}IuXGblwJjGl3UB}lg$1E&xoy=H{;gx2W(yV`>r`x$AbvAo#J8eB` zdSkwM!WXp(&n@`(-hu!Nzj#>@1DYlj@%6K8=5=Js|FVSoi#+dDEfW-?jg4PNV8u z>M1pCTzK>vhG}T6$*po$Ta%r#!bNo1014O+126$OaG(s&!SnC}ybkkl20nyO;Vhhk zui!j<4Hw}OdGtFRe2;?1}jZ^2t}JKm0+*oAvAiM`m5DLjlL zIEv#qfjP8s7G2EaWB3fdh_B(Bcnat7ef$7F#?R!aB2^L&%67HHx^lSIPsOf8bR z771emYX(!-g@l(H1@)Sm*R-q+x!7Bq%SF?-kVye~Bs&7uR9O-5@=7YMBZ9^@vQ0}( z`UsKEJQ1*nuecEOj>onL`fyD)+hXk+F`P$&ChLeL1b=y*v#7MzqUN5aZ zjF@g;=iwXp7Jh&q;b-`r$h90fuEX^h zBXVuR+przCVFxB~H+JJ*?7@9RtphlS2k~A^<1kSyLnO-*$xJ+sGx#tT(8nT{v4W4| zllT-qO_X~HU&dGPReWO+*$!4|CMBM}Otwz# z*9c&JDxK=1e$@ks#V+EkJx=*S$|8w=6)6K3Dz5ktKn-!O7#zcpEj)z@{F0;>{uL<$ icWMXjB>$z40l{H`+W(8GQ2YPCeK1`6C;Wfd|NjZc{sCG5 literal 0 HcmV?d00001 diff --git a/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/component.xml b/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/component.xml new file mode 100755 index 0000000..2a0f79f --- /dev/null +++ b/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/component.xml @@ -0,0 +1,257 @@ + + + xilinx.com + user + KeyboardCtrl + 1.0 + + + + xilinx_verilogsynthesis + Verilog Synthesis + verilogSource:vivado.xilinx.com:synthesis + verilog + KeyboardCtrl + + xilinx_verilogsynthesis_view_fileset + + + + viewChecksum + c8a2a715 + + + + + xilinx_verilogbehavioralsimulation + Verilog Simulation + verilogSource:vivado.xilinx.com:simulation + verilog + KeyboardCtrl + + xilinx_verilogbehavioralsimulation_view_fileset + + + + viewChecksum + c8a2a715 + + + + + xilinx_xpgui + UI Layout + :vivado.xilinx.com:xgui.ui + + xilinx_xpgui_view_fileset + + + + viewChecksum + ce6920f7 + + + + + + + key_in + + out + + 7 + 0 + + + + reg + xilinx_verilogsynthesis + xilinx_verilogbehavioralsimulation + + + + + + is_extend + + out + + + reg + xilinx_verilogsynthesis + xilinx_verilogbehavioralsimulation + + + + + + is_break + + out + + + reg + xilinx_verilogsynthesis + xilinx_verilogbehavioralsimulation + + + + + + valid + + out + + + reg + xilinx_verilogsynthesis + xilinx_verilogbehavioralsimulation + + + + + + err + + out + + + std_logic + xilinx_verilogsynthesis + xilinx_verilogbehavioralsimulation + + + + + + PS2_DATA + + inout + + + std_logic + xilinx_verilogsynthesis + xilinx_verilogbehavioralsimulation + + + + + + PS2_CLK + + inout + + + std_logic + xilinx_verilogsynthesis + xilinx_verilogbehavioralsimulation + + + + + + rst + + in + + + std_logic + xilinx_verilogsynthesis + xilinx_verilogbehavioralsimulation + + + + + + clk + + in + + + std_logic + xilinx_verilogsynthesis + xilinx_verilogbehavioralsimulation + + + + + + + + SYSCLK_FREQUENCY_HZ + Sysclk Frequency Hz + 100000000 + + + + + + xilinx_verilogsynthesis_view_fileset + + src/Ps2Interface.v + verilogSource + + + src/KeyboardCtrl.v + verilogSource + CHECKSUM_36baf34c + + + + xilinx_verilogbehavioralsimulation_view_fileset + + src/Ps2Interface.v + verilogSource + + + src/KeyboardCtrl.v + verilogSource + + + + xilinx_xpgui_view_fileset + + xgui/KeyboardCtrl_v1_0.tcl + tclSource + XGUI_VERSION_2 + CHECKSUM_407cc9d0 + + + + KeyboardCtrl_v1_0 + + + SYSCLK_FREQUENCY_HZ + Sysclk Frequency Hz + 100000000 + + + Component_Name + KeyboardCtrl_v1_0 + + + + + + artix7 + + + /UserIP + + KeyboardCtrl_v1_0 + 2 + 2015-05-31T12:51:28Z + + C:/Users/bill/Desktop/zedboard/basys3/Basys3_master/Library/Interface/Keyboard-Controller/keyboard_cntr_1.0 + C:/Users/bill/Desktop/zedboard/basys3/Basys3_master/Library/Interface/Keyboard-Controller/keyboard_cntr_1.0 + + + + 2014.4 + + + + + + + diff --git a/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/KeyboardCtrl.v b/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/KeyboardCtrl.v new file mode 100755 index 0000000..7d6d416 --- /dev/null +++ b/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/KeyboardCtrl.v @@ -0,0 +1,189 @@ +module KeyboardCtrl#( + parameter SYSCLK_FREQUENCY_HZ = 100000000 +)( + output reg [7:0] key_in, + output reg is_extend, + output reg is_break, + output reg valid, + output err, + inout PS2_DATA, + inout PS2_CLK, + input rst, + input clk +); +////////////////////////////////////////////////////////// +// This Keyboard Controller do not support lock LED control +////////////////////////////////////////////////////////// + + parameter RESET = 3'd0; + parameter SEND_CMD = 3'd1; + parameter WAIT_ACK = 3'd2; + parameter WAIT_KEYIN = 3'd3; + parameter GET_BREAK = 3'd4; + parameter GET_EXTEND = 3'd5; + parameter RESET_WAIT_BAT = 3'd6; + + parameter CMD_RESET = 8'hFF; + parameter CMD_SET_STATUS_LEDS = 8'hED; + parameter RSP_ACK = 8'hFA; + parameter RSP_BAT_PASS = 8'hAA; + + parameter BREAK_CODE = 8'hF0; + parameter EXTEND_CODE = 8'hE0; + parameter CAPS_LOCK = 8'h58; + parameter NUM_LOCK = 8'h77; + parameter SCR_LOCK = 8'h7E; + + wire [7:0] rx_data; + wire rx_valid; + wire busy; + + reg [7:0] tx_data; + reg tx_valid; + reg [2:0] state; + reg [2:0] lock_status; + + always @ (posedge clk, posedge rst) + if(rst) + key_in <= 0; + else if(rx_valid) + key_in <= rx_data; + else + key_in <= key_in; + + always @ (posedge clk, posedge rst)begin + if(rst)begin + state <= RESET; + is_extend <= 1'b0; + is_break <= 1'b1; + valid <= 1'b0; + lock_status <= 3'b0; + tx_data <= 8'h00; + tx_valid <= 1'b0; + end else begin + is_extend <= 1'b0; + is_break <= 1'b0; + valid <= 1'b0; + lock_status <= lock_status; + tx_data <= tx_data; + tx_valid <= 1'b0; + case(state) + RESET:begin + is_extend <= 1'b0; + is_break <= 1'b1; + valid <= 1'b0; + lock_status <= 3'b0; + tx_data <= CMD_RESET; + tx_valid <= 1'b0; + state <= SEND_CMD; + end + + SEND_CMD:begin + if(busy == 1'b0)begin + tx_valid <= 1'b1; + state <= WAIT_ACK; + end else begin + tx_valid <= 1'b0; + state <= SEND_CMD; + end + end + + WAIT_ACK:begin + if(rx_valid == 1'b1)begin + if(rx_data == RSP_ACK && tx_data == CMD_RESET)begin + state <= RESET_WAIT_BAT; + end else if(rx_data == RSP_ACK && tx_data == CMD_SET_STATUS_LEDS)begin + tx_data <= {5'b00000, lock_status}; + state <= SEND_CMD; + end else begin + state <= WAIT_KEYIN; + end + end else if(err == 1'b1)begin + state <= RESET; + end else begin + state <= WAIT_ACK; + end + end + + WAIT_KEYIN:begin + if(rx_valid == 1'b1 && rx_data == BREAK_CODE)begin + state <= GET_BREAK; + end else if(rx_valid == 1'b1 && rx_data == EXTEND_CODE)begin + state <= GET_EXTEND; + end else if(rx_valid == 1'b1)begin + state <= WAIT_KEYIN; + valid <= 1'b1; + end else if(err == 1'b1)begin + state <= RESET; + end else begin + state <= WAIT_KEYIN; + end + end + + GET_BREAK:begin + is_extend <= is_extend; + if(rx_valid == 1'b1)begin + state <= WAIT_KEYIN; + valid <= 1'b1; + is_break <= 1'b1; + end else if(err == 1'b1)begin + state <= RESET; + end else begin + state <= GET_BREAK; + end + end + + GET_EXTEND:begin + if(rx_valid == 1'b1 && rx_data == BREAK_CODE)begin + state <= GET_BREAK; + is_extend <= 1'b1; + end else if(rx_valid == 1'b1)begin + state <= WAIT_KEYIN; + valid <= 1'b1; + is_extend <= 1'b1; + end else if(err == 1'b1)begin + state <= RESET; + end else begin + state <= GET_EXTEND; + end + end + + RESET_WAIT_BAT:begin + if(rx_valid == 1'b1 && rx_data == RSP_BAT_PASS)begin + state <= WAIT_KEYIN; + end else if(rx_valid == 1'b1)begin + state <= RESET; + end else if(err == 1'b1)begin + state <= RESET; + end else begin + state <= RESET_WAIT_BAT; + end + end + default:begin + state <= RESET; + valid <= 1'b0; + end + endcase + end + end + + Ps2Interface #( + .SYSCLK_FREQUENCY_HZ(SYSCLK_FREQUENCY_HZ) + ) Ps2Interface_i( + .ps2_clk(PS2_CLK), + .ps2_data(PS2_DATA), + + .clk(clk), + .rst(rst), + + .tx_data(tx_data), + .tx_valid(tx_valid), + + .rx_data(rx_data), + .rx_valid(rx_valid), + + .busy(busy), + .err(err) + ); + +endmodule diff --git a/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/Ps2Interface.v b/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/Ps2Interface.v new file mode 100755 index 0000000..bf3a9fc --- /dev/null +++ b/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/Ps2Interface.v @@ -0,0 +1,562 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: NTHU +// Engineer: Y.J Shih +// +// Create Date: 2015/05/27 11:15:54 +// Design Name: PS/2 interface +// Module Name: Ps2Interface +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// Original VHDL version is create by Ulrich Zolt. +// +////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// ps2interface.vhd +//////////////////////////////////////////////////////////////////////// +// Author : Ulrich Zolt +// 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 +// tx_valid - 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 +//////////////////////////////////////////////////////////////////////// + + +module Ps2Interface#( + parameter SYSCLK_FREQUENCY_HZ = 100000000 + )( + ps2_clk, + ps2_data, + + clk, + rst, + + tx_data, + tx_valid, + + rx_data, + rx_valid, + + busy, + err +); + inout ps2_clk, ps2_data; + input clk, rst; + input [7:0] tx_data; + input tx_valid; + output reg [7:0] rx_data; + output reg rx_valid; + output busy; + output reg err; + + parameter CLOCK_CNT_100US = (100*1000) / (1000000000/SYSCLK_FREQUENCY_HZ); + parameter CLOCK_CNT_20US = (20*1000) / (1000000000/SYSCLK_FREQUENCY_HZ); + parameter DEBOUNCE_DELAY = 15; + parameter BITS_NUM = 11; + + parameter [0:0] parity_table [0:255] = { //(odd) parity bit table, used instead of logic because this way speed is far greater + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b1,1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b0, + 1'b0,1'b1,1'b1,1'b0,1'b1,1'b0,1'b0,1'b1 + }; + + parameter IDLE = 4'd0; + parameter RX_NEG_EDGE = 4'd1; + parameter RX_CLK_LOW = 4'd2; + parameter RX_CLK_HIGH = 4'd3; + parameter TX_FORCE_CLK_LOW = 4'd4; + parameter TX_BRING_DATA_LOW = 4'd5; + parameter TX_RELEASE_CLK = 4'd6; + parameter TX_WAIT_FIRTS_NEG_EDGE = 4'd7; + parameter TX_CLK_LOW = 4'd8; + parameter TX_WAIT_POS_EDGE = 4'd9; + parameter TX_CLK_HIGH = 4'd10; + parameter TX_WAIT_POS_EDGE_BEFORE_ACK = 4'd11; + parameter TX_WAIT_ACK = 4'd12; + parameter TX_RECEIVED_ACK = 4'd13; + parameter TX_ERROR_NO_ACK = 4'd14; + + + reg [10:0] frame; + wire rx_parity; + + wire ps2_clk_in, ps2_data_in; + reg clk_inter, ps2_clk_s, data_inter, ps2_data_s; + reg [3:0] clk_count, data_count; + + reg ps2_clk_en, ps2_clk_en_next, ps2_data_en, ps2_data_en_next; + reg ps2_clk_out, ps2_clk_out_next, ps2_data_out, ps2_data_out_next; + reg err_next; + reg [3:0] state, state_next; + reg rx_finish; + + reg [3:0] bits_count; + + reg [13:0] counter, counter_next; + + IOBUF IOBUF_inst_0( + .O(ps2_clk_in), + .IO(ps2_clk), + .I(ps2_clk_out), + .T(~ps2_clk_en) + ); + + IOBUF IOBUF_inst_1( + .O(ps2_data_in), + .IO(ps2_data), + .I(ps2_data_out), + .T(~ps2_data_en) + ); + //assign ps2_clk = (ps2_clk_en)?ps2_clk_out:1'bz; + //assign ps2_data = (ps2_data_en)?ps2_data_out:1'bz; + assign busy = (state==IDLE)?1'b0:1'b1; + + always @ (posedge clk, posedge rst)begin + if(rst)begin + rx_data <= 0; + rx_valid <= 1'b0; + end else if(rx_finish==1'b1)begin // set read signal for the client to know + rx_data <= frame[8:1]; // a new byte was received and is available on rx_data + rx_valid <= 1'b1; + end else begin + rx_data <= rx_data; + rx_valid <= 1'b0; + end + end + + assign rx_parity = parity_table[frame[8:1]]; + assign tx_parity = parity_table[tx_data]; + + always @ (posedge clk, posedge rst)begin + if(rst) + frame <= 0; + else if(tx_valid==1'b1 && state==IDLE) begin + frame[0] <= 1'b0; //start bit + frame[8:1] <= tx_data; //data + frame[9] <= tx_parity; //parity bit + frame[10] <= 1'b1; //stop bit + end else if(state==RX_NEG_EDGE || state==TX_CLK_LOW) + frame <= {ps2_data_s, frame[10:1]}; + else + frame <= frame; + end + + // Debouncer + always @ (posedge clk, posedge rst) begin + if(rst)begin + ps2_clk_s <= 1'b1; + clk_inter <= 1'b1; + clk_count <= 0; + end else if(ps2_clk_in != clk_inter)begin + ps2_clk_s <= ps2_clk_s; + clk_inter <= ps2_clk_in; + clk_count <= 0; + end else if(clk_count == DEBOUNCE_DELAY) begin + ps2_clk_s <= clk_inter; + clk_inter <= clk_inter; + clk_count <= clk_count; + end else begin + ps2_clk_s <= ps2_clk_s; + clk_inter <= clk_inter; + clk_count <= clk_count + 1'b1; + end + end + + always @ (posedge clk, posedge rst) begin + if(rst)begin + ps2_data_s <= 1'b1; + data_inter <= 1'b1; + data_count <= 0; + end else if(ps2_data_in != data_inter)begin + ps2_data_s <= ps2_data_s; + data_inter <= ps2_data_in; + data_count <= 0; + end else if(data_count == DEBOUNCE_DELAY) begin + ps2_data_s <= data_inter; + data_inter <= data_inter; + data_count <= data_count; + end else begin + ps2_data_s <= ps2_data_s; + data_inter <= data_inter; + data_count <= data_count + 1'b1; + end + end + + // FSM + always @ (posedge clk, posedge rst)begin + if(rst)begin + state <= IDLE; + ps2_clk_en <= 1'b0; + ps2_clk_out <= 1'b0; + ps2_data_en <= 1'b0; + ps2_data_out <= 1'b0; + err <= 1'b0; + counter <= 0; + end else begin + state <= state_next; + ps2_clk_en <= ps2_clk_en_next; + ps2_clk_out <= ps2_clk_out_next; + ps2_data_en <= ps2_data_en_next; + ps2_data_out <= ps2_data_out_next; + err <= err_next; + counter <= counter_next; + end + end + + always @ * begin + state_next = IDLE; // default values for these signals + ps2_clk_en_next = 1'b0; // ensures signals are reset to default value + ps2_clk_out_next = 1'b1; // when conditions for their activation are no + ps2_data_en_next = 1'b0; // longer applied (transition to other state, + ps2_data_out_next = 1'b1; // where signal should not be active) + err_next = 1'b0; // Idle value for ps2_clk and ps2_data is 'Z' + rx_finish = 1'b0; + counter_next = 0; + case(state) + IDLE:begin // wait for the device to begin a transmission + if(tx_valid == 1'b1)begin // by pulling the clock line low and go to state + state_next = TX_FORCE_CLK_LOW; // RX_NEG_EDGE or, if write is high, the + end else if(ps2_clk_s == 1'b0)begin // client of this interface wants to send a byte + state_next = RX_NEG_EDGE; // to the device and a transition is made to state + end else begin // TX_FORCE_CLK_LOW + state_next = IDLE; + end + end + + RX_NEG_EDGE:begin // data must be read into frame in this state + state_next = RX_CLK_LOW; // the ps2_clk just transitioned from high to low + end + + RX_CLK_LOW:begin // ps2_clk line is low, wait for it to go high + if(ps2_clk_s == 1'b1)begin + state_next = RX_CLK_HIGH; + end else begin + state_next = RX_CLK_LOW; + end + end + + RX_CLK_HIGH:begin // ps2_clk is high, check if all the bits have been read + if(bits_count == BITS_NUM)begin // if, last bit read, check parity, and if parity ok + if(rx_parity != frame[9])begin // load received data into rx_data. + err_next = 1'b1; // else if more bits left, then wait for the ps2_clk to + state_next = IDLE; // go low + end else begin + rx_finish = 1'b1; + state_next = IDLE; + end + end else if(ps2_clk_s == 1'b0)begin + state_next = RX_NEG_EDGE; + end else begin + state_next = RX_CLK_HIGH; + end + end + + TX_FORCE_CLK_LOW:begin // the client wishes to transmit a byte to the device + ps2_clk_en_next = 1'b1; // this is done by holding ps2_clk down for at least 100us + ps2_clk_out_next = 1'b0; // bringing down ps2_data, wait 20us and then releasing + if(counter == CLOCK_CNT_100US)begin // the ps2_clk. + state_next = TX_BRING_DATA_LOW; // This constitutes a request to send command. + counter_next = 0; // In this state, the ps2_clk line is held down and + end else begin // the counter for waiting 100us is enabled. + state_next = TX_FORCE_CLK_LOW; // when the counter reached upper limit, transition + counter_next = counter + 1'b1; // to TX_BRING_DATA_LOW + end + end + + TX_BRING_DATA_LOW:begin // with the ps2_clk line low bring ps2_data low + ps2_clk_en_next = 1'b1; // wait for 20us and then go to TX_RELEASE_CLK + ps2_clk_out_next = 1'b0; + + // 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_en_next = 1'b1; + ps2_data_out_next = 1'b0; + if(counter == CLOCK_CNT_20US)begin + state_next = TX_RELEASE_CLK; + counter_next = 0; + end else begin + state_next = TX_BRING_DATA_LOW; + counter_next = counter + 1'b1; + end + end + + TX_RELEASE_CLK:begin // release the ps2_clk line + ps2_clk_en_next = 1'b0; // keep holding data line low + ps2_data_en_next = 1'b1; + ps2_data_out_next = 1'b0; + state_next = TX_WAIT_FIRTS_NEG_EDGE; + end + + TX_WAIT_FIRTS_NEG_EDGE:begin // state is necessary because the clock signal + ps2_data_en_next = 1'b1; // is not released instantaneously and, because of debounce, + ps2_data_out_next = 1'b0; // delay is even greater. + if(counter == 14'd63)begin // Wait 63 clock periods for the clock line to release + if(ps2_clk_s == 1'b0)begin // then if clock is low then go to tx_clk_l + state_next = TX_CLK_LOW; // else wait until ps2_clk goes low. + counter_next = 0; + end else begin + state_next = TX_WAIT_FIRTS_NEG_EDGE; + counter_next = counter; + end + end else begin + state_next = TX_WAIT_FIRTS_NEG_EDGE; + counter_next = counter + 1'b1; + end + end + + TX_CLK_LOW:begin // place the least significant bit from frame + ps2_data_en_next = 1'b1; // on the data line + ps2_data_out_next = frame[0]; // During this state the frame is shifted one + state_next = TX_WAIT_POS_EDGE; // bit to the right + end + + TX_WAIT_POS_EDGE:begin // wait for the clock to go high + ps2_data_en_next = 1'b1; // this is the edge on which the device reads the data + ps2_data_out_next = frame[0]; // on ps2_data. + if(bits_count == BITS_NUM-1)begin // keep holding ps2_data on frame(0) because else + ps2_data_en_next = 1'b0; // will be released by default value. + state_next = TX_WAIT_POS_EDGE_BEFORE_ACK; // Check if sent the last bit and if so, release data line + end else if(ps2_clk_s == 1'b1)begin // and go to state that wait for acknowledge + state_next = TX_CLK_HIGH; + end else begin + state_next = TX_WAIT_POS_EDGE; + end + end + + TX_CLK_HIGH:begin // ps2_clk is released, wait for down edge + ps2_data_en_next = 1'b1; // and go to tx_clk_l when arrived + ps2_data_out_next = frame[0]; + if(ps2_clk_s == 1'b0)begin + state_next = TX_CLK_LOW; + end else begin + state_next = TX_CLK_HIGH; + end + end + + TX_WAIT_POS_EDGE_BEFORE_ACK:begin // release ps2_data and wait for rising edge of ps2_clk + if(ps2_clk_s == 1'b1)begin // once this occurs, transition to tx_wait_ack + state_next = TX_WAIT_ACK; + end else begin + state_next = TX_WAIT_POS_EDGE_BEFORE_ACK; + end + end + + TX_WAIT_ACK:begin // wait for the falling edge of the clock line + if(ps2_clk_s == 1'b0)begin // if data line is low when this occurs, the + if(ps2_data_s == 1'b0) begin // ack is received + state_next = TX_RECEIVED_ACK; // else if data line is high, the device did not + end else begin // acknowledge the transimission + state_next = TX_ERROR_NO_ACK; + end + end else begin + state_next = TX_WAIT_ACK; + end + end + + TX_RECEIVED_ACK:begin // wait for ps2_clk to be released together with ps2_data + if(ps2_clk_s == 1'b1 && ps2_clk_s == 1'b1)begin // (bus to be idle) and go back to idle state + state_next = IDLE; + end else begin + state_next = TX_RECEIVED_ACK; + end + end + + TX_ERROR_NO_ACK:begin + if(ps2_clk_s == 1'b1 && ps2_clk_s == 1'b1)begin // wait for ps2_clk to be released together with ps2_data + err_next = 1'b1; // (bus to be idle) and go back to idle state + state_next = IDLE; // signal error for not receiving ack + end else begin + state_next = TX_ERROR_NO_ACK; + end + end + + default:begin // if invalid transition occurred, signal error and + err_next = 1'b1; // go back to idle state + state_next = IDLE; + end + + endcase + end + + always @ (posedge clk, posedge rst)begin + if(rst) + bits_count <= 0; + else if(state==IDLE) + bits_count <= 0; + else if(state==RX_NEG_EDGE || state==TX_CLK_LOW) + bits_count <= bits_count + 1'b1; + else + bits_count <= bits_count; + end + +endmodule diff --git a/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/xgui/KeyboardCtrl_v1_0.tcl b/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/xgui/KeyboardCtrl_v1_0.tcl new file mode 100755 index 0000000..498b0de --- /dev/null +++ b/Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/xgui/KeyboardCtrl_v1_0.tcl @@ -0,0 +1,25 @@ +# Definitional proc to organize widgets for parameters. +proc init_gui { IPINST } { + ipgui::add_param $IPINST -name "Component_Name" + #Adding Page + set Page_0 [ipgui::add_page $IPINST -name "Page 0"] + ipgui::add_param $IPINST -name "SYSCLK_FREQUENCY_HZ" -parent ${Page_0} + + +} + +proc update_PARAM_VALUE.SYSCLK_FREQUENCY_HZ { PARAM_VALUE.SYSCLK_FREQUENCY_HZ } { + # Procedure called to update SYSCLK_FREQUENCY_HZ when any of the dependent parameters in the arguments change +} + +proc validate_PARAM_VALUE.SYSCLK_FREQUENCY_HZ { PARAM_VALUE.SYSCLK_FREQUENCY_HZ } { + # Procedure called to validate SYSCLK_FREQUENCY_HZ + return true +} + + +proc update_MODELPARAM_VALUE.SYSCLK_FREQUENCY_HZ { MODELPARAM_VALUE.SYSCLK_FREQUENCY_HZ PARAM_VALUE.SYSCLK_FREQUENCY_HZ } { + # Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value + set_property value [get_property value ${PARAM_VALUE.SYSCLK_FREQUENCY_HZ}] ${MODELPARAM_VALUE.SYSCLK_FREQUENCY_HZ} +} +