Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

decimal (floating point) multiply by integer number in vhdl

Status
Not open for further replies.

fanwel

Full Member level 3
Joined
May 26, 2011
Messages
178
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,298
Activity points
2,878
Hi all,

I try to write VHDL code for multiply a decimal (floating point) number with an integer. For example:

I have a set of vector (integer) as the input, f(n)= (12,3,10,7). Then, I want to multiply the input with 0.25.
As I know, I need to convert the 0.25 to the binary number. Do I need to convert the input also and how the operation will be write in VHDL?
I really need helps, please anyone give me any advise. Thank you.
 

firstly, you should read up a small amount about floating point implementations. In the end, I suggest using a fixed point implementation instead. This is where a decimal point is added. eg, 110010.11 -- a 6.2 fixed point. Math is done as normal, but the decimal point is tracked. eg a 6.2 fixed point, multiplied by 1/4 would simply be a 4.4 fixed point.

eg, in your application, you would just track the location of the decimal point, but no actual operation would be performed.

VHDL2008 adds a fixed point package to aid in this process.
 

It is possible if I convert 0.25 into decimal number and do the multiplication operation as an integer?
 

yes. I would read up on fixed point arithmatic, like permute said. Fixed point is just integer arithmatic with a 2^n bias. also, read up on the fixed point libraries, then conversion is a simple as this:

signal a : ufixed(7 downto -2);

a <= to_ufixed(0.25, a);
 

I have read up on fixed point arithmatic but I'm not fully understand the concept.
The example code above will give value "a" as a binary number right? As the code below where I read from a book;

signal n1: ufixed(4 downto -3);
n1<=to_ufixed (9.75,n1);

Then, n1 will be "01001110"..How can this binary number be multiply with input integer? Sorry, I really not clear with this fixed point process.
I appreciate your helps..
 

The basic idea is to have a number of quarters, or halves, or eights. (or twos, or fours, or etc...)

then 2.25 could be represented as 9 quarters. 1001. or, with the decimal in place -- 10.01 .
prior to the fixed package, the developer would need to keep track of the scale for things like 1.0001 + 100.10 = 101.1001. not only does the number of bits increase, but the location of the decimal place changes as well.

floating point is an extension of the above, where the number and the location of the decimal point are given. The advantage is seen in scientific computing, as there is often a need to multiply numbers of very different scales, eg 1E9 * 1E-9.
 

Can you give simple vhdl code of fixed point multiply with integer..thanks for help

---------- Post added at 03:00 ---------- Previous post was at 02:00 ----------

I try to do like this;

library ieee;
library ieee_proposed;
use ieee_proposed.fixed_pkg.all;
use ieee.all;

entity fix is
port (clk: in bit;
c: in integer;
y: out integer);
end fix;

