Check for ranges in Systemverilog with least synthesis area - range

I have various inputs that vary in width. I have to detect if each input falls within some specific ranges. For example, an input may be 6 bits and hence in theory have values of 0-63. However, I want to check if it happens to be 2-5, 8, 14-50, 52, 54, 56-58, 61-63. Is there any method that is more area-efficient for synthesis than doing straight-up range or equal comparisons? Currently I would have:
always_comb begin
value_is_in_special_range = 1'b0;
if (
(value >= 'd2 && value <= 'd5) ||
(value == 'd8) ||
(value >= 'd14 && value <= 'd50) ||
(value == 'd52) ||
(value == 'd54) ||
(value >= 'd56 && value <= 'd58) ||
(value >= 'd61 && value <= 'd63) ||
) begin
value_is_in_special_range = 1'b1;
end
end
The specific ranges for various inputs are quite random and could fall nicely within relatively few large ranges, or they could be scattered all over the place.

You should be able to put this code into the synthesis tool and optimization should take care of sharing common sub expressions to make all these comparisons most efficient. This assumes all the values and ranges you want comparisons to are constants.
BTW, a simpler way of writing this expression in SystemVerilog is using the set membership operator:
assign value_is_in_special_range =
value inside {[2:5], 8, [14:50], 52, 54, [56:58], [61:63]};

Related

Checking for value within boundaries

I'm trying to create a function that would verify if a value is within chosen boundaries and if it's not, the user must retry until verification.
I wanted to know why my code skips the if condition for any given value and it returns me for the input prompt : "Error: Invalid expression. Check for missing multiplication operator, missing or unbalanced delimiters, or other syntax error."
A=limit(5pi/6,-pi/2,pi/2) for example jumps directly to the else condition while it's true for the if condition
Here is my code :
function alpha = limit(pos,min,max)
if (pos >= max) && (pos <= min)
alpha=pos;
else
while pos >= max || pos <= min
prompt = 'Enter value between max and min';
alpha = input(prompt);
end
end
end
The function first checks whether pos is both greater than or equal to max and less than or equal to min.
I expect you intend max to be greater than min. Therefore, the if line should be:
if (pos <= max) && (pos >= min)
I assume your val_max/val_min are typos (and should be max/min) Then, your while loop depends on the value of pos. But pos is never updated in the loop, so your loop is just going to iterate forever.
You need to update pos inside the while loop for this to work. Try something like this:
function alpha = limit(pos,min,max)
while pos > max || pos < min
prompt = 'Enter value between min and max';
pos = input(prompt);
end
alpha = pos;
end

GEN_NO_GENERATABLE_NOTIF

I want to choose index from list, so the element[index] complies my condition.
MyList[index].num==0
I tried the code bellow:
gen DescIdx2Choose keeping {
it < MyList.size();
MyList[it].num==0;//I tried a few way of read_only
};
How can I do it without using all_indices?
Thanks
Since you generating DescIdx2Choose then MyList will be input to the problem.
Therefore,
If seeking for the first index (if exists) then using random generation isn't required. Use the procedural code "first_index" as user3467290 suggested which is much more efficient:
var fidx := MyList.first_index(.num == 0);
if ( fidx != UNDEF ) {
DescIdx2Choose = fidx;
} else {
// error handling
};
If there are multiple indices and it is required to choose a random one, the most efficient way would be using "all_indices" as Thorsten suggested:
gen DescIdx2Choose keeping {
it in read_only( MyList.all_indices(.num == 0) );
};
The reason is the random generator doesn't need to read all possible values of "MyList.num" only a shorter list of valid indices.
This should do it, but MyList must fulfill the condition otherwise you get a contradiction. Pseudo-method first_index() is not bi-directional which is what we need here.
gen DescIdx2Choose keeping {
MyList.first_index(.num == 0) == it;
};
Maybe i missed something in the question, but If you always want the index of the first element that its num == 0, then why use constraints? can assign DescIdx2Choose == MyList.first_index(.num == 0).
To ensure that there is at least one such element, can constrain MyList.has(.num == 0).
Do you have additional constraints on DescIdx2Choose ?

Binary operator "<=" can't be applied to operands of type Bool and Int

if 1 <= A[i] <= 100 || 1 <= B[i] <= 100
for the above line I get these two error.
1. Adjacent operators are in non-associative precedence group 'Comparision Precendence'
2. Binary operator "<=" can not be applied to type BOOL and Int.
try if (1 <= A[i] && A[i] <= 100) || (1 <= B[i] && B[i] <= 100)
Joe's answer and Leo's comment would both work. My preference would be Leo's approach (using 1...100 ~= A[i]), but whatever floats your boat.
That said, let me explain WHY what you did is giving you an error. Without any parenthesis to break it up, it evaluates that going left to right. So if first checks "is 1 <= A[i]?", and that results in a boolean answer. It then tries to ask "is true <= 100?", which makes no sense.

How can I re-write this MATLAB code in a more idiomatic and efficient way?

Here is the requirement: the input is a number which will divide an image into several equal part. For example, if the input is 4, it will return 3 parts: the values are the imgSize/4 imgSize/4 * 2 and imgSize/4 * 3.
If the input is n, then it will return n - 1 elements, as in the following implementation:
if (colorLevel == 8)
divide_thres = [ round(imgSize/8) round(imgSize/8)*2 round(imgSize/8)*3 round(imgSize/8)*4
round(imgSize/8)*5 round(imgSize/8)*6 round(imgSize/8)*7 ];
elseif (colorLevel == 4)
divide_thres = [ round(imgSize/4) round(imgSize/4)*2 round(imgSize/4)*3 ];
elseif (colorLevel == 3)
divide_thres = [ round(imgSize/3) round(imgSize/3)*2 ];
end
I want to allow the user to input a value between 2 and 255, and then automatically generate the divide_thres corresponding to that input. How can I re-write this code to be more efficient?
There are several problems with your code:
In each case, you unnecessarily divide imgSize by the same factor multiple times (instead of just once and for all).
You perform many "manual" scalar multiplications, but you could simply multiply the scalar value by a vector generated by the range 1 : colorLevel - 1.
Because the length of the resulting divide_thres vector can be easily computed from the value of colorLevel, there is no need to treat each case separately in an if statement.
Moreover, even if you had to compute the length in a different manner for the cases imgSize = 3, 4, and 8, you would be better off using a switch statement instead of an if statement, because the former would save you the trouble of writing imgSize == ... each time, which is prone to errors and a form of code duplication.
Here's a much simplified approach:
if 2 <= colorLevel && colorLevel <= 255
divide_thres = round(imgSize / colorLevel) * (1 : colorLevel - 1);
else
error('invalid colorLevel value') % (or some other informative message)
end
This should do it -
divide_thres = [1:colorLevel-1]*round(imgSize/colorLevel)

Simple if statement for checking whether a co-ordinate is inside a square?

I have an UIImageView and taking the raw touch input. I need to check if a touch is within a certain set of squares. At the moment...
I have this if statement....
if(46 < touchedAt.x && touchedAt.x < 124 && 18 < touchedAt.y && touchedAt.y < 75)
but I have tried to simplify it to this one...
if(46 < touchedAt.x < 124 && 18 < touchedAt.y < 75)
It didn't work. Is it possible to simplify like this or am I stuck with the slightly lengthier version at the top? Is there a reason why the types of comparisons in the bottom if don't work?
I think a better solution would be to use CGRectContainsPoint:
CGRect rect = CGRectMake(46, 18, 124 - 46, 75 - 18);
if (CGRectContainsPoint(rect, touchedAt))
// do whatever
Some languages support the "simple" version (Python, for example) but the C family doesn't.
In C family languages, the comparison operators are binary operators that return a boolean. One operator, two parameters, one result. Try to add another comparison and you end up comparing your boolean result against the next value. That's why you need all the && operators.
I don't know Objective-C, but I assume it does what C does.
To simplify, just write a simple function (perhaps inline) called "bounds_check" or "range_check" or similar that takes three parameters. Or better still, use one that's already written.