描述
最近在vivado中设计一个计算器: 28bit有符号加减法,结果出现行为仿真和时序仿真不一致情况
代码
r_a, r_b : 对计算数据a, b的寄存器存储, 也是计算器的数据输入
s_bit : 符号位
cout : 28bit计算器的进位输出 cout[27] : 最高位进位, 用来判断符号以及加法进位
always@(a, b) begin // 1
// always@(r_a, r_b) begin // 2
case({a[27], b[27]} // 1
case({r_a[27], r_b[27]}) // 2
2'b00: s_bit = 1'b0;
2'b01: s_bit = cout[27] ? 1'b0 : 1'b1;
2'b10: s_bit = cout[27] ? 1'b0 : 1'b1;
2'b11: s_bit = 1'b1;
default:s_bit = s_bit;
endcase
end
输出结果代码
always@(posedge clk or negedge rstn) begin
if(!rstn)
result <= 'd0;
else
result <= {s_bit, sum};
end
当条件为1时行为仿真错误,时序仿真正确, 如下
当条件为2时行为仿真和时序仿真均正确 , 如下
说明
此处的敏感信号列表只有当为r_a, r_b时结果才正确,其他情况均错误
分析
t0 : a0, b0 变化,cout0 = 0, case0 = 2'b00, s_bit0 = 0
t1 : r_a0, r_b0 变化并且开始进行计算,cout1 = 0, case1 = 2'b00, s_bit1 = 0
t2 : a1, b1 变化, cout1 = 0, case = 2'b01, s_bit = 1
t3 : r_a1, r_b1 变化开始进行计算, cout3 = 1, case = 2'b01, s_bit = 1
为什么会发生错误呢?
t0 : a, b变化, 但是此时的cout = 0, 并不是因为计算等于0 ,因为此时并未开始计算,所以s_bit也会错误
t1 : r_a, r_b 变化,开始计算,现在的cout是正确的,但是此时并不更新s_bit,因为敏感信号没有变化
t2 : a, b发生变化, 但是此时的cout却是上一个r_a, r_b计算的结果,但是我们在此时对s_bit进行赋值,还是会发生错误
t3 : 终于输出计算结果, 但是此时的s_bit是错误的, 因为cout与case并不同步, case超前于cout一个上升沿(而非一个clk)
所以,在设计的时候一定要分析好时序, 尽管s_bit使用的是组合逻辑, 但是,在仿真过程中出现了case选项和条件值不同步的情况
另外
代码块A
always@(a, b) begin
case({a[27], b[27]})
2'b00: s_bit = 1'b0;
2'b01: s_bit = cout[27] ? 1'b0 : 1'b1;
2'b10: s_bit = cout[27] ? 1'b0 : 1'b1;
2'b11: s_bit = 1'b1;
default:s_bit = 1'b0;
endcase
end
代码块B
always@(*) begin
case({a[27], b[27]})
2'b00: s_bit = 1'b0;
2'b01: s_bit = cout[27] ? 1'b0 : 1'b1;
2'b10: s_bit = cout[27] ? 1'b0 : 1'b1;
2'b11: s_bit = 1'b1;
default:s_bit = 1'b0;
endcase
end
代码块B 等价于 代码块A, 废话,肯定等价
我的意思是,always@(*) 会自动将case(a,b)变成敏感信号,从而变化为always@(a, b), 其他信号变化无用
如果你的控制变量是别的, 综合工具(此处是vivado)会将控制信号变为敏感信号.
本篇结束,大家设计代码一定要注意时序匹配
标签:仿真,case,27,cout,时序,b0,verilog,bit,b1 From: https://www.cnblogs.com/tiruo/p/17896491.html