ps2lab1.v
module ps2lab1(
// Clock Input (50 MHz)
input CLOCK_50,
// Push Buttons
input [3:0] KEY,
// DPDT Switches
input [17:0] SW,
// 7-SEG Displays
output [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5, HEX6, HEX7,
// LEDs
output [8:0] LEDG, // LED Green[8:0]
output [17:0] LEDR, // LED Red[17:0]
// PS2 data and clock lines
input PS2_DAT,
input PS2_CLK,
// GPIO Connections
inout [35:0] GPIO_0, GPIO_1
);
// set all inout ports to tri-state
assign GPIO_0 = 36'hzzzzzzzzz;
assign GPIO_1 = 36'hzzzzzzzzz;
wire RST;
assign RST = KEY[0];
// Connect dip switches to red LEDs
assign LEDR[17:0] = SW[17:0];
// turn off green LEDs
assign LEDG = 0;
wire reset = 1'b0;
wire [7:0] scan_code;
reg [7:0] history[1:4];
wire read, scan_ready;
oneshot pulser(
.pulse_out(read),
.trigger_in(scan_ready),
.clk(CLOCK_50)
);
keyboard kbd(
.keyboard_clk(PS2_CLK),
.keyboard_data(PS2_DAT),
.clock50(CLOCK_50),
.reset(reset),
.read(read),
.scan_ready(scan_ready),
.scan_code(scan_code)
);
hex_7seg dsp0(history[1][3:0],HEX0);
hex_7seg dsp1(history[1][7:4],HEX1);
hex_7seg dsp2(history[2][3:0],HEX2);
hex_7seg dsp3(history[2][7:4],HEX3);
hex_7seg dsp4(history[3][3:0],HEX4);
hex_7seg dsp5(history[3][7:4],HEX5);
hex_7seg dsp6(history[4][3:0],HEX6);
hex_7seg dsp7(history[4][7:4],HEX7);
always @(posedge scan_ready)
begin
history[4] <= history[3];
history[3] <= history[2];
history[2] <= history[1];
history[1] <= scan_code;
end
// blank remaining digits
/*
wire [6:0] blank = 7'h7f;
assign HEX2 = blank;
assign HEX3 = blank;
assign HEX4 = blank;
assign HEX5 = blank;
assign HEX6 = blank;
assign HEX7 = blank;
*/
endmodule
keyboard.v
module keyboard(keyboard_clk, keyboard_data, clock50, reset, read, scan_ready, scan_code);
input keyboard_clk;
input keyboard_data;
input clock50; // 50 Mhz system clock
input reset;
input read;
output scan_ready;
output [7:0] scan_code;
reg ready_set;
reg [7:0] scan_code;
reg scan_ready;
reg read_char;
reg clock; // 25 Mhz internal clock
reg [3:0] incnt;
reg [8:0] shiftin;
reg [7:0] filter;
reg keyboard_clk_filtered;
// scan_ready is set to 1 when scan_code is available.
// user should set read to 1 and then to 0 to clear scan_ready
always @ (posedge ready_set or posedge read)
if (read == 1) scan_ready <= 0;
else scan_ready <= 1;
// divide-by-two 50MHz to 25MHz
always @(posedge clock50)
clock <= ~clock;
// This process filters the raw clock signal coming from the keyboard
// using an eight-bit shift register and two AND gates
always @(posedge clock)
begin
filter <= {keyboard_clk, filter[7:1]};
if (filter==8'b1111_1111) keyboard_clk_filtered <= 1;
else if (filter==8'b0000_0000) keyboard_clk_filtered <= 0;
end
// This process reads in serial data coming from the terminal
always @(posedge keyboard_clk_filtered)
begin
if (reset==1)
begin
incnt <= 4'b0000;
read_char <= 0;
end
else if (keyboard_data==0 && read_char==0)
begin
read_char <= 1;
ready_set <= 0;
end
else
begin
// shift in next 8 data bits to assemble a scan code
if (read_char == 1)
begin
if (incnt < 9)
begin
incnt <= incnt + 1'b1;
shiftin = { keyboard_data, shiftin[8:1]};
ready_set <= 0;
end
else
begin
incnt <= 0;
scan_code <= shiftin[7:0];
read_char <= 0;
ready_set <= 1;
end
end
end
end
endmodule
oneshot.v
module oneshot(output reg pulse_out, input trigger_in, input clk);
reg delay;
always @ (posedge clk)
begin
if (trigger_in && !delay) pulse_out <= 1'b1;
else pulse_out <= 1'b0;
delay <= trigger_in;
end
endmodule
hex_7seg.v
module hex_7seg(hex_digit,seg);
input [3:0] hex_digit;
output [6:0] seg;
reg [6:0] seg;
// seg = {g,f,e,d,c,b,a};
// 0 is on and 1 is off
always @ (hex_digit)
case (hex_digit)
4'h0: seg = 7'b1000000;
4'h1: seg = 7'b1111001; // ---a----
4'h2: seg = 7'b0100100; // | |
4'h3: seg = 7'b0110000; // f b
4'h4: seg = 7'b0011001; // | |
4'h5: seg = 7'b0010010; // ---g----
4'h6: seg = 7'b0000010; // | |
4'h7: seg = 7'b1111000; // e c
4'h8: seg = 7'b0000000; // | |
4'h9: seg = 7'b0011000; // ---d----
4'ha: seg = 7'b0001000;
4'hb: seg = 7'b0000011;
4'hc: seg = 7'b1000110;
4'hd: seg = 7'b0100001;
4'he: seg = 7'b0000110;
4'hf: seg = 7'b0001110;
endcase
endmodule
fit.summary
Fitter Status : Successful - Thu Jan 24 13:01:05 2008
Quartus II Version : 7.2 Build 175 11/20/2007 SP 1 SJ Web Edition
Revision Name : ps2lab1
Top-level Entity Name : ps2lab1
Family : Cyclone II
Device : EP2C35F672C6
Timing Models : Final
Total logic elements : 95 / 33,216 ( < 1 % )
Total combinational functions : 72 / 33,216 ( < 1 % )
Dedicated logic registers : 68 / 33,216 ( < 1 % )
Total registers : 68
Total pins : 180 / 475 ( 38 % )
Total virtual pins : 0
Total memory bits : 0 / 483,840 ( 0 % )
Embedded Multiplier 9-bit elements : 0 / 70 ( 0 % )
Total PLLs : 0 / 4 ( 0 % )
tan.summary-------------------------------------------------------------------------------------- Timing Analyzer Summary -------------------------------------------------------------------------------------- Type : Worst-case tsu Slack : N/A Required Time : None Actual Time : 3.340 ns From : PS2_CLK To : keyboard:kbd|filter[7] From Clock : -- To Clock : CLOCK_50 Failed Paths : 0 Type : Worst-case tco Slack : N/A Required Time : None Actual Time : 22.298 ns From : history[2][0] To : HEX2[5] From Clock : CLOCK_50 To Clock : -- Failed Paths : 0 Type : Worst-case tpd Slack : N/A Required Time : None Actual Time : 9.857 ns From : SW[16] To : LEDR[16] From Clock : -- To Clock : -- Failed Paths : 0 Type : Worst-case th Slack : N/A Required Time : None Actual Time : -1.367 ns From : PS2_DAT To : keyboard:kbd|ready_set From Clock : -- To Clock : CLOCK_50 Failed Paths : 0 Type : Clock Setup: 'CLOCK_50' Slack : N/A Required Time : None Actual Time : 157.58 MHz ( period = 6.346 ns ) From : keyboard:kbd|scan_ready To : oneshot:pulser|delay From Clock : CLOCK_50 To Clock : CLOCK_50 Failed Paths : 0 Type : Clock Hold: 'CLOCK_50' Slack : Not operational: Clock Skew > Data Delay Required Time : None Actual Time : N/A From : keyboard:kbd|scan_code[2] To : history[1][2] From Clock : CLOCK_50 To Clock : CLOCK_50 Failed Paths : 8 Type : Total number of failed paths Slack : Required Time : Actual Time : From : To : From Clock : To Clock : Failed Paths : 8 --------------------------------------------------------------------------------------
Maintained by John Loomis, last updated Thu Jan 24 13:15:47 2008