我遇到了Verilog乘法器模块的问题

时间:2018-09-23 07:06:07

标签: verilog

给出的图片是我要表达的模块。 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

2 个答案:

答案 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,在那里使用了<=