Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Problem with loop operation

Status
Not open for further replies.

ismailov-e

Member level 1
Joined
Jan 26, 2015
Messages
34
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
295
Hi everybody.
I have an aray of registers named slv_reg (10 registers and 32 bits of each). I want to check and count every register per bite for non zero. But unfortunately it shows different value. Here is a code:

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
28
29
30
31
32
33
34
35
module loop(
    input wire  clock,
    output reg [31:0] outputa
    );
reg [31:0] slv_reg [9:0];
reg [7:0] count = 0;
reg [7:0] temp = 0;
reg off = 0;
integer i, k;
initial begin
slv_reg[0] = 32'b11111111_00001000_11111111_01000000;
slv_reg[1] = 32'b10101010_01010101_10101010_01010101;
slv_reg[2] = 32'b11111111_11111111_00001000_11111111;
slv_reg[3] = 32'b00000100_10000000_11111111_00010000;
slv_reg[4] = 32'b11100011_00011000_11110001_10111000;
slv_reg[5] = 32'b11111111_11111111_00000001_00100000;
slv_reg[6] = 32'b11111110_01111111_01000000_10000000;
slv_reg[7] = 32'b11111111_00001000_11111111_01000000;
slv_reg[8] = 32'b10101010_01010101_10101010_01010101;
slv_reg[9] = 32'b00001000_10011111_00010000_00100000;
end
always@ (posedge clock)
begin
  for (i = 0; i < 10; i = i + 1)
    begin
      for (k = 0; k < 4; k = k + 1)
        begin
         temp = slv_reg[i][(k*8)+:8];
            if (temp != 0)
                count = count + 1;
        end
    end
outputa = count;
end
endmodule


And if i change the sign equal
Code:
count = count + 1
to
Code:
<=
sine it changes a value. Why?
 

A for loop in Verilog does not operate temporally as it does in an imperative programming language. Instead a for loop is unrolled spatially into parallel logic.

Furthermore
<= is a non-blocking assignment and should only be used in edge triggered (i.e. posedge clock) always blocks.
= is a blocking assignment and should only be used in combinational always blocks (i.e. always @*).

Using blocking assignments in a edge triggered always block might sometimes correctly infer a register, but is a very bad coding practice and in this case will result in something that looks like it's working but is trying to run 40 iterations of compares and adds in parallel, which will be a huge slow mess of logic.

Using the non-blocking assignments breaks the simulation as the count <= count + 1 gets scheduled multiple times but only occurs once, so it only increments once each clock cycle. Once again a problem with understanding how the for loop works in Verilog and how non-blocking assignments are scheduled.
 

A for loop in Verilog does not operate temporally as it does in an imperative programming language. Instead a for loop is unrolled spatially into parallel logic.

Furthermore
<= is a non-blocking assignment and should only be used in edge triggered (i.e. posedge clock) always blocks.
= is a blocking assignment and should only be used in combinational always blocks (i.e. always @*).

Using blocking assignments in a edge triggered always block might sometimes correctly infer a register, but is a very bad coding practice and in this case will result in something that looks like it's working but is trying to run 40 iterations of compares and adds in parallel, which will be a huge slow mess of logic.

Using the non-blocking assignments breaks the simulation as the count <= count + 1 gets scheduled multiple times but only occurs once, so it only increments once each clock cycle. Once again a problem with understanding how the for loop works in Verilog and how non-blocking assignments are scheduled.
Thanks a lot ads-ee. Helpful information.
More interesting thing that no matter what sign in equating "temp" register, the value of "temp" is showing right. Seems that problem exist in this part of code: (the value of "count" shows 48 insteed 40)
Code:
if (temp != 0)
                count = count + 1;

- - - Updated - - -

One more thing. I took an example from the tutorial. But result seems unexpected.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module initmem;
           reg [15:0] mem16_256 [255:0];
           reg [15:0] address;
           integer    index;
 
           initial begin
              address = 24;
              for(index = 0; index < 256; index = index + 1) begin
              mem16_256 [index] = address;
              address = address + 1;
              $display("%d", mem16_256[index]);
              end
           end
 
        endmodule // initmem


