VHDL - 从另一个模块的输出信号中制作时钟

时间:2012-12-19 10:11:05

标签: text keyboard project vhdl clock

我正在网上修改一个简单的键盘接口found供我使用。这个想法是每当有新的扫描码时,它会将输出命名为" Scan_Dav"走高,然后走低。因此,当我将Scan_Dav指向另一个模块作为时钟时,只要按下新的ScanCode,该模块的时钟就会有一个上升沿。我的思维方式有什么错误吗?因为我尝试了它并将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的来源,代码来自here: (您可以忽略过滤部分)

    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的一个问题,但我无法解决它是什么问题。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

从逻辑输出驱动时钟输入通常是不好的做法(并且一些FPGA架构根本不允许它)。当源于器件内部的专用时钟逻辑时,时钟运行最佳,良好的设计应最大限度地减少时钟数。理想情况下,你只有一个,但这并不总是可能的。

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

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

答案 1 :(得分:1)

如果我看得正确,则在释放Key时避开F0但不过滤第二个扫描码。 它总是像这样

扫描码---按键 F0 --- relesase Key 扫描码

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

它没有完整的描述,但显示最重要和认为。 http://en.wikipedia.org/wiki/Scancode

这会导致描述性问题。飞 - &gt; FFLLYY。