vhdl "for loop" with step size not equal to 1 - for-loop

I have a simple question . Is it possible to write a VHDL for loop with step size not equal to 1 e.g 16
The loop should go like
0--> 16 --> 32--> 48.... to some value
any immediate help is appreciated

A possible solution is to use a range that is 1/16th of the desired range and unroll the loop inside it to generate the desired range:
for i in 0 to 3 -- Actually 0 to 48
loop
x(16*i) <= ...
x((16*i)+1) <= ...
(...)
x((16*i)+15) <= ...
end loop;
Another solution would be to use a while instead. Assuming your count variable is an integer:
while (i < 48)
loop
--Do something
i := count + 16;
end loop;
Edit: I haven't tested the code above, you might be unable to change the variable count inside the loop, I'm not sure. Maybe the first solution is the best one.
It is not possible to have a for loop with a step different then 1. You are not even allowed to change it inside the for, like this:
--THIS WILL NOT WORK
for i in 0 to 48 loop
--Do Something
i := i + 15; -- This will NOT increment the loop index by 16
end loop;
And finally, for steps of 2 or 3 you might use nested for's.
But anyway, What are you trying to accomplish? VHDL is a low-level hardware description language, you should be able to achieve whatever you are trying to without fancy for loops.

VHDL has no step parameter in for loop, so the step is always 1 for to
range direction and -1 for downto range direction.
So if you need loop with start and step value, you can do:
...
constant FOR_START : natural := 1;
constant FOR_STEP : natural := 2;
variable idx_v : natural; -- Support index variable
...
for idx_pre in 0 to 3 loop
idx_v := FOR_START + FOR_STEP * idx_pre;
z_o(idx_v) <= a_i(idx_v);
end loop;
A while loop can also be used as alternative:
constant FOR_START : natural := 1;
constant FOR_STEP : natural := 2;
constant FOR_MAX : natural := 7;
variable idx_v : natural;
...
idx_v := FOR_START;
while idx_v <= FOR_MAX loop
z_o(idx_v) <= a_i(idx_v);
idx_v := idx_v + FOR_STEP;
end loop;

How about looping over the entire range, but then using an 'if' statement to only act on every 16th value?
for i in start_thing to end_thing loop
if i mod 16 = 0 then
do things(i)
end if;
end loop; -- i
Or alternately use Next:
for i in start_thing to end_thing loop
next when i mod 16 /= 0 ;
do_things(i)
end loop; -- i

My research says no, but you can declare a second variable that acts as a multiple of your variable inside of your loop.

Yes, it is possible to "for loop" with a step size not equal to 1.
for i in range 1 downto 0 loop
foo(i) <= bar(1-i);
end
loop;

Related

VHDL: assign new value to the specific element of 2D Array

I want to copy the Average Variable value to the specific location of 2d Array. For this code it is array_new_signal11(3,2).
Can anyone guide me how can I do this? This code gives me error while simulation.
architecture Behavioral of Correction is
type array_new is array (0 to 4, 0 to 4) of integer;
signal array_new_signal: array_new;
begin
array_new_signal11 <= ((1,2,3,4,5),
(4,5,6,7,8),
(7,8,9,0,1),
(1,3,6,5,9),
(2,3,5,4,5));
Process(kelvin)
variable Sum1: integer:= 0;
Variable Sum2: integer:= 0;
Variable Total_Sum: integer:= 0;
Variable Average: integer:= 0;
begin
for Row in 0 to 4 loop
for Column in 0 to 4 loop
if(Row = 1 and Column = 1) then
for Column in 1 to 3 loop
sum1 := array_new_signal11(Row, Column) + Sum1;
end loop;
end if;
if(Row = 2 and Column = 1) then
for Column in 1 to 3 loop
sum2 := array_new_signal11(Row, Column) + Sum2;
end loop;
end if;
end loop;
end loop;
Total_Sum := Sum1 + Sum2;
Average := Total_Sum / 8;
**array_new_signal11(3,2) <= Average;**
end Process;
end Behavioral;
Constructing a Minimal, Complete and Verifiable example from the question:
entity correction is
end correction;
architecture behavioral of correction is
type array_new is array (0 to 4, 0 to 4) of integer;
signal array_new_signal11: array_new := ((1,2,3,4,5),
(4,5,6,7,8),
(7,8,9,0,1),
(1,3,6,5,9),
(2,3,5,4,5));
signal kelvin: boolean;
begin
-- array_new_signal11 <= ((1,2,3,4,5),
-- (4,5,6,7,8),
-- (7,8,9,0,1),
-- (1,3,6,5,9),
-- (2,3,5,4,5));
process (kelvin)
variable sum1: integer:= 0;
variable sum2: integer:= 0;
variable total_sum: integer:= 0;
variable average: integer:= 0;
begin
for row in 0 to 4 loop
for column in 0 to 4 loop
if row = 1 and column = 1 then
for column in 1 to 3 loop
sum1 := array_new_signal11(row, column) + sum1;
end loop;
end if;
if row = 2 and column = 1 then
for column in 1 to 3 loop
sum2 := array_new_signal11(row, column) + sum2;
end loop;
end if;
end loop;
end loop;
total_sum := sum1 + sum2;
average := total_sum / 8;
report "sum1 = " & integer'image(sum1) & ", " &
"sum2 = " & integer'image(sum2) & ", " &
"average = " & integer'image(average);
array_new_signal11(3,2) <= average;
end process;
MONITOR_PROCESS:
process
begin
wait on array_new_signal11;
for row in 0 to 4 loop
report "row" & integer'image(row) & " = " &
integer'image(array_new_signal11(row,0)) & ", " &
integer'image(array_new_signal11(row,1)) & ", " &
integer'image(array_new_signal11(row,2)) & ", " &
integer'image(array_new_signal11(row,3)) & ", " &
integer'image(array_new_signal11(row,4));
end loop;
end process;
end behavioral;
We see the report statements tell us the average and report the new array values.
We see the Row 3 Column 2 was initialized to 6 and is now 4:
ghdl -a correction.vhdl
ghdl -e correction
ghdl -r correction
correction.vhdl:42:7:#0ms:(report note): sum1 = 18, sum2 = 17, average = 4
correction.vhdl:52:13:#0ms:(report note): row0 = 1, 2, 3, 4, 5
correction.vhdl:52:13:#0ms:(report note): row1 = 4, 5, 6, 7, 8
correction.vhdl:52:13:#0ms:(report note): row2 = 7, 8, 9, 0, 1
correction.vhdl:52:13:#0ms:(report note): row3 = 1, 3, 4, 5, 9
correction.vhdl:52:13:#0ms:(report note): row4 = 2, 3, 5, 4, 5
as specified by the value of average.
As Renaud Pacalet notes you have two different processes driving array_new_signal11, which is not legal in VHDL, as it's element type integer is not a resolved data type.
The solution is to initialize the array in this case where it's declared.
Otherwise every assignment to an element of array signal must be in the same process. The concurrent signal assignment you had will be elaborated to an equivalent process statement and generate an error when elaborated as it was originally shown:
ghdl -r correction
for signal: .correction(behavioral).array_new_signal11(3,2)
./correction:error: several sources for unresolved signal
./correction:error: error during elaboration
(For the ghdl simulator part of elaboration (which consists of linking and loading) is done when invoking simulation (the -r command, the loading part, where the design network is created)).
Renaud Pacalet suggests assigning the array value inside the process, but without an intervening wait statement the values are not available for subsequent use in the same simulation cycle. The new signal values are not available in the same simulation cycle they are assigned.
Each signal assignment schedules a waveform update and only one entry for a particular simulation time is available. In this case it would guarantee array(3, 2) would be the average of eight values of integer'left (which would be incorrect, you should get errors causing simulation to end during the accumulation of sum1 in the unlabelled 3rd loop statement first loop iteration).
And that tells us you need the array initialized before being read.
The only reason the above example succeeds is that there are no array elements when added together won't violate the value range of type integer with the values you specified.
You can get around this sort of thing by using binary array equivalents of integers and paying attention to the needed accuracy.
There are several morals to this story. First, VHDL isn't a programming language, second it's strongly typed and third signals assignment values are never visible in the simulation cycle they are made in.
Note that kelvin has been added as boolean signal to trigger execution of the process once without changing it.
You are trying to drive the array_new_signal11 signal from two different processes. Yes, your first concurrent signal assignment:
array_new_signal11 <= ((1,2,3,4,5),
(4,5,6,7,8),
(7,8,9,0,1),
(1,3,6,5,9),
(2,3,5,4,5));
is a shorthand for a process. It models a hardware driver that continuously imposes these values to your array signal (which is just a bunch of wires, at the end).
Your second process also tries to impose a value to one cell of your array (cell array_new_signal11(3,2)). In electrical engineering, this situation is called a short-circuit: what would you expect when the two drivers disagree? This is also the reason why your simulator refuses this: it does not know what to do with this signal.
Solution: drive this signal from one single process:
process(kelvin)
...
begin
array_new_signal11 <= (
(1,2,3,4,5),
(4,5,6,7,8),
...
for Row in 0 to 4 loop
...
end process;
Notes:
Average being a variable you should have another error on:
Average <= Total_Sum / 8;
which should be:
Average := Total_Sum / 8;
You are using the same loop index (Column) in two nested loops. Not sure what you are trying to do but this is not very safe.
Even with my suggestion to fix your error you will hit another problem: the array_new_signal11 is both an input (you read it) and an output (you assign it) of your process. It should thus also be listed in the sensitivity list. In electrical engineering this is called a combinatorial loop and is usually highly undesirable, except if you want to create an oscillator or a kind of random generator.
Your process is sensitive to signal Kelvin but does not use it. Strange situation. Do you have a clear idea of what hardware you are trying to model?
You probably believe that your process variables are re-initialized to 0 each time the process resumes (that is, each time Kelvin changes). This is not the case: they retain the last value they were assigned. Probably not what you want. You should initialize them at the beginning of your process body.

maximum value of for loop in PL/SQL

I'd like to know, what is the maximum value in a for loop statement?
Is the datatype NUMBER?
BEGIN
-- Bounds are numeric literals:
FOR j IN 1..5000 LOOP
NULL;
END LOOP;
END;
I will need up to 3x10^14
As noted in the documentation, the lower and upper bounds of a for expression are stored in a temporary pls_integer variable. According to pls_integer's documentation, it can hold values from -2147483648 to 2147483647, represented in 32 bits.
You can give yourself some more room with regards to the upper bound on the loop iterator. For example if you have a loop like this:
declare
lower_bound number := 2147483640;
upper_bound number := 2147483650; -- <==Exceeds PLS_INTEGER max value
begin
for i in lower_bound..upper_bound
loop
... do something with i ...
end loop;
end;
that encounters an ORA-01426: numeric overflow error you can rewrite your loop like this:
declare
lower_bound number := 2147483640;
upper_bound number := 2147483650;
i number;
begin
for j in 0 .. upper_bound-lower_bound
loop
i := j + lower_bound;
... do something with i ...
end loop;
end;
In the above code, I've changed the loop iterator from i to j, changed the loop bounds to always iterate from zero to the number of iterations required, and added a new local variable i to be used by your original code. Finally adding i := j + lower_bound; as the first statement inside the loop ensures that your code sees i the way it expects.
Now as long as you aren't iterating 2,147,483,647 times you should be good.
I am not sure, why you may needed this much bigger loop.
may be you can try this
Thanks,
Thangamani Eraniyan
BEGIN
FOR j IN 3 LOOP
begin
FOR K IN 10 LOOP
begin
for L in 14 loop
Null /* you can try your code here */
End Loop;
End Loop;
END LOOP;
END;

vhdl code (for loop)

Description:
I want to write vhdl code that finds the largest integer in the array A which is an array of 20 integers.
Question:
what should my algorithm look like, to input where the sequential statements are?
my vhdl code:
highnum: for i in 0 to 19 loop
i = 0;
i < 20;
i<= i + 1;
end loop highnum;
This does not need to be synthesizable but I dont know how to form this for loop a detailed example explaining how to would be appreciated.
Simply translating the C loop to VHDL, inside a VHDL clocked process, will work AND be synthesisable. It will generate a LOT of hardware because it has to generate the output in a single clock cycle, but that doesn't matter if you are just simulating it.
If that is too much hardware, then you have to implement it as a state machine with at least two states, Idle and Calculating, so that it performs only one loop iteration per clock cycle while Calculating, and returns to the Idle state when done.
First of all you should know how have you defined the array in vhdl.
Let me define an array for you.
type array_of_integer array(19 downto 0) of integer;
signal A : array_of_integer :=(others => 0);
signal max : integer;
-- Now above is the array in vhdl of integers all are initialized to value 0.
A(0) <= 1;
A(1) <= 2;
--
--
A(19)<= 19;
-- Now the for loop for calculating maximum
max <= A(0);
for i in 0 to 19 loop
if (A(i) > max) then
max <= A(i);
end if;
end loop;
-- Now If you have problems in understating that where to put which part of code .. in a ----vhdl entity format .. i.e process, ports, etc... you can reply !

how to count leading 0 in vector

back:while (sub1_mantissa(52)='0') loop
sub1_mantissa := sub1_mantissa(51 downto 0) & '0';
count := count + "000000000001";
end loop back;
hi .i want to count leading zeros in vector...like if my result is 0001 so it will show 3 zeros..so my counter will be increment by 3..and when i will get the first 1 in msb then my loop will stop...
i m using the above code..but it is not working...counter value it takes is too large like 1100111...i am not getting where is d problem...guys plz help me...n reply soon
I would use a for loop to count this, something like this:
variable zero_count : natural := 0;
for i in sub1_mantissa'range loop
if sub1_mantissa(i) = '0' then
zero_count := zero_count + 1;
else
exit;
end if;
end loop;
NOTE: this will only count the leading zeros if sub1_mantissa is declared using DOWNTO notation.

Short VHDL for loop code i dont understand

I do understand how to convert a binary number into a decimal number but the following code thats supposed to do that doesnt make sense. I mean lets sat we have a binary number 10, then v(i) would be 0, so result stays 0. Upon the next iteration v(i) will be 1 so result will be 0 + 1 . The loop stops and the function will return the value of result which is 1 and not 2 which is the value of the binary number put into the function. Could someone tell me why I am wrong? This code comes with a university assignment so it should be correct. Thanks. :)
-------------------------------------------------------------------------------
-- convert std_logic vector v to natural
-------------------------------------------------------------------------------
FUNCTION s2n(v: std_logic_vector)
RETURN natural IS
VARIABLE result: natural := 0;
BEGIN
FOR i IN v'range LOOP
result := result * 2;
IF v(i) = '1' THEN
result := result + 1;
END IF;
END LOOP;
RETURN result;
END s2n;
The 'range loop works from left to right. The convention is for the most-significant bit to be on the left
By decoding that first, the *2 operation gets run most times on the MSB as you'd expect.
(BTW, if you want the range to go the other way for some reason, you can use the 'reverse_range attribute)

Resources