de2lab2c.v
module de2lab2c(
// 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
inout PS2_DAT,
inout 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;
one_pulse oneshot1(read,scan_ready,CLOCK_50);
ps2_rcv rcv(
.ps2_clk(PS2_CLK),
.ps2_data(PS2_DAT),
.clock50(CLOCK_50),
.reset(reset),
.read_ack(read),
.write_ack(write_ack),
.data_ready(scan_ready),
.data(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, negedge RST)
if (!RST)
begin
history[4] <= 4'h0;
history[3] <= 4'h0;
history[2] <= 4'h0;
history[1] <= 4'h0;
end
else 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'b111_1111;
assign HEX2 = blank;
assign HEX3 = blank;
assign HEX4 = blank;
assign HEX5 = blank;
assign HEX6 = blank;
assign HEX7 = blank;
*/
reg start;
reg [7:0] command;
wire write_ack, wait_ack, timeout_error;
wire cmd1, cmd2, cmd3;
assign LEDG[2] = start;
assign LEDG[1] = wait_ack;
assign LEDG[0] = timeout_error;
ps2_xmt xmt(
.clock50(CLOCK_50),
.nRESET(RST),
.command(command),
.start(start),
.wait_ack(wait_ack),
.write_ack(write_ack),
.timeout_error(timeout_error),
.ps2_data(PS2_DAT),
.ps2_clock(PS2_CLK)
);
reg [3:0] ir;
reg [3:0] pc;
wire xmt_complete = (wait_ack && scan_ready);
one_pulse oneshot2(cmd1,~KEY[3],CLOCK_50);
one_pulse oneshot3(cmd2,~KEY[2],CLOCK_50);
one_pulse oneshot4(cmd3,~KEY[1],CLOCK_50);
wire [3:0] npc = pc + 1'b1;
wire [1:0] opcode = ir[3:2];
always @(posedge CLOCK_50, negedge RST)
if (!RST) pc <= 3'b000;
else case (opcode)
2'h1: begin
start <= 1'b1;
command <= data;
pc <= npc;
end
2'h2: if (xmt_complete)
begin
start <= 1'b0;
pc <= npc;
end
default:
begin
start <= 1'b0;
if (cmd1) pc <= 4'h1;
else if (cmd2) pc <= 4'h4;
else if (cmd3) pc <= 4'h7;
end
endcase
assign LEDG[7:4] = pc;
always
case (pc)
4'h0: ir = 4'b0000; // halt
4'h1: ir = 4'b0101; // write 1 (FF)
4'h2: ir = 4'b1000; // wait (for acknowledgement signal)
4'h3: ir = 4'b0000; // halt
4'h4: ir = 4'b0110; // write 2 (E9)
4'h5: ir = 4'b1000; // wait
4'h6: ir = 4'b0000; // halt
4'h7: ir = 4'b0111; // write 3 (EB)
4'h8: ir = 4'b1000; // wait
4'h9: ir = 4'b0000; // halt
default: ir = 4'b0000; // halt
endcase
reg [7:0] data;
always
case (ir[1:0])
2'b01: data <= 8'hFF;
2'b10: data <= 8'hE9;
2'b11: data <= 8'hEB;
default: data <= 8'h00;
endcase
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
one_pulse.v
module one_pulse(pulse_out,trigger_in, clk);
input trigger_in,clk;
output pulse_out;
reg pulse_out, delay;
always @ (posedge clk)
begin
if (trigger_in && !delay) pulse_out <= 1'b1;
else pulse_out <= 1'b0;
delay <= trigger_in;
end
endmodule
ps2_rcv.v
module ps2_rcv(ps2_clk, ps2_data, clock50, reset, read_ack, write_ack, data_ready, data);
input ps2_clk;
input ps2_data;
input clock50; // 50 Mhz system clock
input reset;
input read_ack, write_ack;
output data_ready;
output [7:0] data;
reg ready_set;
reg [7:0] data;
reg data_ready;
reg read_char;
reg clock; // 25 Mhz internal clock
reg [3:0] incnt;
reg [8:0] shiftin;
reg [7:0] filter;
reg ps2_clk_filtered;
// data_ready is set to 1 when data is available.
// user should set read_ack to 1 and then to 0 to clear data_ready
always @ (posedge ready_set or posedge read_ack)
if (read_ack) data_ready <= 1'b0;
else data_ready <= 1'b1;
// divide-by-two 50MHz to 25MHz
always @(posedge clock50)
clock <= ~clock;
// This process filters the raw clock signal coming from the ps2
// using an eight-bit shift register and two AND gates
always @(posedge clock)
begin
filter <= {ps2_clk, filter[7:1]};
if (filter==8'b1111_1111) ps2_clk_filtered <= 1;
else if (filter==8'b0000_0000) ps2_clk_filtered <= 0;
end
// This process reads in serial data coming from the terminal
always @(posedge ps2_clk_filtered)
begin
if (reset==1)
begin
incnt <= 4'b0000;
read_char <= 0;
end
else if (!ps2_data && (!read_char || write_ack))
// this is either start bit or write acknowledgement bit
begin
if (!write_ack) read_char <= 1;
ready_set <= 0;
end
else
begin
// shift in next 8 data bits to assemble a data code
if (read_char == 1)
begin
if (incnt < 9)
begin
incnt <= incnt + 1'b1;
shiftin = { ps2_data, shiftin[8:1]};
ready_set <= 0;
end
else
begin
incnt <= 0;
data <= shiftin[7:0];
read_char <= 0;
ready_set <= 1;
end
end
end
end
endmodule
ps2_xmt.v
module ps2_xmt(input clock50, input nRESET,
input [7:0] command, input start,
inout ps2_data, inout ps2_clock, output reg write_ack,
output wait_ack, output timeout_error);
reg [7:0] filter;
reg clock25;
reg clock_posedge, filtered_clock;
// generate 25MHz clock from 50MHz clock
always @(posedge clock50)
clock25 = ~clock25;
// Filter the PS2_clock signal
always @(posedge clock25)
begin
filter <= {filter[6:0],ps2_clock};
if (filter==8'hff)
begin
clock_posedge <= (filtered_clock==1'b0);
filtered_clock <= 1'b1;
end
if (filter==8'h00)
begin
//clock_negedge = (filtered_clock==1'b1);
filtered_clock <= 1'b0;
end
end
reg [19:0] counter;
reg [2:0] state;
parameter
WAIT_INIT = 2500, // 100 us (2500/25MHz)
WAIT_TIMEOUT = 750000; // 30 ms
parameter
IDLE = 3'h0,
INIT = 3'h1,
WAIT_FOR_CLOCK = 3'h2,
TRANSMIT = 3'h3,
WAIT_ACK = 3'h4,
TIMEOUT = 3'h5;
always @(posedge clock25)
begin
if (!nRESET || state==IDLE) counter = 20'h00000;
else counter <= counter + 1'b1;
end
always @(posedge clock25)
if (!nRESET) state <= IDLE;
else case (state)
IDLE:
state <= (start? INIT: IDLE);
INIT:
if (counter==WAIT_INIT) state <= WAIT_FOR_CLOCK;
WAIT_FOR_CLOCK:
if (clock_posedge) state <= TRANSMIT;
else if (counter>=WAIT_TIMEOUT) state <= TIMEOUT;
TRANSMIT:
if (write_ack) state <= WAIT_ACK;
else if (counter>=WAIT_TIMEOUT) state <= TIMEOUT;
WAIT_ACK:
if (!start) state <= IDLE;
TIMEOUT: state <= (!start? IDLE: TIMEOUT);
default: state <= IDLE;
endcase
wire parity = ~(^command);
reg [9:0] bits;
reg [3:0] bitcount;
always @ (negedge filtered_clock)
if (state==TRANSMIT)
begin
if (bitcount<=4'b1001)
begin
bitcount <= bitcount + 1'b1;
bits <= {1'b1, bits[9:1]};
end
else write_ack <= 1'b1;
end
else
begin
bits <= {parity,command,1'b0};
bitcount <= 4'h0;
write_ack <= 1'b0;
end
assign ps2_clock = (state==INIT? 1'b0: 1'bz);
assign ps2_data = (state==WAIT_FOR_CLOCK? 1'b0: (state==TRANSMIT? bits[0]: 1'bz));
assign wait_ack = (state==WAIT_ACK);
assign timeout_error = (state==TIMEOUT);
endmodule
fit.summaryFitter Status : Successful - Tue Jun 12 13:19:15 2007 Quartus II Version : 6.0 Build 178 04/27/2006 SJ Full Version Revision Name : de2lab2c Top-level Entity Name : de2lab2c Family : Cyclone II Device : EP2C35F672C6 Timing Models : Final Total logic elements : 188 / 33,216 ( < 1 % ) Total registers : 125 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 : 6.063 ns From : KEY[0] To : command[4] From Clock : -- To Clock : CLOCK_50 Failed Paths : 0 Type : Worst-case tco Slack : N/A Required Time : None Actual Time : 21.576 ns From : history[1][4] To : HEX1[2] From Clock : CLOCK_50 To Clock : -- Failed Paths : 0 Type : Worst-case tpd Slack : N/A Required Time : None Actual Time : 9.804 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.029 ns From : PS2_DAT To : ps2_rcv:rcv|ready_set From Clock : -- To Clock : CLOCK_50 Failed Paths : 0 Type : Clock Setup: 'CLOCK_50' Slack : N/A Required Time : None Actual Time : 90.68 MHz ( period = 11.028 ns ) From : ps2_xmt:xmt|write_ack To : ps2_xmt:xmt|state.TRANSMIT 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 : command[4] To : ps2_xmt:xmt|bits[3] From Clock : CLOCK_50 To Clock : CLOCK_50 Failed Paths : 37 Type : Total number of failed paths Slack : Required Time : Actual Time : From : To : From Clock : To Clock : Failed Paths : 37 --------------------------------------------------------------------------------------
Maintained by John Loomis, last updated Tue Jun 12 13:25:36 2007