VHDL coding tips and tricks: January 2012

Thursday, January 19, 2012

Real data types and Synthesisability - Part 1

First of all sorry that I haven't updated this blog for so long. To make up my negligence towards readers I have decided to write a post on the most common problem a vhdl coder may face. How to deal with real type signals in vhdl, when you have to create a synthesisable design?

The truth is that its not possible to make the code synthesisable if you use real type anywhere in your design. The only way to work around this problem is to first convert the real type into a equivalent binary format and then write custom functions to deal with it.

Generally,a real number can be represented in binary in two formats - Fixed point and  Floating point formats. In this article I will talk about only fixed point formats.

When it comes to fixed point, I prefer the Q format. In Q format, we mention the number of integer bits and fractional bits. The number of these bits depends on the actual range and resolution of real numbers you want to deal with. A Q format, will be written as Qm.n where m represents the number integer bits and n represents the number of fractional bits. By default there will be a sign bit as the MSB(Most significant bit) which makes the total size of the binary number as m+n+1.

Range and resolution of a binary number in Qm.n format: 

  • its range is [-2m, 2m - 2-n]
  • its resolution is 2-n

For example for a Q2.6 number,
range is  [-22, 22 - 2-6] = [-4 , 3.984375 ].
resolution is 2-= 2-= 0.015625.

Plan before you decide the value of m and n:

For accuracy and easiness in coding, its better to have a high values for m and n. But a higher value of m and n indicates that the size of your binary number will be high and hence more resource usage. For devices like Spartan 3 etc, its better to stick to a 8 bit binary if possible. Find your own optimized boundary between accuracy and size of design.

Examples for Q format.

3.5 in Q2.2 format = "0.11.10"  = "01110".
3.5 in Q3.5 format = "0.011.10000" = "001110000".
3.4 in Q2.4 format = "0.11.0110" = "0110110".
3.4 in Q2.6 format = "0.11.011001" = "011011001".

How to easily convert a number to Q format?

As far as I know there is no software tool available for a general conversion between a real number and any sized Q format. Some calculators can do this job, but the fastest way is to write a vhdl snippet.

For this purpose we can use the fixed point package available in the ieee_proposed library. This package doesnt work with most of the synthesisers, but it can be used in the form of a testbench code to convert real numbers into Q format.

Follow these steps:
  1. Store the real numbers, which you want to convert to Q format, in a text file.
  2. Write a vhdl snippet to read the real numbers one by one and store in a variable array named, say r. See this post to know how to read and write a text file.
  3. Now declare another array which have elements of sfixed type. One by one convert the values in r to this sfixed type using the to_sfixed function. See the below example:

    variable r : real;
    variable s : sfixed(m downto -n);
    s := to_sfixed(r,s); --convert r to type of s and store it in variable s.
  4. Write a vhdl snippet to write the values in s to another text file.
 Matlab for file handling:

I use Matlab software to easily manipulate text files. Using Matlab you can read or write text files of csv format. Some times I have the real values stored in a MS Excel file. To convert it into a text file, I just have to save it as a csv file, use the Matlab Import feature and then use the dlmwrite command in Matlab to write the text file. This will save a lot of your time and frustration. 
 
Note:- In the next part, I will talk about how to write, custom arithmetic functions for fixed point format numbers.

Friday, January 13, 2012

Reading and writing real numbers using Files - Part 3

After the previous posts on file handling, now I have come up with another way to read and write files.

In this article I will show how to read a text file containing real numbers and store the square roots of these real numbers in another text file. The input file is named as "1.txt" and output file is named as "2.txt".

Contents of 1.txt:

12.23
34.4343
23.11
5.0
25.0
49.0
81.88
1000000.0
121.0
78.9

Contents of 2.txt:

3.497142e+00
5.868075e+00
4.807286e+00
2.236068e+00
5.000000e+00
7.000000e+00
9.048757e+00
1.000000e+03
1.100000e+01
8.882567e+00

VHDL code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.MATH_REAL.ALL;
library std;
use std.textio.all;

entity file_handle is
end file_handle;

architecture Behavioral of file_handle is

type real_array is array(1 to 10) of real;

begin

process

variable line_var : line;
file text_var : text;
variable r : real_array;


begin        

       
   --Open the file in read mode.
   file_open(text_var,"1.txt",read_mode);
    --run the loop 10 times to read 10 real values from the file.
    for i in 1 to 10 loop
    --make sure its not the end of file.
    if(NOT ENDFILE(text_var)) then
     readline(text_var,line_var);   --read the current line.
      --extract the real value from the read line and store it in the variable.
     read(line_var,r(i));
    end if;
    end loop;
    file_close(text_var); --close the file after reading.
 
    --Write the square root values of variable 'r' to another file.
    file_open(text_var,"2.txt",write_mode);
    --run the loop 10 times to write 10 real values to the file.
    for i in 1 to 10 loop
      write(line_var,sqrt(r(i))); --sqrt is a fucntion for finding square root.
        writeline(text_var,line_var);
    end loop;
    file_close(text_var);

  wait;

end process;

end Behavioral;

This way of reading and writing files is very helpful in many situations. In my next post I will show an example based on this code snippet.