Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Verilog 按$signal进行的算术移位在条件表达式中给出不同的结果,并且总是阻塞_Verilog_Iverilog - Fatal编程技术网

Verilog 按$signal进行的算术移位在条件表达式中给出不同的结果,并且总是阻塞

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

我正在为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 >> 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语句。

FYI
c
在第一个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) ...