⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps2_driver.v

📁 ps2_driver.经常见的PS/2接口的驱动程序
💻 V
📖 第 1 页 / 共 2 页
字号:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//公司:
//工程师: 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 + -