For Loop In Verilog Does Not Converge - for-loop

I'm attempting to using a for loop to count the repeated leading bit in a 32-bit number. For this, I am doing:
input[31:0] A;
output reg result;
Integer i;
for (i = 31; i > -1; i = i - 1) begin
if (A[i] == 0) begin
result = result + 1;
end
else if (A[i] == 1) begin
i = -1;
end
end
However, when I synthesize the program, I receive a warning saying that the program does not converge. Am I using the for loop wrong? Before this I used i >= 0 and even used a while instead but it doesn't change the outcome. I would appreciate any help. Should I set result to 0 before running the loop?

A[i] == 1 makes number of iterations non-deterministic and causes synthesis to fail. The way around it is letting the loop to unroll till the end and use a conditional variable to handle your calculations. Something like the following:
input[31:0] A;
output reg result;
Integer i;
reg flag;
flag = 0;
for (i = 31; i > -1; i = i - 1) begin
if (flag == 0 && A[i] == 0) begin
result = result + 1;
end
else if (A[i] == 1) begin
flag = 1;
end
end
I assume that it was some type of a flop logic, since in any case this would produce state elements. So, you need to use correct nbas for result and flag.

For synthesis for loops must converge during COMPILE time. Your condition of A[i]==1 can not be determined at compile time so the loops goes from 32 to 2^31-1 before it ends.
Verilog is an HDL, which in many aspects is totally different from standard computer languages.

Related

Verilog parameterized one-hot encoder

I'm a bit embarrassed as I thought this would be easy to write.
A fixed-width one-hot encoder would be easy to write with a case statement. But I'm wracking my brain trying to write a parameterized N-bit one-hot encoder. So far, I have:
module onehot_enc #(
parameter WIDTH
) (
input logic [WIDTH-1:0] in,
input logic [$clog2(WIDTH-1:0] out
);
genvar i;
generate
for(i = 0; i < WIDTH; i++) begin
assign out |= in[i] ? i : 0;
end
endgenerate
endmodule
But apparently "|=" is not an operator.
Anyone have any suggestions on writing this? It seemed so simple to do in my head...
You definitely need a loop for it. No generate block should be used here. The encider can be implemented within an always block.
Because you used 'logic' in your example, I assumed that system verilog syntax is ok here. So, please add the 'system verilog' tag.
In the following example the loop runs through the whole set of iterations without any 'break' to make it synthesizable. So, in this case the last '1' wins. The first out=0 statement assigns the default value of '0' to 'out'. It also makes the code combinational. Otherwise it would be a latch.
module onehot_enc #(
parameter WIDTH = 1
) (
input logic [WIDTH-1:0] in,
output logic [$clog2(WIDTH)-1:0] out
);
always_comb begin
out = 0;
for (int i = 0; i < WIDTH; i++) begin
if (in[i])
out = i;
end
end
endmodule
This only works if your one-hot is truly one-hot, but it doesn't try to priorty-encode the inputs, so it synthesizes smaller.
// one-hot to binary encode
function binary_type_t to_binary_f(vector_type_t v);
to_binary_f = '0;
for (int i=0; i<$bits(binary_type_t); i++) begin
for (int j=0; j<$bits(vector_type_t); j++) to_binary_f[i] |= (j%(2**(i+1)) >= 2**i) ? v[j] : '0;
end
endfunction

Find the Maximum of an input vector in verilog

Im trying to get the maximum of an input vector. Im assuming all inputs are unsigned and that it should work on a range of bitwidths and array lengths.
I have to keep the parameters and input and output logic the way they are. Here is what I have, but I get a syntax error at the if statement:
module max
#(parameter int bW=16,
parameter int eC=8)
(input logic [bW-1:0] a[eC-1:0],
output logic [bW-1:0] z);
logic i=0;
always #* begin
for (i=0; i<size; i++) {
if(a[i] >z)
z = a[i];
}
end
endmodule
Maybe using a case statement would be better? I dont know. Any help would be nice!
Two simple problems.
You used brackets {/} instead of begin/end to wrap your looping statement. No need to wrap a single statement anyways.
You defined i as a single bit. use an int.
You'll also want to use a default for the initial value, then compute max from there.
For example:
module max
#(parameter int bW=16,
parameter int eC=8)
(input logic [bW-1:0] a[eC-1:0],
output logic [bW-1:0] z);
always #(*) begin
// defaults
z = 0;
for (int i=0; i<size; i++) begin
if (a[i] > z)
z = a[i];
end
end
endmodule
In addition to the other comments, I believe the for comparison value should be 'eC', not 'size'. This compiles for me (with the sverilog flag of course):
module max #(
parameter int bW = 16,
parameter int eC = 8
)
(
input logic [bW-1:0] a [eC-1:0],
output logic [bW-1:0] z
);
always #* begin
z = a[0];
for (int i=1; i<eC; i++) begin
if(a[i] > z) begin
z = a[i];
end
end
end
endmodule

