Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > VHDL > Dividing by 48

Reply
Thread Tools

Dividing by 48

 
 
ALuPin@web.de
Guest
Posts: n/a
 
      11-08-2006
Hi,

I have a signal (integer). How can I describe synthesizable code
for dividing that signal by 48 ? Result (ls_rowaddr) should
be whole-number that is integer.

SIGNAL ls_pos : integer RANGE 0 TO 8191;
SIGNAL ls_rowaddr : integer RANGE 0 TO 191;

PROCESS(Reset, Clk)
BEGIN
IF Reset='1' THEN
ls_pos <= 0;

ELSIF rising_edge(Clk) THEN
IF load='1' THEN
ls_pos <= LoadAddr;
END IF;

END IF;
END PROCESS;

-- synthesis ???
PROCESS(ls_pos)
BEGIN
ls_rowaddr <= ls_pos / 48;
END IF;

How can 32 (2^5) and 16 (2^4) be combined ?

Thank you for your comments



Rgds
André

 
Reply With Quote
 
 
 
 
wallge
Guest
Posts: n/a
 
      11-08-2006
factor 48 into (16 * 3)
you can first bit shift to the right by four places then
divide by three using division (division by 3 is much faster than by 48
and requires less logic i suspect)

PROCESS(clk, ls_pos)
variable unsigned_ls_pos : unsigned(12 downto 0);
variable shifted_ls_pos : unsigned(7 downto 0);
BEGIN
if rising_edge(clk) then
unsigned_ls_pos := to_unsigned(ls_pos, 13); --convert to
unsigned
shifted_ls_pos := unsigned_ls_pos(12 downto 4); --chop off
bottom 4 bits same as x/16
ls_rowaddr <= to_integer(shifted_ls_pos / to_unsigned(3, 2));
--divide by 3
END IF;
end process;

use ieee.numeric_std.all as the library for arithmetic
dont use std_logic_unsigned or std_logic_arith,
these will conflict (they are bad packages anyway and being gradually
phased out)

if you have quartus or xilinx ISE this code should synthesize
(i would expect synopsys or synplify as well)



http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> Hi,
>
> I have a signal (integer). How can I describe synthesizable code
> for dividing that signal by 48 ? Result (ls_rowaddr) should
> be whole-number that is integer.
>
> SIGNAL ls_pos : integer RANGE 0 TO 8191;
> SIGNAL ls_rowaddr : integer RANGE 0 TO 191;
>
> PROCESS(Reset, Clk)
> BEGIN
> IF Reset='1' THEN
> ls_pos <= 0;
>
> ELSIF rising_edge(Clk) THEN
> IF load='1' THEN
> ls_pos <= LoadAddr;
> END IF;
>
> END IF;
> END PROCESS;
>
> -- synthesis ???
> PROCESS(ls_pos)
> BEGIN
> ls_rowaddr <= ls_pos / 48;
> END IF;
>
> How can 32 (2^5) and 16 (2^4) be combined ?
>
> Thank you for your comments
>
>
>
> Rgds
> André


 
Reply With Quote
 
 
 
 
jens
Guest
Posts: n/a
 
      11-08-2006
wallge wrote:
> factor 48 into (16 * 3)
> you can first bit shift to the right by four places then
> divide by three using division (division by 3 is much faster than by 48
> and requires less logic i suspect)


Assuming the divide by 48 is to be rounded down, the divide by 3 can be
replaced by * 171 / 512 (shift right by 9) and will yield the desired
result.

 
Reply With Quote
 
ALuPin@web.de
Guest
Posts: n/a
 
      11-08-2006
Hi wallge,

I get the following error message with SynplifyPro 8.6.2:


Right argument must evaluate to a constant integer power of 2


library ieee;

use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

ENTITY divider IS
PORT( Reset : IN std_logic;
Clk : IN std_logic;
DataIn : IN std_logic_vector(12 DOWNTO 0);
DataOut : OUT std_logic_vector(12 DOWNTO 0)
);
END divider;

ARCHITECTURE rtl OF divider IS


