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.
 
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 ) ;
 
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.
 
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.
 
Reactions: shaiko

    shaiko

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

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…