📄 ps2_sie.v
字号:
//////////////////////////////////////////////////////////////////////////////
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
// SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR
// XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION
// AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION
// OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS
// IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
// AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
// FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
// WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
// IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
// REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
// INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE.
//
// (c) Copyright 2004 Xilinx, Inc.
// All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////
// Filename: ps2_sie.v
//
// Description: PS/2 Serial Interface Engine
//
// Host2Device: Host changes data only when clock line is LOW
// Device latches data at Rising edge
// Device2Host: Device changes data only when clock line is high
// Host latches data at falling edge
// Restriction: System Clock (Clk) must be much faster than PS2Clk.
// Typical usage is 1000x of PS2Clk(10kHz~20kHz).
//////////////////////////////////////////////////////////////////////////////
// Structure:
//
//////////////////////////////////////////////////////////////////////////////
//
// History:
// wph 10/10/01
//
//////////////////////////////////////////////////////////////////////////////
// Naming Conventions:
// active low signals: "*_n"
// clock signals: "clk", "clk_div#", "clk_#x"
// Rst signals: "rst", "rst_n"
// generics: "C_*"
// user defined types: "*_TYPE"
// state machine next state: "*_ns"
// state machine current state: "*_cs"
// combinatorial signals: "*_com"
// pipelined or register delay signals: "*_d#"
// counter signals: "*cnt*"
// clock enable signals: "*_ce"
// internal version of output port "*_i"
// device pins: "*_pin"
// ports: - Names begin with Uppercase
// processes: "*_PROCESS"
// component instantiations: "<ENTITY_>I_<#|FUNC>
//////////////////////////////////////////////////////////////////////////////
module ps2_sie(
//global signal
Clk, // I system clock
Rst, // I system reset + software reset (offset)
//PS2 interface signal
Clkin, // I PS2 Bi-di Clock in
Clkpd, // O PS2 Bi-di Clock Pull down
Rx, // I PS2 Bi-di serial data in
Txpd, // O PS2 Bi-di serial data out pull down
//interface signal for memory mapped registers
rx_full_sta, // I
rx_full_set, // O
rx_err_set, // O
rx_ovf_set, // O
tx_full_sta, // I
tx_full_clr, // O
tx_ack_set, // O
tx_noack_set, // O
wdt_tout_set, // O
tx_data, // I
rx_data // O
);
///////////////////////////////////////////////////////////////////////////////
// Port Declarations
//////////////////////////////////////////////////////////////////////////////
//global signal
input Clk; // I system clock
input Rst; // I system reset + software reset (offset)
//PS2 interface signal
input Clkin; // I PS2 Bi-di Clock in
output Clkpd; // O PS2 Bi-di Clock Pull down
input Rx; // I PS2 Bi-di serial data in
output Txpd; // O PS2 Bi-di serial data out pull down
//interface signal for memory mapped registers
input rx_full_sta; // I
output rx_full_set; // O
output rx_err_set; // O
output rx_ovf_set; // O
input tx_full_sta; // I
output tx_full_clr; // O
output tx_ack_set; // O
output tx_noack_set; // O
output wdt_tout_set; // O
input [0:7] tx_data; // I
output [0:7] rx_data; // O
///////////////////////////////////////////////////////////////////////////////
// Parameter Declarations
///////////////////////////////////////////////////////////////////////////////
// Tuning Timer Value
//REAL
parameter BIT_WDT_TMR_VALUE = 40000; // 400 us
parameter BIT_WDT_TMR_BITS = 15;
parameter DBC_TMR_VALUE = 370; // 3.7us
parameter DBC_TMR_BITS = 9;
parameter REQ_SND_VALUE = 10000; //at least 100us
parameter REQ_SND_BITS = 15;
//testmode
//parameter BIT_WDT_TMR_VALUE = 400; // 400 us
//parameter BIT_WDT_TMR_BITS = 15;
//parameter DBC_TMR_VALUE = 10; // 3.7us
//parameter DBC_TMR_BITS = 9;
//parameter REQ_SND_VALUE = 100; //at least 100us
//parameter REQ_SND_BITS = 15;
///////////////////////////////////////////////////////////////////////////////
// Signal Declarations
///////////////////////////////////////////////////////////////////////////////
reg clkin_1, clkin_2;
reg rx_1, rx_2;
reg [0:10] q;
reg [0:4] rx_bit_count;
wire bit_err1;
wire rx_err_set;
wire [0:7] rx_data;
wire rx_full_set;
wire rx_ovf_set;
reg rx_full_sta_dly;
reg Txpd;
reg txpd_i;
reg Clkpd;
wire tx_ack_set;
wire tx_noack_set;
wire tx_full_clr;
wire dbc_done;
wire bit_wdt_done;
wire wdt_tout_set;
wire rts_cnt_done;
reg [0: DBC_TMR_BITS - 1] dbc_counter;
reg [0: BIT_WDT_TMR_BITS - 1] bit_wdt_counter;
reg [0: REQ_SND_BITS - 1] rts_counter;
reg tx_ack_set_temp ;
reg tx_noack_set_temp ;
reg tx_full_clr_temp ;
///////////////////////////////////////////////////////////////////////////////
// Sate Machine Declarations
///////////////////////////////////////////////////////////////////////////////
parameter DETECT_CLK_HIGH = 6'b000001;//5
parameter DETECT_CLK_FALL = 6'b000010;//4
parameter DETECT_CLK_FDBC = 6'b000100;//3
parameter DETECT_CLK_LOW = 6'b001000;//2
parameter DETECT_CLK_RISE = 6'b010000;//1
parameter DETECT_CLK_RDBC = 6'b100000;//0
reg [0:5] detect_clk_cs, detect_clk_ns;
wire clk_fall, clk_rise;
assign clk_fall = detect_clk_cs[4];
assign clk_rise = detect_clk_cs[1];
parameter RX_CTL_IDLE = 6'b000001; //5
parameter RX_CTL_STARTCNT = 6'b000010; //4
parameter RX_CTL_GETB1 = 6'b000100; //3
parameter RX_CTL_CHECKB1 = 6'b001000; //2
parameter RX_CTL_ERR1 = 6'b010000; //1
parameter RX_CTL_USEB1 = 6'b100000; //0
reg [0:5] rx_ctl_cs, rx_ctl_ns;
wire rx_sta_idle, rx_sta_startcnt, rx_sta_err1, rx_sta_useb1;
assign rx_sta_idle = rx_ctl_cs[5];
assign rx_sta_startcnt = rx_ctl_cs[4];
assign rx_sta_err1 = rx_ctl_cs[1];
assign rx_sta_useb1 = rx_ctl_cs[0];
parameter TX_CTL_IDLE = 16'b0000000000000001; //15
parameter TX_CTL_WAIT = 16'b0000000000000010; //14
parameter TX_CTL_CLKPD = 16'b0000000000000100; //13
parameter TX_CTL_DATAPD = 16'b0000000000001000; //12
parameter TX_CTL_SND7 = 16'b0000000000010000; //11
parameter TX_CTL_SND6 = 16'b0000000000100000; //10
parameter TX_CTL_SND5 = 16'b0000000001000000; //9
parameter TX_CTL_SND4 = 16'b0000000010000000; //8
parameter TX_CTL_SND3 = 16'b0000000100000000; //7
parameter TX_CTL_SND2 = 16'b0000001000000000; //6
parameter TX_CTL_SND1 = 16'b0000010000000000; //5
parameter TX_CTL_SND0 = 16'b0000100000000000; //4
parameter TX_CTL_PRTY = 16'b0001000000000000; //3
parameter TX_CTL_STOP = 16'b0010000000000000; //2
parameter TX_CTL_WAITFEDGE = 16'b0100000000000000; //1
parameter TX_CTL_CHKACK = 16'b1000000000000000; //0
reg [0:15] tx_ctl_cs, tx_ctl_ns;
wire tx_sta_idle,tx_busy,tx_sta_clkpd,tx_sta_datapd,
tx_sta_chkack, tx_sta_waitfedge, tx_sta_clkpd_next, tx_sta_idle_next;
wire tx_sta_wait;
assign tx_sta_wait = tx_ctl_cs[14];
assign tx_sta_idle = tx_ctl_cs[15];
assign tx_sta_idle_next = tx_ctl_ns[15];
assign tx_busy = (~ tx_ctl_cs[15]) && (~ tx_ctl_cs[14]);
assign tx_sta_clkpd = tx_ctl_cs[13];
assign tx_sta_clkpd_next = tx_ctl_ns[13];
assign tx_sta_datapd = tx_ctl_cs[12];
assign tx_sta_waitfedge = tx_ctl_cs[1];
assign tx_sta_chkack = tx_ctl_cs[0];
///////////////////////////////////////////////////////////////////////////////
//begin
///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------
//Receiving serial rx and Clkin,reisters to avoid metastability
//-----------------------------------------------------------------
always @(posedge Clk)
begin
if (Rst)
begin
clkin_1 <= 1'b1;
clkin_2 <= 1'b1;
rx_1 <= 1'b1;
rx_2 <= 1'b1;
end
else
begin
clkin_1 <= Clkin;
clkin_2 <= clkin_1 ;
rx_1 <= Rx;
rx_2 <= rx_1;
end
end
//-----------------------------------------------------------------
// This State machine - Detect Clock basically detects
// the clock edges and wait for debouncing done.
//-----------------------------------------------------------------
always @(posedge Clk)
begin
if (Rst) detect_clk_cs <= DETECT_CLK_HIGH;
else detect_clk_cs <= detect_clk_ns;
end
always @(detect_clk_cs or
clkin_2 or
dbc_done )
begin
case (detect_clk_cs)
DETECT_CLK_HIGH: begin
if (~ clkin_2) detect_clk_ns <= DETECT_CLK_FALL;
else detect_clk_ns <= DETECT_CLK_HIGH;
end
DETECT_CLK_FALL: detect_clk_ns <= DETECT_CLK_FDBC;
DETECT_CLK_FDBC: begin
if (dbc_done) detect_clk_ns <= DETECT_CLK_LOW;
else detect_clk_ns <= DETECT_CLK_FDBC;
end
DETECT_CLK_LOW: begin
if (clkin_2) detect_clk_ns <= DETECT_CLK_RISE;
else detect_clk_ns <= DETECT_CLK_LOW;
end
DETECT_CLK_RISE: detect_clk_ns <= DETECT_CLK_RDBC;
DETECT_CLK_RDBC: begin
if (dbc_done) detect_clk_ns <= DETECT_CLK_HIGH;
else detect_clk_ns <= DETECT_CLK_RDBC;
end
default : detect_clk_ns <= DETECT_CLK_HIGH;
endcase
end
//-----------------------------------------------------------------
//This statemachine performs RX flow control.
//-----------------------------------------------------------------
//If Host is transmitting command (tx_busy),
//RX statemachine has to be forced to be WAIT status.
always @(posedge Clk)
begin
if (Rst || tx_busy || bit_wdt_done || tx_sta_clkpd_next)
rx_ctl_cs <= RX_CTL_IDLE;
else rx_ctl_cs <= rx_ctl_ns ;
end
always @(rx_ctl_cs or
clk_fall or
tx_sta_idle or
rx_bit_count or
bit_err1 )
begin
case (rx_ctl_cs)
RX_CTL_IDLE: begin
if (clk_fall && tx_sta_idle) rx_ctl_ns <= RX_CTL_STARTCNT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -