4 * Generic PS2 interface module
6 * istrobe, oreq, oack and timeout are all 1-clk strobes,
7 * ibyte must be latched on that strobe, obyte is latched
8 * as oreq is detected, oreq is ignore while already
11 * we ignore bad parity on input for now
14 module ps2(input sysclk,
47 localparam ps2_state_idle = 0;
48 localparam ps2_state_ring = 1;
49 localparam ps2_state_send = 2;
50 localparam ps2_state_recv = 3;
52 always@(posedge sysclk or posedge reset) begin
54 state <= ps2_state_idle;
57 state <= ps2_state_idle;
62 state <= ps2_state_ring;
64 state <= ps2_state_recv;
68 state <= ps2_state_send;
72 state <= ps2_state_idle;
76 state <= ps2_state_ring;
78 state <= ps2_state_idle;
83 assign dbg_state = state;
85 /* Tristate control of clk & data */
86 assign datout = state == ps2_state_ring || state == ps2_state_send;
87 assign ps2dat = (datout & ~shiftreg[0]) ? 1'b0 : 1'bz;
88 assign ps2clk = (state == ps2_state_ring) ? 1'b0 : 1'bz;
91 always@(posedge sysclk or posedge reset) begin
95 if (state == ps2_state_idle)
97 else if (state == ps2_state_ring)
99 else if (clkdown && state != ps2_state_ring)
100 shiftcnt <= shiftcnt - 1;
104 /* Shift register, ticks on falling edge of ps2 clock */
105 always@(posedge sysclk or posedge reset) begin
110 shiftreg <= { 1'b1, opar, obyte, 1'b0 };
111 else if (clkdown && state != ps2_state_ring)
112 shiftreg <= { datsync, shiftreg[10:1] };
117 /* Ack/strobe logic */
118 assign shiftend = shiftcnt == 0;
119 assign oack = (state == ps2_state_send && shiftend);
120 assign istrobe = (state == ps2_state_recv && shiftend);
121 assign ibyte = shiftreg[8:1];
123 /* Filters/synchronizers on PS/2 clock */
124 always@(posedge sysclk or posedge reset) begin
131 clkbuf <= { clkbuf[6:0], ps2clk };
132 if (clkbuf[7:2] == 6'b000000)
134 if (clkbuf[7:2] == 6'b111111)
138 assign clkdown = clkprev & ~clksync;
140 /* Filters/synchronizers on PS/2 data */
141 always@(posedge sysclk or posedge reset) begin
146 datbuf <= { datbuf[6:0], ps2dat };
147 if (datbuf[7:2] == 6'b000000)
149 if (datbuf[7:2] == 6'b111111)
154 /* Parity for output byte */
155 assign opar = ~(obyte[0] ^ obyte[1] ^ obyte[2] ^ obyte[3] ^
156 obyte[4] ^ obyte[5] ^ obyte[6] ^ obyte[7]);
159 always@(posedge sysclk or posedge reset) begin
166 timecnt <= timecnt + 1;
169 assign timeout = (timecnt == 24'hff_ffff);