Verilog Case 块级联语法

Verilog Case Block Concatenation Syntax

我似乎无法弄清楚在 case 块中 {c_out, result} = {a + b + c_in} 正确的语法是什么。 c_out 在我的测试台上不起作用,如果我添加 32'hffffffff + 1'b1 我得到 c_out = 0, result = 32'b0。正确的做法是什么?

module verification_alu(
input c_in
input [W-1:0] a, b,
input [2:0] operation,
output reg [W-1:0] result
output reg c_out
);
parameter W = 32;

always@*
begin
    case(operation)
        0: result = a;
        1: result = ~a;
        2: {c_out, result} = {a + b + c_in};
        3: {c_out, result} = {a - b + c_in};
        4: result = a | b;
        5: result = a & b;
        default: {c_out, result} = {W-2'b0}; // will this line fill with zeros properly?
    endcase
end
endmodule

此外,附带问题,32'b0 - 1'b1 的正确输出应该是什么?我应该得到 32'hffffffff 吗?

修改后的描述:

module verification_alu #(parameter W=32) (
  input wire c_in,
  input wire [W-1:0] a,
  input wire [W-1:0] b,
  input wire [2:0] operation,
  output reg [W-1:0] result,
  output reg c_out
);

  always @* begin
    case(operation)
      0: result = a;
      1: result = ~a;
      2: {c_out, result} = a + b + c_in;
      3: {c_out, result} = a - b + c_in;
      4: result = a | b;
      5: result = a & b;
      default: {c_out, result} = 0; // will this line fill with zeros properly?
    endcase
  end
endmodule

关键是要确保至少有一个操作数与您想要的结果大小相同,所以我在 a 和 b 前加了一个 0 位。

我已经验证了即使对于远远超出普通整数大小的大小也能正常工作:

module tb;
  reg c_in;
  reg [127:0] a;
  reg [127:0] b;
  reg [2:0] op;
  wire [127:0] res;
  wire c_out;

  verification_alu #(.W(128)) uut (c_in, a, b, op, res, c_out);

  initial begin
    c_in = 0;
    a = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
    b = 128'h00000000000000000000000000000001;
    op = 3'd2;    
    #100;
    $display ("RES = %H  C_OUT = %d\n", res, c_out);

    #100;
    c_in = 0;
    a = 128'h00000000000000000000000000000000;
    b = 128'h00000000000000000000000000000001;
    op = 3;    
    #100;
    $display ("RES = %H  C_OUT = %d\n", res, c_out);

    #100;
    op = 7;    
    #100;
    $display ("RES = %H  C_OUT = %d\n", res, c_out);

    $finish;
    end
endmodule

Chronologic VCS simulator copyright 1991-2014
Contains Synopsys proprietary information.
Compiler version J-2014.12-SP1-1; Runtime version J-2014.12-SP1-1;  Oct 11 17:47 2015
RES = 00000000000000000000000000000000  C_OUT = 1

RES = ffffffffffffffffffffffffffffffff  C_OUT = 1

RES = 00000000000000000000000000000000  C_OUT = 0

$finish called from file "testbench.sv", line 35.
$finish at simulation time                  500

您可以在 http://www.edaplayground.com/x/CJV

编辑 and/or 运行 测试平台以及修改后的模块

编辑:哎哟!我没有意识到 OP 使用连接运算符 { } 来包含三个操作数。是的!您的代码要简单得多。我将编辑我的答案中的代码。

加法和减法运算不起作用的原因是您将计算包装在连接运算符 ({}) 中。 Verilog 部分根据表达式中的操作数以及该表达式的上下文来确定操作的位大小。在您的情况下,表达式 a + b + c_in 被评估为 W 位,因为该表达式中任何变量的最大长度为 W (即 ab是那个长度,因为 Verilog 将首先计算这个加法(或两个加法),然后再继续计算包装它的 {} 运算符)。通过删除这个不需要的步骤,您应该得到 a + b + c_in 的正确 (W+1) 位评估;所以该行将是:3: {c_out, result} = a - b + c_in;。有关详细信息,请参阅 IEEE1800-2012,第 11.6 节。

回答你的另外两个问题:

不,表达式 {W-2'b0} 不会填零,而是会导致值 W,因为您告诉模拟器从 W 中减去 2'b0。你想的是{(W-2){1'b0}},或者专门用来补零的'0(因为很常用,你也可以用'1'x,或者'z来填充1,分别不在乎或高Z)。 (注意 {c_out, result} 的宽度为 W+1,但不是 W-2

最后,32'b0 - 1'b1 很可能会产生 32'hffffffff,但它受制于上述大小调整规则(以及符号扩展规则)。

首先,根据您的代码,编译器将无法访问输入端口中的参数定义,并且会抛出语法错误,您必须在 i/o 声明之前提及参数定义,因为它已在 i/o 声明中访问,verilog 带有一个语法来避免这个

module module_name #(parameter W =value)

{} 是与“,”一起使用的串联运算符,例如:a=1bit b= 1bit c=2bit 所以我们可以给出 c={a,b}; 所以正确的语法就像

一样简单
2: {c_out, result} = a + b + c_in;
3: {c_out, result} = a - b + c_in;

用零填充参数和大括号的混合将有助于解析(内部大括号将充当复制运算符)

default: {c_out, result} = {(W-2){1'b0}};