这部分代码是小伙伴写的,我负责修正和综合,在修正过程中解决了一个问题,个人感觉这个经验应该非常有用。小伙伴写的倒计时代码内嵌了一个校时模块,拿到手,仿真后发现了一个问题:我自己写的校时模块是每个按键对应一个进程,用该按键变化作为进程的边沿触发,而小伙伴的代码由于把校时并入其中,所以只能使用时钟作为边沿触发。在按键按下时,倘若以按键变化触发,那只需要做好按键消抖就好。但以时钟作为边沿触发时,校时部分只能这样写
IF clk'event and clk='1' THEN
IF key2='0' THEN
IF h2="1001" THEN
h2<= "0000";
IF h1="1001" THEN
h1 <= "0000";
ELSE
h1 <= h1 + '1';
END IF;
ELSE
h2 <= h2 + '1';
END IF;
END IF;
END IF;
这样带来一个非常大的问题,就是每次按键按下的时间肯定不止一个时钟周期,这样每次按下,校时都会触发很多次。由消抖的启发我找到了这个问题的解决方法:
process(clk)
begin
if clk'event and clk='1' then
temp2_1<=key2;
temp2_2<=temp2_1;
tempkey2<=temp2_1 xnor temp2_2;
end if;
end process;
这个原理跟消抖一模一样,不赘述,关键是这个进程能在每次按键按下时,无论按下多久,都只会产生一个脉冲信号,而且是在按键一按下就产生。
IF key2='0' THEN
IF tempkey2='0' then
IF h2="1001" THEN
h2<= "0000";
IF h1="1001" THEN
h1 <= "0000";
ELSE
h1 <= h1 + '1';
END IF;
ELSE
h2 <= h2 + '1';
END IF;
END IF;
然后用这个脉冲作为启动信号,问题完美解决。这个经验的有用之处在于,众所周知双时钟在是VHDL里面是被禁止的,而它能解决所有需要双时钟的情况,非常有用。