📄 keyboard_test1.v
字号:
////////////////////////////////////////////////////////////////////////////////
//公司: <Company Name>
//工程师: Lawson_jian
//
//创建日期: 2004年12月10日
//设计名字:
//模块名字: 键盘驱动器 KeyBoard Divider
//目标装置:
//工具版本: <tool_versions>
//描述:
//
//属性:
// <Dependencies here>
//修改:
// <Code_revision_information>
//附加说明:
// <Additional_comments>
////////////////////////////////////////////////////////////////////////////////
`timescale 1 ns / 1 ns
module keyboard_test1 (
PS2K_DATA,
PS2K_CLK,
R_DATA,
W_DATA,
BUSY,
Complete,
Error,
RW,
ENA,
CLK,
CLR
);
//+---------------------------KeyBoard 状态设置---------------------------+
parameter Data_Width = 8; //输入/输出数据宽度
parameter Count = 5; //状态码宽度
//+-----------------------------------------------------------------------+
inout PS2K_DATA;
inout PS2K_CLK;
input [Data_Width-1:0] W_DATA;
input RW;
input ENA;
input CLR; // synthesis attribute clock_buffer of CLR is ibufg;
input CLK;
output [Data_Width-1:0] R_DATA;
output BUSY;
output Complete;
output [1:0] Error;
//+---------------------------频率发生器状态代码-------------------------+
parameter Add_CounteState = 0;
parameter Dec_CounteState = 1;
//+---------------------------KeyBoard 读状态代码-------------------------+
parameter Read_start = 4'h0;
parameter Read_start_complete = 4'h1;
parameter Read_data = 4'h2;
parameter Read_data_complete = 4'h3;
parameter Read_parity = 4'h4;
parameter Read_parity_complete = 4'h5;
parameter Read_stop = 4'h6;
parameter Read_finish = 4'h7;
//+---------------------------KeyBoard 写状态代码--------------------------+
parameter Write_start = 4'h0;
parameter Restrain_read = 4'h1;
parameter Write_data = 4'h2;
parameter Write_data_complete = 4'h3;
parameter Write_parity = 4'h4;
parameter Write_parity_complete = 4'h5;
parameter Write_stop = 4'h6;
parameter Write_stop_complete = 4'h7;
parameter Write_ACK = 4'h8;
parameter Write_finish = 4'h9;
//+-----------------------------KeyBoard 错误代码--------------------------+
parameter No_R_stop_signal = 4'h1;
parameter Checkout_error = 4'h2;
parameter No_ACK_signal = 4'h3;
//+------------------------------------------------------------------------+
reg [3:0] W_State;
reg [3:0] R_State;
reg [Data_Width-1:0] R_DATA;
reg [Data_Width-1:0] W_Reg;
reg CLK_W;
reg DATA_W;
reg K_DATA;
reg BUSY;
reg Complete;
reg P_Reg;
reg [7:0] Counter;
reg [1:0] Error;
reg [Data_Width-1:0] Counter_reg; //计数器寄存器
reg CounteState; //计数器状态寄存器
reg Pulse_Out_reg; //脉冲发生寄存器
wire [Data_Width-1:0] Half_Frequency_Data;
wire [Data_Width-1:0] Frequency_Data;
wire us_CLK;
wire P;
//----------------------------------------------------------------------------//
// //
// 接口逻辑函数 //
// //
//----------------------------------------------------------------------------//
assign Frequency_Data = 8'd100; //频率数据
assign us_CLK = Pulse_Out_reg;
assign Half_Frequency_Data = Frequency_Data/2;
assign PS2K_DATA = DATA_W ? 1'bz : K_DATA;
assign PS2K_CLK = CLK_W ? 1'bz : 0;
assign P = RW ? ^~R_DATA : ^~W_Reg;
//----------------------------------------------------------------------------//
// //
// 1ms脉冲发生器 //
// //
//----------------------------------------------------------------------------//
always @(posedge CLK or negedge CLR)
begin
if (!CLR) //复位
begin
Counter_reg = 1;
CounteState = Add_CounteState;
Pulse_Out_reg = 0;
end
else begin
Counter_reg = Counter_reg + 1;
case (CounteState)
Add_CounteState : //增量计数状态
begin
if(Counter_reg == Half_Frequency_Data) //Half_Frequency_Data = Frequency_Reg/2 产生半个时钟脉冲
begin
CounteState = Dec_CounteState;
Pulse_Out_reg = 1;
end
end
Dec_CounteState : //减量计数状态
begin
if(Counter_reg == Frequency_Data) //产生完整时钟脉冲
begin
Counter_reg = 1;
CounteState = Add_CounteState;
Pulse_Out_reg = 0;
end
end
endcase
end
end
//----------------------------------------------------------------------------//
// //
// KeyBoard Read or Wrie //
// //
//----------------------------------------------------------------------------//
always @( posedge us_CLK or negedge CLR)
if (!CLR) begin
R_DATA = 0;
W_Reg = 0;
CLK_W = 1;
DATA_W = 1;
K_DATA = 0;
BUSY = 0;
Complete = 0;
Counter = 0;
P_Reg = 0;
Error = 0;
Counter = 0;
W_State = Write_start;
R_State = Read_start;
end
else if (ENA) begin
if(RW) begin
case (R_State)
Read_start: begin
CLK_W = 1;
DATA_W = 1;
Error = 0;
Complete = 0;
if( PS2K_CLK == 0 && PS2K_DATA == 0) begin
BUSY = 1;
R_State = Read_start_complete;
end
else begin
R_State = Read_start;
end
end
Read_start_complete: begin
if( PS2K_CLK == 1) begin
Counter = 8'd0;
R_State = Read_data;
end
else R_State = Read_start_complete;
end
Read_data: begin
if( PS2K_CLK == 0 ) begin
R_DATA[Counter] = PS2K_DATA;
Counter = Counter + 1;
R_State = Read_data_complete;
$display("read R_DATA[%d] BIT is %b",Counter,PS2K_DATA);
end
else R_State = Read_data;
end
Read_data_complete: begin
if( PS2K_CLK == 1 ) begin
if( Counter == 8'd8) begin
R_State = Read_parity;
end
else begin
R_State = Read_data;
end
end
else R_State = Read_data_complete;
end
Read_parity: begin
if( PS2K_CLK == 0 ) begin
P_Reg = PS2K_DATA;
R_State = Read_parity_complete;
$display("read PS2K parity bit ");
end
else R_State = Read_parity;
end
Read_parity_complete: begin
if( PS2K_CLK == 1 ) begin
R_State = Read_stop;
end
else R_State = Read_parity_complete;
end
Read_stop: begin
if( PS2K_CLK == 0) begin
if(PS2K_DATA == 1) begin
$display("PS2K_DATA STOP ");
R_State = Read_finish;
end
else begin
Error = No_R_stop_signal;
R_State = Read_finish;
end
end
else R_State = Read_stop;
end
Read_finish: begin
if( PS2K_CLK == 1) begin
BUSY = 0;
Complete = 1;
$display("PS2K parity bit is %b",P_Reg);
if( P == P_Reg ) begin
$display("PS2K parity bit is right");
$display("Complete read R_DATA is %b",R_DATA);
R_State = Read_start;
end
else begin
$display("PS2K parity bit is error");
Error = Checkout_error;
R_State = Read_start;
end
end
else R_State = Read_finish;
end
default: begin
R_State = Read_start;
end
endcase
end
else begin
case (W_State)
Write_start: begin
CLK_W = 0;
DATA_W = 0;
W_Reg = W_DATA;
K_DATA = 1;
Counter = 0;
BUSY = 1;
Complete = 0;
Error = 0;
W_State = Restrain_read;
end
Restrain_read: begin
if(Counter == 8'd100) begin //抑制键盘通讯400μS
K_DATA = 0;
Counter = 0;
CLK_W = 1;
$display("Complete Restrain Read ");
W_State = Write_data;
end
else begin
Counter = Counter + 1;
W_State = Restrain_read;
end
end
Write_data: begin
if( PS2K_CLK == 0 ) begin
K_DATA = W_Reg [Counter];
Counter = Counter + 1;
$display("write W_DATA[%d] BIT is %b",Counter,W_DATA[Counter]);
W_State = Write_data_complete;
end
else W_State = Write_data;
end
Write_data_complete: begin
if( PS2K_CLK == 1 ) begin
if( Counter == 8'd8) W_State = Write_parity;
else W_State = Write_data;
end
else W_State = Write_data_complete;
end
Write_parity: begin
if( PS2K_CLK == 0 ) begin
K_DATA = P;
$display("write Parity Bit is %b",P);
W_State = Write_parity_complete;
end
else W_State = Write_parity;
end
Write_parity_complete: begin
if( PS2K_CLK == 1 ) begin
W_State = Write_stop;
end
else W_State = Write_parity_complete;
end
Write_stop: begin
if( PS2K_CLK == 0 ) begin
$display("Write stop ");
K_DATA = 1;
W_State = Write_stop_complete;
end
else W_State = Write_stop;
end
Write_stop_complete: begin
if( PS2K_CLK == 1 ) begin
DATA_W = 1;
W_State = Write_ACK;
end
else W_State = Write_stop_complete;
end
Write_ACK: begin
if( PS2K_CLK == 0) begin
if( PS2K_DATA == 0) begin
$display("PS2K_DATA ACK ");
W_State = Write_finish;
end
else begin
$display("PS2K_DATA NO ACK ");
Error = No_ACK_signal;
W_State = Write_finish;
end
end
else begin
W_State = Write_ACK;
end
end
Write_finish: begin
if( PS2K_DATA == 1 && PS2K_CLK == 1 ) begin
$display("Complete write PS2K DATA");
BUSY = 0;
Complete = 1;
W_State = Write_start;
end
else begin
W_State = Write_finish;
end
end
default: begin
W_State = Write_start;
end
endcase
end
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -