For-loop in Verilog

2019-08-15 07:59发布

问题:

I am new to Verilog so I am having some problems working with if

Basically I have a 5 bit number, and a want to split it so I can have a 2 digits decimal number. For doing so I have this piece of code

reg [4:0] position, aux;
reg [3:0] display1, display2;
reg [2:0] secondDigit;

always @(negedge iKEY[1] or negedge iKEY[2]) begin
    aux = position;

    for(secondDigit = 2'b0; aux >= 5'b01010; secondDigit = secondDigit + 2'b01)
        aux = aux - 5'b01010;

    assign display1 = aux[3:0];
    assign display2 = {2'b0, secondDigit};

end

The problem is I am getting this message of

loop with non-constant loop condition must terminate within 250 iterations


I also tried substituting the for loop for this while, but keep getting the same error

aux = position;
secondDigit = 2'b0;
while(aux > 5'b01010) begin
    aux = aux - 5'b01010;
    secondDigit = secondDigit + 2'b01;
end

Can somebody help me? Thank you

回答1:

It would be easier if you divided your logic up into a two always blocks. One for combination logic and one for synchronous logic. In the combination logic should looks something like below. Note that the for-loop can unravel to three sequential if-statements.

integer index;
always @* begin // combination logic
  aux = position;
  secondDigit = 2'b00;
  for(index = 0; index < 3; index = index + 1) begin
    if(firstDigit >= 5'b0_1010) begin
      aux = aux- 5'b0_1010;
      secondDigit = secondDigit + 1'b1;
    end
  end
end

As Morgan mentioned, you should not use @(negedge iKEY[1] or negedge iKEY[2]) because it will generate weird synthesis results. It looks like you intend to have a flop. I would recommend the following:

wire enable = !(iKEY[1] && iKEY[2]); // clocking signal
always @(posedge enable) begin // use enable as a clock
  display1 <= aux[3:0];
  display2 <= {2'b00,secondDigit[1:0]};
end

Working code with bare-bone test-bench : http://www.edaplayground.com/s/6/245



回答2:

I only use for loops in RTL which can be statically unrolled, this might be the case here but I do not see it.

You are using the loop to increment secondDigit while the condition is based on aux. To me this suggests a variable number of times around the loop.

The line aux = aux - 5'b01010; will be executed n times implying variable number of subtractors in parallel.

Although looking at your condition aux >= 5'b01010 doe this not imply at most once around the loop? Would an if statement not be much simpler here?

It looks like you are doing the same as:

if ( aux >= 5'b01010 ) begin
  secondDigit = 2'b01 ;
  aux         = aux - 5'b01010;
end

NB: do not use assign inside always blocks it is just:

always @(negedge iKEY[1] or negedge iKEY[2]) begin
  display1 = aux[3:0];
  display2 = {2'b0, secondDigit};
end

What hardware are you trying to imply with always@(negedge iKEY[1] or negedge iKEY[2])?



回答3:

There's nothing wrong with your loop condition - have you changed the code? What sim are you using?



标签: verilog