1
\$\begingroup\$

I am trying to generate some sequential blocks in Verilog, but the problem is that I need another variable to control double-layer for-loop. For the second layer, the loop bound comparing parameter should be changed for each iteration of the first loop layer. But, the problem is that I do not know how to set a different loop bound comparing parameter for each iteration as I get error "par is not a constant" in compiling process. In below summarized description, I simply showed what I expected. The problem with this is that "par" cannot be set in this way as it is not a C code to perform commands line by line.

parameter sel = 10;
integer par;
...
generate    
    for ( i = 0 ; i < sel ; i = i + 1) 
    begin
        for ( j = 0 ; j < par ; j = j + 1) 
        begin
            always @(posedge clk) <statement>
            
            par= <a function of par>;
        end
    end

In the next description, I showed how might be able to do it through an array but here again the error appeared: "parameter 'par' cannot be declared without a default value" while I need to set the values of the constant array through a for-loop, detached from where it is defined!

parameter sel = 10;
parameter integer par[0:sel-1];
initial begin
    for ( i = 0 ; i < sel ; i = i + 1) 
    begin
        par[i]= <a function of par>;
    end
end 
...
generate    
    for ( i = 0 ; i < sel ; i = i + 1) 
    begin
        for ( j = 0 ; j < par[i] ; j = j + 1) 
        begin
            always @(posedge clk) <statement>
        end
    end

How can I solve this problem?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

There is an easy solution to this if you can move to SystemVerilog. It allows functions to return arrays, but the syntax requires you to use a typedef. The you can use the result of the function to be the initialization of a parameter.

parameter sel = 10;
typedef int par_type[sel];
parameter par_type par = par_func(sel);
function par_type par_func(input int sel);
  for (int i = 0 ; i < sel ; i = i + 1) 
    begin
        par_func[i]= <a function of par>;
    end
endfunction
// generate loops
for ( genvar i = 0 ; i < sel ; i++) 
    for ( genvar j = 0 ; j < par[i] ; j++) 
        always @(posedge clk) <statement>
end

Those generate loops could have been written exactly the way you did in Verilog, just showing you how much more compact they are in SystemVerilog.

After answering this, I realized you could do this in old-style Verilog by using a large vector and indexing into a part select.

parameter [32*sel-1:0] par = par_func(sel);
function [32*sel-1:0] par_func(input int sel);
  for (int i = 0 ; i < sel ; i = i + 1) 
    begin
        par_func[i*32+:32]= <a function of par>;
    end
\$\endgroup\$
1
\$\begingroup\$

The purpose of generate for loops is to create a constant number of hardware logic items. sel is fine because it is a constant value because you declared it with a parameter and gave it a numeric value (10).

However, par is a runtime variable because you declared it as with the integer keyword; it is not a runtime constant. It is illegal Verilog syntax to make an assignment to it within the body of the for loop:

        par= <a function of par>;

With your second code example, you are again violating Verilog syntax.

You need to determine a fixed number of hardware items you want to have in your design ahead of time. It can not be determined during simulation runtime.

I recommend writing your code out manually without the for loops (using small numbers for sel for now). Once you have a clearer picture of how many items you need, then consider shortening the code with loops. For people who are new to Verilog, it is tempting to jump right in using loops. However, depending on what is inside the always blocks, it is often simpler to write code without loops. If you do have working code without loops and you want feedback on it, I recommend posting the full code on CodeReview. Make sure to read the policy first.

\$\endgroup\$
2
  • \$\begingroup\$ the process just calculates how the fix design should be generated once and for all based on the fixed parameter . \$\endgroup\$
    – cr re
    Commented Aug 20 at 13:35
  • 1
    \$\begingroup\$ @crre, when you wrote for ( j = 0 ; j < par ; j = j + 1) you made the number of devices depend on a runtime variable, not a fixed parameter. Instead try for(j=0; j<max_j; j=j+1) and then make the block inside only act if j<par. For example, par = par + (j < par ? 1 : 0) or whatever. \$\endgroup\$
    – The Photon
    Commented Aug 20 at 15:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.