I added an edge triggered ( posedge clock) always blocks and changed to non-blocking assignment. After i got correct result. The code is below:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module initmem;
           reg [15:0] mem16_256 [255:0];
           reg [15:0] address;
           reg clock;
           integer    index;
 
           initial begin
           address = 1;
           clock = 0;
           forever #10 clock = ~clock;
           end
             always @(posedge clock) begin
              for(index = 0; index < 256; index = index + 1) begin
              mem16_256 [index] <= address;
              address <= address + 1;
              $display("%d", mem16_256[index]);
              end
           end
 
endmodule // initmem



- - - Updated - - -

Sorry guys. I was not attentive. Both module work fine. Second module just work for each clock cycle. Two example proven ads-ee's reply.
 

One more thing guys!!
If you using initial block with a blocking assignments - it is working fine, but you can use it only once(you can not update if new value comes). If you using always@(posedge clock) block with non blocking assignments it will not work for a single register. You can use array registers with with loop variable in indexes.
For example it will not work as below:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
//initial begin
    always @(posedge clock) begin
    //if (collect == 1)begin
    for (i = 0; i < 16; i = i + 1) 
   
        begin
        variable[(i*8)+:8] = strings[i];
        if (strings[i] == 8'b00011111)
        
        count <= count + 1;
        
        $display("%d%d",strings[i],count);    
        end


But if you declare count as an array for each count will equate 1.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
//initial begin
    always @(posedge clock) begin
    //if (collect == 1)begin
    for (i = 0; i < 16; i = i + 1) 
   
        begin
        variable[(i*8)+:8] = strings[i];
        if (strings[i] == 8'b00011111)
        
        count[i] <= count[i] + 1;
        
        $display("%d%d",strings[i],count[i]);    
        end

 

Instead of saying your code "doesn't work" you should better say "I don't understand what this Verilog code means and how it's expected to work".

If I understand your problem right, the initial code is much neared to the solution, it only misses an initialization of variable count:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
always@ (posedge clock)
begin
  count = 0;
  for (i = 0; i < 10; i = i + 1)
    for (k = 0; k < 4; k = k + 1)
      if (slv_reg[i][(k*8)+:8] != 0)
        count = count + 1;
  outputa <= count;
end

 

Problem with loop with always procedural block.

Hi everyone!! Once i have posted related issue.
For example: if i use an initial block with blocking assignments - no problem.
But if some data needs to be updated i need to use an always procedural bock.
This example with initial block:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
initial block begin
for (i = 0; i < 16; i = i + 1) begin
        variable[(i*8)+:8] = strings[i];
        if (strings[i] == 8'b00011111)begin
             counter =  counter + 1;
        end        
        $display("%d%d",strings[i],counter);    
        end
    end


If i use an always block with blocking assignments there are seems no affect of loop. After every clock cycle "counter" increment continuously.
Only possible way i found if i will use a "i" variable in indexes of array register.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
reg [0:0] counter [15:0];
 always @(posedge clock) begin
             for (i = 0; i < 16; i = i + 1) 
       
            begin
            variable[(i*8)+:8] = strings[i];
            if (strings[i] == 8'b00011111)begin
            counter[i] <= 1;
    end        
            $display("%d%d",strings[i],counter);    
            end
         end


As you see above for each bit will be set 1.
Is there any other options?
 
Last edited by a moderator:

The problem has been discussed, and IMHO solved in the previous thread.

Calculating the count in one clock cycle as you are apparently intending means to generate a respective large block of combinational logic in front of the registered assignment. There are basically two ways to describe it in Verilog:

- have a continuous assignment or a combinational always block to calculate the count value and assign it in the edge triggered always block
- describe the combinational logic inside the edge triggered always block using blocking assignments

The solution suggested in post #5 refers to the second approach.

- - - Updated - - -

There's also a large offer of literature discussuing appropriate usage of blocking and non-blocking assignments, e.g. the "classical" cummings paper Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill! see www.sunburst-design.com/papers

http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top