Initial commit
This commit is contained in:
commit
a22ff94e72
BIN
Keyboard Sample Code/.DS_Store
vendored
Normal file
BIN
Keyboard Sample Code/.DS_Store
vendored
Normal file
Binary file not shown.
46
Keyboard Sample Code/KeyboardConstraints.xdc
Executable file
46
Keyboard Sample Code/KeyboardConstraints.xdc
Executable file
@ -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]
|
||||||
|
|
126
Keyboard Sample Code/KeyboardDecoder.v
Executable file
126
Keyboard Sample Code/KeyboardDecoder.v
Executable file
@ -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
|
17
Keyboard Sample Code/OnePulse.v
Executable file
17
Keyboard Sample Code/OnePulse.v
Executable file
@ -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
|
108
Keyboard Sample Code/SampleDisplay.v
Executable file
108
Keyboard Sample Code/SampleDisplay.v
Executable file
@ -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
|
66
Keyboard Sample Code/SevenSegment.v
Executable file
66
Keyboard Sample Code/SevenSegment.v
Executable file
@ -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
|
BIN
Keyboard Sample Code/ip/.DS_Store
vendored
Normal file
BIN
Keyboard Sample Code/ip/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
Keyboard Sample Code/ip/Keyboard-Controller/.DS_Store
vendored
Normal file
BIN
Keyboard Sample Code/ip/Keyboard-Controller/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/.DS_Store
vendored
Normal file
BIN
Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/.DS_Store
vendored
Normal file
Binary file not shown.
257
Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/component.xml
Executable file
257
Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/component.xml
Executable file
@ -0,0 +1,257 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<spirit:component xmlns:xilinx="http://www.xilinx.com" xmlns:spirit="http://www.spiritconsortium.org/XMLSchema/SPIRIT/1685-2009" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<spirit:vendor>xilinx.com</spirit:vendor>
|
||||||
|
<spirit:library>user</spirit:library>
|
||||||
|
<spirit:name>KeyboardCtrl</spirit:name>
|
||||||
|
<spirit:version>1.0</spirit:version>
|
||||||
|
<spirit:model>
|
||||||
|
<spirit:views>
|
||||||
|
<spirit:view>
|
||||||
|
<spirit:name>xilinx_verilogsynthesis</spirit:name>
|
||||||
|
<spirit:displayName>Verilog Synthesis</spirit:displayName>
|
||||||
|
<spirit:envIdentifier>verilogSource:vivado.xilinx.com:synthesis</spirit:envIdentifier>
|
||||||
|
<spirit:language>verilog</spirit:language>
|
||||||
|
<spirit:modelName>KeyboardCtrl</spirit:modelName>
|
||||||
|
<spirit:fileSetRef>
|
||||||
|
<spirit:localName>xilinx_verilogsynthesis_view_fileset</spirit:localName>
|
||||||
|
</spirit:fileSetRef>
|
||||||
|
<spirit:parameters>
|
||||||
|
<spirit:parameter>
|
||||||
|
<spirit:name>viewChecksum</spirit:name>
|
||||||
|
<spirit:value>c8a2a715</spirit:value>
|
||||||
|
</spirit:parameter>
|
||||||
|
</spirit:parameters>
|
||||||
|
</spirit:view>
|
||||||
|
<spirit:view>
|
||||||
|
<spirit:name>xilinx_verilogbehavioralsimulation</spirit:name>
|
||||||
|
<spirit:displayName>Verilog Simulation</spirit:displayName>
|
||||||
|
<spirit:envIdentifier>verilogSource:vivado.xilinx.com:simulation</spirit:envIdentifier>
|
||||||
|
<spirit:language>verilog</spirit:language>
|
||||||
|
<spirit:modelName>KeyboardCtrl</spirit:modelName>
|
||||||
|
<spirit:fileSetRef>
|
||||||
|
<spirit:localName>xilinx_verilogbehavioralsimulation_view_fileset</spirit:localName>
|
||||||
|
</spirit:fileSetRef>
|
||||||
|
<spirit:parameters>
|
||||||
|
<spirit:parameter>
|
||||||
|
<spirit:name>viewChecksum</spirit:name>
|
||||||
|
<spirit:value>c8a2a715</spirit:value>
|
||||||
|
</spirit:parameter>
|
||||||
|
</spirit:parameters>
|
||||||
|
</spirit:view>
|
||||||
|
<spirit:view>
|
||||||
|
<spirit:name>xilinx_xpgui</spirit:name>
|
||||||
|
<spirit:displayName>UI Layout</spirit:displayName>
|
||||||
|
<spirit:envIdentifier>:vivado.xilinx.com:xgui.ui</spirit:envIdentifier>
|
||||||
|
<spirit:fileSetRef>
|
||||||
|
<spirit:localName>xilinx_xpgui_view_fileset</spirit:localName>
|
||||||
|
</spirit:fileSetRef>
|
||||||
|
<spirit:parameters>
|
||||||
|
<spirit:parameter>
|
||||||
|
<spirit:name>viewChecksum</spirit:name>
|
||||||
|
<spirit:value>ce6920f7</spirit:value>
|
||||||
|
</spirit:parameter>
|
||||||
|
</spirit:parameters>
|
||||||
|
</spirit:view>
|
||||||
|
</spirit:views>
|
||||||
|
<spirit:ports>
|
||||||
|
<spirit:port>
|
||||||
|
<spirit:name>key_in</spirit:name>
|
||||||
|
<spirit:wire>
|
||||||
|
<spirit:direction>out</spirit:direction>
|
||||||
|
<spirit:vector>
|
||||||
|
<spirit:left spirit:format="long" spirit:resolve="immediate">7</spirit:left>
|
||||||
|
<spirit:right spirit:format="long" spirit:resolve="immediate">0</spirit:right>
|
||||||
|
</spirit:vector>
|
||||||
|
<spirit:wireTypeDefs>
|
||||||
|
<spirit:wireTypeDef>
|
||||||
|
<spirit:typeName>reg</spirit:typeName>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogsynthesis</spirit:viewNameRef>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogbehavioralsimulation</spirit:viewNameRef>
|
||||||
|
</spirit:wireTypeDef>
|
||||||
|
</spirit:wireTypeDefs>
|
||||||
|
</spirit:wire>
|
||||||
|
</spirit:port>
|
||||||
|
<spirit:port>
|
||||||
|
<spirit:name>is_extend</spirit:name>
|
||||||
|
<spirit:wire>
|
||||||
|
<spirit:direction>out</spirit:direction>
|
||||||
|
<spirit:wireTypeDefs>
|
||||||
|
<spirit:wireTypeDef>
|
||||||
|
<spirit:typeName>reg</spirit:typeName>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogsynthesis</spirit:viewNameRef>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogbehavioralsimulation</spirit:viewNameRef>
|
||||||
|
</spirit:wireTypeDef>
|
||||||
|
</spirit:wireTypeDefs>
|
||||||
|
</spirit:wire>
|
||||||
|
</spirit:port>
|
||||||
|
<spirit:port>
|
||||||
|
<spirit:name>is_break</spirit:name>
|
||||||
|
<spirit:wire>
|
||||||
|
<spirit:direction>out</spirit:direction>
|
||||||
|
<spirit:wireTypeDefs>
|
||||||
|
<spirit:wireTypeDef>
|
||||||
|
<spirit:typeName>reg</spirit:typeName>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogsynthesis</spirit:viewNameRef>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogbehavioralsimulation</spirit:viewNameRef>
|
||||||
|
</spirit:wireTypeDef>
|
||||||
|
</spirit:wireTypeDefs>
|
||||||
|
</spirit:wire>
|
||||||
|
</spirit:port>
|
||||||
|
<spirit:port>
|
||||||
|
<spirit:name>valid</spirit:name>
|
||||||
|
<spirit:wire>
|
||||||
|
<spirit:direction>out</spirit:direction>
|
||||||
|
<spirit:wireTypeDefs>
|
||||||
|
<spirit:wireTypeDef>
|
||||||
|
<spirit:typeName>reg</spirit:typeName>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogsynthesis</spirit:viewNameRef>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogbehavioralsimulation</spirit:viewNameRef>
|
||||||
|
</spirit:wireTypeDef>
|
||||||
|
</spirit:wireTypeDefs>
|
||||||
|
</spirit:wire>
|
||||||
|
</spirit:port>
|
||||||
|
<spirit:port>
|
||||||
|
<spirit:name>err</spirit:name>
|
||||||
|
<spirit:wire>
|
||||||
|
<spirit:direction>out</spirit:direction>
|
||||||
|
<spirit:wireTypeDefs>
|
||||||
|
<spirit:wireTypeDef>
|
||||||
|
<spirit:typeName>std_logic</spirit:typeName>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogsynthesis</spirit:viewNameRef>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogbehavioralsimulation</spirit:viewNameRef>
|
||||||
|
</spirit:wireTypeDef>
|
||||||
|
</spirit:wireTypeDefs>
|
||||||
|
</spirit:wire>
|
||||||
|
</spirit:port>
|
||||||
|
<spirit:port>
|
||||||
|
<spirit:name>PS2_DATA</spirit:name>
|
||||||
|
<spirit:wire>
|
||||||
|
<spirit:direction>inout</spirit:direction>
|
||||||
|
<spirit:wireTypeDefs>
|
||||||
|
<spirit:wireTypeDef>
|
||||||
|
<spirit:typeName>std_logic</spirit:typeName>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogsynthesis</spirit:viewNameRef>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogbehavioralsimulation</spirit:viewNameRef>
|
||||||
|
</spirit:wireTypeDef>
|
||||||
|
</spirit:wireTypeDefs>
|
||||||
|
</spirit:wire>
|
||||||
|
</spirit:port>
|
||||||
|
<spirit:port>
|
||||||
|
<spirit:name>PS2_CLK</spirit:name>
|
||||||
|
<spirit:wire>
|
||||||
|
<spirit:direction>inout</spirit:direction>
|
||||||
|
<spirit:wireTypeDefs>
|
||||||
|
<spirit:wireTypeDef>
|
||||||
|
<spirit:typeName>std_logic</spirit:typeName>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogsynthesis</spirit:viewNameRef>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogbehavioralsimulation</spirit:viewNameRef>
|
||||||
|
</spirit:wireTypeDef>
|
||||||
|
</spirit:wireTypeDefs>
|
||||||
|
</spirit:wire>
|
||||||
|
</spirit:port>
|
||||||
|
<spirit:port>
|
||||||
|
<spirit:name>rst</spirit:name>
|
||||||
|
<spirit:wire>
|
||||||
|
<spirit:direction>in</spirit:direction>
|
||||||
|
<spirit:wireTypeDefs>
|
||||||
|
<spirit:wireTypeDef>
|
||||||
|
<spirit:typeName>std_logic</spirit:typeName>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogsynthesis</spirit:viewNameRef>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogbehavioralsimulation</spirit:viewNameRef>
|
||||||
|
</spirit:wireTypeDef>
|
||||||
|
</spirit:wireTypeDefs>
|
||||||
|
</spirit:wire>
|
||||||
|
</spirit:port>
|
||||||
|
<spirit:port>
|
||||||
|
<spirit:name>clk</spirit:name>
|
||||||
|
<spirit:wire>
|
||||||
|
<spirit:direction>in</spirit:direction>
|
||||||
|
<spirit:wireTypeDefs>
|
||||||
|
<spirit:wireTypeDef>
|
||||||
|
<spirit:typeName>std_logic</spirit:typeName>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogsynthesis</spirit:viewNameRef>
|
||||||
|
<spirit:viewNameRef>xilinx_verilogbehavioralsimulation</spirit:viewNameRef>
|
||||||
|
</spirit:wireTypeDef>
|
||||||
|
</spirit:wireTypeDefs>
|
||||||
|
</spirit:wire>
|
||||||
|
</spirit:port>
|
||||||
|
</spirit:ports>
|
||||||
|
<spirit:modelParameters>
|
||||||
|
<spirit:modelParameter xsi:type="spirit:nameValueTypeType" spirit:dataType="integer">
|
||||||
|
<spirit:name>SYSCLK_FREQUENCY_HZ</spirit:name>
|
||||||
|
<spirit:displayName>Sysclk Frequency Hz</spirit:displayName>
|
||||||
|
<spirit:value spirit:format="long" spirit:resolve="generated" spirit:id="MODELPARAM_VALUE.SYSCLK_FREQUENCY_HZ">100000000</spirit:value>
|
||||||
|
</spirit:modelParameter>
|
||||||
|
</spirit:modelParameters>
|
||||||
|
</spirit:model>
|
||||||
|
<spirit:fileSets>
|
||||||
|
<spirit:fileSet>
|
||||||
|
<spirit:name>xilinx_verilogsynthesis_view_fileset</spirit:name>
|
||||||
|
<spirit:file>
|
||||||
|
<spirit:name>src/Ps2Interface.v</spirit:name>
|
||||||
|
<spirit:fileType>verilogSource</spirit:fileType>
|
||||||
|
</spirit:file>
|
||||||
|
<spirit:file>
|
||||||
|
<spirit:name>src/KeyboardCtrl.v</spirit:name>
|
||||||
|
<spirit:fileType>verilogSource</spirit:fileType>
|
||||||
|
<spirit:userFileType>CHECKSUM_36baf34c</spirit:userFileType>
|
||||||
|
</spirit:file>
|
||||||
|
</spirit:fileSet>
|
||||||
|
<spirit:fileSet>
|
||||||
|
<spirit:name>xilinx_verilogbehavioralsimulation_view_fileset</spirit:name>
|
||||||
|
<spirit:file>
|
||||||
|
<spirit:name>src/Ps2Interface.v</spirit:name>
|
||||||
|
<spirit:fileType>verilogSource</spirit:fileType>
|
||||||
|
</spirit:file>
|
||||||
|
<spirit:file>
|
||||||
|
<spirit:name>src/KeyboardCtrl.v</spirit:name>
|
||||||
|
<spirit:fileType>verilogSource</spirit:fileType>
|
||||||
|
</spirit:file>
|
||||||
|
</spirit:fileSet>
|
||||||
|
<spirit:fileSet>
|
||||||
|
<spirit:name>xilinx_xpgui_view_fileset</spirit:name>
|
||||||
|
<spirit:file>
|
||||||
|
<spirit:name>xgui/KeyboardCtrl_v1_0.tcl</spirit:name>
|
||||||
|
<spirit:fileType>tclSource</spirit:fileType>
|
||||||
|
<spirit:userFileType>XGUI_VERSION_2</spirit:userFileType>
|
||||||
|
<spirit:userFileType>CHECKSUM_407cc9d0</spirit:userFileType>
|
||||||
|
</spirit:file>
|
||||||
|
</spirit:fileSet>
|
||||||
|
</spirit:fileSets>
|
||||||
|
<spirit:description>KeyboardCtrl_v1_0</spirit:description>
|
||||||
|
<spirit:parameters>
|
||||||
|
<spirit:parameter>
|
||||||
|
<spirit:name>SYSCLK_FREQUENCY_HZ</spirit:name>
|
||||||
|
<spirit:displayName>Sysclk Frequency Hz</spirit:displayName>
|
||||||
|
<spirit:value spirit:format="long" spirit:resolve="user" spirit:id="PARAM_VALUE.SYSCLK_FREQUENCY_HZ">100000000</spirit:value>
|
||||||
|
</spirit:parameter>
|
||||||
|
<spirit:parameter>
|
||||||
|
<spirit:name>Component_Name</spirit:name>
|
||||||
|
<spirit:value spirit:resolve="user" spirit:id="PARAM_VALUE.Component_Name" spirit:order="1">KeyboardCtrl_v1_0</spirit:value>
|
||||||
|
</spirit:parameter>
|
||||||
|
</spirit:parameters>
|
||||||
|
<spirit:vendorExtensions>
|
||||||
|
<xilinx:coreExtensions>
|
||||||
|
<xilinx:supportedFamilies>
|
||||||
|
<xilinx:family xilinx:lifeCycle="Production">artix7</xilinx:family>
|
||||||
|
</xilinx:supportedFamilies>
|
||||||
|
<xilinx:taxonomies>
|
||||||
|
<xilinx:taxonomy>/UserIP</xilinx:taxonomy>
|
||||||
|
</xilinx:taxonomies>
|
||||||
|
<xilinx:displayName>KeyboardCtrl_v1_0</xilinx:displayName>
|
||||||
|
<xilinx:coreRevision>2</xilinx:coreRevision>
|
||||||
|
<xilinx:coreCreationDateTime>2015-05-31T12:51:28Z</xilinx:coreCreationDateTime>
|
||||||
|
<xilinx:tags>
|
||||||
|
<xilinx:tag xilinx:name="xilinx.com:ip:KeyboardCtrl:1.0_ARCHIVE_LOCATION">C:/Users/bill/Desktop/zedboard/basys3/Basys3_master/Library/Interface/Keyboard-Controller/keyboard_cntr_1.0</xilinx:tag>
|
||||||
|
<xilinx:tag xilinx:name="xilinx.com:user:KeyboardCtrl:1.0_ARCHIVE_LOCATION">C:/Users/bill/Desktop/zedboard/basys3/Basys3_master/Library/Interface/Keyboard-Controller/keyboard_cntr_1.0</xilinx:tag>
|
||||||
|
</xilinx:tags>
|
||||||
|
</xilinx:coreExtensions>
|
||||||
|
<xilinx:packagingInfo>
|
||||||
|
<xilinx:xilinxVersion>2014.4</xilinx:xilinxVersion>
|
||||||
|
<xilinx:checksum xilinx:scope="fileGroups" xilinx:value="8d502939"/>
|
||||||
|
<xilinx:checksum xilinx:scope="ports" xilinx:value="ccdd728c"/>
|
||||||
|
<xilinx:checksum xilinx:scope="hdlParameters" xilinx:value="67486889"/>
|
||||||
|
<xilinx:checksum xilinx:scope="parameters" xilinx:value="815c6f95"/>
|
||||||
|
</xilinx:packagingInfo>
|
||||||
|
</spirit:vendorExtensions>
|
||||||
|
</spirit:component>
|
189
Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/KeyboardCtrl.v
Executable file
189
Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/KeyboardCtrl.v
Executable file
@ -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
|
562
Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/Ps2Interface.v
Executable file
562
Keyboard Sample Code/ip/Keyboard-Controller/keyboard_cntr_1.0/src/Ps2Interface.v
Executable file
@ -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
|
@ -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}
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user