Skip to content
Snippets Groups Projects
Commit c9f9529c authored by Fang Lu's avatar Fang Lu
Browse files

input - PS/2 communication protocol

TODO:
* Decode protocol
* Fix bit ordering
parent da4d5e9e
No related branches found
No related tags found
No related merge requests found
*.pdf *.pdf
db/
incremental_db/
output_files/
simulation/
*.qws
*.qarlog
*.bak
module hexdriver (
input logic [3:0] In,
output logic [6:0] Out
);
always_comb begin
unique case (In)
4'b0000 : Out = 7'b1000000; // '0'
4'b0001 : Out = 7'b1111001; // '1'
4'b0010 : Out = 7'b0100100; // '2'
4'b0011 : Out = 7'b0110000; // '3'
4'b0100 : Out = 7'b0011001; // '4'
4'b0101 : Out = 7'b0010010; // '5'
4'b0110 : Out = 7'b0000010; // '6'
4'b0111 : Out = 7'b1111000; // '7'
4'b1000 : Out = 7'b0000000; // '8'
4'b1001 : Out = 7'b0010000; // '9'
4'b1010 : Out = 7'b0001000; // 'A'
4'b1011 : Out = 7'b0000011; // 'b'
4'b1100 : Out = 7'b1000110; // 'C'
4'b1101 : Out = 7'b0100001; // 'd'
4'b1110 : Out = 7'b0000110; // 'E'
4'b1111 : Out = 7'b0001110; // 'F'
default : Out = 7'bX;
endcase
end
endmodule
/**
* ps2
*
* PS2 Keyboard driver (Avalon slave)
*
* 16 addresses are allocated for this module. The first 8 bits contain
* keydown events and the latter 8 bits contain keyup events.
* A non-zero value denotes that the event has been triggered with the keycode
* value as indicated.
* After retrieving the event, the software should zero the address so that the
* hardware can reuse the location. Otherwise the hardware will not be able to
* sent new events.
*
* ```
* volatile uint32_t *kbdr = BASE;
* kbdr[0-7]: Keydown events
* kbdr[8-15]: Keyup events
* ```
*
*/
module ps2 (
// Avalon Clock Input
input logic CLK,
// Avalon Reset Input
input logic RESET,
// Avalon-MM Slave Signals
input logic AVL_READ, // Avalon-MM Read
input logic AVL_WRITE, // Avalon-MM Write
input logic AVL_CS, // Avalon-MM Chip Select
input logic [3:0] AVL_BYTE_EN, // Avalon-MM Byte Enable
input logic [3:0] AVL_ADDR, // Avalon-MM Address
input logic [31:0] AVL_WRITEDATA, // Avalon-MM Write Data
output logic [31:0] AVL_READDATA, // Avalon-MM Read Data
// Exported Conduit
inout wire PS2_CLK, PS2_DATA, // Exported Conduit Signal to LEDs
// Debug exports
output logic [7:0] debug_keycode,
output logic [2:0] debug_state, debug_counter
);
// Debug
logic [7:0] debug_keycode_next;
// Static assignments
logic clock_we, data_we, clock_out, data_out, clock_in, data_in;
assign PS2_CLK = (clock_we) ? clock_out : 1'bZ;
assign PS2_DATA = (data_we) ? data_out : 1'bZ;
enum logic [2:0] {
idle, b_data, b_parity, b_end, b_enqueue, b_error
} state, state_next;
logic [2:0] counter, counter_next;
logic clock_wait, clock_wait_next, error, error_next;
assign debug_state = state;
assign debug_counter = counter;
// Avalon MM functionalities
logic[7:0] keydown[8], keydown_next[8], keyup[8], keyup_next[8], keycode, keycode_next;
always_ff @(posedge CLK) begin
if(RESET) begin
for (int i = 0; i < 8; i++) begin
keydown[i] <= 8'h0;
keyup[i] <= 8'h0;
clock_in <= 1'b1;
data_in <= 1'b1;
state <= idle;
keycode <= 8'h0;
counter <= 3'b0;
clock_wait <= 1'b0;
error <= 0;
debug_keycode <= 8'hCC;
end
end else begin
for (int i = 0; i < 4; i++) begin
keydown[i] <= keydown_next[i];
keyup[i] <= keyup_next[i];
clock_in <= PS2_CLK;
data_in <= PS2_DATA;
state <= state_next;
keycode <= keycode_next;
counter <= counter_next;
clock_wait <= clock_wait_next;
error <= error_next;
debug_keycode <= debug_keycode_next;
end
end
end
always_comb begin
// Avalon IO
// Defaults
for (int i = 0; i < 4; i++) begin
keydown_next[i] = keydown[i];
keyup_next[i] = keyup[i];
end
AVL_READDATA = 32'hCCCC;
if (AVL_CS) begin
if (AVL_READ) begin
if (AVL_ADDR[3] == 1'b0) // Keydown
AVL_READDATA = {24'h0, keydown[AVL_ADDR[2:0]]};
else
AVL_READDATA = {24'h0, keyup[AVL_ADDR[2:0]]};
end else if (AVL_WRITE && AVL_BYTE_EN[0]) begin
if (AVL_ADDR[3] == 1'b0) // Keydown
keydown_next[AVL_ADDR[2:0]] = AVL_WRITEDATA[7:0];
else
keyup_next[AVL_ADDR[2:0]] = AVL_WRITEDATA[7:0];
end
end
// PS2 Logic
debug_keycode_next = debug_keycode;
state_next = state;
counter_next = counter;
clock_wait_next = clock_wait;
keycode_next = keycode;
error_next = error;
clock_we = 1'b0;
data_we = 1'b0;
unique case (state)
idle: begin
if (!clock_in && !clock_wait) begin
clock_wait_next = 1'b1;
if (data_in != 1'b0)
error_next = 1'b1;
else
error_next = 1'b0;
end
if (clock_in && clock_wait) begin
clock_wait_next = 1'b0;
counter_next = 3'b0;
keycode_next = 8'h0;
state_next = b_data;
end
end
b_data: begin
if (!clock_in && !clock_wait) begin
clock_wait_next = 1'b1;
keycode_next[counter] = data_in;
end
if (clock_in && clock_wait) begin
clock_wait_next = 1'b0;
counter_next = counter+1;
if (counter == 3'h7)
state_next = b_parity;
end
end
b_parity: begin
if (!clock_in && !clock_wait) begin
clock_wait_next = 1'b1;
if (data_in != keycode[0] ^ keycode[1] ^ keycode[2] ^
keycode[3] ^ keycode[4] ^ keycode[5] ^ keycode[6] ^
keycode[7])
error_next = 1'b1;
end
if (clock_in && clock_wait) begin
clock_wait_next = 1'b0;
state_next = b_end;
end
end
b_end: begin
if (!clock_in && !clock_wait) begin
clock_wait_next = 1'b1;
if (data_in != keycode[0] ^ keycode[1] ^ keycode[2] ^
keycode[3] ^ keycode[4] ^ keycode[5] ^ keycode[6] ^
keycode[7])
error_next = 1'b1;
end
if (clock_in && clock_wait) begin
clock_wait_next = 1'b0;
state_next = b_enqueue;
end
end
b_enqueue: begin
debug_keycode_next = keycode;
state_next = idle;
end
b_error: begin
debug_keycode_next = 8'hDD;
state_next = idle;
end
endcase
end
endmodule
# -------------------------------------------------------------------------- #
#
# Copyright (C) 2017 Intel Corporation. All rights reserved.
# Your use of Intel Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Intel Program License
# Subscription Agreement, the Intel Quartus Prime License Agreement,
# the Intel MegaCore Function License Agreement, or other
# applicable license agreement, including, without limitation,
# that your use is for the sole purpose of programming logic
# devices manufactured by Intel and sold by Intel or its
# authorized distributors. Please refer to the applicable
# agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus Prime
# Version 17.0.0 Build 595 04/25/2017 SJ Lite Edition
# Date created = 23:41:32 November 11, 2017
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "17.0"
DATE = "23:41:32 November 11, 2017"
# Revisions
PROJECT_REVISION = "osu_fpga_toplevel"
This diff is collapsed.
module osu_fpga_toplevel (
input logic CLOCK_50,
input logic[3:0] KEY,
inout wire PS2_KBCLK, PS2_KBDAT,
output logic [6:0] HEX0, HEX1, HEX4, HEX6
);
logic [7:0] keycode;
logic [2:0] state, counter;
ps2 kb(.CLK(CLOCK_50), .RESET(~KEY[0]), .AVL_READ(0), .AVL_WRITE(0), .AVL_CS(0),
.AVL_BYTE_EN(0), .AVL_ADDR(0), .AVL_WRITEDATA(0), .AVL_READDATA(0),
.PS2_CLK(PS2_KBCLK), .PS2_DATA(PS2_KBDAT),
.debug_keycode(keycode), .debug_state(state), .debug_counter(counter));
hexdriver h0(.In(keycode[3:0]), .Out(HEX0));
hexdriver h1(.In(keycode[7:4]), .Out(HEX1));
hexdriver h4(.In({1'b0, state}), .Out(HEX4));
hexdriver h6(.In({1'b0, counter}), .Out(HEX6));
endmodule
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment