Project: de2lab2c

Contents

Verilog Files

de2lab2c.v
hex_7seg.v
one_pulse.v
ps2_rcv.v
ps2_xmt.v

Quartus Files

fit.summary
tan.summary

Verilog Files

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

Quartus Compilation Summary

fit.summary

Fitter 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