architecture fix of fix is
signal a: ufixed (7 downto -2);
begin
process(clk)
begin
if (clk'event and clk='1') then
a <= to_ufixed (0.25,a);
y <= c * a;
end if;
end process;
end fix;

For sure I get error when I compile the code:
Error (10327): VHDL error at fix.vhd(19): can't determine definition of operator ""*"" -- found 0 possible definitions

really need helps..=(
 
you are forgetting the typing system in VHDL. And you havent looked at the functings inside the fixed package.
an integer * ufixed will produce another ufixed, not an integer. an integer is 32 bits, and "a" is 10 bits, so your result will be 42 bits, 40 integer and 2 fractional.
But, because you are only multiplying by 0.25, it is exactly the same as dividing by 4. So in this case, this option would be much simpler:

y <= a/4;

if you insided on having an integer and a ufixed, I suggest you do this:

Code:
process(clk)
begin
  if rising_edge(clk) then
    y <= to_integer( to_ufixed(c, 31, 0) * to_ufixed(0.25, -2, -2) );
  end if;
end process;


I also suggest you read this user guide: **broken link removed**


if you wanted a to be a changing fixed point number, you cannot output an integer without having to round or saturate/overflow your integer (depending on the number of bits).

---------- Post added at 08:16 ---------- Previous post was at 08:11 ----------

my bad - there is no integer* ufixed function - you need to convert the integer to a ufixed first.
 
Hi TrickyDicky,

my bad - there is no integer* ufixed function - you need to convert the integer to a ufixed first.

That mean I need to convert my input to a ufixed? If my input is a vector of integer where I not fix the values, how can I convert it to a ufixed?
 

you'll have to convert them one by one in a for loop.
or dont use integer in the first place.
 

Referring to your design interface:
Code:
entity fix is
port (clk: in bit;
c: in integer;
y: out integer);
end fix;

The first thing that should be done to turn it into a clearly specified, synthesizable design would be to specify an range for input and output numbers. Integer is an abstract type, it can be only synthesized by assuming a bit length. This will be either the default implementation specific size (mostly 32 bit) or any bit length implicitely defined by the internal connections in your design. I guess, you'll agree, that it would be much better to have it clearly specified. For hardware design, it would be much more reasonable to use a signed or unsigned type in it's place. It avoids several problems e.g. in assigning pins to the individual bits.

I didn't previously answer to your post, because I found that there should be at least a minimal specification of the intended output number representation. Although there are still open points (the range), it's clearer now by your code example.

If you want to scale a number and keep it's bit length, it's mostly reasonable to use a fixed point or pure fractional representation of the constant and get the final length by cutting the lower bits of the product. You don't necessarily need the said fixed point package to do so, but it's a great tool to avoid auxilary calculations by pencil and paper and guarantee the correctness of the result.
 

Sorry, what do you mean by dont use integer in the first place?..Thanks for reply
 

Like FvM said. Integers without a range specification are 32 bits, which makes them quite large in an FPGA.
You would be better off using signed/unsigned, or setting a range on the integers when you decalre them.
 

For convert the input integer into ufixed, I do like this;
---------------------------------------------------------------------------
package my_data_types is
typr vector is array (natural range <>) of integer;
end my_data_types;

library ieee;
library ieee_proposed;
use ieee_proposed.fixed_pkg.all;
use ieee.all;
use work.my_data_types.all;

entity fix is
port (clk: in bit;
A: in vector (7 downto 0);
Y: out vector (7 downto 0));
end fix;

architecture fix of fix is
begin
process(clk)
begin
if (clk'event and clk ='1') then
for i in 7 downto 0 loop
Y <= to_unsigned (A,Y);
end loop;
end if;
end process;
end fix;
--------------------------------------------------------------------------------
Please correct me if I do mistake..
 

There are problems.
1. Y is a vector type (please change this type to another name, because otherwise you get confused with other posts refering to vector) which is an array of integers. It is not an array of unsigned.
2. You cannot assign unsigned to Y, because it is a Vector
3. you will need another type to store an array of unsigned.
4. This code is pointless - type conversions like this are free and are not required to be registered.

Please try out your code before posting it on here. If you do not do things for yourself, how do you expect to learn?

---------- Post added at 10:14 ---------- Previous post was at 10:13 ----------

Also to add - you forgot the numeric_std library for the unsigned type. You do not need the fixed point library.
 

Very sorry because I post a code before I compile it. I will write it back based on all your advises.
Many thanks for helps.
 

If you want to multiply it by just 0.25( not ant any random number ) then you can do this..

0.25= 0.01 in binary..

so multiplying a number by 0.01 is equal to right shifting it by 2.

for example,

"10001101011" * "0.01" = "100011010.11"
"1011.01" * "0.01" = "10.1101".

and so on..

if the number is random then you have to just follow normal multiplication methods..
 

Hi vipinlal,

I want to multiply by just 0.25(not random number), but my input is a random number. Do I need to convert the input to binary first? Or I can't use the method you give above? Thanks for reply

---------- Post added at 02:26 ---------- Previous post was at 01:33 ----------

I write the input conversion code like this:
-------------------------------------------------------------------------
package my_data_types is
type exam is array (natural range <>) of integer;
end my_data_types;

library ieee;
library ieee_proposed;
use ieee_proposed.fixed_pkg.all;
use ieee.all;
use work.my_data_types.all;

entity fix is
port (clk: in bit;
A: in exam (7 downto 0);
O: out ufixed (8 downto 0));
end fix;

architecture fix of fix is
begin
process(clk)
begin
if (clk'event and clk ='1') then
for i in 7 downto 0 loop
O(i) <= to_ufixed (A(i),O(i));
end loop;
end if;
end process;
end fix;
-----------------------------------------------------------------------------
I get this error:
Error (10511): VHDL Qualified Expression error at fix.vhd(23): to_ufixed type specified in Qualified Expression must match std_ulogic type that is implied for expression by context

What mean by that error?..My input is an integer and try to convert it to ufixed type. Please help..thanks

---------- Post added at 02:27 ---------- Previous post was at 02:26 ----------

I write the input conversion code like this:
-------------------------------------------------------------------------
package my_data_types is
type exam is array (natural range <>) of integer;
end my_data_types;

library ieee;
library ieee_proposed;
use ieee_proposed.fixed_pkg.all;
use ieee.all;
use work.my_data_types.all;

entity fix is
port (clk: in bit;
A: in exam (7 downto 0);
O: out ufixed (8 downto 0));
end fix;

architecture fix of fix is
begin
process(clk)
begin
if (clk'event and clk ='1') then
for i in 7 downto 0 loop
O(i) <= to_ufixed (A(i),O(i));
end loop;
end if;
end process;
end fix;
-----------------------------------------------------------------------------
I get this error:
Error (10511): VHDL Qualified Expression error at fix.vhd(23): to_ufixed type specified in Qualified Expression must match std_ulogic type that is implied for expression by context

What mean by that error?..My input is an integer and try to convert it to ufixed type. Please help..thanks
 

it will work fine for any random numer.. Just convert the random number into binary and right shift it by 2 as shown in the example..
 

The problem seems to become more and more confused. Now you have an array of integer (with unspecified size) as input and try to copy the it to a single ufixed output signal. How is that supposed to work? You should clarify (primarly for yourself) what you want to achieve.

If a fixed scaling factor of 0.25 respectively 1/4 is intended, a simple rightshift will be in fact the obvious solution. Unfortunately you never mentioned these points.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top