给出的图片是我要表达的模块。 MulCell
由于某种原因,我不得不使用线从数字数组中调出被乘数或乘数。 ex)wire [3:0] abc = 4'b1111;
但是很奇怪!当我将导线abc的特定值分配给“乘数”时,它工作良好。但是,如果将其分配给“被乘数”,则会看到红线,就像在图片中一样。 redline
知道发生了什么问题吗?谢谢
MulCell代码
module MulCell(Multiplicand,Multiplier,Sin,Cin,Sout,Cout);
input Multiplicand,Multiplier,Sin,Cin;
output Sout,Cout;
reg Sout,Cout;
wire tmp;
assign tmp=Multiplicand&Multiplier;
always@(tmp) begin
{Cout,Sout} <= tmp+Sin+Cin;
end
endmodule
testbench_MulCell的代码
`timescale 1ns/1ns
module testbench_MulCell();
reg Multiplicand,Multiplier,Sin,Cin;
wire Sout,Cout;
MulCell MC(Multiplicand,Multiplier,Sin,Cin,Sout,Cout);
wire [3:0]abc;
assign abc=4'b1111;
initial begin
Multiplicand=abc[2];
Multiplier=1'b1;
Sin=1'b1;
Cin=1'b1;
#10 //expecting 11
Multiplicand=1'b0;
Multiplier=abc[1];
Sin=1'b1;
Cin=1'b1;
#10 $stop;//expecting 10
end
endmodule
答案 0 :(得分:1)
我可能是错的,但是似乎在向abc
赋值和运行initial
块之间存在竞争条件。在初始块开始运行时,assign abc =..
尚未执行。这就是为什么在波形视图中出现x
/ red_lines的原因。
答案 1 :(得分:0)
Verilog是事件驱动的模拟器。这意味着每个“ always ...”,“ assign”块均具有输入和输出。 Always块中的输入由其敏感度列表表示。在您的情况下,将是tmp
信号。当且仅当检测到输入变化时,整个模块才会开始评估。
此外,在模块中,initial
被安排为在仿真期间执行一次,并且始终在任何Always块之前执行(始终优先执行)(在系统Verilog中为特殊情况除外)。因此,在您的情况下,在 assign 语句的之前执行初始块的前几个语句(在第一个#10之前)。因此,对于abc
的前10个周期,值将为`4bxxxx ,这将说明您的红线。出于同样的原因,值。结果,被乘数的值以及 MC / tmp,Sout,Cout 的值也将为“ x”。
在#10处,您将更改变量的值,从而使MC中的总是block会重新评估为新值。到那时abc已经设置为 1111 ,所有的“ x”都消失了。
因此,有效地,您仅模拟了第二组值,但模拟了第一组。 建议是:在初始块前面添加一个小的延迟:
initial begin
#1
Multiplicand=abc[2];
Multiplier=1'b1;
Sin=1'b1;
这将延迟语句的执行,并且此时将设置'abc'的值。红线会有一小段时间(1),但是您会看到所设置值的结果。
另一种可能性是首先在初始块中设置abc的值,但是您需要一个 reg 变量来实现:
reg[3:0] abcSet;
assign abc = abcSet;
initial begin
abcSet = 4'b1111;
...
另一件事,在始终阻止中,您使用非阻止分配(<=)。不要!这对触发器和锁存器有利,但对简单的组合逻辑不利。在其中使用常规作业(=)。
{Cout,Sout} = tmp+Sin+Cin;
此外,如果您仅更改Sin或Cin并且tmp保持不变,则不会始终评估此阻止。您应该将它们添加到灵敏度列表中:
always @(tmp, Sin, Cin)
或使用always @*
代替。实际上,始终使用此构造而不是常规的V95 Always Block是一个好主意。这样,您就可以避免设计中可能存在的隐式闩锁(例如,就灵敏度列表的缺失部分而言)。
此外,通常大多数现代设计都是同步设计,并使用时钟信号进行同步。在您的情况下,多生产商的售货机也应同步,则您需要提供一个切换时钟信号。在这种情况下,您的操作可能如下所示:
always @(posedge clk)
{Cout,Sout} <= tmp+Sin+Cin;
它使评估发生在clk
信号的上升沿,它是灵敏度列表中的唯一成员。所有其他信号应在时钟更改之前设置。是的,它是flop
,在那里使用了<=
。