945595199 发表于 2016-7-30 23:06:23

新手请教一个verilog代码的问题,就一个命令。

小弟最近刚学verilog,我看网上的教程中,基本的模子就是 always@(posedge CLK or negedge RESET)
我试着写了如下代码:
(目的是每按一次按键,8个led就翻转一次)
output wire ledR,
reg rledR;
always@(posedge CLK or negedge key0)
begin
        if(!key0)
                rledR = ~rledR;
end
assign ledR = rledR;

但实际情况是8个led随机亮灭。
但是如果在always敏感条件中去掉"posedge CLK ",结果就正常了。
想问下,是什么原因?
下面是仿真波形:

945595199 发表于 2016-7-30 23:07:55

不好意思,图发大了。

945595199 发表于 2016-7-30 23:20:32

在线做等,有人不{:lol:}

945595199 发表于 2016-7-31 00:41:50

{:biggrin:}

huangguimina4 发表于 2016-7-31 00:53:00

按键都没消抖处理,正常就怪了

945595199 发表于 2016-7-31 02:20:29

de2的板子已经硬件消抖了

tangwei039 发表于 2016-7-31 07:22:13

CLK 检测好多次,出现亮或灭,判断按键沿

champion_yan 发表于 2016-7-31 07:35:49

将key0,打两拍,检测key0的边沿,根据是检测上升沿还是下降沿,能实现按下去就翻转还是松手翻转。

另外外部信号不做时钟同步,不是个好习惯

ArthurBruin 发表于 2016-7-31 10:02:38

always@(posedge CLK or negedge key0)
信号别加在敏感列表中,最基本的习惯

gwj221 发表于 2016-7-31 10:15:30

你的clk有用吗

simplorer 发表于 2016-7-31 10:18:13

没有打拍,而且信号直接搞到了列表中,全是坏习惯。

945595199 发表于 2016-7-31 10:25:40

tangwei039 发表于 2016-7-31 07:22
CLK 检测好多次,出现亮或灭,判断按键沿

但按键下降沿只会检测到一次吧,CLK到来时,我若不按,并不满足条件 if(!key0)吧 ,那就什么也不执行

945595199 发表于 2016-7-31 10:29:13

gwj221 发表于 2016-7-31 10:15
你的clk有用吗

没有用,所以我只是试一下,但结果就不对了,不知道什么原因

945595199 发表于 2016-7-31 10:39:44

champion_yan 发表于 2016-7-31 07:35
将key0,打两拍,检测key0的边沿,根据是检测上升沿还是下降沿,能实现按下去就翻转还是松手翻转。

另外外 ...

打两拍是什么意思?我现在就是下降沿(按下去)就翻转的,
另外,我这里外部时钟需要同步什么吗?不明白..

stdio 发表于 2016-7-31 11:27:26

试试这个:
always @ (negedge key0)
    rledR <= ~rledR;

945595199 发表于 2016-7-31 11:47:47

stdio 发表于 2016-7-31 11:27
试试这个:
always @ (negedge key0)
    rledR

这个当然可以了,我上面也说过了

why1220 发表于 2016-7-31 12:24:50

always@(posedge CLK)不要把敏感信号key0放里面;虽然always @ (negedge key0)做做代码小实验是可行的,但不实用,因为key0是有抖动的,放always里在抖动的过程会执行若干次并且没有办法做去抖动处理的,led还好,若是白炽灯早被你闪爆了!

945595199 发表于 2016-7-31 12:52:41

why1220 发表于 2016-7-31 12:24
always@(posedge CLK)不要把敏感信号key0放里面;虽然always @ (negedge key0)做做代码小实验是可行的,但不 ...

恩,我知道你的意思,但那8个灯的亮灭是随机的,你看上面的时序就是这样,比如57h,aah,6eh...而不是ffh,00h

jm2011 发表于 2016-7-31 13:09:46

"但是如果在always敏感条件中去掉"posedge CLK ",结果就正常了。" 你的复位一直有效的吧;你把RESET的信号也抓出来看一下;

1:对于DE2的板子,判断按键是否按下,应该判断下降沿或者上升沿;
2:还是按键对于clk是异步信号,应该使用两级DFF稳定一下;

