新手请教一个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 ",结果就正常了。
想问下,是什么原因?
下面是仿真波形:
不好意思,图发大了。 在线做等,有人不{:lol:} {:biggrin:} 按键都没消抖处理,正常就怪了 de2的板子已经硬件消抖了 CLK 检测好多次,出现亮或灭,判断按键沿 将key0,打两拍,检测key0的边沿,根据是检测上升沿还是下降沿,能实现按下去就翻转还是松手翻转。
另外外部信号不做时钟同步,不是个好习惯 always@(posedge CLK or negedge key0)
信号别加在敏感列表中,最基本的习惯 你的clk有用吗 没有打拍,而且信号直接搞到了列表中,全是坏习惯。 tangwei039 发表于 2016-7-31 07:22
CLK 检测好多次,出现亮或灭,判断按键沿
但按键下降沿只会检测到一次吧,CLK到来时,我若不按,并不满足条件 if(!key0)吧 ,那就什么也不执行 gwj221 发表于 2016-7-31 10:15
你的clk有用吗
没有用,所以我只是试一下,但结果就不对了,不知道什么原因 champion_yan 发表于 2016-7-31 07:35
将key0,打两拍,检测key0的边沿,根据是检测上升沿还是下降沿,能实现按下去就翻转还是松手翻转。
另外外 ...
打两拍是什么意思?我现在就是下降沿(按下去)就翻转的,
另外,我这里外部时钟需要同步什么吗?不明白.. 试试这个:
always @ (negedge key0)
rledR <= ~rledR;
stdio 发表于 2016-7-31 11:27
试试这个:
always @ (negedge key0)
rledR
这个当然可以了,我上面也说过了 always@(posedge CLK)不要把敏感信号key0放里面;虽然always @ (negedge key0)做做代码小实验是可行的,但不实用,因为key0是有抖动的,放always里在抖动的过程会执行若干次并且没有办法做去抖动处理的,led还好,若是白炽灯早被你闪爆了! why1220 发表于 2016-7-31 12:24
always@(posedge CLK)不要把敏感信号key0放里面;虽然always @ (negedge key0)做做代码小实验是可行的,但不 ...
恩,我知道你的意思,但那8个灯的亮灭是随机的,你看上面的时序就是这样,比如57h,aah,6eh...而不是ffh,00h "但是如果在always敏感条件中去掉"posedge CLK ",结果就正常了。" 你的复位一直有效的吧;你把RESET的信号也抓出来看一下;
1:对于DE2的板子,判断按键是否按下,应该判断下降沿或者上升沿;
2:还是按键对于clk是异步信号,应该使用两级DFF稳定一下; 随机亮灭说的有点模糊,是不是按下按钮有时会有效,有时会无效? always@(posedge CLK or negedge key0) ,一看就是错误的。
原因是,在一个基本逻辑的敏感表里,不能有两个以上的不同边沿触发。
试想一下,如果允许两个以上的不同边沿触发发生在一个基本逻辑里,那么你的设计将对应什么样的基本逻辑电路?
答案是,找不到这样的基本逻辑电路来对应,尽管你觉得硬件描述语言语法上似乎是站得住脚的(类似C语言)。但硬件描述语言,必须有对应硬件可实现,软件语言只是个实现硬件设计的载体和工具而已。
解决方法,就是将你的思维再细化一点,一直细分到每个 always@() 里只有一个边沿触发事件(电平敏感可任意),然后再将N个 always@() 关联起来即可。
key0 又不是one clk wide pulse 翻转多少次是随机的 本帖最后由 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的状态会一致。
你这个是既检测clk也检测key0 不去除clk,当key0按下后它会一直取反跳动,因为变化太快了人眼发现不了的! huanger 发表于 2016-8-1 10:27
不去除clk,当key0按下后它会一直取反跳动,因为变化太快了人眼发现不了的! ...
这是根本原因,人按下键是毫秒级的,你clk是多少? sme 发表于 2016-8-1 09:24
晕,这么多人都没扯到点子上。
1
你说的有道理,不过我不太明白为什么key0是电平信号?为什么成了电平锁存器?不应该是只有当key0下降沿时才满足always的条件吗?其他时候并不满足negedge key0呀,我可能还不太了解verilog是依据什么来对应硬件电路的 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]