AAT
发表于 2010-6-26 11:29:27
抖动肯定会有,所以应该有消抖动处理。<br>
<br>
10#建议正点, 对于任何一个设计都应该先做仿真测试再下载测试的,这样就可以确定是设计问题还是硬件的问题。
ATA
发表于 2010-6-26 12:21:18
我用的Quartus II 是 Web Edition版本,好象是过期了,不能防真<br>
我有做软件消抖的
FFT
发表于 2010-6-26 13:24:28
楼主的代码中,如果要消除锁存器,一种就是进程用时钟触发。另一种就是把<br>
if key=0 的else条件补冲。不过第二种有个问题,如果你的key不是锁存过的信号,直接按键输入的话,保持0或1的时间就太短了,还是不能达到要求。<br>
至于敏感变量,是为了让实际电路和仿真行为一致。如果敏感变量不放在process中,仿真软件在这个变量变化时不会触发进程。而实际电路是已经存在的电路,不会有这种情况。
tim
发表于 2010-6-26 14:09:47
按键输入是一定要消抖的,另外最好用同步电路实现。<br>
楼主的设计就会出现在一次按下按键时,出现多次‘0’和‘1’的抖动,因此led就会亮灭多次,最后稳定在一个状态。
CHANG
发表于 2010-6-26 15:35:30
我用过时钟触发出发的方式,下面是我实现这个功能的程序,大家看看有什么问题吗?<br>
<br>
SIGNAL flag: STD_LOGIC:='0'; ---一个标志位<br>
SIGNAL key,flag1,flag2:STD_LOGIC;<br>
SIGNAL counter: STD_LOGIC_VECTOR(3 DOWNTO 0):="0000";<br>
key<=counter(0) AND counter(1) AND counter(2) AND counter(3);<br>
<br>
------------------------------------------按键消抖------------------------------------------------------<br>
--原理就是当有按键按下时,key_pre会变成低电平,这时把flag2变成高电平 --<br>
--flag2的变化会引发最后一个进程,flag2变成高电平,并且counter不为 --<br>
--“1111”时flag1变为高电平,内部计数器开始计数,从“0000”到“1111” --<br>
-- 当计数到“1111”时,key输出高电平 --<br>
PROCESS(GCLK)<br>
BEGIN<br>
IF (GCLK'event and GCLK='1') THEN<br>
IF flag1='0' THEN<br>
counter<="0000";<br>
ELSE<br>
counter<=counter+1;<br>
END IF;<br>
END IF;<br>
END PROCESS;<br>
PROCESS(GCLK)<br>
BEGIN<br>
IF (GCLK'event and GCLK='1') THEN<br>
IF key_pre='0' THEN --低电平则有按键按下<br>
IF flag2='0' THEN --按键处理<br>
flag2<='1';<br>
END IF;<br>
ELSIF flag1='0' THEN<br>
flag2<='0';<br>
END IF;<br>
END IF;<br>
END PROCESS;<br>
PROCESS(flag2,counter)<br>
BEGIN <br>
IF flag2='1' THEN<br>
IF counter="1111" THEN --计数到,去抖动<br>
flag1<='0';<br>
ELSE<br>
flag1<='1'; --否则,继续计数<br>
END IF;<br>
END IF;<br>
END PROCESS;<br>
--------------------------------------------------------------------------------------------------------------------<br>
<br>
PROCESS(GCLK,key)<br>
begin<br>
IF (GCLK'event and GCLK='1') THEN <br>
IF key='1' THEN --按键被按下<br>
IF flag='0' THEN <br>
flag<='1';<br>
ELSE <br>
flag<='0';<br>
END IF;<br>
IF flag='1' THEN<br>
LED<='0'; --标志为为 1 时,LED灯亮<br>
ELSE<br>
LED<='1'; --标志为为 0 时,LED灯灭<br>
END IF;<br>
END IF; <br>
END IF;<br>
END PROCESS;<br>
<br>
[ 本帖最后由 FerrariTim 于 2007-1-25 10:35 编辑 ]
usd
发表于 2010-6-26 16:35:55
看不懂。你要做的不是在你按key的时候你的二极管不停开关(当然眼睛看到的都是亮的),放开的时候随机停在1或者0吗。。。到底你的目的是什么哦。
UFP
发表于 2010-6-26 17:37:22
我的目的是,按一下按键,LED灯亮,再按一下按键(同一个按键),LED灯灭,如此循环<br>
<br>
toyibm,谢谢你提醒了我,我这样写的话,按键被按下的时候,LED灯一直是处于变化的过程(开关开关...),放手的时候,就成了随机的了<br>
<br>
[ 本帖最后由 FerrariTim 于 2007-1-29 13:27 编辑 ]
interig
发表于 2010-6-26 18:49:57
我觉得你先用一个D触发器,将Q反端连接DIN端,试试行不行吧,这是最简单的方法,按键接CP时钟端,功能是一样的,先试试吧~~
CHAN
发表于 2010-6-26 20:36:55
去陡的话可以用下面的代码(Verilog):<br>
reg key_in,key_d;<br>
reg key_out;<br>
<br>
always(posedge clk)<br>
begin<br>
key_d<=~key_in;<br>
end<br>
<br>
always(posedge clk)<br>
begin<br>
key_out<= key_d && key_in;<br>
end<br>
<br>
我电脑不能连网,上面的代码语法没有验证过,但原理是验证过的,各位可以验证下<br>
<br>
[ 本帖最后由 lg20025779 于 2007-1-29 14:34 编辑 ]
longtim
发表于 2010-6-26 21:10:28
支持18楼,建议写个rs触发器,再加一个翻转器就能搞定了,不用那么复杂