0

I have a problem that is caused by this keyboard interface. I'm trying to make a digital piano with a keyboard and an amplifier but the sound does not come as we press the button; there is a ~1 second delay. Can you help me with this problem please? Also when we change the code part

Shift2_next <= Shift1(0) & Shift2(10 downto 1);
to
Shift2_next <= PS2Df & Shift2(10 downto 1);

the key gives the sound instantly as wanted but now the sound does not stop; the break code is corrupted in that case I think. Hope you can help. Thanks.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity keyboard_ctrl is
  port(
    clk25 : in STD_LOGIC;
    PS2C : in STD_LOGIC;
    PS2D : in STD_LOGIC;
    xkey : out STD_LOGIC_VECTOR(16 downto 1)
  );
end keyboard_ctrl;

architecture keyboard of keyboard_ctrl is
  signal PS2Cf, PS2Df: std_logic;
  signal PS2Cf_next, PS2Df_next: std_logic;
  signal ps2c_filter, ps2d_filter: std_logic_vector(7 downto 0);
  signal shift1,shift2: std_logic_vector(10 downto 0);
  signal shift1_next,shift2_next: std_logic_vector(10 downto 0);
begin

  xkey <= shift1(8 downto 1)&shift2(8 downto 1);

  -- filter for PS2 clock and data
  filter: process(clk25)
  begin
    if clk25'event and clk25 = '1' then 
        ps2c_filter(7) <= PS2C;
        ps2c_filter(6 downto 0) <= ps2c_filter(7 downto 1);
        ps2d_filter(7) <= PS2D;
        ps2d_filter(6 downto 0) <= ps2d_filter(7 downto 1);

        PS2Cf <= PS2Cf_next;
        PS2Df <= PS2Df_next;
    end if;
  end process filter;
    PS2Cf_next <= '1' when ps2c_filter = X"FF" else 
                  '0' when ps2c_filter = X"00" else
                  PS2Cf;
    PS2Df_next <= '1' when ps2d_filter = X"FF" else 
                  '0' when ps2d_filter = X"00" else
                  PS2Df;

  --Shift used to clock in scan codes from PS2--
  shift: process(PS2Cf)
  begin
    if (PS2Cf'event and PS2Cf = '0') then
        shift1 <= shift1_next;
        shift2 <= shift2_next;
    end if;
  end process shift;

  Shift1_next <= PS2Df & Shift1(10 downto 1);
  Shift2_next <= Shift1(0) & Shift2(10 downto 1);
end keyboard; 
Paebbels
  • 15,573
  • 13
  • 70
  • 139
Alp
  • 63
  • 6
  • This design has no double-FF input synchronization (it's essential for the PS2 protocol). It's not a synchronous design, because `shift1` and `shift2` are clocked with an self generate clock signal -> use enables to improve this part. Why are you using an AND filter on ps2c and ps2d? You can assume these wires are glitch free. Your circuit pays no attention to: bus idle, start condition, parity, end condition on the bus. – Paebbels Dec 25 '14 at 08:32

1 Answers1

0

You have to change the design to be synchronous specially when using PS2. I recommend you check the clock for the PS2 make sure it is attached to the 25 MHz pin or try use a higher frequency clock and divide it until you get the correct timing. Attached example of dividing a clock by 3, you can change it and use it

Best Wishes,

library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;

entity divide_by_3 is
    port (
        cout   :out std_logic;  -- Output clock
        clk    :in  std_logic;  -- Input clock
        reset  :in  std_logic   -- Input reset
    );
end entity;

architecture rtl of divide_by_3 is
    signal pos_cnt :std_logic_vector (1 downto 0);
    signal neg_cnt :std_logic_vector (1 downto 0);
begin
    process (clk, reset) begin
        if (reset = '1') then
            pos_cnt <= (others=>'0');
        elsif (rising_edge(clk)) then
            if (pos_cnt = 2) then
                pos_cnt <= pos_cnt + 1;
            end if;
        end if;
    end process;

    process (clk, reset) begin
        if (reset = '1') then
            neg_cnt <= (others=>'0');
        elsif (falling_edge(clk)) then
            if (neg_cnt = 2) then
                neg_cnt <= neg_cnt + 1;
            end if;
        end if;
    end process;

    cout <= '1' when ((pos_cnt /= 2) and (neg_cnt /= 2)) else
            '0';
end architecture;
-------------------------------------------------------
--  Testbench to check the divide_by_3 logic
-------------------------------------------------------
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_textio.all;
    use std.textio.all;

entity div3_tb is
end entity;
architecture test of div3_tb is

    signal cout   :std_logic;
    signal clk    :std_logic := '1';
    signal reset  :std_logic := '1';

    component divide_by_3 is
    port (
        cout   :out std_logic;
        clk    :in  std_logic;
        reset  :in  std_logic
    );
    end component;
begin

    -- Generate clock
    clk   <= not clk after 10 ns;
    reset <= '0' after 20 ns;

    Inst_div3 : divide_by_3


      port map (
            cout   => cout,   -- Output
            clk    => clk,    -- Input
            reset  => reset   -- Iinput
        );
    end architecture

;