4
votes

I wanted to calculate and simulate clock phase shifting, when I ran into the problem that VHDL has no mod operator defined for REAL values.

I check my old VHDL book and this online source. Both mention mod for integers, but not for numbers (including floats).

GHDL also reports mod as unknown.

Example calculation:

constant Period     : TIME := 10.0 ns;
constant PhaseDelay : TIME := Period * (((Phase + 360.0) mod 360.0) / 360.0);

Why is the mod operator not defined for real values?

Modulo/Remainer definition for positive integer values a, b:
a = (a/b)*b + (a REM b)

This equation can be used for remainer calculation on negative numers, too. The modulo operation on negative numbers need some tricks to handle the sign, but it's also base on add, sub, mult, div.

2
It's even worse than you think. This is not a VHDL problem (nor any language). Modulus on real numbers is not even defined on a pure mathematical point of view. The reason is that there is no quotient / remainder notion with real numbers. They make sense only with integers.Renaud Pacalet
Essentially, because division is exact.user_1818839
Oooh .... IEEE.math_real comes with a mod operator defined as: X = Y*N + mod (X, Y). As far as I can see it was introduced in VHDL-93.Paebbels

2 Answers

4
votes

Modulo is well defined for integers, but not for reals. Modulo gives you the remainder of integer division a / b, but real division doesn't have remainders, it gives you a real...

For instance, if you perform 13 divided by 3. Integer division will give you a result of 4 with a remainder (modulo) of 1. Real division will give you approximately 4.333333333333, no remainder since it is exact (ignoring finite representation of number).

To get the modulo after real division of a / b = c, you would have to do something like (c - floor(c))*b. In the case of  13/4 example, it gives you back 1.

0
votes

I had a similar problem, which I solved easily. I have a real number variable r that I need to clamp (as in modulo) so it stays within the range 0.0 to 1.0. First I create an integer i = floor(r). Then I subtract i from r to get my answer. If your code allows you to scale the result, I suspect multiplying this by 360 would give the desired result.

This may not satisfy the definition of ‘modulo for reals’, but for my purposes at least, the result is satisfactory.