0

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.

John Horstkamp
  • 87
  • 1
  • 1
  • 10
  • If you were working in floating-point math, what would the operation "increment a vector by a fractional amount" look like? If we all knew what that meant, we'd have a better chance to figure out the fixed-point arithmetic you want. – David K Jul 17 '14 at 20:44
  • Do you mean this (partial logic): 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; if(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. – John Horstkamp Jul 17 '14 at 21:19
  • Can someone tell me why my formatting doesn't show up after I add a comment that contains code? – John Horstkamp Jul 17 '14 at 21:22
  • I have not figured out how to put code in a comment, but you can edit example code into the question and point out the parts where you think it needs to be improved. It looks like you could do that with the formatted version of the code in your comment. – David K Jul 17 '14 at 21:35
  • Thanks for the Edit Brian! Thanks for the info re formatting code David! – John Horstkamp Jul 17 '14 at 22:19

1 Answers1

0

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.

Kevin Thibedeau
  • 3,299
  • 15
  • 26
  • Thanks! I'll give it a test in a few hours. I actually did try the fixed_pkg (VHDL-93) during my initial iteration of this project (about 1.5 years ago) but it would not synthesize. Maybe it got fixed, or maybe it was just me :) - my VHDL has gotten better these last few years - I'm (now) using ISE 14.7 with a Spartan 6 device. – John Horstkamp Jul 18 '14 at 00:31
  • Hmmm...if my initial cx value is E0000000 - -2.0 using fixed point Q4.28 then if I add .00625 I'll get -1.99375. My testbench is showing E019999A. Shouldn't the most significant hex digit(E) be F (for -1) ? – John Horstkamp Jul 18 '14 at 00:47
  • E019999A -> 1FE66665 (1's complement) -> 1FE66666 (2's complement) -> 1.99374999, your expected result. You wouldn't see F in the MSB unless the 2's complement caused a carry into bit 28. – Kevin Thibedeau Jul 18 '14 at 04:19
  • The most significant _bit_ is the sign bit, so the most significant digit of a negative number could be 8, 9, A, B, C, D, E, or F. The only numbers with leading digit F are the negative numbers closest to zero. – David K Jul 18 '14 at 13:02
  • Ah - so this confusion I have is due to isim displaying the "real" (so to speak) bit pattern and not taking 2's compliment? Or am I still confused? :) – John Horstkamp Jul 18 '14 at 13:14