Search code examples
vhdlfixed-pointmandelbrot

vhdl - incrementing a vector in the complex plane by a fractional amount


I am working on a project that will generate and display the Mandelbrot set on a 640 x 480 vga display (other higher resolutions are planned).

Mapping the VGA x coord to the complex plane is fairly straightforward - If I take the Mandelbrot x region from -2.0 to + 2.0, and map it onto the VGA I get an x increment of .00625 ( 4/640) so that as the the vga x coord increases from 0 to 639, the complex coord needs to increment from -2.0 in steps of .00625. I have been experimenting with fixed-point math with a format of Q4.28 (4 bits for the integer part and 28 bits for the fractional part). Starting is easy enough - xE0000000 maps to -2.0 in the Q4.28 format.

My question is, in VHDL, and using fixed point arithmetic, how do I increment a vector by a fractional amount?

Note: my previous attempts while incorrect yielded results that "looked" correct as an image but were not, if one looks at the data set generated by the test bench and some c# code I wrote to compare results. Thanks in advance.

EDIT : partial logic (from comment)

signal x_DELTA : signed(31 downto 0):= x"00199999"; 
signal cx_MIN : signed(31 downto 0):= x"E0000000"; 
signal cx : signed(31 downto 0); 

process(clk, reset, other stuff) 
begin 
   if reset = '1' then 
      cx <= cx_MIN; 
   elsif rising_edge(clk) then 
      cx <= cx + x_DELTA; 

Note: this code has been shortened and abbreviated to show relevant parts and to conform with comment character limits.


Solution

  • Fixed point addition works the same as regular integer addition. You have to ensure that the addends are both scaled (shifted) so that their binary points align. Multiply your increment by 2**28 to use it in your current format. Then you just add them together like any other integer.

    If this increment will only be a constant it is better show the arithmetic to generate it in VHDL rather than manually compute a magic number by hand:

    constant x_DELTA : integer := integer(4.0/640.0 * 2.0**28);
    ...
    cx <= cx + x_DELTA;
    

    If you have to do a lot of fixed-point work you can make things easier by using the VHDL-2008 fixed_pkg package instead of manually keeping track of binary points and shifts. A VHDL-93 version was created during its initial development and should work in any current simulator and synthesizer.