编写模块时,遇到了信号仿真变成红色未定态X的问题,经过仔细检查,发现是always块内部编写出现错误,这里进行记录:
错误代码:
//key_f
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
key_f <= 1'b1;
if(cnt_L > delay)
key_f <= 1'b0;
else if(cnt_H > delay)
key_f <= 1'b1;
else
key_f <= key_f;
end
错误波形:
可以看到在达到设置的计数器之前,key_f信号一直是未定状态。
这是由于代码编写时第二个if前面忘记加else导致的。
没有加else导致代码逻辑变成这样:
如果通过复位下降沿或者时钟上升沿,进入了always;
开始判断一下复位信号,如果为低,将key_f信号置为高电平,然后本应退出模块。
但是这里继续运行后面的if,前两项if计数器因为程序刚开始,计数器初值都赋的是0,所以没有进入if,直接进入最后的else;
虽然前面进行了赋值,但是这里还在过程块内,并行执行的过程块并不知道key_f的值,所以右侧是未定状态,在过程块结束后,key_f被赋值两次第一次是1,第二次是未定,以最后一次为准,所以前面全是未定状态。
(关于为什么赋值两次以第二次为准,可以看下一篇测试文章,我现在也不知道结果等下试试)
这里我又测试了一下,加入了更多逻辑,这里已经非常混乱,又加了两行if else
//key_f
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
key_f <= 1'b1;
if(cnt_L > delay)
key_f <= 1'b0;
else if(cnt_H > delay)
key_f <= 1'b1;
else
key_f <= key_f;
if(cnt_L < delay)
key_f <= 1'b1;
else
key_f <= 1'b0;
end
这样就有可能被赋值三次,所以当加了太多if else之后前面的全都失效了,下面是波形图
把上面的逻辑全部注释掉,结果也是一样的:
//key_f
always @(posedge sys_clk or negedge sys_rst_n) begin
// if(!sys_rst_n)
// key_f <= 1'b1;
// if(cnt_L > delay)
// key_f <= 1'b0;
// else if(cnt_H > delay)
// key_f <= 1'b1;
// else
// key_f <= key_f;
if(cnt_L < delay)
key_f <= 1'b1;
else
key_f <= 1'b0;
end
没有任何区别。
总结
1.always块中只写一个{if else if ……else}组合,是合理的,如果写了大量{if else if ……else}组合就会导致赋值非常混乱,前面的很多逻辑就会失效,会带来很多问题
2.在一个always块中,前面对一个变量赋值之后,后面是无法调取变量的最新值的,调取的还是上一次的值,需要注意