I think that the solution from Rob Gaddi is the best one, but if you want to do a division, here is
how you can do :
You could use the new fixed point type from fixed_pkg and use the function reciprocal to calculate
1/5. If you use this function with a non constant then it won't synthetize well because it will do
the whole calculation in 1 clock cycle.
If we want to calculate 1/x where x is not a constant, we can use this ideal relation :
y = 1.0/x => x * y = 1.0 = x * y_m + x * y_(m-1) + ... + x * y_(n+1) + x * y_n = Mult
where y_k is either 2**k, either 0
In the reality, Mult <= 1 because sometimes the division is not exact but rounded to low.
The goal here will be to make Mult the closest possible to 1.0. First we calculate Mult = x * y_m,
then Mult = x * y_m + x * y_(m-1), then Mult = x * y_m + x * y_(m-1) + x * y_(m-2) and so on until
k=n. At each iteration, we will try to set y_k = 2**k, but if we see that Mult would become higher
than 1.0, then we will set y_k to 0. Then at each iteration, Mult will come closer to 1.0 if y_k =
2**k or stay with its current value if y_k = 0.
Here is how can be declared x and y in VHDL :
signal x : UFixed (a downto b); -- for example a = 11, b = -4
signal y : UFixed (m downto n); -- m = -b-1 = 3; n = -a-1 = -12 => (3 downto -12)
Here is some pseudo VHDL code :
First iteration :
Code:
Mult_Next_Tmp := x * 2**m; -- We try to set y_m to 2**m
Mult_Next := Mult_Next_Tmp when Mult_Next_Tmp <= 1.0 else
0;
y(m) <= '1' when Mult_Next_Tmp <= 1.0 else
'0';
Second iteration :
Code:
Mult_Next_Tmp := Mult + x * 2**(m-1); -- We try to set y_(m-1) to 2**(m-1)
Mult_Next := Mult_Next_Tmp when Mult_Next_Tmp <= 1.0 else
Mult;
y(m-1) <= '1' when Mult_Next_Tmp <= 1.0 else
'0';
Third iteration :
Code:
Mult_Next_Tmp := Mult + x * 2**(m-2); -- We try to set y_(m-2) to 2**(m-2)
Mult_Next := Mult_Next_Tmp when Mult_Next_Tmp <= 1.0 else
Mult;
y(m-2) <= '1' when Mult_Next_Tmp <= 1.0 else
'0';
Last iterations :
(...)
Jonas