2

I am trying to read a pressed key from a PS/2 keyboard and display it on a LCD1602 display. I wrote one entity and architecture which detects a pressed key. If it received the 11 bits (1 start bit, 8 data bits, 1 parity bit and 1 stop bit) then I write the received 11 bits to a signal. This is a code snippet that does that job

process(KCI)
    variable IDX : integer range 0 to 11;
begin
    if(falling_edge(KCI)) then
        if(IDLE = '1') then
            IDX := 0;
        else
            MSG_BFR(IDX) <= KDI;
            IDX := IDX + 1;
            if(IDX = 11) then
                IDX := 0;
                MSG_RCV <= MSG_BFR;
            end if;
        end if;
    end if;
end process;    

On a Keyboard Clock Input (KCI) it reads the Keyboard Data in (KDI) and writes it in a Message Buffer (MSG_BFR). Once received all 11 bits it writes to that signal Message Received (MSG_RCV).

Another process in this keyboard architecture writes it to a signal which is port mapped to the 'main' VHDL code.

process(MSG_RCV)
begin
    KEY <= MSG_RCV(8 downto 1);
end process;

The 'main' VHDL code just passes this information via a port map to the LCD1602 code using a simple process

process(KEY_M)
begin
    CHAR_M <= KEY_M;
end process;

The LCD1602 writes the character in an array using this process

process(CHAR)
    variable ARRAY_IDX : integer range 7 to 14 := 7;
begin
    if(CHAR = "01000010") then
        LCD_CMD(ARRAY_IDX)(7 downto 0) <= CHAR;
        ARRAY_IDX := ARRAY_IDX + 1;
        if(ARRAY_IDX = 14) then
            ARRAY_IDX := 7;
        end if;
    end if;
end process;

This actually writes only the character K in array at a specific index.

Parallel to this function is the code also reading from this array and writing the bytes from this array to the LCD1602 screen. Running this code actually writes just a character B in all the places in the array.

photo of LCD display showing repeated "B" characters

The code that writes the bytes to the LCD1602 can be seen below

    process(CLK1602)
    variable i : integer := 0;
    variable j : integer := 1;

begin
    if CLK1602'event and CLK1602 = '1' then

        if i <= 1000000 then
            i := i + 1;
            E1602 <= '1';
            DATA1602 <= LCD_CMD(j)(7 downto 0);
        elsif i > 1000000 and i < 2000000 then
            i := i + 1;
            E1602 <= '0';
        elsif i = 2000000 then
            j := j + 1;
            i := 0;
        end if;

        if j <= 5  then
            RS1602 <= '0';    --command signal
        elsif j > 5   then
            RS1602 <= '1';   --data signal
        end if;

        if j = 37 then  --repeated display of data
            j := 5;
        end if;

    end if;

end process;

I have been stuck on this problem for 3 days now. All I want is to write a pressed character to the LCD and increment the array index by one, so the next pressed character can be written to that location. Can anyone point me to the source of the problem, which is why I do not get the desired behavior?

SamGibson
  • 17,231
  • 5
  • 37
  • 58
Xhendos
  • 21
  • 1
  • 2
    I'm not going to debug your code -- I just wanted to point out that the key codes that you get from a PS/2 keyboard are not the ASCII characters that the display expects to receive. You need to translate from one to the other in order to get anything meaningful. – Dave Tweed Oct 23 '19 at 16:07
  • If you want help on this, you need to explain how the hardware is wired to the FPGA. If you're using a COTS evaluation board, tell us which one it is. – Dave Tweed Oct 23 '19 at 16:08
  • This is the fpga development board EP4CE6E22C8N – Xhendos Oct 23 '19 at 16:33
  • That's a challenging project you tackled. It's admirable that you have come as far as you have, but worth considering that there is no sound reason to attempt to do this without a sequential processor of *some* sort, especially as your current goal only makes sense as the initial step of a larger one. Dedicated logic is a very poor fit for complex things which happen infrequently, especially as the starting and stopping may end up being a large part of the difficulty. Even something with an organized state machine expression would be an improvement. – Chris Stratton Oct 23 '19 at 16:50
  • EP4CE6E22C8N is actually a part number for a particular Cyclone IV FPGA from Intel (formerly Altera). Are you using one of the Terasic boards that are based on this chip? – Dave Tweed Oct 23 '19 at 20:30
  • 1
    The board can be seen [here](https://www.aliexpress.com/item/32670541876.html). The files that come with it can be downloaded [here](http://www.mediafire.com/file/wyhlxgfw3g3755p/A-C4E6E10_board.rar/file). Those include VHDL examples for a P/S2 keyboard interface and LCD 1602 display. –  Oct 24 '19 at 02:24
  • P/S2 keyboards have make and break scan codes the string of 'b' characters you see are from make codes (the raw value of a key press down for successive serial character times). The VHDL sample code with the board uses a second 11 bit shift register to capture break codes (when a key is released) allowing a single character to be captured. See the RAR archive VHDL-Examples/PS2_test/keyboardVHDL.vhd --Shift Registers used to clock in scan codes from PS2 (lacking process labels). –  Oct 25 '19 at 20:11
  • The scan codes are found in tables in various places including the [Digikey P/S2 keyboard interface](https://www.digikey.com/eewiki/pages/viewpage.action?pageId=28278929) where you see that some break codes have three byte values but the actual ASCII key value is always preceded by x"F0" which is why the keyboardVhdl.vhd process requires the previous character to be that value. –  Oct 25 '19 at 20:16

0 Answers0