if语句</signal>中的“<signal>不是常量”错误

时间:2012-08-06 21:43:34

标签: verilog

我正在尝试编写一个简单的模块,根据四个输入信号的值输出一个14位数。我的尝试如下所示。

module select_size(
    input a,
    input b,
    input c,
    input d,
    output [13:0] size
);

    if (a) begin
        assign size = 14'h2222;
    end
    else begin
        if (b) begin
            assign size = 14'h1111;
        end
        else begin
            if (c) begin
                assign size = 14'h0777;
            end
            else begin
                assign size = 14'h0333;
            end
        end
    end

endmodule

编译后,我收到以下错误:

  

错误:HDLCompiler:44 - 第67行:c不是常数

我不明白为什么如果前面的另外两个if语句不起作用的话。我已经尝试将条件更改为

if (c == 1) begin

但无济于事。

有人知道如何解决这个错误吗?谢谢!

2 个答案:

答案 0 :(得分:6)

两个问题:

1)您需要将if语句放在always块中。

如果您使用verilog-2001,则可以使用

always @*
   if ....
   end
end

否则指定灵敏度列表中的所有输入:

always @(a or b or c or d)
   if ....
   end
end

<小时/> 2)if语句中不允许进行常量赋值。

assign块中的任何语句中删除if关键字:

if (a) begin
    size = 14'h2222;
end

您还必须将尺寸声明为reg类型。

但是我的偏好是用条件运算符重写整个模块,我觉得它更适合阅读。以下模块实现了相同的结果:

module select_size(
    input a,
    input b,
    input c,
    input d,
    output [13:0] size
);

    assign size = a ? 14'h2222 :
                  b ? 14'h1111 :
                  c ? 14'h0777 : 
                      14'h0333 ;

endmodule

答案 1 :(得分:1)

@Tim已经使用reg块内的always类型或wire assign来回答。

@Tim还描述了嵌套的三元赋值,虽然在这个例子中编写得非常好,但它们通常被认为是不好的做法。它们意味着很长的组合路径并且难以维护。组合路径可以通过合成进行优化,这应该意味着具有优化选择逻辑的多路复用器。

更容易维护代码将降低拥有成本,并且只要它不会导致更大的合成设计,通常是首选。

我的实现是使用casez,(?不关心)。我发现每个值的优先级更容易看/调试。

module select_size(
  input a,
  input b,
  input c,
  input d,
  output logic [13:0] size //logic (SystemVerilog) or reg type
);

always @* begin
  casez ({a,b,c})
    3'b1?? : size = 14'h2222 ;
    3'b01? : size = 14'h1111 ;
    3'b001 : size = 14'h0777 ;
    3'b000 : size = 14'h0333 ;
    default: size = 'bx      ;
  endcase
end

endmodule