7

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

但无济于事。

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

4

2 回答 2

13

两个问题:

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

您还必须将 size 声明为一种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
于 2012-08-06T21:57:15.463 回答
1

正如@Tim 已经回答的那样,使用块reg内的类型alwayswirewith 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
于 2012-08-08T08:00:22.960 回答