0

I have an issue when converting a SystemVerilog file to Verilog-2001 file coming from a GitHub project. It seems that in Verilog-2001, it not possible to place an unrolled loop of a table within a function:

  function [31:0] gen_val;
    input [31:0] old_val;
    input [31:0] new_val;
    input [3:0] be;

    integer n;

    for (n = 0 ; n < 4 ; n = n + 1) 
        gen_val[n*8+8:n*8] = be[n] ? new_val[n*8+8:n*8] : old_val[n*8+8:n*8];

  endfunction

When compiling with Icarus Verilog (iverilog) I get multiple error messages:

./tb_tiny.v:39: error: A reference to a wire or reg (`n') is not allowed in a constant expression.
./tb_tiny.v:39: error: Part select expressions must be constant.
./tb_tiny.v:39:      : This lsb expression violates the rule: (n)*('sd8)
./tb_tiny.v:39: error: A reference to a wire or reg (`n') is not allowed in a constant expression.
./tb_tiny.v:39: error: Part select expressions must be constant.
./tb_tiny.v:39:      : This msb expression violates the rule: ((n)*('sd8))+('sd8)
.....

Would anyone have an idea about the way to fix this in Verilog-2001 ?

Regards

1 Answers1

0

IEEE standard for Verilog HDL (IEEE Std 1364-2001) clause 4.2.1 defines two types of part-selects: a constant part-select and an indexed part-select.

... A constant part-select of a vector reg or net is given with the following syntax:

vect[msb_expr:lsb_expr]

Both expressions shall be constant expressions. ...

An indexed part select of a vector net, vector reg, integer variable, or time variable is given with the following syntax:

reg [15:0] big_vect;
reg [0:15] little_vect;

   big_vect[lsb_base_expr +: width_expr]
little_vect[msb_base_expr +: width_expr]

   big_vect[msb_base_expr -: width_expr]
little_vect[lsb_base_expr -: width_expr] 

The width_expr shall be a constant expression. It also shall not be affected by run-time parameter assignments. The lsb_base_expr and msb_base_expr can vary at run-time. ...

Your function can be rewritten using an indexed part-select:

function [31:0] gen_val;
    input [31:0] old_val;
    input [31:0] new_val;
    input [3:0] be;

    integer n;

    for (n = 0 ; n < 4 ; n = n + 1) 
        gen_val[n*8 +: 8] = be[n] ? new_val[n*8 +: 8] : old_val[n*8 +: 8];

endfunction
Dmitry
  • 1
  • Dear Dmitry, Thanks for your feedback and that definitely fixed the problem. On my side, I don"t understand why the initial statement did not work and was fixed by the introduction of the indexed part select. I expected them to be equivalent but apparently this is not the case. Thanks again. – st6hacker Jan 11 '21 at 15:56