The most interesting head scratching "break" command problem in Simulink these days

1 view (last 30 days)
Below is a simple snippet to implement in Simulink HDL Coder, however, to my surprise the "break" command is not valid in HDL coder nor is the "for-iterator block", which has led me to wonder if its at all possible to implement this in Simulink for HDL
a) I could avoid the "for-iterator block" (because its not available in HDL), by using a user defined function block and writing the for loop in there (which is where the snippet is from below), but I'm not sure how one can get around a break command
b) I doubt one would find a command similar to "break" for HDL, and so will therefore rule out the user-defined-function block as an option, leaving you with just counter and logical blocks to solve the problem, but in which lies the dilemma
Does anyone know how you can implement the code below? I tried all sorts of limited counters and memory blocks, but cant seem to solve it and break out of the loop. Any tips and help would be greatly appreciated
function y = fcn(gs,g)
%#codegen
n = length(gs);
for i = n:-1:1
if gs(i) >= g
idx = i;
break
else
idx = 0;
end
end
y = idx;

Accepted Answer

Bharath Venkataraman
Bharath Venkataraman on 22 Sep 2016
In this case, since you are passing in the 80x1 matrix, here's what you do:
% returns last index that matches gs >= g
for ii = fi(1:80)
if gs(ii) >= g
idx = ii;
end
end
To use the first/smallest index of gs that is >= g, do the following:
% returns smallest index of gs that is >= g
for ii = fi(80:-1:1)
if gs(ii) >= g
idx = ii;
end
end
In both these cases, you are trying to loop over all 80 indices in one clock cycle, which means 80 comparisons in one cycle. If instead, you were able to pass in the 80x1 matrix one value at a time to the function, that would help compare one value of gs at a time.
  1 Comment
DN
DN on 22 Sep 2016
Ok then so you have to use a for loop. I was hoping to use only Simulink blocks or your "persistent variable idea" above (although not fully clear), as even you suggested is best practice not to have for loops. I guess this is not too a big for loop so should be ok when synthesise. Thanks

Sign in to comment.

More Answers (2)

Tim McBrayer
Tim McBrayer on 21 Sep 2016
A break statement exits a loop statement at an arbitrary iteration. In your code it is entirely data dependent. A loop will in general get fully unrolled in hardware and implemented in parallel, with each iteration getting its own hardware and computing their values in parallel. In the case of your loop, all possible values of idx will be computed in parallel and the correct value selected. I'm sure you can see how these two concepts (break statements and fully unrolled loops) don't work well together.
You can rewrite the loop to not need the break statement. Here is one possibility for finding the highest index i where gs(i) > g, without using a break statement.
idx = 0;
for i = n:-1:1
if idx == 0 && gs(i) >= g
idx = i;
end
end

Bharath Venkataraman
Bharath Venkataraman on 21 Sep 2016
For HDL, having a variable sized for loop is problematic. What you want to do is to loop over all the indices, but only store the index you find to work for you.
function y = fcn(gs,g)
%#codegen
n = length(gs);
idx = 0;
for i = n:-1:1
if gs(i) >= g && ide ~= 0
idx = i;
end
end
y = idx;
What you may also want to do is consider whether gs can be streamed in, in which case you do not need a for loop at all, all you will have is one value of gs at a time compared to g and you can update the index at that time.
function y = fcn(gs,g)
%#codegen
persistent idx; % define index as a register
if isempty(idx)
idx = 0;
end
if gs >= g && idx ~= 0
% if idx has been updated, do not update it again (that is, get "first" update only)
idx = i;
end
y = idx;
You probably want to consider a fixed point type for idx instead of double, say idx = fi(0,0,10,0) for a 10 bit unsigned index value.
  1 Comment
DN
DN on 21 Sep 2016
Thanks Bharath, Tim, I see where you coming from.
Bharath, I actually do prefer to use simulink blocks and avoid for-loops like a plague as you can see from my screenshot, however, I'm not sure what you mean by "stream". I have my matrix gs, which I then push through a column/row selector, then do my relational operator (can do it before too and then use selector), but then I get stuck to find my "last" index for which is true, and could only do it with a "break" in a fu block as we know now. I can see what you mean in above code, however, I'm still unsure what you define "i" as here and what you mean by updating all the time/streaming (because as you know I need the last value that's 1 or true). I run this diagram every 1 clock cycle. Of course I would love not to use a user defined fu block and best practice, but if I do use your fu block option I still cannot run it in the attached pic which I'm guessing is the dismissal of the for-loop and undefined "i"

Sign in to comment.

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!