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.

error with restoring division

Status
Not open for further replies.

shaiko

Advanced Member level 5
Joined
Aug 20, 2011
Messages
2,644
Helped
303
Reputation
608
Reaction score
297
Trophy points
1,363
Activity points
18,302
I wrote a restoring division function and tried to test it with modelsim.
Signals a,b,c are defined as follows:

Code:
signal a : unsigned ( 3 downto 0 ) := "1000" ;
signal b : unsigned ( 1 downto 0 ) := "10" ;
signal c : unsigned ( 3 downto 0 ) ;

I run the simulation in 2 different ways:

Code:
c <= restoring_divide ( a , b ) ; -- works proparly ( c gets "0100" )
Code:
c <= restoring_divide ( "1000" , "10" ) ; -- fails

The error message from modelsim:
Slice range direction (downto) does not match slice prefix direction (to).

The function description:
Code:
function restoring_divide 
( 
numerator : 	unsigned ; 
denominator : 	unsigned 
) 
return unsigned is
variable temp_numerator : unsigned ( numerator ' range ) := numerator ;
variable temp_numerator_with_denominator_length : unsigned ( denominator ' range ) := ( others => '0' ) ;	
variable temp_denominator : unsigned ( denominator ' range ) := denominator ;
variable temp_denominator_with_numerator_length : unsigned ( numerator ' range ) := ( others => '0' ) ;	
variable temp_remainder : unsigned ( denominator ' length downto 0 ) := ( others => '0' ) ;
variable temp_remainder_with_numerator_length : unsigned ( numerator ' length downto 0 ) := ( others => '0' ) ;	
begin
if numerator ' length = denominator ' length then 
for index in 0 to denominator ' length - 1 
loop
temp_remainder ( denominator ' length - 1 downto 1 ) := temp_remainder ( denominator ' length - 2 downto 0 ) ;
temp_remainder ( 0 ) := temp_numerator ( numerator ' length - 1 ) ;
temp_numerator ( numerator ' length - 1 downto 1 ) := temp_numerator ( numerator ' length - 2 downto 0 ) ;
temp_remainder := temp_remainder - temp_denominator ;
if ( temp_remainder ( denominator ' length ) = '1' ) then
temp_numerator ( 0 ) := '0' ;
temp_remainder := temp_remainder + temp_denominator ;
else
temp_numerator ( 0 ) := '1' ;
end if ;
end loop ;
return temp_numerator ;
elsif numerator ' length > denominator ' length then 
temp_denominator_with_numerator_length := resize ( denominator , numerator ' length ) ;	
for index in 0 to temp_denominator_with_numerator_length ' length - 1 
loop
temp_remainder_with_numerator_length ( temp_denominator_with_numerator_length ' length - 1 downto 1 ) := 
temp_remainder_with_numerator_length ( temp_denominator_with_numerator_length ' length - 2 downto 0 ) ;
temp_remainder_with_numerator_length ( 0 ) := temp_numerator ( numerator ' length - 1 ) ;
temp_numerator ( numerator ' length - 1 downto 1 ) := temp_numerator ( numerator ' length - 2 downto 0 ) ;
temp_remainder_with_numerator_length := temp_remainder_with_numerator_length - temp_denominator ;
if ( temp_remainder_with_numerator_length ( temp_denominator_with_numerator_length ' length ) = '1' ) then
temp_numerator ( 0 ) := '0' ;
temp_remainder_with_numerator_length := temp_remainder_with_numerator_length + temp_denominator ;
else
temp_numerator ( 0 ) := '1' ;
end if ;
end loop ;
return temp_numerator ;			
else 
temp_numerator_with_denominator_length := resize ( numerator , denominator ' length ) ;	
for index in 0 to denominator ' length - 1 
loop
temp_remainder ( denominator ' length - 1 downto 1 ) := temp_remainder ( denominator ' length - 2 downto 0 ) ;
temp_remainder ( 0 ) := temp_numerator_with_denominator_length ( temp_numerator_with_denominator_length ' length - 1 ) ;
temp_numerator_with_denominator_length ( temp_numerator_with_denominator_length ' length - 1 downto 1 ) :=
 temp_numerator_with_denominator_length ( temp_numerator_with_denominator_length ' length - 2 downto 0 ) ;
temp_remainder := temp_remainder - temp_denominator ;
if ( temp_remainder ( denominator ' length ) = '1' ) then
temp_numerator_with_denominator_length ( 0 ) := '0' ;
temp_remainder := temp_remainder + temp_denominator ;
else
temp_numerator_with_denominator_length ( 0 ) := '1' ;
end if ;
end loop ;
return temp_numerator_with_denominator_length ;
end if ;			
end function restoring_divide ;
 
Last edited:

by default, a constant array will default to rather than downto. Your function constantly uses downto, hence the problem when the numerator and denominator are (a to b) rather than (b downto a).

3 fixes:
1. Make the function direction neutral - check if the range is to with the 'ascending attribute so you can flip it over.

if a'ascending then
--do something.

2. Dont allow to direction (using an assert)
3. Dont call the function with arrays like that. Use constants.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
thanks TrickyDicky.

1. Make the function direction neutral - check if the range is to with the 'ascending attribute so you can flip it over.

Can you please show me an example on a specific line in my code?
 

the temp_numerator_with_denominator_length variable is declared using the 'range of the denominator, but you access it using downto:

temp_numerator_with_denominator_length ( temp_numerator_with_denominator_length ' length - 1 downto 1 ) :=
temp_numerator_with_denominator_length ( temp_numerator_with_denominator_length ' length - 2 downto 0 ) ;
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
And how do you suggest to change the code in order to fix it ?
 

There are many ways to enforce a regular descending direction for the test bench input, e.g. to_unsigned(8,4). Taking provisions for a bit string interpreted as unsigned with ascending direction doesn't seem but a weird idea, it will most likely collide with the numeric_std default direction at the next best operation.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
FvM,

Are you saying that "to_unsigned" returns a descending bit string
yet writing for example: "01000001" returns an ascending bit string?
 

numeric_std functions will always returning downto numbers.

string literals are always ascending, unless otherwise specified. "010100" is not an unsigned. It is just a string. It is just an unsigned from the context.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top