OpenEdv-开源电子网

标题: 请问always块电平触发时,每次电平改变,always块只执行一次吗? [打印本页]

作者: kqkqk    时间: 2019-9-2 17:11
标题: 请问always块电平触发时,每次电平改变,always块只执行一次吗?
在触摸按键那一节的实验中,我想这个触摸键应该不用按键消抖,就准备不用时钟信号,直接电平触发了,下面是我写的代码:
module key_touch(input touch,output reg led);
always@(touch)
begin
  if(touch==1)
   led=~led ;
end
endmodule
我的想法是每次检测到电平变化,就检测一次电平信号是不是高电平,如果是高的话就改变led信号变化,结果把程序烧到fpga里并不能达到触摸按键改变灯亮灭。
检查rtl视图发现quartus是只生成了一个锁存器,然后touch接锁存器的使能端,锁存器的输出取反接输入。
这样的话,只要是touch为高电平,led的信号就一直发生变化,并不是我所设想的touch信号变一次,always块执行一次而是always块一直在执行。
请问问题出在哪,是我对always的理解有问题还是这段程序逻辑有什么错误?

作者: candylife9    时间: 2019-9-2 17:11
本帖最后由 candylife9 于 2019-9-9 09:52 编辑

不是你对alway理解有问题,是你用软件的思维去设计硬件。综合结果是没有问题的,硬件行为也是按照你描述的去做的。就这个例子来说,你硬件描述语言被综合之后,就会生成这个锁存器,而不是在运行的时候,或者说touch改变的时候才生产的,它就是个硬件电路,就一直在那里,但是这个电路的行为是在描述语言里面定义的,硬件是没有什么运行的概念的。你这里是描述了一个锁存器的功能,就是在touch有效的时候,取反led。硬件是一直有效的,而你是把verilog当成了软件,想成了他是一条一条执行的。------------我的想法是每次检测到电平变化,就检测一次电平信号是不是高电平,如果是高的话就改变led信号变化-------------,你这个想法,很明显就是软件思维,硬件的思维是:不管touch有没有变化,led都会有输出的(不管touch有没有变化,touch的电平都会对led状态有影响,而不是变的时候才检测一次)。

重点:1.你这个例子,begin--end里面的行为就是描述了一个带使能的反相器。(alway描述的就是使能端有效或无效)
          2.你没有理解硬件描述语言。
          3.verilog是硬件描述语言,它描述硬件的行为,是描述,描述,描述,而不是硬件需要执行的代码,代码,代码。

作者: 正点原子    时间: 2019-9-3 02:45
帮顶
作者: LíuQían    时间: 2019-9-3 09:33
电平发生变化的时候,不论从高到底还是从低到高,都会触发,这个程序我也不知道错在哪儿了,帮顶,或者你可以改成touch边沿触发试试
作者: kqkqk    时间: 2019-9-3 17:35
LíuQían 发表于 2019-9-3 09:33
电平发生变化的时候,不论从高到底还是从低到高,都会触发,这个程序我也不知道错在哪儿了,帮顶,或者你可 ...

改成边沿触发就得用原子的代码检测高电平了,我就想看看这个这个代码的问题错误出现在哪
作者: LíuQían    时间: 2019-9-3 19:19
kqkqk 发表于 2019-9-3 17:35
改成边沿触发就得用原子的代码检测高电平了,我就想看看这个这个代码的问题错误出现在哪

会不会是 硬件的问题 你知道modlesim吗,装一个 然后写一下测试代码 看一下结果,可能触摸了以后,电平就是不稳定,会来回跳
作者: kqkqk    时间: 2019-9-4 11:37
LíuQían 发表于 2019-9-3 19:19
会不会是 硬件的问题 你知道modlesim吗,装一个 然后写一下测试代码 看一下结果,可能触摸了以后,电平就 ...

应该不是硬件的问题,电路图生成锁存器就应该是错的,而且如果有按键抖动的话,原子的代码也不对
作者: denike    时间: 2019-9-4 16:42
本帖最后由 denike 于 2019-9-4 16:44 编辑

module key_touch(input touch,output reg led);
always@(touch)
begin
  if(touch==1)
   led=~led ;
else
led=led ;
end
endmodule
改成这样才不会生成锁存器,if else 最好要写全
作者: QinQZ    时间: 2019-9-6 16:01
直接 assign led = touch即可。
作者: candylife9    时间: 2019-9-6 16:31
FPGA是数字电路,一个上升沿对应着一次电路状态的刷新,就跟刷新一个网页一样,不要按照代码的思维去理解FPGA的verilog。另外,这不叫作代码,叫硬件描述语言。
作者: MY40130064    时间: 2019-9-6 18:01
always@(posedge touch)
        begin
        led<=!led ;
          end
作者: kqkqk    时间: 2019-9-6 19:14
QinQZ 发表于 2019-9-6 16:01
直接 assign led = touch即可。

那样的话,不就是触碰按键,led亮,离开按键led灭了吗,和要求不符啊
作者: kqkqk    时间: 2019-9-6 19:16
candylife9 发表于 2019-9-6 16:31
FPGA是数字电路,一个上升沿对应着一次电路状态的刷新,就跟刷新一个网页一样,不要按照代码的思维去理解FP ...

谢谢 你回复,但我感觉你好像没明白我的问题……
作者: kqkqk    时间: 2019-9-6 19:23
MY40130064 发表于 2019-9-6 18:01
always@(posedge touch)
        begin
        led

这两个逻辑应该是一样的吧,把你代码综合后生成的rtl图还是和之前一样的
作者: QinQZ    时间: 2019-9-8 09:15
kqkqk 发表于 2019-9-6 19:14
那样的话,不就是触碰按键,led亮,离开按键led灭了吗,和要求不符啊

如果你想触摸一次,改变LED的状态,那么只能像例程一样去采上升沿了
作者: MY40130064    时间: 2019-9-9 09:09
(, 下载次数: 4)