SIGNAL ls_data_out : unsigned(12 DOWNTO 0);

BEGIN

DataOut <= std_logic_vector(ls_data_out);

PROCESS(Reset, Clk)
variable v_data : unsigned(12 DOWNTO 0);
variable v_data_shift : unsigned(8 DOWNTO 0);
BEGIN
IF Reset='1' THEN
ls_data_out <= (OTHERS => '0');

ELSIF rising_edge(Clk) THEN
v_data := unsigned(DataIn);
v_data_shift := unsigned(v_data(12 DOWNTO 4));

ls_data_out <= (v_data_shift / to_unsigned(3,2));

END IF;
END PROCESS;

END rtl;

 
Reply With Quote
 
wallge
Guest
Posts: n/a
 
      11-08-2006
hmm...
I guess synplify wont do handle division for some reason.
if you have quartus you can instantiate a mega-function divider
component to do the division,
and even choose how many pipe stages are in the divider.

I am pretty sure that xilinx ISE has the same king of thing, i forget
the name of the tool off the top of my head, but i know xilinx also has
customizable arithmetic blocks within ISE that can be instantiated in
your VHDL code as components in your design...




(E-Mail Removed) wrote:
> Hi wallge,
>
> I get the following error message with SynplifyPro 8.6.2:
>
>
> Right argument must evaluate to a constant integer power of 2
>
>
> library ieee;
>
> use ieee.std_logic_1164.all;
> use ieee.numeric_std.all;
>
> ENTITY divider IS
> PORT( Reset : IN std_logic;
> Clk : IN std_logic;
> DataIn : IN std_logic_vector(12 DOWNTO 0);
> DataOut : OUT std_logic_vector(12 DOWNTO 0)
> );
> END divider;
>
> ARCHITECTURE rtl OF divider IS
>
>
> SIGNAL ls_data_out : unsigned(12 DOWNTO 0);
>
> BEGIN
>
> DataOut <= std_logic_vector(ls_data_out);
>
> PROCESS(Reset, Clk)
> variable v_data : unsigned(12 DOWNTO 0);
> variable v_data_shift : unsigned(8 DOWNTO 0);
> BEGIN
> IF Reset='1' THEN
> ls_data_out <= (OTHERS => '0');
>
> ELSIF rising_edge(Clk) THEN
> v_data := unsigned(DataIn);
> v_data_shift := unsigned(v_data(12 DOWNTO 4));
>
> ls_data_out <= (v_data_shift / to_unsigned(3,2));
>
> END IF;
> END PROCESS;
>
> END rtl;


 
Reply With Quote
 
Ray Andraka
Guest
Posts: n/a
 
      11-09-2006
(E-Mail Removed) wrote:

> Hi,
>
> I have a signal (integer). How can I describe synthesizable code
> for dividing that signal by 48 ? Result (ls_rowaddr) should
> be whole-number that is integer.
>
> SIGNAL ls_pos : integer RANGE 0 TO 8191;
> SIGNAL ls_rowaddr : integer RANGE 0 TO 191;
>
> PROCESS(Reset, Clk)
> BEGIN
> IF Reset='1' THEN
> ls_pos <= 0;
>
> ELSIF rising_edge(Clk) THEN
> IF load='1' THEN
> ls_pos <= LoadAddr;
> END IF;
>
> END IF;
> END PROCESS;
>
> -- synthesis ???
> PROCESS(ls_pos)
> BEGIN
> ls_rowaddr <= ls_pos / 48;
> END IF;
>
> How can 32 (2^5) and 16 (2^4) be combined ?
>
> Thank you for your comments
>
>
>
> Rgds
> André
>


For division by a constant, instead multiply by the reciprocal of the
divisor (the reciprocal is also a constant). You'll want to scale by a
power of two, which is to say you move the position of the implied radix
point. 1/48 = 0.0208333. To make that an integer, scale it by a power
of 2 that gives an appropriate amount of precision for your task. For
example, you might scale it by 2^16 so your reciprocal is 1365*2^-16.
Then when you multiply the dividend, you wind up with a product that is
also weighted 2^-16, so you need to right shift it 16 places to restore
the scaling of the dividend. The multiply in this case is a repeating
pattern of bits (0x555), which can be done with a tree of adders rather
than a multiplier if you do not have full multipliers available.
 
