我认为你在用
always
陈述和连续作业。正如前面提到的其他用户,我也认为如果你能看看一些基本的verilog教程,这将是很好的。asic-world.com提供了一些很好的教程,例如,
Verilog in One Day
作者:迪帕克·库马尔·塔拉。
不过,让我试着向你解释一下。您在示例中使用的是
连续赋值语句
. 您可以在第103.2节中找到更多关于此的内容。
IEEE Std 1800-2012
. 手册上说:
网络或变量的分配应是连续和自动的。在
换句话说,每当右边表达式中的操作数改变时
值时,应评估整个右侧。
这里不是这样,因为所有赋值语句的右侧操作数都是相同的。它不是自动的,因为它取决于你的if语句。看看下面这个非常简单的例子。如果你一直想
result
成为
a & b
你可以使用下面的代码。然而,正如你可以想象的,对于更复杂的逻辑,这变得相当漫长。
module alu(
input [31:0] a,
input [31:0] b,
output [31:0] result,
);
assign result = (a & b);
endmodule
这就是为什么SystemVerilog提供
总是
,
always_comb
,
always_latch
和
always_ff
(IEEE标准1800-2012第9节)。例如,您应该使用
一直梳
. 引用本手册第9.2.2.2节:
systemverilog为建模提供了一个特殊的always_comb过程
组合逻辑行为。
有了这个,我们可以重写你的代码
module alu(
input [31:0] a,
input [31:0] b,
input [2:0] f,
output [31:0] result,
);
reg [31:0] result_;
always_comb
begin
/*000*/
if (f[0]==0 && f[1]==0 && f[2]===0)
begin
result_ = a & b;
end
/*001*/
else if (f[0]==0 && f[1]==0 && f[2]==1)
begin
result_ = a | b;
end
/*010*/
else if (f[0]==0 && f[1]==1 && f[2]==0)
begin
result_ = a + b;
end
/*011 not used*/
else if(f[0]==0 && f[1]==1 && f[2]==1)
begin
result_ = -1;
end
/*100*/
else if (f[0]==1 && f[1]==0 && f[2]==0)
begin
assign result = a & ~b;
end
/*101*/
else if (f[0]==1 && f[1]==0 && f[2]==1)
begin
result_ = a | ~b;
end
/*110*/
else if (f[0]==1 && f[1]==1 && f[2]==0)
begin
result_ = a - b;
end
/*111 slt*/
else
begin
result_ = -1;
end
end // End of always_comb
assign result = result_;
endmodule
请注意,你可以连续分配一个
wire
,但您需要将变量声明为
reg
在“总是”块中使用它。这就是我使用的原因
result_
,而不是直接指定
结果
. 在代码块的末尾,我不断地指定
小精灵
到
结果
. asic-world.com还有一个关于
difference between regs and wires
.
如果你不想考虑是否使用
规则
或
电线
,也可以使用新关键字
logic
.
编辑:正如奥尔德法特指出的,我根本忘了修正你的if…else语句。在你的代码中,你总是使用
else
而不是
else if
. 这可能也是编译器向您抛出错误的直接原因。