Use of Function in For loop in c programming

Can we make use of function in for loop in c programming language like the below example...
#include <stdio.h>
int main()
{
int i = 0;
for (foo(); i == 1; i = 2)
printf("In for loop\n");
printf("After loop\n");
}
int foo()
{
return 1;
}
Also please explain the output of this code ....Answer --->After loop.
yes you can, so it will return 1 and the loop will never be executed. the loop will be executed if i==1 but i is still 0. This will mean the statement printf("In for loop\n"); is not executed and it will continue after this loop -> printf("After loop\n");
for better understanding you could use brackets surrounding the for loop and indentation.without brackets the for loop includes just the next statement:
for (foo(); i == 1; i = 2){
printf("In for loop\n");
}
printf("After loop\n");
The way you are using for loops does not make a whole lot of sense.
The place where you are calling foo() is where the loop variable usually gets initialized.
Think about the general concepts of for loops:
for (INITIALIZATION; CONDITION; AFTERTHOUGHT)
It would make more sense to write
for (i = foo(); i == 1; i = 2)
I see another problem with your for loop in the AFTERTHOUGHT part.
You usually want to modify the loop variable there, but in a way that it depends on the previous state. In the most simple case just increment it, thus write:
for (i = foo(); i == 1; i++)
Then look at the CONDITION part. It should be true for a range of values, otherwise the loop will terminate quickly (after one iteration in this case). You would maybe want to write something like
for (i = foo(); i <= 3; i++)
to have 3 iterations.
You get the basic idea?

warning: suggest parentheses around assignment used as truth value in for loop

I am working on a program, but am having trouble with a for loop
for (int i = N-1; i = 0; i--) {
guessarray [i] = guess % 10;
guess /= 10;
}//for
With my g++ compiler I keep getting the error "warning: suggest parentheses around assignment used as truth value. I understand that I am working backwards in the loop, from low to high, but I don't see how that could be a problem. I have tried putting in parentheses in different places, but it doesn't work. I also know it has nothing to do with the assignment operator since I want to use the assignment operator. The warning is placed directly after N-1.
The compiler is simply calling your attention to the assignment in the for loop. It is probably doing so because the "for" statement has 3 semicolon-delimited expressions which is rather dense and prone to human error. By changing
for (int i = N-1; i = 0; i--)
to
for (int i = (N-1); i = 0; i--)
you are telling the compiler, that yes you really intended the for the initial value of i to be (N-1).
==================
Note also that there is what appears to be a logic flaw in the condition section of the for loop (the 2nd expresses ion)
You have
i = 0;
which means the loop will never execute (unless N==1). I assume your intent was to count down from (N-1) to 0. Thus You should probably have the following:
for (int i = (N-1); i >= 0; i--) // note the i >= 0 condition

Adding the sum of numbers using a loop statement

