Verilog 按$signal进行的算术移位在条件表达式中给出不同的结果,并且总是阻塞
我正在为MIPS写ALU 我以前把它写成顺序逻辑(或者总是块?我不知道为什么,但是Verilog 按$signal进行的算术移位在条件表达式中给出不同的结果,并且总是阻塞,verilog,iverilog,Verilog,Iverilog,我正在为MIPS写ALU 我以前把它写成顺序逻辑(或者总是块?我不知道为什么,但是c必须是reg所以我猜它是顺序逻辑?) 这似乎是组合逻辑 always @* begin case (op) 4'b0000: c = mux_a + mux_b; 4'b0001: c = mux_a - mux_b; 4'b0010: c = mux_b << mux_a[4:0]; 4'b0011: c = mux_b &g
c
必须是reg
所以我猜它是顺序逻辑?)
这似乎是组合逻辑
always @* begin
case (op)
4'b0000: c = mux_a + mux_b;
4'b0001: c = mux_a - mux_b;
4'b0010: c = mux_b << mux_a[4:0];
4'b0011: c = mux_b >> mux_a[4:0];
4'b0100: c = $signed(mux_b) >>> mux_a[4:0];
4'b0101: c = mux_a & mux_b;
4'b0110: c = mux_a | mux_b;
4'b0111: c = mux_a ^ mux_b;
4'b1000: c = ~(mux_a | mux_b);
4'b1001: c = (mux_a < mux_b) ? 32'b1 : 32'b0; // sltu
4'b1010: c = ($signed(mux_a) < $signed(mux_b)) ? 32'b1 : 32'b0; // slt
4'b1011: c = mux_a + mux_b - 4;
default: c = 0;
endcase
end
除了c
是一条wire
之外,它几乎是相同的
我运行这段代码,它告诉我,4294967280(FFFFFFF0)>>>8=33554431(1fffffff),这太荒谬了
PC= 388, Fetched 00000000000100011001101000000011.
Decoder done. alu=4294967280.
ALUOP=0100 ALUMASK=10 Calc Result= 33554431
rs= 0 rt=4294967280
aluflag = 0000
Written(0000) 01ffffff to RegAddr:19
但是如果我使用(op==4'b0100)?({31{mux_b[32]},mux_b}>>mux_a[4:0]):
相反,我可以得到正确的结果
谁能告诉我原因吗?以下是如何定义这些变量(使用33位作为溢出标志)
这是伊维洛格的一个错误。关于组合
$signed
和条件运算符?:
。无论您使用的是连续赋值(assign
语句)还是always块
当mux\u b[32]
为1时,$signed(mux\u b)>>>mux\u a[4:0]
将在(1'b1)时给出正确的输出?($signed(mux_b)>>mux_a[4:0]):33'h0
将给出错误的输出
如果您愿意,您可以提交一个bug并
解决方法是将操作分开。例如:
assign op4 = $signed(mux_b) >>> mux_a[4:0];
assign c = (op == 4'b0000) ...
(op == 4'b0100) ? op4 :
(op == 4'b0101) ...
或者(op==4'b0100)?({31{mux_b[32]},mux_b}>>mux_a[4:0]):
正如问题中已经指出的那样
仅供参考:根据我的经验,条件运算符
?:
经常合成为显式2:1 mux,即使4:1或其他mux类型更为理想。你的经历可能不同。一般来说,我建议对任何大于3:1的muxing使用case语句。FYIc
在第一个always块中仍然被认为是战斗性的。时序逻辑在时钟边缘触发(例如始终@(posedge clk)
)<当新值确定时(不取决于其先前值),code>always@*为组合逻辑,否则为锁存逻辑reg
并不意味着失败。这让我很困惑。。$signed(mux_b)>>mux_a[4:0]
在始终@*
或条件运算符(如果它们都是组合逻辑)中有什么区别呢..格雷格,我在VCS 2014.10
上尝试了两种实现(使用case
和assign
语句),令我惊讶的是,这两种实现给出了不同的输出。case语句
one给出了正确的结果,而assign语句
给出了错误的结果。这是两个实现——请建议我是否误解了这里的任何内容,或者在实现中是否存在任何错误?在我看来,它们看起来不错,正如你所建议的,连续作业和总是阻塞应该不重要。不确定我是否遗漏了什么。@RahulBehl,这与始终
与分配
无关。它与在?:
中使用有符号算法有关。如果在always块内使用?:
方法,则应得到相同的错误结果。我在EDA操场上无法接触到VCS或Incisive。里维埃拉专业版也是一个问题(我不记得上次有过)。我创建了一个宏来证明不一致性(使用宏来确保不一致性不是由打字错误造成的)。如果这不是跨多个模拟器的bug,那么这是一个非常不直观的特性。感谢您花时间编写测试。我知道这是有道理的。
input [31:0] a;
input [31:0] b;
input [31:0] imm1;
input [31:0] imm0;
input [3:0] op;
input [1:0] mask;
output [31:0] result;
output [3:0] flags;
wire [31:0] _mux_a;
wire [31:0] _mux_b;
wire [32:0] mux_a;
wire [32:0] mux_b;
wire [32:0] c;
assign _mux_a = mask[1] ? imm1 : a;
assign _mux_b = mask[0] ? imm0 : b;
assign mux_a = {_mux_a[31], _mux_a};
assign mux_b = {_mux_b[31], _mux_b};
assign result = c[31:0];
//zf of uf
assign flags = {c[31], result == 0, c[32:31] == 2'b01, c[32:31] == 2'b10};
assign op4 = $signed(mux_b) >>> mux_a[4:0];
assign c = (op == 4'b0000) ...
(op == 4'b0100) ? op4 :
(op == 4'b0101) ...