# How to divide complex number in VHDL?

I know how to divide numbers in VHDL (or using one of the Xilinx IP core generators) but I do not know how to do it in the case the numbers are complex.

In my case I have defined a complex number as this:

type complex12 is record
re  : std_logic_vector (11 downto 0);
im  : std_logic_vector (11 downto 0);
end record;


So my complex number it is just two vectors of 12 bits, one for the real part an other for the imaginary part.

Let say that now I have a and b complex numbers:

signal A : complex12 := (re => (others=>'0'), im => (others=>'0'));
signal B : complex12 := (re => (others=>'0'), im => (others=>'0'));


I know that the theory for dividing to complex numbers tell us two approaches for doing a division:

$$c = \frac{a_r + j\cdot a_i}{b_r + j\cdot b_i} = \frac{(a_r + j\cdot a_i) \cdot (b_r - j\cdot b_i)}{b_r^2 + b_i^2}$$

Alternatively: $$c = \frac{|a|}{|b|} \cdot e^{j (\angle a - \angle b)}$$

But both approaches seem very difficult to implement in VHDL. What would be the preferred approach? Is there an easy way to divide complex numbers? Is there any Xilinx block that can save the day? I am bit lost on how to approach this.

• what is exactly that you find difficult in your first approach? just continue the calculation, and separate the real and imaginary parts. – Vladimir Cravero Jun 24 '18 at 20:37
• You appear to have the right idea about dividing complex numbers. Have you compiled the code and see if it's thrown any exceptions at you? – KingDuken Jun 24 '18 at 20:44
• That second one looks like a combination of a DSP (The squared terms for the magnitude) and some mixture of LUT + Newtons method or something else iterative (for the square root) and either an NCO block or CORDIC for the complex exponential, you already know how to do the real valued division. – Dan Mills Jun 24 '18 at 22:16
• Get rid of those dots for multiplication unless you're talking about taking dot products. – alex.forencich Jun 25 '18 at 7:31

## 2 Answers

You've got the right idea with that first equation. You've just got to do some more algebra:

$$c = \frac{a_r + j a_i}{b_r + j b_i} = \frac{(a_r + j a_i) (b_r - j b_i)}{b_r^2 + b_i^2}$$

$$c = \frac{a_r b_r + a_i b_i + j a_i b_r - j a_r b_i}{b_r^2 + b_i^2}$$

$$c = \frac{(a_r b_r + a_i b_i) + j (a_i b_r - a_r b_i)}{b_r^2 + b_i^2}$$

$$c = \frac{a_r b_r + a_i b_i}{b_r^2 + b_i^2} + j \frac{a_i b_r - a_r b_i}{b_r^2 + b_i^2}$$

Yes, there are a lot of operations required. Looks like 6 multiplies, two additions, one subtraction, and two divisions. Yes, implementing this in Verilog/VHDL will be rather complex. If you don't need maximum throughput, then you can probably get away with one multiplier and one divider and then sequence the operations with a state machine. Compute the denominator first, store it, then do the numerators, computing the second one while the divider is working on the real part of the output.

Alex is right. It's pretty straightforward VHDL, but tedious.

Be aware that word widths grow under arithmetic operations; the product of two signed 12 bit numbers is effectively 23 bits, etc. (Why 23 not 24? Because you have 2 sign bits).

If hardware is scarce, you probably want to round back to 12 (or 16 or 18 or 20) bits to limit further growth on further operations. So there are subtleties, and you probably want to start with a bit-accurate model derived from your equations, and make sure it meets your accuracy/noise specifications before getting in to the detailed design.

(I find the built-in fixed point types in Ada ideal for this modeling, but choose the approach that best suits you. Behavioural simulation using VHDL's numeric_std types works too)

Once the math is right, converting to pipelined VHDL is relatively easy.

OR ... look around for another algorithm that doesn't involve a division in the first place.