我为ALU编写了这个编码器。此ALU由artisan serve
信号控制,并执行一些工作,如加,减,和或......当输出为零时,ctrl
信号应处于活动状态。
我在标记的行中有一些错误。我的错是什么?
oZero
答案 0 :(得分:1)
~|
中使用的 4'b0011: out<=iA~|iB;
运算符被IDE视为简化运算符而不是NOR运算。要解决此问题,您可以使用例如以下构造:
out <= ~(iA | iB);
第二个问题是您忘记在endcase
构造的末尾使用case
关键字。
选中edaplayground以查看应用于您的代码的更改。
答案 1 :(得分:1)
正如邱指出的那样,iA~|iB
应该是~(iA|iB)
而你错过了endcase
。除此之外:
ctrl
需要为4位宽。 IE input [3:0] ctrl
always @(ctrl)
模拟器将不会使用iA
或iB
中的更改。而是使用always @*
进行自动感知。您应该始终对组合逻辑使用自动敏感性,除非您仅限于1995年版本的IEEE Std 1364(可能性不大),在这种情况下您需要always @(ctrl or iA or iB or iCin)
。自动敏感度(@*
或@(*)
)已于2001年添加到标准中。<=
)与组合逻辑一起使用,使用阻止分配(=
)。应使用非阻塞来分配触发器和锁存器。 out
和oCarry
未在每种情况下分配已知值,因此将其推断为锁存器。锁存逻辑设计容易出现时序问题,需要谨慎使用。大多数FPGA的锁存器数量有限,有些则有一些。编码样式的更改可以删除感应锁存器,有两种主要方法可以实现。
在每种情况下分配输出。确保在case语句中声明了一个默认条件:
always @* begin
case(ctrl)
4'b0000 :
begin
out = iA&iB;
oCarry = 1'b0;
end
// conditions assigning both 'out' and 'oCarry'
default:
begin
out = 32'0;
oCarry = 1'b0;
end
endcase
end
在case语句之前将值分配给默认值。 case语句将覆盖默认值。
always @* begin
// default value
out = 32'd0;
oCarry = 1'b0;
// calculate value, override default
case(ctrl)
4'b0000 : out = iA&iB;
// ...
4'b0010: {oCarry ,out} = iA+iB;
// ...
4'b1000: out = iA/iB;
endcase
end
oZero
也是推断锁存器。它只能分配给1,没有0的路径。您可以:
always @* oZero = (out==0);
oZero = (out==0);
endcase
合并
assign oZero = (out==0); // Make sure 'oZero' is a wire (not reg)
其他建议(可选)
ANSI样式标题。在IEEE Std 1364-2001中添加,并得到所有现代模拟器和合成器的支持。它比IEEE标准1364-1995的非ANSI风格更紧凑。
module ALU_32 (
input [31:0] iA, iB,
input iCin,
input [3:0] ctrl,
output reg oCarry, oZero,
output reg [31:0] out );
您建议iA*iB
和iA/iB
出现错误。在verilog中,没有任何错误。合成工具可能存在问题,因为32位乘32位乘法器/分频器往往会占用大量资源。您可能需要在单独的模块中管理操作。 FPGA可能有预定义的模块,因此请查看数据表。