[SOLVED] Verilog for loop in test bench produces error in ModelSim

Status
Not open for further replies.

nervecell_23

Member level 1
Joined
Apr 26, 2013
Messages
38
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Visit site
Activity points
1,565
Here's the snippet of the code:
DUT is an array of RAM blocks. I tried to compare the entries in the blocks with a truth table. Compile failed reporting the error: Index value in hierarchical path is not constant. Please suggest whether I can use the for loop to do what I tried to do in the code?
Code:
integer i, j;

initial
begin
    @(checkData);
    for(i=0;i<60;i=i+1)
    begin

        for(j=0;j<187;j=j+1)
	begin
            @(negedge ge_clk);
	    force dut.memory_inst.arraygen[i].memory.rden = 1;
	    force dut.memory_inst.arraygen[i].memory.address = j;
	    @(negedge ge_clk);
	    force dut.memory_inst.arraygen[i].memory.rden = 0;
	    @(posedge ge_clk);
	    #1
	    if(dut.memory_inst.arraygen[i].memory.q != truethTable[i*187+j])
	        $display("Result does not match: i=%d, j=%d",i,j);
	
            -> stopSim;
	end
    end
    
    release dut.memory_inst.arraygen[i].memory.rden;
    release dut.memory_inst.arraygen[i].memory.address;
end
 

Shouldn't the release statement be within the for loop??

Yes you are right (sorry it seems I can't edit thread any more). But the error still exists when I move the 'release' statements into the loop.
I also tried using repeat loop instead of for loop, but it didn't work either. Compile succeeded when I replace the variable indices with fixed integer, but in that case I couldn't test the entire array of RAM blocks efficiently.
 

You can't use a variable to select the instances those have to be static values.

Given the way you've structured your code I can't see any way around this. You might have to resort to creating a task that has the contents of the j for loop and using that 60 times with the i instance being statically set by a task input.

- - - Updated - - -

The other option would be to pass the rden and the address back through the hierarchy to the memory_inst module, but that would entail port changes. I'm not that familiar with all the changes to SV, but maybe there is a chance they added something in SV that could help.
 
You can easily create a generate for-loop for the outer for loop that creates 60 concurrent initial blocks, and use a counter to make the contents execute serially. Don't even need SystemVerilog

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
genvar i;
integer j, k;
 
 for(i=0;i<60;i=i+1)
    begin : static_loop;
    initial begin
      k = 0;
      @(checkData)
      wait (k==i)
        for(j=0;j<187;j=j+1)
      begin : dynamic loop
            @(negedge ge_clk);
        force dut.memory_inst.arraygen[i].memory.rden = 1;
        force dut.memory_inst.arraygen[i].memory.address = j;
        @(negedge ge_clk);
        force dut.memory_inst.arraygen[i].memory.rden = 0;
         @(posedge ge_clk);
        #1
        if(dut.memory_inst.arraygen[i].memory.q != truethTable[i*187+j])
            $display("Result does not match: i=%d, j=%d",i,j);
            -> stopSim;
      end // dynamic loop
        release dut.memory_inst.arraygen[i].memory.rden;
        release dut.memory_inst.arraygen[i].memory.address;
        k = k +1;
    end // initial
end // static loop

 
Dave,

You know I thought about suggesting something like that, but didn't think it would work. I've picked up a number of tricks from reading your replies.

Regards
 

Hi Dave, your code compiles successfully. I've got two questions about your code:
1) Is there particular reason for executing the outer loop in serial?
2) What is the difference between generate for-loop with/without GENERATE BLOCK?
3) This snippet of code is used as an EVENT. Usually an event is defined in an initial block, but now it seems I can not put your code in an initial block, then how can I jump to/from this node?

Thanks!
 
Last edited:

  1. I was just recreating the functionality in your code. If you unroll a for-loop in a procedural block, you get a serial set (or sequential series) of statements. Generate-for loops unroll into a set of concurrent declarations. In this example, a concurrent set of initial blocks. If that was not your intent, you can remove that serialization.
  2. The generate/endgenerate keywords are optional in Verilog. The compiler can figure out the difference. But perhaps it would be better if I used them to clearly show my intent.
  3. Again, I was creating my code using only the example code you showed. Your code waits for a global checkData event only once. My code has all the generated initial blocks waiting for the same event. If you want to be able to "trigger" this code multiple times, you could have used an always block instead.The ->stopSim is a trigger that you can use to jump to other code.
There are probably more elegant ways of doing this in Verilog and SystemVerilog, but that would require a little more knowledge of what you are trying to accomplish overall.

Dave
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…