我正在网上修改一个简单的键盘接口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的一个问题,但我无法解决它是什么问题。任何帮助将不胜感激。
答案 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。