Reply With Quote
 
ALuPin@web.de
Guest
Posts: n/a
 
      11-09-2006
Mr Andraka,

thank you for your suggestion.

> The multiply in this case is a repeating
> pattern of bits (0x555), which can be done with a tree of adders rather
> than a multiplier if you do not have full multipliers available.


Can you elaborate on your last comment. How would those adders
be combined ?

Rgds
André

 
Reply With Quote
 
ALuPin@web.de
Guest
Posts: n/a
 
      11-09-2006
Do you mean the following:

multiplying with 1365 = x555

implies the following


C * 1365 = C * (2^10 + 2^8 + 2^6 + 2^4 + 2^2 + 2^0)

= (C* 2^10) + (C*2^ + ...

where the multiplications can be achieved with shift left operations.

Rgds
André

 
Reply With Quote
 
ALuPin@web.de
Guest
Posts: n/a
 
      11-09-2006
Hi again,

I have found out that my concept has some fault.
Functional simulation and Timing simulation show both
that I have some kind of offset by one in my result:

I get for example : 6000/48 = 124 (instead of 125)

Is there some kind of rounding error I did not think of.

Here is the code and the corresponding testench:

library ieee;

use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

ENTITY divider48 IS
PORT ( Reset : IN std_logic;
Clk : IN std_logic;
Data2DivBy48 : IN std_logic_vector (12 downto 0);
Data2DivBy48Valid : IN std_logic;
DataDividedOut : OUT std_logic_vector (12 downto 0);
DataDividedValidOut : OUT std_logic
);
END divider48;


ARCHITECTURE rtl OF divider48 IS

SIGNAL ls_shift_data_left10 : unsigned(22 DOWNTO 0);
SIGNAL ls_shift_data_left8 : unsigned(22 DOWNTO 0);
SIGNAL ls_shift_data_left6 : unsigned(22 DOWNTO 0);
SIGNAL ls_shift_data_left4 : unsigned(22 DOWNTO 0);
SIGNAL ls_shift_data_left2 : unsigned(22 DOWNTO 0);
SIGNAL ls_shift_data_left0 : unsigned(22 DOWNTO 0);

SIGNAL ls_sum1, ls_sum2, ls_sum3 : unsigned(22 DOWNTO 0);
SIGNAL ls_sum4, ls_sum5 : unsigned(22 DOWNTO 0);

SIGNAL ls_sum123_valid : std_logic;
SIGNAL ls_sum4_valid : std_logic;
SIGNAL ls_sum5_valid : std_logic;

SIGNAL ls_shift_data_right16 : unsigned(22 DOWNTO 0);
SIGNAL ls_shift_right : std_logic;

BEGIN

DataDividedOut <= std_logic_vector(ls_shift_data_right16(12 DOWNTO 0));


ls_shift_data_left0 <= ("0000000000" & unsigned(Data2DivBy4);

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
SL10_reg: PROCESS(Reset, Clk)
BEGIN
IF Reset='1' THEN
ls_shift_data_left10 <= (OTHERS => '0');

ELSIF rising_edge(Clk) THEN

IF Data2DivBy48Valid='1' THEN
ls_shift_data_left10(22 DOWNTO 10) <= unsigned(Data2DivBy4;
ls_shift_data_left10(9 DOWNTO 0) <= (OTHERS => '0');
END IF;

END IF;
END PROCESS SL10_reg;

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
SL8_reg: PROCESS(Reset, Clk)
BEGIN
IF Reset='1' THEN
ls_shift_data_left8 <= (OTHERS => '0');

ELSIF rising_edge(Clk) THEN

IF Data2DivBy48Valid='1' THEN
ls_shift_data_left8(22 DOWNTO 21) <= (OTHERS => '0');
ls_shift_data_left8(20 DOWNTO <= unsigned(Data2DivBy4;
ls_shift_data_left8(7 DOWNTO 0) <= (OTHERS => '0');
END IF;

END IF;
END PROCESS SL8_reg;

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
SL6_reg: PROCESS(Reset, Clk)
BEGIN
IF Reset='1' THEN
ls_shift_data_left6 <= (OTHERS => '0');

ELSIF rising_edge(Clk) THEN

IF Data2DivBy48Valid='1' THEN
ls_shift_data_left6(22 DOWNTO 19) <= (OTHERS => '0');
ls_shift_data_left6(18 DOWNTO 6) <= unsigned(Data2DivBy4;
ls_shift_data_left6(5 DOWNTO 0) <= (OTHERS => '0');
END IF;

END IF;
END PROCESS SL6_reg;

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
SL4_reg: PROCESS(Reset, Clk)
BEGIN
IF Reset='1' THEN
ls_shift_data_left4 <= (OTHERS => '0');

ELSIF rising_edge(Clk) THEN

IF Data2DivBy48Valid='1' THEN
ls_shift_data_left4(22 DOWNTO 17) <= (OTHERS => '0');
ls_shift_data_left4(16 DOWNTO 4) <= unsigned(Data2DivBy4;
ls_shift_data_left4(3 DOWNTO 0) <= (OTHERS => '0');
END IF;

END IF;
END PROCESS SL4_reg;

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
SL2_reg: PROCESS(Reset, Clk)
BEGIN
IF Reset='1' THEN
ls_shift_data_left2 <= (OTHERS => '0');

ELSIF rising_edge(Clk) THEN

IF Data2DivBy48Valid='1' THEN
ls_shift_data_left2(22 DOWNTO 15) <= (OTHERS => '0');
ls_shift_data_left2(14 DOWNTO 2) <= unsigned(Data2DivBy4;
ls_shift_data_left2(1 DOWNTO 0) <= (OTHERS => '0');
END IF;

END IF;
END PROCESS SL2_reg;

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
SUM_reg: PROCESS(Reset, Clk)
BEGIN
IF Reset='1' THEN
ls_sum123_valid <= '0';
ls_sum4_valid <= '0';
ls_sum5_valid <= '0';
ls_sum1 <= (OTHERS => '0');
ls_sum2 <= (OTHERS => '0');
ls_sum3 <= (OTHERS => '0');
ls_sum4 <= (OTHERS => '0');
ls_sum5 <= (OTHERS => '0');

ELSIF rising_edge(Clk) THEN
ls_sum123_valid <= Data2DivBy48Valid;
ls_sum4_valid <= ls_sum123_valid;
ls_sum5_valid <= ls_sum4_valid;

IF ls_sum123_valid='1' THEN
ls_sum1 <= ls_shift_data_left10 + ls_shift_data_left8;
ls_sum2 <= ls_shift_data_left6 + ls_shift_data_left4;
ls_sum3 <= ls_shift_data_left2 + ls_shift_data_left0;
END IF;

IF ls_sum4_valid='1' THEN
ls_sum4 <= ls_sum1 + ls_sum2;
END IF;

IF ls_sum5_valid='1' THEN
ls_sum5 <= ls_sum4 + ls_sum3;
END IF;

END IF;
END PROCESS SUM_reg;

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
SR16_reg: PROCESS(Reset, Clk)
BEGIN
IF Reset='1' THEN
ls_shift_data_right16 <= (OTHERS => '0');
ls_shift_right <= '0';
DataDividedValidOut <= '0';

ELSIF rising_edge(Clk) THEN
ls_shift_right <= ls_sum5_valid;
DataDividedValidOut <= '0';

IF ls_shift_right='1' THEN
DataDividedValidOut <= '1';
ls_shift_data_right16(22 DOWNTO 7) <= (OTHERS => '0');
ls_shift_data_right16(6 DOWNTO 0) <= ls_sum5(22 DOWNTO 16);
END IF;

END IF;
END PROCESS SR16_reg;

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
END rtl;






library ieee;

use ieee.std_logic_1164.all;
--use ieee.numeric_std.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

ENTITY tb_divider48 IS
END tb_divider48;

ARCHITECTURE testbench OF tb_divider48 IS

COMPONENT divider48
PORT( Reset : IN std_logic;
Clk : IN std_logic;
Data2DivBy48 : IN std_logic_vector(12 DOWNTO 0);
Data2DivBy48Valid : IN std_logic;
DataDividedOut : OUT std_logic_vector(12 DOWNTO 0);
DataDividedValidOut : OUT std_logic
);
END COMPONENT;


SIGNAL t_Reset : std_logic;
SIGNAL t_Clk : std_logic;
SIGNAL t_Clkstim : std_logic;
SIGNAL t_Data2DivBy48 : std_logic_vector(12 DOWNTO 0);
SIGNAL t_Data2DivBy48Valid : std_logic;
SIGNAL t_DataDividedOut : std_logic_vector(12 DOWNTO 0);
SIGNAL t_DataDividedValidOut : std_logic;

BEGIN

UUT : divider48
PORT MAP ( Reset => t_Reset,
Clk => t_Clk,
Data2DivBy48 => t_Data2DivBy48,
Data2DivBy48Valid => t_Data2DivBy48Valid,
DataDividedOut => t_DataDividedOut,
DataDividedValidOut => t_DataDividedValidOut
);

-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
CLOCK_gen: PROCESS
BEGIN
t_Clk <= '1'; WAIT FOR 3.75 ns;
t_Clk <= '0'; WAIT FOR 3.75 ns;
END PROCESS CLOCK_gen;

-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
CLOCKstim_gen: PROCESS
BEGIN
t_Clkstim <= '0'; WAIT FOR 3.75 ns;
t_Clkstim <= '1'; WAIT FOR 3.75 ns;
END PROCESS CLOCKstim_gen;
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
MAIN_gen: PROCESS
BEGIN
t_Data2DivBy48 <= (OTHERS => '0');
t_Data2DivBy48Valid <= '0';
t_Reset <= '1';

FOR i IN 0 TO 13 LOOP
WAIT UNTIL rising_edge(t_Clkstim);
END LOOP;

t_Reset <= '0';

WAIT UNTIL rising_edge(t_Clkstim);
t_Data2DivBy48Valid <= '1';
WAIT UNTIL rising_edge(t_Clkstim);
t_Data2DivBy48Valid <= '0';

FOR i IN 0 TO 170 LOOP
WAIT UNTIL t_DataDividedValidOut='1';
WAIT UNTIL rising_edge(t_Clkstim);
t_Data2DivBy48 <= t_Data2DivBy48 + 48;
t_Data2DivBy48Valid <= '1';
WAIT UNTIL rising_edge(t_Clkstim);
t_Data2DivBy48Valid <= '0';
END LOOP;

WAIT;
END PROCESS MAIN_gen;
-----------------------------------------------------------------------------

END testbench;

 
Reply With Quote
 
Ray Andraka
Guest
Posts: n/a
 
      11-09-2006
(E-Mail Removed) wrote:
> Mr Andraka,
>
> thank you for your suggestion.
>
>
>>The multiply in this case is a repeating
>>pattern of bits (0x555), which can be done with a tree of adders rather
>>than a multiplier if you do not have full multipliers available.

>
>
> Can you elaborate on your last comment. How would those adders
> be combined ?
>
> Rgds
> André
>

x is input

a= x + x<<2 = x*5
b= a + a<<4 = a*0x11 = x*0x55
y= a+ b<<4 = a + b*0x10 = x*0x555
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Sub dividing the block of IPs in different backbones medamuralikrishna@gmail.com Cisco 1 02-24-2006 01:54 PM
dividing numbers =?Utf-8?B?cm9kY2hhcg==?= ASP .Net 2 06-28-2005 02:22 AM
Dividing a large wav file into smaller pieces Marco Bakker Computer Support 3 08-21-2004 09:34 AM
Dividing Real Numbers? kwaj VHDL 2 02-10-2004 10:52 AM
Dividing a clock Steve VHDL 0 01-01-2004 12:55 AM



Advertisments