Verilog 如何使用don'参数化case语句;你不在乎吗?

Verilog 如何使用don'参数化case语句;你不在乎吗?,verilog,system-verilog,Verilog,System Verilog,我有一根叫做“输入”的电线,我想检测引线的数量 我试图创建一个模块,它使用下面的case语句根据前导零的数量更改输出数据。但是,输入的大小是可参数化的 如果X是4的固定值,我会创建一个case语句 case (input) 4'b0001 : o_data = {i_data[0]}; 4'b001x : o_data = {i_data[1],1'b0}; 4'b01xx : o_data = {i_data[2],2'b0}; 4'b1xxx : o_data = {

我有一根叫做“输入”的电线,我想检测引线的数量 我试图创建一个模块,它使用下面的case语句根据前导零的数量更改输出数据。但是,输入的大小是可参数化的

如果X是4的固定值,我会创建一个case语句

case (input)
  4'b0001  : o_data = {i_data[0]};
  4'b001x  : o_data = {i_data[1],1'b0};
  4'b01xx  : o_data = {i_data[2],2'b0};
  4'b1xxx  : o_data = {i_data[3],3'b0};
  default  : o_data = 4'b0000;
endcase
但是对于变量X,如何定义所有情况


这个问题类似于这个问题:

您不能像这样真正地参数化
case
语句,但您可以使用
for
循环:

module lead_detector #(parameter int WIDTH = 4) (
  input logic[WIDTH - 1:0] in,
  output logic[WIDTH - 1:0] out
);
  always_comb begin
    out = '0;
    for (int i = WIDTH - 1; i >= 0; i--)
      if (in[i] == 1'b1) begin
        out[i] = 1;
        break;
      end
  end
endmodule

这是我看到我的设计人员一直在编写的代码(尽管是用VHDL编写的),但它应该是可合成的。

如果我理解得很好,OP正在尝试设计某种参数化优先级编码器。我有一个综合性很好的设计

module priority_encoder #(parameter WIDTH=4) (
    input wire [WIDTH-1:0] i,  // input data
    input wire [WIDTH-1:0] c,  // input control
    output reg [WIDTH-1:0] o   // output data
    );
        
    // Deal with the most significant bit case apart
    always @* begin
        if (c[WIDTH-1]==1'b1)
            o[WIDTH-1] = i[WIDTH-1];
        else
            o[WIDTH-1] = 1'b0;
    end
    
    // Deal with the rest of bits
    genvar idx;
    generate
    for (idx = WIDTH-2; idx >=0; idx = idx-1) begin :gen_cases
        always @* begin
            if (c[idx]==1'b1 && c[WIDTH-1:idx+1]=='b0)
                o[idx] = i[idx];
            else
                o[idx] = 1'b0;
        end
     end
     endgenerate
endmodule
我为此设计创建的测试台模块如下所示:

module tb_prioencoder;
    parameter WIDTH=3;
    // Inputs
    reg [WIDTH-1:0] i;
    reg [WIDTH-1:0] c;

    // Outputs
    wire [WIDTH-1:0] o;

    // Instantiate the Unit Under Test (UUT)
    priority_encoder #(WIDTH) uut (
        .i(i), 
        .c(c[WIDTH-1:0]), 
        .o(o)
    );

    initial begin
        i = {WIDTH{1'b1}};
        c = {WIDTH{1'b0}};
        repeat (2**WIDTH) begin
            #10;
            c = c + 1;
        end
    end      
endmodule
这就引出了这个计时图(对于
宽度
=3):

case语句不能像那样参数化。其他人提到的for循环是解决问题的好方法

这里有一个不同的解决方案:如果您想解决相反的问题,即从右侧查找前导1,您可以在
中按位和
及其两个补码。因此,要从左侧查找前导1,您可以先将中的进行位反转,按位将其与其两个补码相加,然后对结果进行位反转:

logic [X - 1:0] reverse_in, reverse_out;
always_comb 
begin 
  reverse_in = { << {in} }; //Bit-reverse of input (using stream operator)
  reverse_out = (~(reverse_in) + 1) & reverse_in; //And with two's complement
  out = { << {reverse_out} };  //Bit-reverse of output
end
逻辑[X-1:0]反向输入,反向输出;
总是用梳子
开始

reverse_in={o_数据在每种情况下分配了不同数量的位。我们是否必须假设未分配的位为零?如果您将
always_comb
更改为
always@(in),这在Verilog中也应该起作用
。我怀疑上面的代码是否可以合成?会不会破坏
语句效果合成?@Jithin:是的,上面的代码可以合成。至少在Altera Quartus和Cadence Engus上是这样。尽管我注意到Cadence Xcelium xprop检查在任何always_uuz(comb | ff)上都会被禁用块中包含break语句,因为它尚未完全受支持。