0

ネット上で見つけたシンプルなキーボードインターフェイスを自分の用途に合わせて変更しています。アイデアは、新しいスキャンコードがあるときはいつでも、「Scan_Dav」という名前の出力をハイにしてからローにするというものです。したがって、Scan_Davをクロックとして別のモジュールに送信すると、新しいScanCodeが押されるたびに、そのモジュールのクロックが立ち上がりエッジになります。私の考え方に誤りはありますか?私はそれを試し、scancodeとscan_davをプロジェクトの残りの部分に向けたため(指定されたスキャンコードと並んで文字を書き込み、7セグメントディスプレイに表示します)、表示されるテキストには各文字が2つ含まれていました(つまり、FLYを書くとテキストはFFLLYYのようでした)。エラーがない場合は、コードを共有して、なぜ機能しないのかを尋ねます。ありがとう :)

編集:これは、Scan_Davの値に従ってシフトが行われる場所です

signal bytes : std_logic_vector(63 downto 0);
signal Scan_Dav_Sync: std_logic_vector(1 downto 0):="00";
signal Previous_Scan_Dav: std_logic:='0';
begin
    process (clk) begin --, Scan_Dav) begin
        if rising_edge(clk) then
             Scan_Dav_Sync(0) <= Scan_Dav;
             Scan_Dav_Sync(1) <= Scan_Dav_Sync(0);
             Previous_Scan_Dav <= Scan_Dav_Sync(1);
             if (Previous_Scan_Dav = '0') and (Scan_Dav_Sync(1) = '1') then
                 bytes <= bytes (bytes'high-8 downto 0) & Data_in;
             end if;
          end if;
    end process;

これがScan_Davの由来であり、コードはここから取得されます:(フィルタリング部分は無視してかまいません)

    Architecture Behavioral of KeyboardController is
    signal PS2_Datr : std_logic;
    subtype Filter_t is std_logic_vector(7 downto 0);
    signal Filter : Filter_t;
    signal Fall_Clk : std_logic;
    signal Bit_Cnt : unsigned (3 downto 0);
    signal Scan_DAVi : std_logic;
    signal S_Reg : std_logic_vector(8 downto 0);
    signal PS2_Clk_f : std_logic;
    Type State_t is (Idle, Shifting);
    signal State : State_t;
    signal Scan_Code : std_logic_vector(7 downto 0);
    signal Flag : std_logic:='0';

    begin
        process (Clk,Reset)
        begin
            if Reset='1' then
                PS2_Datr <= '0';
                PS2_Clk_f <= '0';
                Filter <= (others=>'0');
                Fall_Clk <= '0';
            elsif rising_edge (Clk) then
                PS2_Datr <= PS2_Data and PS2_Data; -- also turns 'H' into '1'
                Fall_Clk <= '0';
                Filter <= (PS2_Clk and PS2_CLK) & Filter(Filter'high downto 1);
                if Filter = Filter_t'(others=>'1') then
                    PS2_Clk_f <= '1';
                elsif Filter = Filter_t'(others=>'0') then
                    PS2_Clk_f <= '0';
                        if PS2_Clk_f = '1' then
                            Fall_Clk <= '1';
                        end if;
                end if;
            end if;
        end process;

            -- This simple State Machine reads in the Serial Data
            -- coming from the PS/2 peripheral.
        process(Clk,Reset)
        begin
            if Reset='1' then
            State <= Idle;
            Bit_Cnt <= (others => '0');
            S_Reg <= (others => '0');
            Scan_Code <= (others => '0');
            Scan_Out <= (others => '0');
            Scan_Davi <= '0';
        elsif rising_edge (Clk) then

    --  if Scan_Davi = '1' then
    --      Scan_Davi <= '0';
    --  end if;

            case State is
                when Idle =>
                    Bit_Cnt <= (others => '0');
                    -- note that we dont need to clear the Shift Register
                    if Fall_Clk='1' and PS2_Datr='0' then -- Start bit
                        State <= Shifting;
                    end if;
                when Shifting =>
                if Bit_Cnt >= 9 then
                    if Fall_Clk='1' then -- Stop Bit
                        Scan_Code <= S_Reg(7 downto 0);

                        if (Flag = '1' and Scan_Code /= "11110000")  then 
                        --to ignore makecode
                            Scan_Out <= Scan_Code;
                            Flag <= '0';
                            Scan_Davi <= '1';
                        end if;

                        if (Flag = '0' and Scan_Code = "11110000") then
                        --to ignore F0
                            Flag <= '1';
                            Scan_Davi <= '0';
                        end if;

                        State <= Idle;
                    end if;
                elsif Fall_Clk='1' then
                    Bit_Cnt <= Bit_Cnt + 1;
                    S_Reg <= PS2_Datr & S_Reg (S_Reg'high downto 1); -- Shift right
                end if;
                when others => -- never reached
                    State <= Idle;
            end case;
        end if;
    end process;
        Scan_DAV <= Scan_DAVi;
end Behavioral;

更新:残っている唯一の問題は、文字とテキストの表示とシフトの遅延です。VHDLを書いている間、Vを押しても何も得られません。次に、Hを押すとVが得られ、そのようになります。最後の文字は別のキーを押すまで表示されません。Scan_Davの問題のようですが、それが何であるかを解決できません。どんな助けでもありがたいです。

4

2 に答える 2

2

ロジック出力からクロック入力をドライブすることは、一般的に悪い習慣です (FPGA ファブリックによっては、まったく許可されません)。クロックは、デバイス内の専用クロック ロジックから供給された場合に最適に動作し、優れた設計ではクロック数を最小限に抑える必要があります。理想的には 1 つしかないのですが、それが常に可能であるとは限りません。

ロジックからクロック入力を実行する代わりに、すべてを 1 つのクロックで実行し、「イネーブル」を使用して必要な場合にのみロジックをアクティブにすることを検討してください。この場合、scan_davダウンストリーム モジュール内部の立ち上がりエッジ遷移を検出し、その遷移が発生したときにのみ反応します。検出ロジックは、モジュールと同じクロックで実行されscan_davます。

二重文字が表示される理由をこれで説明できるとは思いません。分析するコードを投稿する必要があります。ただし、ロジックからクロックを駆動しないように再ツールすることをお勧めします。

于 2012-12-19T15:58:06.753 に答える
1

私が正しく見れば、キーを離すときに F0 を避けますが、2 番目のスキャンコードをフィルタリングしません。いつもこんな感じです

スキャンコード --- キー F0 を押します --- キースキャンコードを解放します

一部のキー (ALT GR など) では、E0 も取得できます。

完全な説明ではありませんが、最も重要で考えられることを示しています。 http://en.wikipedia.org/wiki/Scancode

これにより、説明されている問題が発生します。フライ -> FFLLYY。

于 2012-12-20T19:08:20.440 に答える