Forum: FPGA, VHDL & Verilog PS2 Keyboard and RAM block interaction Verilog

Author: Sarah (Guest)
Posted on:

Rate this post
0 useful
not useful
Hi, I am working on a circuit for FPGA that would take input from a ps2 
keyboard and write it into a ram block (storing each letter) so that the 
data can be used later and outputted on VGA. I had the ps2 keyboard 
working in a simple module that directly outputs the data onto a hex but 
when I tried to incorporate a ram block into said circuit, it did not 
work. Could someone please help me see what I am doing wrong, no matter 
how many times I modified the FSM, I still had no new output going to 

For now, I have only tried the case for 1 letter.


module keyTest (KEY, CLOCK_50, PS2_CLK, PS2_DAT, HEX0, HEX2);

    input [3:0] KEY;
    input CLOCK_50;
    inout PS2_CLK, PS2_DAT;
    output [6:0] HEX0, HEX2;

    wire reset, go1, go2, enable, print;

    assign go1 = ~KEY[1];
    assign go2 = ~KEY[2];
    assign reset = KEY[0];

    wire [7:0] letter;

    // Internal Wires
    wire [7:0]  ps2_key_data;
    wire ps2_key_pressed;

    // Internal Registers
    reg  [7:0]  last_data_received;
    wire [7:0] hex_data, address;

    wire [8:0] counter, print_counter;

    //assigning new data for write-in if data received from keyboard
    always @(posedge CLOCK_50)
            if (!reset)
                last_data_received <= 8'h00;
            else if (ps2_key_pressed == 1'b1)
                last_data_received <= ps2_key_data;


    //ps2 control
    PS2_Controller PS2 (.CLOCK_50(CLOCK_50), .reset(~reset), 
.PS2_CLK(PS2_CLK), .PS2_DAT(PS2_DAT), .received_data(ps2_key_data), 

  //storing ram up to 256 8 bit character
    inputRam256x8 u0 (.address(address), .clock(CLOCK_50), 
.data(last_data_received), .wren(enable), .q(letter));

    control a1 (.clock(CLOCK_50), .reset(reset), .go1(go1), .go2(go2), 
.ps2_key_pressed(ps2_key_pressed), .enable(enable), .print(print), 
.counter(counter), .print_counter(print_counter));
    datapath a2 (.clock(CLOCK_50), .reset(reset), .enable(enable), 
.print(print), .last_data_received(last_received_data), .letter(letter), 
.counter(counter), .print_counter(print_coutner), .hex_data(hex_data), 

    hex_decoder m0 (.hex_digit(hex_data[3:0]), .segments(HEX0));
    hex_decoder m1 (.hex_digit(hex_data[7:0]), .segments(HEX2));


module control (clock, reset, go1, go2, ps2_key_pressed, enable, print, 
counter, print_counter);

     input clock, reset, go1, go2, ps2_key_pressed;
     output reg enable, print;
     output reg [8:0] counter, print_counter;
     reg [5:0] current_state, next_state;

     localparam S_READ_PS2       = 5'd0, //read in data from ps2
                S_WRITE          = 5'd1, //write data into ram
          S_WAIT1     = 5'd2, //wait for a signal to go to wait2
                S_PRINT          = 5'd3, //print every letter on hex
    S_WAIT2           = 5'd4, //wait for signal to either continue 
reading data or start printing
          S_READ_WAIT      = 5'd6; //wait for new input to start reading

    // Next state logic aka our state table
    begin: state_table
        case (current_state)
    S_READ_WAIT: next_state = ps2_key_pressed ? S_READ_PS2 : 
          S_READ_PS2: next_state = ps2_key_pressed ? S_READ_PS2 : 
          S_WRITE: next_state = (counter == 9'b100000000) ? S_PRINT : 
    S_WAIT1: next_state = go1 ? S_WAIT2 : S_WAIT1;
    S_WAIT2: next_state =  go2 ? S_PRINT: S_READ_WAIT;
    S_PRINT: next_state = (print_counter <= counter) ? S_PRINT : 
          default: next_state = S_READ_WAIT;
    end // state_table

  // Output logic aka all of our datapath control signals
    always @(*)
    begin: enable_signals
        // By default make all our signals 0
    enable = 1'b0;
    print = 1'b0;

        case (current_state)
            S_READ_PS2: begin
      enable = 1'b0;
      S_WRITE: begin
      enable = 1'b1;
      S_PRINT: begin
      enable = 1'b0;
      print = 1'b1;
        // default:    // don't need default since we already made sure 
all of our outputs were assigned a value at the start of the always 
    end // enable_signals

  initial counter = 9'd0;

  //count up to 256 to make sure there is available memory space
    always @(posedge clock)
            if (!reset) begin
      counter <= 9'b00000000;
            else if (counter == 9'b100000000)
      counter <= 9'b000000000;
            else if (current_state == S_WRITE)
      counter <= counter + 1'b1;

     initial print_counter = 9'd0;

     always @(posedge clock)
            if (!reset) begin
      print_counter <= 9'b00000000;
            else if (print_counter == 9'b100000000)
      print_counter <= 9'b000000000;
            else if (current_state == S_PRINT)
      print_counter <= print_counter + 1'b1;


module datapath (clock, reset, enable, print, last_data_received, 
letter, counter, print_counter, hex_data, address);

     input clock, reset, enable, print;
     input [7:0] last_data_received, letter;
     input [8:0] counter, print_counter;
     output reg [7:0] hex_data, address;

     always @(posedge clock) begin
    hex_data <= 8'd0;
      else if (print)
    hex_data <= letter;

     always @(posedge clock) begin
    address <= 8'd0;
      else if (print)
    address <= print_counter[7:0];
    else if (enable)
      address <= counter[7:0];


//hex module for test
module hex_decoder(hex_digit, segments);

    input [3:0] hex_digit;
    output reg [6:0] segments;

    always @(*)
        case (hex_digit)
            4'h0: segments = 7'b100_0000;
            4'h1: segments = 7'b111_1001;
            4'h2: segments = 7'b010_0100;
            4'h3: segments = 7'b011_0000;
            4'h4: segments = 7'b001_1001;
            4'h5: segments = 7'b001_0010;
            4'h6: segments = 7'b000_0010;
            4'h7: segments = 7'b111_1000;
            4'h8: segments = 7'b000_0000;
            4'h9: segments = 7'b001_1000;
            4'hA: segments = 7'b000_1000;
            4'hB: segments = 7'b000_0011;
            4'hC: segments = 7'b100_0110;
            4'hD: segments = 7'b010_0001;
            4'hE: segments = 7'b000_0110;
            4'hF: segments = 7'b000_1110;
            default: segments = 7'h7f;

Author: S. R. (svenska)
Posted on:

Rate this post
0 useful
not useful
First, please mark code in tags so that it appears readable.

Second, I can't read Verilog, sorry.

Then, split your problem in multiple parts and test each of those:
- in PS/2, the keyboard decides the clock, so you must
  synchronize the CLK and DATA lines with out FPGA clock;
- the keyboard will send multiple bytes for each key press, example:
  "0x1C" means "A pushed down", and "0xF0, 0x1C" means "A released",
  so you need to build a shift register to receive each byte separately
  and turn those into a byte stream (scancode)
- this byte stream should be fed into a state machine to turn it into
  a set of events handling keys
- whenever you get a key event you are interested in, you feed it into
  another FSM to write it to memory (in order to read memory, you need
  a FSM anyway, so don't bother doing without)

Simulate each step!


Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]

Bild automatisch verkleinern, falls nötig