I need serious help dividing the positive numbers and the negative numbers.
I am to accumulate the total of the negative values and separately accumulate the total of the positive values. After the loop, you are then to display the sum of the negative values and the sum of the positive values.
The data is suppose to look like this:
-2.3 -1.9 -1.5 -1.1 -0.7 -0.3 0.1 0.5 0.9 1.3 1.7 2.1 2.5 2.9
Sum of negative values: -7.8 Sum of positive
values: 12
So far I have this:
int main () {
int num, num2, num3, num4, num5, sum, count, sum1;
int tempVariable = 0;
int numCount = 100;
int newlineCount = 0, newlineCount1 = 0;
float numCount1 = -2.3;
while (numCount <= 150)
{
cout << numCount << " ";
numCount += 2;
newlineCount ++;
if(newlineCount == 6)
{
cout<< " " << endl;
newlineCount = 0;
}
}
**cout << "" << endl;
while (numCount1 <=2.9 )
{
cout << numCount1 << " ";
numCount1 += 0.4;
newlineCount1 ++;
} while ( newlineCount1 <= 0 && newlineCount >= -2.3 );
cout << "The sum is " << newlineCount1 << endl;**
return 0;
}
I do not know C/C++ but here is a general idea of the loop assuming the values are coming from an array. (since I am unaware of how they are coming in, i.e. user input, etc.)
Logic:
Use a for loop structure opposed to a while, to loop over each element of the array.
Initialize two variables to keep count, positiveSum and negativeSum.
At each iteration of the element, check to see if it's greater than 0. That's how you can divide the positive and negative numbers accordingly.
If greater than zero, add the element onto the running positiveSum, else add it to the running sum of negativeSum.
When the loop finishes, positiveSum and negativeSum should have the calculated sum.
If this is homework, (I don't remember if the homework tag was there prior to the question, or was added on later) this pseudo code should point you in the right direction without explicitly doing the entire work for you.
Pseudo Java Code (not tested or compiled)
// as a good convention, I always initialize variables,
// for numbers I always use zero's.
double positiveSum, negativeSum = 0.0;
// assuming array holds the array of values.
for (i=0; i < array.length; i++) {
// if positive, add it to the count
if (array[i] > 0) positiveSum = positiveSum + array[i];
// else negative
else negativeSum = negativeSum + array[i];
}
Once it's completed, both positiveSum and negativeSum should hold the correct calculated sum.
If you have any questions along the way, I can edit my answer to help you achieve the correct answer, I wish I could give it away but that's what your responsibilities are for homework.
I would loop through each number individually, let's call it currentValue
if the number is negative, negativeNumberTotal += currentValue
else if positive, positiveNumberTotal += currentValue
You will get your individual totals that way. Very simple.
You are clearly overcomplicating the problem. First of all you don't need two separate loops for the numbers, as there is a constant 0.4 difference between them, even between -0.3 and 0.1. You only have to check if it's negative or not to know how to sum them up.
Loops are simpler if you use an integer as counter. As you want 14 numbers you can simply count from 0 to 13, and from that you can easily calculate the corresponding floating point value.
Example C# code:
double negSum = 0.0, posSum = 0.0;
for (int i = 0; i < 14; i++) {
double number = -2.3 + (double)i * 0.4;
if (number < 0) {
negSum += number;
} else {
posSum += number;
}
}
You can of course use a floating point number in the loop, but then you need to take into account the inexact nature of floating point numbers. You should make sure to use an ending interval that is something like halfway between the last number that you want and the next.
double negSum = 0.0, posSum = 0.0;
for (double number = -2.3; number < 3.1; number += 0.4) {
if (number < 0) {
negSum += number;
} else {
posSum += number;
}
}
Also, when repeatedly accumulating floating point numbers (like adding 0.4 over and over again), you also accumulate rounding errors. Most numbers can't be represented exactly as floating point numbers, so it's likely that you are actually adding something like 0.3999999999999994225 instead of 0.4 each iteration. It's not likely to add up to something that is enough to show up in this small example, but you should be aware of this effect so that you can anticipate it in situations with more numbers.
You have several magic numbers, whose purpose I'm not sure of, e.g numcount1 = -2.3 In general you want to avoid magic numbers.
You might want to give your variables more descriptive names than num1, num2, etc.
Could you explain more precisely what the parameters are for your assignment?
EDIT:
I've noticed that you are using very weird conditions to control your loop. You are continuing until numcount1 is = 2.9, which is a very fragile sort of setup. The first thing I would do in your shoes is to rewrite your program so that the loop terminates when there are no more numbers to add. (Alternatively, you could just make it stop after, say 12 values.)
EDIT AGAIN:
OK, how about this
int sumOfPos = 0, sumOfNeg = 0, currentValue = -2.3, terminationValue = 2.9;
while (currentValue <= terminationValue) {
if ( /* there is a missing condition here */ ) {
// need a statement here to increment your negative counter
} else {
// need a statement here to increment your positive counter
}
}
// put some statements here to do output
This is easily solvable with pure math:
lowerBound = -2.3
upperBound = 2.9
incAmount = 0.4
signChange = lowerBound % incAmount
numBelowChange = -(lowerBound-signChange)/incAmount
avgNegValue = -(numBelowChange+1)/2.0*incAmount + signChange
sumOfNegative = numBelowChange*avgNegValue
numAboveChange = (upperBound-signChange)/incAmount
avgPosValue = (numAboveChange+1)/2.0*incAmount + signChange
sumOfPositive = numAboveChange*avgPosValue + signChange
It's more accurate, and more efficient than looping and adding.
With the constants you provided,
signChange = 0.1
numBelowChange = 6.0
avgNegValue = -1.3
sumOfNegative = -7.8
numAboveChange = 7.0
avgPosValue = 1.7
sumOfPositive = 12.0
If you're unfamiliar with the % operator, x%y means "divide x by y and return the remainder". So 5%2=1
http://en.wikipedia.org/wiki/Modulo_operator
I'm not a programmer, but I thought it was best to keep the inside of a loop as lean as possible. This version works without any if statements inside the loop, just simple addition. It's late at night, and I've had a couple of whiskies, but I think this algorithm would work (it worked when I tried implementing it in python). It's psuedo code, so you'll have to write it up in yr language of choice:
neg_total =0
abs_total=0
loop with i in all_your_numbers
total += i
abs_total += abs(i)
end
neg_total=(total-abs_total)/2
pos_total=abs_Total+neg_Total
print "sum of negative values =", neg_total
print "sum of positive values =", pos_total
I'm not sure if this is good programming practice, I'm just chuffed that it worked. Points if you can explain how.

Resources