📄 ps2_driver.v
字号:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//公司:
//工程师: Lawson
//
//创建日期: 2004年10月10日
//设计名字:
//模块名字: PS2驱动器 Driver
//目标装置:
//工具版本: Xilinx ISE 6.3.02i
//描述:
// 按照PS2协议,驱动PS2设备并给出错误信号
//属性:
//
//修改:
//
//附加说明:
//
//
// 读时序状态图:
//
// CLK:
//______| ̄ ̄ ̄ ̄ ̄ ̄|____________________| ̄ ̄ ̄ ̄ ̄ ̄|____________________| ̄ ̄ ̄ ̄ ̄ ̄|_____…………………………______| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
//
// 延时时钟信号
// key_clk:
//_______| ̄ ̄ ̄ ̄ ̄ ̄|____________________| ̄ ̄ ̄ ̄ ̄ ̄|____________________| ̄ ̄ ̄ ̄ ̄ ̄|_____…………………………______| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
// 状态: Idle | Read_start | Read_start_complete| Read_data |
Read_data_complete | Read_data ←→ Read_data_complete |
Read_finish | Idle
//
// bit_0 bit_1 - bit_7,P_bit,stop_bit
// DATA:
// ̄ ̄ ̄ ̄ ̄ ̄ ̄|________________________________|〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓|〓〓〓〓………………………… ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
// ↑ ↑ ↑
// 操作: 数据读入 counter_reg加一 数据读入
//
//
// 写时序状态图:
// 延时100uS
// CLK:
//_____________________| ̄ ̄ ̄ ̄ ̄ ̄ ̄|___________________| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|______………………………………… ̄ ̄ ̄|_______________| ̄ ̄ ̄ ̄ ̄ ̄ ̄|_______________| ̄ ̄ ̄ ̄ ̄
//
// 状态: Idle | Inhibit_com || Write_start | Write_data |
//Write_data_complete | Write_data ←→ Write_data_complete | Write_stop |
// Read_ACK | Write_finish | Idle
// ↑
// Inhibit_com_complete
// bit_0 bit_1 - bit_7,P_bit stop_bit
// DATA:
// ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|________________|〓〓〓〓〓〓〓〓〓〓|〓〓〓〓〓〓〓〓〓〓〓〓〓…………………………………〓〓〓〓| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|______________________| ̄ ̄ ̄
// ↑ ↑ ↑ ↑ ↑
// 操作: 释放时钟线 写数据 写数据 释放数据线
//读ACK
// 下拉数据线 counter_reg加一
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
`timescale 1 ns / 1 ns
module PS2_Driver (
//bidirectional
ps2_data, //ps2设备数据端
ps2_clk, //ps2设备时钟端
//input
w_data, //驱动器数据输入端
ena, //驱动器使能端
rw, //驱动器读写控制端(1:读,0:写)
drv_clk, //驱动器时钟端
clr_n, //驱动器复位端
//output
r_data, //驱动器数据输出端
ready, //驱动器完成信号
error //驱动器错误代码输出端
);
//+--------------------------- 参数设置-----------------------------------+
parameter DATA_WIDTH = 8; //输入/输出数据宽度
parameter COUNT = 4; //状态码宽度
parameter TIME = 8'd100; //抑制通信时间
//+-----------------------------------------------------------------------+
inout ps2_data /* synthesis xc_padtype = "IOBUF_LVTTL_F_24" */;
inout ps2_clk /* synthesis xc_padtype = "IOBUF_LVTTL_F_24" */;
input [DATA_WIDTH-1:0] w_data;
input rw;
input ena;
input clr_n;
input drv_clk;
output [DATA_WIDTH-1:0] r_data;
output ready;
output [1:0] error;
//+-------------------------------PS2状态代码------------------------------+
parameter Idle = 4'h0; //初始化
parameter Read_start = 4'h1; //读开始位
parameter Read_start_complete = 4'h2; //完成读开始位
parameter Read_data = 4'h3; //读数据
parameter Read_data_complete = 4'h4; //完成读数据
parameter Read_finish = 4'h5; //完成读操作
parameter Inhibit_com = 4'h6; //抑制通讯
parameter Inhibit_com_complete = 4'h7; //完成抑制通讯
parameter Write_start = 4'h8; //写开始位
parameter Write_data = 4'h9; //写数据
parameter Write_data_complete = 4'hA; //完成写数据
parameter Write_stop = 4'hB; //写停止位
parameter Read_ACK = 4'hC; //读应答位
parameter Write_finish = 4'hD; //完成写操作
//+-----------------------------KeyBoard 错误代码--------------------------+
parameter PARITY_ERROR = 2'h1; //效验错误
parameter NO_ACK = 2'h2; //无应答错误
//+------------------------------------------------------------------------+
reg [COUNT-1:0] current_state;
reg [COUNT-1:0] next_state;
reg [DATA_WIDTH:0] r_data_reg; // | 8 | 7-0 |
// 效验位 数据位
// | P | DATA |
reg [DATA_WIDTH:0] w_data_reg; // | 8 | 7-0 |
// 效验位 数据位
// | P | DATA |
reg clk_w;
reg data_w;
reg key_reg;
reg ready;
reg [9:0] clk_sampling_reg;
reg [2:0] data_sampling_reg;
reg [1:0] error;
reg [DATA_WIDTH-1:0] counter_reg;
wire key_data;
wire k_data;
wire key_clk;
wire k_clk;
wire clr_n;
wire write_parity;
wire read_parity;
//------------------------------------------------------------------------------//
// //
// 接口逻辑函数 //
// //
//------------------------------------------------------------------------------//
assign r_data = r_data_reg [7:0];
assign write_parity = ^~w_data;
assign read_parity = ^~r_data_reg [7:0];
//对延时4个时钟,延时7个时钟,延时10个时钟后的ps2_clk信号进行取样
assign key_clk = (clk_sampling_reg[3]&clk_sampling_reg[6])|
(clk_sampling_reg[6]&clk_sampling_reg[9])|(clk_sampling_reg[3]&clk_sampling_reg[9]);
assign key_data = (data_sampling_reg[0]&data_sampling_reg[1])|
(data_sampling_reg[1]&data_sampling_reg[2])|(data_sampling_reg[2]&data_sampling_reg[0]);
//ps2_data双向IO口
assign ps2_data = data_w ? 1'bz : key_reg; // 1:输入 0:输出
assign k_data = ps2_data;
//ps2_data双向IO口
assign ps2_clk = clk_w ? 1'bz : 1'b0;
assign k_clk = ps2_clk;
//------------------------------------------------------------------------------//
// //
// 采样输入 //
// //
//------------------------------------------------------------------------------//
always @ (posedge drv_clk or negedge clr_n)
if (!clr_n) clk_sampling_reg <= 0;
else clk_sampling_reg <= {clk_sampling_reg[8:0],k_clk};
always @ (posedge drv_clk or negedge clr_n)
if (!clr_n) data_sampling_reg <= 0;
else data_sampling_reg <= {data_sampling_reg[1:0],k_data};
//------------------------------------------------------------------------------//
// //
// PS2驱动器状态机 //
// //
//------------------------------------------------------------------------------//
always @(posedge drv_clk or negedge clr_n)
if (!clr_n) begin
current_state <= Idle;
end
else begin
current_state <= next_state;
end
always @(current_state or ena or rw or k_clk or k_data or key_clk or
key_data or counter_reg)
case(current_state)
Idle: begin
if(ena) begin
if(rw) begin
next_state = Read_start;
end
else next_state = Inhibit_com;
end
else begin
next_state = Idle;
end
end
//---------------------------------PS2驱动器读状态-------------------------------//
Read_start: begin
if( key_clk == 0 && key_data == 0) begin
next_state = Read_start_complete;
end
else next_state = Read_start;
end
Read_start_complete: begin
if( key_clk == 1) begin
next_state = Read_data;
end
else next_state = Read_start_complete;
end
Read_data: begin //读数据和效验位
if( key_clk == 0 ) begin
next_state = Read_data_complete;
end
else next_state = Read_data;
end
Read_data_complete: begin
if( key_clk == 1 ) begin
if( counter_reg == 8'd9) begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -