how to count leading 0 in vector - vhdl

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.

Related

VHDL - looping through an array

I wanted to loop through an array elements and later output them.
I don't think that the for loop is correct.
Could someone help with this, please ?
enter image description here
In VHDL, a for loop is a shorthand notation for creating parallel paths of logic.
In your example, the loop becomes a shift-by-1 index mapping assignment:
r_array(1) <= myArray1(0);
r_array(2) <= myArray1(1);
r_array(3) <= myArray1(2);
r_array(4) <= myArray1(3);
r_array(5) <= myArray1(4);
r_array(6) <= myArray1(5);
r_array(7) <= myArray1(6);
Since r_array is scalar type integer type and not a vector, this won't work as is.
Try using r_array as an index counter, then on each rising edge clock the next index of myArray will be assigned and our array index counter will increment by 1 (or wrap over back 0).
if rising_edge(i_CE1Hz) then
if r_array <= 7 then
r_array <= r_array + 1;
else
r_array <= 0;
end if;
o_element <= myArray(r_array); -- new output signal
end if;

VHDL storing individual numbers of a timer into an array to display in a seven segment display

So, I have a code that shows me a timer that counts up perfectly fine and has a working multiplexer, I now want to add a way to basically store the individual value of each number (1, 10 and 100s ) so I can display them. My VHDL knowledge is really basic but here is an example :
signal n ; integer ;= 0; --this is the lap counter
type laptimeone is array (integer range <>) of integer;
type laptimeten is array (integer range <>) of integer;
type laptimehundred is array (integer range <>) of integer;
where laptimeone, ten and hundred is each of the digits I want to save in my array. and n is just there to help me find my way back to that array with another process.
begin
if (StopState = '0') then
--counter, in seconds. with pause.
if(second_clk'event and secondclk='1') then
bcd0 <= one;
bcd1 <= ten;
bcd2 <= hundred;
one <= one + 1;
if (one = 9) then
one <= 0;
ten <= ten +1;
end if;
if (ten = 9) and (one = 9) then
ten <= 0;
hundred <= hundred + 1;
end if;
if (hundred= 9) and (ten= 9) and (one= 9) then
hundred <= 0;
end if;
end if;
elsif (StopState ='1')
laptimeone(n)<= one
laptimeten(n) <= ten
laptimehundred(n) <= hundred
Now I am using some logic I know from other programming languages, but my endgame is simply that when stopstate is 1 , the timer stops, and the last numbers for one,ten and hundred are stored in my array depending on N which is a lap that I will change on another process.
How would I declare and initialize the arrays that could help me ? and am I able to do what I want to do in here in VHDL where I move my way around an array when storing and reading data by simply using that N ?

In Verilog, when using a for-loop within a sequential process, how can you increment the sequential variable?

Here is a snippet of code, hopefully you are alright without the preamble:
always # (posedge clk)
begin
if(rst)
begin
i<=0;
j<=0;
end
else
begin
for(j = 0 ; j < 16 ; j = j+1)
begin
if(i<8)
begin
var[j] <= var_2[i];
i <= i+1;
end
end
end
end
Basically, I am wondering if the outer "for-loop" will erroneously increment the counter variable i, rather than simply calculating the 16 vars in parallel. If this is the case, should I cut the for-loop short so that the variable is incremented outside the for-loop?
Thanks!
You are making the code unnecessary complex.
If i<8 then these get executed:
var[j] <= var_2[i];
i <= i+1;
But the i is not incremented until after the clock edge.
As 'i' does not change the condition does not change and thus once true it stays true for all values of j.
Probably a better way of understanding this is to write the code as follows which has the exact same behavior:
always # (posedge clk)
begin
if(rst)
begin
i<=0;
j<=0;
end
else
begin
for (j = 0 ; j < 16 ; j = j+1)
begin
if(i<8)
var[j] <= var_2[i];
end
// i increment independent from the 'j' loop
if(i<8)
i <= i+1;
end
end

Division on the last outputs

Counter count the number of input samples. Then the counter output (n) and I want to check if the number of samples is even,then n_of_samples = (n*n) else if odd make that ((n*n)-1)
will be something like that
signal dis : integer range 0 to 255 := 0;
signal n : integer range 0 to 255 :=0;
if n mod 2=1 then
n_of samples<= ((n*n)-1);
else
n_of_samples <= n*n;
end if;
norm_dis <= dis / n_of_samples ;
the two signals will have values as (1,6,9,8,.....100) and (0,2,8,9.......,200)
and i want to fetch the two last outputs from the two signal (100,200)
and divide 100/200.how can i write it in vhdl and how can overcome the divide by zero error.
just make sure that you do not divide by zero!
if n_of_samples/=0 then
norm_dis <= dis / n_of_samples ;
end if;

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

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;

Resources