我如何在 Verilog 上制作可合成的参数化编码器?

问题描述

我尝试过这样做:

module encoder 
#(
    parameter WIDTH = 4
 )
(
    input wire [WIDTH-1: 0] in,output reg [$clog2(WIDTH)-1: 0] out
);

  genvar i; 
  generate
    for (i = 0;i < WIDTH;i = i+1) 
    begin :gen_block
      always @* 
      begin
        if (in[i]==1'b1) 
          out = i;
      end
    end
  endgenerate
endmodule

它在模拟中运行良好,但我不确定是否可以合成。 generate block生成 always block 的多个副本,我猜在 out 的前一个值之间会存在竞争条件以及 out 的更新值。

关于无法合成此代码的假设是否正确?如果是这样,我要更改什么才能使其正确合成?

解决方法

是的,您在模拟中确实存在竞争条件,并且无法综合。您不能有多个 always 块并行分配给同一个变量(当设置了 in 中的多个位时发生)。您需要一个常规的过程 for 循环,而不是一个 generate-for 循环。

module encoder 
#(
    parameter WIDTH = 4
 )
(
    input wire [WIDTH-1: 0] in,output logic [$clog2(WIDTH)-1: 0] out
);
      always_comb begin
        out = 'x; // don't care if no 'in' bits set
        for (int i = 0;i < WIDTH;i++)
            if (in[i]==1'b1) begin
               out = i;
               break; // priority goes from LSB-to-MSB
        end
    end
endmodule

编辑: 对于不支持 break 的工具

always_comb begin
        bit Break;
        Break = 0;
        out = 'x; // don't care if no 'in' bits set
        for (int i = 0;i < WIDTH;i++)
            if (in[i]==1'b1 && !Break) begin
               out = i;
               Break = 1;
        end
    end