在if-statement中不是一个恒定的错误。

时间:2022-09-22 20:27:32

I am trying to write a simple module to output a 14-bit number based on the value of four input signals. My attempt is shown below.

我尝试编写一个简单的模块,根据四个输入信号的值输出一个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

Upon compilation, I receive the following error:

在编译时,我收到以下错误:

ERROR:HDLCompiler:44 - Line 67: c is not a constant

错误:HDLCompiler:44 - Line 67: c不是常量。

I don't understand why that particular if-statement isn't working if the other two preceding it are. I have tried changing the condition to

我不明白为什么这个特定的if语句在前面的两个是无效的。我已经试过把条件改为。

if (c == 1) begin

but to no avail.

但无济于事。

Does anybody know how to solve this error? Thank you!

有人知道怎么解决这个错误吗?谢谢你!

2 个解决方案

#1


6  

Two problems:

两个问题:

1) You need to put if statements inside an always block.

你需要把if语句放在一个总是块中。

If you use verilog-2001, you can use

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

always @*
   if ....
   end
end

Otherwise specify all the inputs in the sensitivity list:

否则,请指定敏感列表中的所有输入:

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


2) Constant assignments are not allowed inside if statements.

Remove the assign keyword from any statements inside the if block:

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

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

You will also have to declare size as a reg type.

您还必须声明大小为reg类型。

However my preference would be to rewrite the entire module with conditional operator, I find it much preferrable to read. This following module achieves the same result:

然而,我的首选是用条件操作符重写整个模块,我发现它更适合阅读。该模块实现了相同的结果:

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

#2


1  

As @Tim has already answered, using reg types inside always blocks or wire with assign.

正如@Tim已经回答的那样,使用reg类型的内部总是块或线的分配。

@Tim has also described the nested ternary assignments, while in the example are written very well, they are generally seen as bad practice. They imply a very long combinatorial path and can be hard to maintain. The combinatorial path may be optimised by synthesis which should imply a mux with optimised selection logic.

@Tim还描述了嵌套的三元分配,而在例子中写得很好,它们通常被认为是糟糕的实践。它们意味着一个非常长的组合路径,并且很难维护。组合路径可以通过合成来优化,这意味着一个具有优化选择逻辑的mux。

Easier to maintain code will have a lower cost of ownership, and as long as it does not lead to a larger synthesised design it is normally preferred.

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

My implementation would be to use a casez, (? are don't cares). I find the precedence of each value easier to see/debug.

我的实现将是使用一个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

#1


6  

Two problems:

两个问题:

1) You need to put if statements inside an always block.

你需要把if语句放在一个总是块中。

If you use verilog-2001, you can use

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

always @*
   if ....
   end
end

Otherwise specify all the inputs in the sensitivity list:

否则,请指定敏感列表中的所有输入:

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


2) Constant assignments are not allowed inside if statements.

Remove the assign keyword from any statements inside the if block:

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

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

You will also have to declare size as a reg type.

您还必须声明大小为reg类型。

However my preference would be to rewrite the entire module with conditional operator, I find it much preferrable to read. This following module achieves the same result:

然而,我的首选是用条件操作符重写整个模块,我发现它更适合阅读。该模块实现了相同的结果:

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

#2


1  

As @Tim has already answered, using reg types inside always blocks or wire with assign.

正如@Tim已经回答的那样,使用reg类型的内部总是块或线的分配。

@Tim has also described the nested ternary assignments, while in the example are written very well, they are generally seen as bad practice. They imply a very long combinatorial path and can be hard to maintain. The combinatorial path may be optimised by synthesis which should imply a mux with optimised selection logic.

@Tim还描述了嵌套的三元分配,而在例子中写得很好,它们通常被认为是糟糕的实践。它们意味着一个非常长的组合路径,并且很难维护。组合路径可以通过合成来优化,这意味着一个具有优化选择逻辑的mux。

Easier to maintain code will have a lower cost of ownership, and as long as it does not lead to a larger synthesised design it is normally preferred.

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

My implementation would be to use a casez, (? are don't cares). I find the precedence of each value easier to see/debug.

我的实现将是使用一个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