Verilog中特定整数整数的位数

时间:2019-07-09 08:44:22

标签: verilog system-verilog

请在下面查看我的Verilog测试平台代码。实际上,我想用一个或两个表达式替换所有if-else语句。这样的代码看起来非常松散和肮脏。有人可以告诉我如何使这段代码更紧凑。请注意,变量“ i”和“ len”是重点。

module xyz();

......
....some parts and variable declarations;
......


initial begin
for(i = 1; i <= 65535; i = i+1) begin
    if        (i <= 1)               len = 1;
    else if   (i>1 & i <= 3)         len = 2;
    else if   (i>3 & i <= 7)         len = 3;
    else if   (i>7 & i <= 15)        len = 4;
    else if   (i>15 & i <= 31)       len = 5;
    else if   (i>31 & i <= 63)       len = 6;
    else if   (i>63 & i <= 127)      len = 7;
    else if   (i>127 & i <= 255)     len = 8;
    else if   (i>255 & i <= 511)     len = 9;
    else if   (i>511 & i <= 1023)    len = 10;
    else if   (i>1023 & i <= 2047)   len = 11;
    else if   (i>2047 & i <= 4095)   len = 12;
    else if   (i>4095 & i <= 8191)   len = 13;
    else if   (i>8191 & i <= 16383)  len = 14;
    else if   (i>16383 & i <= 32767) len = 15;
    else if   (i>32767 & i <= 65535) len = 16;

    // This is a task(integer, integer, integer, vector)
    universal_test_task(len, 1, i, 16'hFFFF); 
    end
end
endmodule

该代码的主要目的是控制特定计数的位数。

3 个答案:

答案 0 :(得分:2)

Verilog和System Verilog具有内置的系统功能$clog2(),即,login-of-log2。

可以证明,正整数 k 的基数 b 中的位数是

在您的情况下,您可以将所有if-else语句替换为单行:

len = $clog2(i+1)

同样,只要您为$ clog2提供一个在编译期间恒定的值,它就会得到所有主要综合工具的支持。

答案 1 :(得分:1)

这听起来像是递归 log2函数的工作:

  function int log2 (int i); 
    if (i <= 1)
      return 0;
    else
      return log2(i/2) + 1;
  endfunction

此函数是递归的,因为它会自行调用。它使用以下两个事实进行工作:

  1. 1的对数基数2为0
  2. 任意数量的对数基数2是一半的对数基数2 数字加1

您的测试平台需要此功能,但是您会发现此功能实际上是可综合的。


https://www.edaplayground.com/x/3bTN

module xyz;

  function int log2 (int i); 
    if (i <= 1)
      return 0;
    else
      return log2(i/2) + 1;
  endfunction

  initial
    begin
      int len;
      for (int i = 1; i <= 65535; i++)
        begin
          len = log2(i)+1;
          $display("i=%d, len=%d", i, len);
        end
    end

endmodule

答案 2 :(得分:0)

在Verilog中,您可以使用三元运算符来实现该功能。

module test(i,len);
 input wire [16:0] i;
 output reg [16:0] len;
  
 initial 
     begin
       len = i> 32767 ? 16 :
             i> 16383 ? 15 :         
             i> 8191  ? 14 :
             i> 4095  ? 13 :
             i> 2047  ? 12 :         
             i> 1023  ? 11 :
             i> 511   ? 10 :
             i> 255   ? 9 :         
             i> 127   ? 8 :
             i> 63    ? 7 :
             i> 31    ? 6 :         
             i> 15    ? 5 :
             i> 7     ? 4 :
             i> 3     ? 3 :         
             i> 1     ? 2 : 1 ;
       
       $display(i,,,,,len);
     end
endmodule

在系统Verilog中,$ clog2()将帮助您完成此操作

module test;
 
 bit [16:0] i;
 bit [5:0] b;
 bit [16:0] len;
      
 
      
 initial
  begin
    repeat(5)
      begin
        assert(std::randomize(i,b) with { b inside {[1:15]};
                                          i == 2**b; });
        len = $clog2(i)+1;
        $display(i,,,,,len);
      end
  end
  
endmodule