0

我正在修改我在网上找到的一个简单的键盘界面以供我使用。这个想法是每当有一个新的扫描码时,它会使名为“Scan_Dav”的输出变高,然后变低。因此,当我将 Scan_Dav 作为时钟指向另一个模块时,只要按下新的 ScanCode,该模块的时钟就会有一个上升沿。我的思维方式有什么错误吗?因为我尝试了它并将扫描码和 scan_dav 定向到我的项目的其余部分 - 它与给定的扫描码并排写字母并在七段显示器上显示它们 - 显示的文本每个字符有 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 架构根本不允许这样做)。时钟来自器件内部的专用时钟逻辑时运行最佳,良好的设计应尽量减少时钟数量。理想情况下,您只有一个,但这并不总是可能的。

与其从逻辑运行时钟输入,不如考虑从一个时钟运行所有内容,并仅在需要时使用“启用”来激活逻辑。在这种情况下,您将检测到下游模块内部的上升沿转换,scan_dav并且仅在该转换发生时才做出反应。scan_dav检测逻辑将使用与模块相同的时钟。

我认为这不能解释为什么你会看到双字符,你需要发布一些代码来分析。但是,我建议您重新工具以不从逻辑驱动时钟。

于 2012-12-19T15:58:06.753 回答
1

如果我没看错,您在释放密钥时避免 F0,但您不过滤第二个扫描码。总是这样

Scancode --- 按 Key F0 --- 释放 Key Scancode

在某些键(例如 ALT GR)上,您也可以获得 E0。

它不是完整的描述,但显示了最重要的想法。 http://en.wikipedia.org/wiki/Scancode

这将导致所描述的问题。飞 -> FFLLYY。

于 2012-12-20T19:08:20.440 回答