guzhen24 发表于 2016-7-31 16:11:00

随机亮灭说的有点模糊,是不是按下按钮有时会有效,有时会无效?

wiser803 发表于 2016-7-31 17:20:05

always@(posedge CLK or negedge key0)   ,一看就是错误的。
原因是,在一个基本逻辑的敏感表里,不能有两个以上的不同边沿触发。
试想一下,如果允许两个以上的不同边沿触发发生在一个基本逻辑里,那么你的设计将对应什么样的基本逻辑电路?
答案是,找不到这样的基本逻辑电路来对应,尽管你觉得硬件描述语言语法上似乎是站得住脚的(类似C语言)。但硬件描述语言,必须有对应硬件可实现,软件语言只是个实现硬件设计的载体和工具而已。
解决方法,就是将你的思维再细化一点,一直细分到每个 always@() 里只有一个边沿触发事件(电平敏感可任意),然后再将N个 always@() 关联起来即可。

lulinchen 发表于 2016-7-31 18:40:59

key0 又不是one clk wide pulse 翻转多少次是随机的

sme 发表于 2016-8-1 09:24:07

本帖最后由 sme 于 2016-8-1 09:26 编辑

晕,这么多人都没扯到点子上。

1
always@(posedge CLK or negedge key0)
begin
      if(!key0)
                rledR = ~rledR;
end
楼主的以上代码的写法,key0是作为异步复位/置位,即异步置数,在这里由于CLK没有使用到,所以电路实际上是一个8位的LATCH,即电平有效的锁存器,其8位输出端/Q接至D,这样即是一个死循环的电路,D -> Q -> /Q -> D,最后Q的状态取决于key0的上升沿。但是在key0为低电平的整个脉宽时间内(再重复,key0是电平信号),LATCH一直在翻转,由于8个LATCH从D至/Q的延时不可能绝对一致,所以虽然每个LATCH都是自身取反,但8个之间并不同步,这样就会出现楼主位的波形,看上去8个LATCH的结果是随机的。

2
但是如果在always敏感条件中去掉"posedge CLK ",结果就正常了。

这样修改后的代码,就变成了8个DFF,所以在key0的每次下降沿,DFF只会翻转一次,而且8个DFF的状态会一致。

易尘 发表于 2016-8-1 10:14:30

你这个是既检测clk也检测key0

huanger 发表于 2016-8-1 10:27:44

不去除clk,当key0按下后它会一直取反跳动,因为变化太快了人眼发现不了的!

jjl3 发表于 2016-8-1 16:08:23

huanger 发表于 2016-8-1 10:27
不去除clk,当key0按下后它会一直取反跳动,因为变化太快了人眼发现不了的! ...

这是根本原因,人按下键是毫秒级的,你clk是多少?

945595199 发表于 2016-8-1 21:42:12

sme 发表于 2016-8-1 09:24
晕,这么多人都没扯到点子上。

1


你说的有道理,不过我不太明白为什么key0是电平信号?为什么成了电平锁存器?不应该是只有当key0下降沿时才满足always的条件吗?其他时候并不满足negedge key0呀,我可能还不太了解verilog是依据什么来对应硬件电路的

sme 发表于 2016-8-2 08:29:57

945595199 发表于 2016-8-1 21:42
你说的有道理,不过我不太明白为什么key0是电平信号?为什么成了电平锁存器?不应该是只有当key0下降沿时 ...

always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
...
else
...
end
这种写法,rst_n是作为复位信号。而且是异步复位,为低电平有效,非边沿有效。

如果你是一组信号,非单个信号,例如
q <= 8'h5a;

则rst_n对赋值为0的位是复位,对赋值1的位是置位。

同理,如果赋值的不是常量,则是会从RST/SET端赋值过去,例如
q <= a;   // a is some signals

你的写法,实际上是将一组8位寄存器的QB再通过DFF的RST/SET端置进去,同时,因为你没有else部分,因此clk没有起作用。即电路如下:

QB -> SET/RESET -> QB

这形成了一个loop,而且延时就是器件延时。
页: [1]
查看完整版本: 新手请教一个verilog代码的问题,就一个命令。