编写一个 Verilog 函数来定位向量中右侧第一个的索引

Writing a Verilog function to Locate the index of the first one on the right in the vector

我正在编写一个 Verilog 函数来定位 vector.If 向量中右边第一个的索引,该函数应该 return 将值设为向量的最高值index + 1. 这是代码:

module m ();
 parameter n = 3;
  function integer Locate_one (input [n-1:0] a );
    Locate_one ='dx;
    for (integer i =n-1 ; i<=0 ; i=i-1)
      begin
        if(a[i] == 1'b1)
          begin
          Locate_one=i;
            break; 
          end
    end
  
    if (Locate_one=='dx)
      Locate_one=n;
  
  
  
  endfunction
initial begin 
  reg [n-1:0] a = 3'b111;
integer result =  Locate_one (a);
  
  $display("output is %d ", result);
end 
endmodule

题目如下:

  1. 找到最高的怎么跳出函数?我使用了关键字 break,这是我在网上找到的,是一个有效的 SystemVerilog 关键字,而不是 Verilog 关键字。
  2. 我曾经知道向量中没有一个的策略是我已经将 return 整数初始化为 X 然后我在函数结束时将变量与 X 进行了比较.这是这样做的好方法还是有另一种更好的方法来进行比较?

我会在功能块内使用一个临时变量,指示是否已找到“1”。没有必要用 X 初始化索引变量,这应该可以完成工作:(我相信这是为了模拟目的,因为没有 input/output 端口)

module first_one ();

  parameter n = 3;
  reg [n-1:0] a;

  function integer locate_one;
    input [n-1:0] a;
    integer i;
    reg found_temp;
    begin
    found_temp = 0;
    for (i=0; i<n; i=i+1) begin
      if(a[i] == 1'b1 & ~found_temp) begin
        locate_one = i;
        found_temp = 1;
      end
    end
    if(~found_temp)
      locate_one = n;
    end
  endfunction

  initial begin
    a = 0;
    $monitor("a = %b : index = %d", a, result);
    #100 $finish;
  end

  wire [$clog2(n)-1:0] result = locate_one(a);

  always
    #1 a = $urandom;

endmodule

这可以用 icarus verilog 测试:

iverilog first_one.v -o first_one.tb
vvp first_one.tb

你的代码有很多问题。

  1. 您不能使用 ==x 进行比较——它总是 returns 错误。您必须使用 === 运算符
  2. 您正在初始化两个静态变量 aresult,并且未定义初始化顺序。它们不是程序性陈述。 SystemVerilog 已将过程代码中的隐式静态变量初始化设为非法,这是我能想到的唯一与 Verilog 的向后不兼容。
  3. 除了 break 之外,您的代码还有很多 SystemVerilog 结构
    1. for 循环中声明一个变量
    2. 一个 function/task 没有 begin/end 关键字的正文。
  4. 您不应在代码中使用 x 值。它不可综合,如果您犯了错误,它会使调试代码变得更加困难。
  5. 您的循环条件与您需要的相反。

如果您想要严格的 Verilog 兼容性,您可以使用 disable 语句来获得类似于 break 的功能。

module m ();
 parameter n = 5;
  function integer Locate_one (input [n-1:0] a );
    integer i;
    begin : block
    Locate_one = n;
      for (i =n-1 ; i>=0 ; i=i-1)
      begin
        if(a[i] == 1'b1)
          begin
          Locate_one=i;
            disable block; 
          end
    end
    end 
  endfunction
  
    reg [n-1:0] a = 3'b111;
initial begin 
integer result;  
  result =  Locate_one (a);     
  $display("output is %d ", result);
end 
endmodule

这是SystemVerilog代码

module m ();
 parameter n = 5;
  function int Locate_one (input [n-1:0] a );
    Locate_one = n;
      for (int i =n-1 ; i>=0 ; i=i-1)
      begin
        if(a[i] == 1'b1)
          begin
          Locate_one=i;
            break; 
          end
    end
  endfunction
    logic [n-1:0] a = 3'b111;
    int result;
initial begin 
  result =  Locate_one (a);     
  $display("output is %d ", result);
end 
endmodule