2

I'm trying to receive data from a keyboard via the PS/2 port on the Papilio One Arcade Megawing. Eventually I'll want to implement this from scratch, but I thought I'd get some public code working first as a form of smoke-test.

The three sources I played with were

I've modified each by changing the UCF file to

NET "Clk"      LOC="P89"  | IOSTANDARD = LVCMOS25 | PERIOD=31.25ns;
NET "Reset"    LOC="P67"  | IOSTANDARD=LVTTL | PULLDOWN;
NET "PS2_Clk"  LOC="P91"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP;
NET "PS2_Data" LOC="P92"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP;
NET "LED1"     LOC="P57"  | IOSTANDARD=LVTTL;
NET "LED2"     LOC="P53"  | IOSTANDARD=LVTTL;
NET "LED3"     LOC="P40"  | IOSTANDARD=LVTTL;

and I'm driving LED1 straight from PS2_Clk, LED2 from PS2_Data and LED3 from a register that should go from low to high (and stay high) when the first complete scancode is read.

The problem is, with all three implementations, what I get instead is

  • LED1 and LED2 are continuously on
  • LED3 never turns on

The keyboard I'm using is a Microsoft Natural Keyboard 4000 via a USB-to-PS/2 dongle. The function key lock LED on the keyboard lights up when I connect it to the Papilio so at least I know it's getting juice.

Full Xilinx ISE project dumps are available at http://forum.gadgetfactory.net/index.php?/topic/1917-ps2-ports-on-arcade-megawing/

@Leor mentioned below that the PS/2 port uses a clock frequency of 10 KHz. Does n't that mean that I should see a blinking LED (with about 1.6 second frequency) with the following code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity main is
    Port ( CLK : in  STD_LOGIC;
           PS2_CLK : in  STD_LOGIC;
           LED : out  STD_LOGIC);
end main;

architecture Behavioral of main is
signal counter: unsigned(13 downto 0) := (others => '0');
signal PS2_CLK_PREV : std_logic := '1';
signal LED_clamped : std_logic := '0';
begin
LED <= LED_clamped;
process(CLK) is
begin
  if rising_edge(CLK) then
    if not (PS2_CLK = PS2_CLK_PREV) then
      counter <= counter + 1;
    end if;

    if counter = 0 then
      LED_clamped <= not LED_clamped;
    end if;

    PS2_CLK_PREV <= PS2_CLK;
  end if;
end process;

end Behavioral;

Because if I try this, the LED is still continuously on.

Cactus
  • 295
  • 3
  • 9
  • I've updated my code so that the LED is driven from a latch that is flipped every time counter reaches 0. It is still always on for me. – Cactus Feb 12 '14 at 10:34
  • The page at http://papilio.cc/index.php?n=Papilio.ArcadeMegaWing lists the PS/2 clock pins as *output* pins.. which confuses me even more. – Cactus Feb 12 '14 at 10:40

2 Answers2

1

PS/2 uses a 10 KHz clock, so connecting an LED to the clock or data lines will just result in the LED appearing always on at a brightness corresponding to the signal duty cycle.

Have you tried simulating the example code with the ISE simulator? That would at least tell you that the clock and data outputs are doing something sensible.

Update If I'm understanding the second code correctly:

The CLK signal is a 32 MHz clock The PS2_CLK signal is a 10 KHz (PS2 allows between 10 and 16 KHz apparently - do you know exactly what this signal is?) which is generated... somewhere?

The second piece of code you posted is going to:

  1. Initiate the counter at 0, PS2_CLK_PREV at 1
  2. On every CLK rising edge (ie at 32 MHz), the process will run

The process you've defined will increment the counter whenever PS2_CLK has changed.

So the counter will be incremented once for every positive and negative clock transition on PS2_CLK (ie at 20 KHz).

The counter will increment until it overflows and goes back to 0. As it's 14 bits, that means it will take 16384 increments, which at 20 KHz increment rate (twice per clock cycle) is 0.819 seconds.

Your LED is only 1 when the counter is 0, which will happen for 5 uS every 0.819 seconds. That's not long enough for you to notice it turned on, and so the LED is essentially 0.

If the LED is appearing to be constantly turned on, it means that the counter is constantly at 0. That suggests that PS2_CLK always equals PS2_CLK_PREV, which suggests that perhaps your PS2_CLK isn't doing anything. I'd suggest looking at what's driving that clock signal (is it a DCM that you've instantiated? A simple clock divider?)

LeoR
  • 1,066
  • 5
  • 10
  • The mention of a 10KHz clock gave me an idea; see my edited question. I'm still not seeing blinking on the LED. – Cactus Feb 10 '14 at 14:32
  • Is your 10 KHz PS2 clock the same as your logic CLK? Most FPGA logic runs at clock speeds in the 10s to 100s of MHz, which would result in your timer rolling over in less than a millisecond. I'd be surprised if your logic is clocked at 10MHz (unless you're specifically tying the logic to that clock) as there will be lots of other stuff that needs to happen before and after the data transmission. – LeoR Feb 11 '14 at 09:13
  • 2
    Saying that, the LED should appear off if the code above is working correctly. I think there's another issue somewhere. Have you successfully written, synthesised and loaded functional code to do something simple - perhaps make an LED blink? – LeoR Feb 11 '14 at 09:14
  • But I only decrease the counter when the PS2_CLK signal changes. I'm sampling the 10 KHz signal at 32 MHz, at least that's what I thought. – Cactus Feb 11 '14 at 12:53
  • about smoke-testing the board per se: stuff in general works on the same board, e.g. I just wrote and loaded on it a small configuration which uses the four buttons via a soft debouncer to toggle the four LEDs. I'd say that proves the clock and the LEDs work. I've also successfully generated VGA signal on the same board before. – Cactus Feb 11 '14 at 13:38
  • I've added some comments to my answer regarding your second piece of code. – LeoR Feb 11 '14 at 16:46
  • I thought the keyboard would be generating the ps2 clock. Is this not the case? – Cactus Feb 11 '14 at 23:30
  • Hmm I see now why the LED would only be 1 for the small timewhen counter is exactly 0... what I really wanted to do was to have a one-bit register which I flip every time counter is 0. I'll fix my program and test that. – Cactus Feb 12 '14 at 03:06
  • You're right - the device generates the clock signal. I'm not familiar with PS/2. – LeoR Feb 12 '14 at 09:50
  • The description of the protocol here: http://www.computer-engineering.org/ps2protocol/ suggests that the clock is high when there's no communication thanks to a pullup resistor. Do you have pullups on your data lines? There's so many variables it's hard to point at any one issue. I'd suggest buying a cheap logic analyser (cheap Saleae clones cost about $10) or scope to act as a sanity check. – LeoR Feb 12 '14 at 09:58
0

It turned out the problem was the combination of the Microsoft Natural 4000 keyboard that I was using for testing and the USB to PS/2 dongle. After I got a proper PS/2 keyboard, the test configurations work as expected.

Cactus
  • 295
  • 3
  • 9
  • I am not sure if I should accept this answer of mine, or delete my original question... I think I'll accept this answer since someone else might get into the same situation with a newer keyboard. – Cactus Feb 15 '14 at 02:35