123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- /*
- * Reads PS/2 keyboard keycodes sends interrupt when one is received for one tick
- * Code is practically copied from "https://embeddedthoughts.com/2016/07/05/fpga-keyboard-interface/"
- */
- module Keyboard
- (
- input wire clk, reset,
- input wire ps2d, ps2c, // ps2 data and clock inputs
- output reg rx_done_tick, // ps2 receive done tick
- output wire [7:0] rx_data // data received
- );
- // FSMD state declaration
- localparam
- idle = 1'b0,
- rx = 1'b1;
-
- // internal signal declaration
- reg state_reg, state_next; // FSMD state register
- reg [7:0] filter_reg; // shift register filter for ps2c
- wire [7:0] filter_next; // next state value of ps2c filter register
- reg f_val_reg; // reg for ps2c filter value, either 1 or 0
- wire f_val_next; // next state for ps2c filter value
- reg [3:0] n_reg, n_next; // register to keep track of bit number
- reg [10:0] d_reg, d_next; // register to shift in rx data
- wire neg_edge; // negative edge of ps2c clock filter value
- // register for ps2c filter register and filter value
- always @(posedge clk)
- if (reset)
- begin
- filter_reg <= 8'd0;
- f_val_reg <= 1'b0;
- end
- else
- begin
- filter_reg <= filter_next;
- f_val_reg <= f_val_next;
- end
- // next state value of ps2c filter: right shift in current ps2c value to register
- assign filter_next = {ps2c, filter_reg[7:1]};
- // filter value next state, 1 if all bits are 1, 0 if all bits are 0, else no change
- assign f_val_next = (filter_reg == 8'b11111111) ? 1'b1 :
- (filter_reg == 8'b00000000) ? 1'b0 :
- f_val_reg;
- // negative edge of filter value: if current value is 1, and next state value is 0
- assign neg_edge = f_val_reg & ~f_val_next;
- // FSMD state, bit number, and data registers
- always @(posedge clk)
- if (reset)
- begin
- state_reg <= idle;
- n_reg <= 4'd0;
- d_reg <= 11'd0;
- end
- else
- begin
- state_reg <= state_next;
- n_reg <= n_next;
- d_reg <= d_next;
- end
- // FSMD next state logic
- always @*
- begin
-
- // defaults
- state_next = state_reg;
- rx_done_tick = 1'b0;
- n_next = n_reg;
- d_next = d_reg;
-
- case (state_reg)
-
- idle:
- if (neg_edge) // start bit received
- begin
- n_next = 4'b1010; // set bit count down to 10
- state_next = rx; // go to rx state
- end
-
- rx: // shift in 8 data, 1 parity, and 1 stop bit
- begin
- if (neg_edge) // if ps2c negative edge...
- begin
- d_next = {ps2d, d_reg[10:1]}; // sample ps2d, right shift into data register
- n_next = n_reg - 1'b1; // decrement bit count
- end
-
- if (n_reg == 4'd0) // after 10 bits shifted in, go to done state
- begin
- rx_done_tick = 1'b1; // assert dat received done tick
- state_next = idle; // go back to idle
- end
- end
- endcase
- end
-
- assign rx_data = d_reg[8:1]; // output data bits
- endmodule
|