Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
21611 Discussions

Multiplication by 0,6

Altera_Forum
Honored Contributor II
2,735 Views

Hi i have an input of 8 bits and i need to make a  

multiplication by 0,6. I doesn't has to be precise so  

i thaught to do :  

INPUT * 19 /32  

 

This is not a working code but is displays what i wanna do: 

 

array_amp_to_find(column_counter) <= std_logic_vector (to_unsigned ((to_integer(CAM_DATA)*19/32), 8)); 

 

Both input (CAM_DATA) and output (array_amp_to_find) are  

std_logic_vectors (7 downto 0). 

 

Q: How to make it work in one cycle? Or first the calculation then take the 8 LSB's?
0 Kudos
15 Replies
Altera_Forum
Honored Contributor II
1,038 Views

Please note that there's no need to perform the actual /32 division. You can simply multiply 19 and discard the 5 LSB. 

 

Moreover multiplication *19 can be reduced to a three terms addition:  

CAM_DATA*16 + CAM_DATA*2 + CAM_DATA*1 

which is equivalent to: 

result <= ("0" & CAM_DATA & "0000") + ("0000" & CAM_DATA & "0") + ("00000" & CAM_DATA) 

where result is std_logic_vector(12 downto 0). 

Then: 

array_amp_to_find(column_counter) <= result(12 downto 5); 

So, neither an actual multiplier is required.  

 

I think this can be easily synthesized to work in a single cycle. 

(I'm not sure about this VHDL syntax, please check; I'm used with Verilog)  

 

 

Regards
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

Thx, 

Does someone has an ID how to take the (12 downto 5) in the sametime 

with the calculation ? 

 

<= (12 dwonto 5) (("0" & CAM_DATA & "0000") + ("0000" & CAM_DATA & "0") + ("00000" & CAM_DATA)); 

 

is not working :)
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

I believe the calculation takes one clk cycle even if you use the temporary variable result, 

since the last one is a continuous assignment, not clock sensitive. 

The actual VHDL code could be: 

 

multiply_0_6 : process (clk, CAM_DATA) 

begin 

if (clk'event and clk='1') then 

result <= ("0" & CAM_DATA & "0000") + ("0000" & CAM_DATA & "0") + ("00000" & CAM_DATA) 

end if; 

array_amp_to_find(column_counter) <= result(12 downto 5); 

end process; 

 

(disclaimer: I'm not a VHDL expert, so I don't know if this is the correct syntax and if my code is actually working as supposed)
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

Yea thaught so. I would be nicer to write a code in one line.  

Thx anyway!
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

 

--- Quote Start ---  

Yea thaught so. I would be nicer to write a code in one line.  

Thx anyway! 

--- Quote End ---  

 

 

 

Library IEEE; use IEEE.Std_Logic_1164.all; use IEEE.numeric_std.all; . . . dn <= to_integer( unsigned( CAM_DATA )) ; Q <= std_logic_vector( to_unsigned( dn * 16 + dn * 2 +dn , 13))(12 downto 5) ; -- or in 1 line Q <= std_logic_vector( to_unsigned( to_integer( unsigned( CAM_DATA )) * 16 + to_integer( unsigned( CAM_DATA )) * 2 + to_integer( unsigned( CAM_DATA )) , 13))(12 downto 5) ;
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

Thx josby, 

never thaught of writing it in the back.  

 

Learned something
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

Just remembered I did some mult by 2^n ages ago and the compiler didn't infer shift but true multiplier!!. Are you sure it is not still the case.

0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

If you simply muötiply with 19, there are two options, depending on your FPGA resources and Quartus synthesis settings: 

- a true hardware multiplier is inferred, can be prevented by synthesis attributes if you want keep the resource for other purposes 

- the multiply operation is synthesized in logic cells, ending up in the same construct as generated by the above suggested sum of terms. So just writing *19 should be no problem.
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

 

--- Quote Start ---  

Just remembered I did some mult by 2^n ages ago and the compiler didn't infer shift but true multiplier!!. Are you sure it is not still the case. 

--- Quote End ---  

 

I checked the RTL before posting (originally): the complier nicely inferred two adders to do the job. If you try to write the * 19 in one go, it infers a multiplier ...
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

Thanks Josyb, 

 

If it was me I will also add a further 16 to the list of addition, so I get rounding up at truncation
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

 

--- Quote Start ---  

the complier nicely inferred two adders to do the job. If you try to write the * 19 in one go, it infers a multiplier ... 

--- Quote End ---  

 

You're apparently describing the RTL netlist. To see, how it's synthesized, you have to examine the gate level. I also guessed, that a hardware multiplier would be inferred. If you have plenty of them, there's nothing against it, I think. Otherwise you would specify multstyle "logic" for the respective node.
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

 

--- Quote Start ---  

You're apparently describing the RTL netlist. To see, how it's synthesized, you have to examine the gate level. I also guessed, that a hardware multiplier would be inferred. If you have plenty of them, there's nothing against it, I think. Otherwise you would specify multstyle "logic" for the respective node. 

--- Quote End ---  

I did go down to the Technology map viewer, they are different, but in the end there is no hardware multiplier used (as witnessed in de Flow Summary). I guess the mapping and fitting are able to deal quite well with the 'one operand' being a fixed value. 

 

 

--- Quote Start ---  

If it was me I will also add a further 16 to the list of addition, so I get rounding up at truncation 

--- Quote End ---  

We have to make a choice here: 

floor (== truncate) : what is in the example code 

ceil : should add 31 (and then truncated), or better said add 2^n - 1 

financial rounding : like kaz proposes adding 16 or 2^(n-1). This looks interesting ...
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

My rounding based on adding 2^(n-1) is the most common rounding used in hardware computations but is now termed (dc biased rounding) Vs dc unbiassed rounding. The difference is really trivial. 

The biassed rounding(adding 16 in our case) goes wrong at so called ties i.e. exact (.5) points if the values are negative otherwise it is identical to "round" function. 

Matlab has now functions like convergent, nearest, round, to give better performance mostly for bit accurate testbenching
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

 

--- Quote Start ---  

My rounding based on adding 2^(n-1) is the most common rounding used in hardware computations but is now termed (dc biased rounding) Vs dc unbiassed rounding. The difference is really trivial. 

The biassed rounding(adding 16 in our case) goes wrong at so called ties i.e. exact (.5) points if the values are negative otherwise it is identical to "round" function. 

Matlab has now functions like convergent, nearest, round, to give better performance mostly for bit accurate testbenching 

--- Quote End ---  

 

Thanks, Kaz. 

Like I said interesting! I will take that into account in my future work. I probably will have no issue with rounding negative numbers as I favour using sign-magnitude representations where truncation goes toward zero in contrast to 2's complement numbers where truncation goes towards -infinity. Unfortunately sign-magnitude is not so efficient to implement.
0 Kudos
Altera_Forum
Honored Contributor II
1,038 Views

I use the * 16 + * 2 + *1 code and no multiplyers were used.  

I also add the +16 or 2^(n-1) for rounding but with that i was familiar with.  

 

Thx all!
0 Kudos
Reply