VHDL coding tips and tricks: real variable
Showing posts with label real variable. Show all posts
Showing posts with label real variable. Show all posts

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.

Thursday, June 16, 2011

Using real data types in VHDL


   Apart from the standard types like integer and std_logic_vector's VHDL also offer real data types. But a real data type has a big disadvantage. It is not synthesis-able. It can be used only for simulation purposes. This disadvantage limits its use to a large extend, but there are plenty of projects where we look only for simulation results.

  Before starting the coding part of a VHDL project,one has to decide whether the project to be implemented on a real FPGA or just a computer simulation is required. If it has to be ran on FPGA, then forget about the real package and use only synthesis-able data types like std_logic,integer etc... Otherwise you can reduce the time and complexity of your project by using real data types.

The real data type is defined in the library called MATH_REAL. So you have to include the following line before the entity declaration in the code:
use ieee.math_real.all;

The math_real package also offers some elementary mathematical functions for real data types. You can see the math_real.vhd file at the following address.

See the below code to get an idea on how to use these functions:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.MATH_REAL.ALL;

entity real_demo is
end real_demo;

architecture Behavioral of real_demo is

--signals declared with the REAL data type.
--MATH_PI is a constant defined in the math_real package.
signal X : real := -MATH_PI/3.0; --A real variable X, initialized to pi/3(60 degreee).
signal sign_result,ceil_result,floor_result,round_result,trunc_result : real := 0.0;
signal max,min,root,cube,power1,power2,exp_result : real := 0.0;
signal log_result,log2_result,log10_result,log_result2,sine,cosine,tangent : real := 0.0;
signal sin_inv,cos_inv,tan_inv,sin_hyp,cos_hyp,tan_hyp : real := 0.0;
signal inv_sin_hyp,inv_cos_hyp,inv_tan_hyp : real := 0.0;

begin

process
begin

sign_result <= SIGN(X);  --sign of X
ceil_result <= CEIL(X); --smallest integer value not less than X
floor_result <= FLOOR(X); --largest integer value not greater than X
round_result <= ROUND(X); --round to the nearest integer.
trunc_result <= TRUNC(X); --truncation.
max <= REALMAX(4.5,4.6); --return the maximum
min <= REALMIN(2.3,3.2); --return the minimum
root <= SQRT(4.0);  --square root
cube <= CBRT(64.0); --cube root
power1 <= 2**3.0; --power of an integer
power2 <= 3.0**3.0; --power of a real
exp_result <= EXP(1.0); --returns e**X.
log_result <= LOG(2.73); --natural logarithm
log2_result <= LOG2(16.0); --log to the base 2.
log10_result <= LOG10(100.0); --log to the base 10.
log_result2 <= LOG(27.0,3.0); --log to the given base.
sine <= SIN(X); --sine of the given angle(in rad)
cosine <= COS(X);--cosine of the given angle(in rad)
tangent <= TAN(X);--tangent of the given angle(in rad)
sin_inv <= ARCSIN(SIN(X)); --sine inverse.
cos_inv <= ARCCOS(COS(X)); --cosine inverse.
tan_inv <= ARCTAN(TAN(X)); --tangent inverse.
sin_hyp <= SINH(X); --Hyperbolic sine
cos_hyp <= COSH(X); --Hyperbolic cosine.
tan_hyp <= TANH(X); --Hyperbolic tangent.
inv_sin_hyp <= ARCSINH(SINH(X)); --Inverse hyperbolic sine.
inv_cos_hyp <= ARCCOSH(COSH(X)); --Inverse hyperbolic cosine.
inv_tan_hyp <= ARCTANH(TANH(X)); --Inverse hyperbolic tangent.
wait;

end process;   

end Behavioral;

Almost all the functions available in the real package are shown above and comments are provided on what they are used for. For your reference I have attached the simulation result below:


As you can see its a pretty useful library. Dont forget to use it if you have a simulation project in VHDL. Contact me for any kind of help. I always use this package when I need to convert a matlab code to corresponding VHDL(for just simulation). Using this package, helps me to write the vhdl code like a pseudo code.