Xilinx floating-pt IP not working?

A

Anon Anon

I am trying to use the Xilinx floating-point IP, provided as part of the
ISE Foundation V8.1 to produce an entity that determines the smallest
element from an array of floating-point numbers. The entity uses the
Xilinx less-than comparator, which takes two inputs (a and b) and
returns a '1' if a < b or '0' otherwise. Unfortunately, I am getting
some strange (and incorrect) results.

This may be down to an error in the IP, or an error in my VHDL - since I
am quite new to this area. The code is shown below - if anybody can see
the flaw could they please advise?

Many thanks!

=== SNIP ========================
entity float_min_array is
generic(len : integer);
port (
clk : in std_logic;
start : in std_logic := '0';
floats : in FLOAT_ARRAY;
index : out integer := -1;
finished : out std_logic := '0');
end float_min_array;

architecture Behavioral of float_min_array is

signal a: std_logic_VECTOR(63 downto 0);
signal b: std_logic_VECTOR(63 downto 0);
signal operation_nd: std_logic;
signal operation_rfd: std_logic;
signal result: std_logic_VECTOR(0 downto 0);
signal rdy: std_logic;

signal dummy : integer;

-- the Xilinx floating point comparator
component flessthan IS
port (
a: IN std_logic_VECTOR(63 downto 0);
b: IN std_logic_VECTOR(63 downto 0);
operation_nd: IN std_logic;
operation_rfd: OUT std_logic;
clk: IN std_logic;
result: OUT std_logic_VECTOR(0 downto 0);
rdy: OUT std_logic);
END component flessthan;

begin

process (clk)
type entity_state is (wait_rfd, is_rfd, wait_rdy, done);

variable state : entity_state := wait_rfd;
variable lowest, i : integer := floats'LOW(1);

begin
if rising_edge(clk) then
case state is
when wait_rfd =>
if start = '1' and
operation_rfd = '1' then
lowest := i;
index <= lowest;
state := is_rfd;
end if;
when is_rfd =>
if (i < floats'LENGTH) then
assert operation_rfd='1'
report "Not ready for data!";
i := i + 1;
dummy <= i; -- for debugging only!
a <= floats(i);
b <= floats(lowest);
operation_nd <= '1';
state := wait_rdy;
else
state := done;
end if;
when wait_rdy =>
if rdy = '1' then
if result(0) = '1' then
lowest := i;
index <= lowest;
end if;

-- operation_nd <= '0';
-- result(0) <= '0';
state := is_rfd;
end if;
when done =>
finished <= '1';
end case;
end if;
end process;

FM:flessthan PORT MAP(a,b,operation_nd,operation_rfd,clk,result,rdy);

end Behavioral;

=== SNIP ========================
 
A

Anon Anon

Anon said:
I am trying to use the Xilinx floating-point IP, provided as part of the
ISE Foundation V8.1 to produce an entity that determines the smallest
element from an array of floating-point numbers. The entity uses the
Xilinx less-than comparator, which takes two inputs (a and b) and
returns a '1' if a < b or '0' otherwise. Unfortunately, I am getting
some strange (and incorrect) results.

This may be down to an error in the IP, or an error in my VHDL - since I
am quite new to this area. The code is shown below - if anybody can see
the flaw could they please advise?

Many thanks!

=== SNIP ========================
entity float_min_array is
generic(len : integer);
port (
clk : in std_logic;
start : in std_logic := '0';
floats : in FLOAT_ARRAY;
index : out integer := -1;
finished : out std_logic := '0');
end float_min_array;

architecture Behavioral of float_min_array is

signal a: std_logic_VECTOR(63 downto 0);
signal b: std_logic_VECTOR(63 downto 0);
signal operation_nd: std_logic;
signal operation_rfd: std_logic;
signal result: std_logic_VECTOR(0 downto 0);
signal rdy: std_logic;

signal dummy : integer;

-- the Xilinx floating point comparator
component flessthan IS
port (
a: IN std_logic_VECTOR(63 downto 0);
b: IN std_logic_VECTOR(63 downto 0);
operation_nd: IN std_logic;
operation_rfd: OUT std_logic;
clk: IN std_logic;
result: OUT std_logic_VECTOR(0 downto 0);
rdy: OUT std_logic);
END component flessthan;

begin

process (clk)
type entity_state is (wait_rfd, is_rfd, wait_rdy, done);

variable state : entity_state := wait_rfd;
variable lowest, i : integer := floats'LOW(1);

begin
if rising_edge(clk) then
case state is
when wait_rfd =>
if start = '1' and
operation_rfd = '1' then
lowest := i;
index <= lowest;
state := is_rfd;
end if;
when is_rfd =>
if (i < floats'LENGTH) then
assert operation_rfd='1'
report "Not ready for data!";
i := i + 1;
dummy <= i; -- for debugging only!
a <= floats(i);
b <= floats(lowest);
operation_nd <= '1';
state := wait_rdy;
else
state := done;
end if;
when wait_rdy =>
if rdy = '1' then
if result(0) = '1' then
lowest := i;
index <= lowest;
end if;

state := is_rfd;
end if;
when done =>
finished <= '1';
end case;
end if;
end process;

FM:flessthan PORT MAP(a,b,operation_nd,operation_rfd,clk,result,rdy);

end Behavioral;

=== SNIP = = = = = = = = = = = = = =
I spotted a missing type declaration (from a separate package):

subtype MY_FLOAT is std_logic_vector(63 downto 0);
type FLOAT_ARRAY is array(NATURAL RANGE said:
> === SNIP-SNIP ========================

I have also removed the two commented-out lines from my first posting,
which were part of an unsuccessful attempt to resolve my problems.
 
W

walke

Please could you tell me why are you driving the core output to zero
when in wait_rdy state? (i.e. why is the line result(0) <= '0'
present?)
 
J

Jonathan Bromley

This may be down to an error in the IP, or an error in my VHDL - since I
am quite new to this area. The code is shown below - if anybody can see
the flaw could they please advise?

I think you are failing to re-initialise the array index each time the
processing state machine starts work.
variable lowest, i : integer := floats'LOW(1);

BAD IDEA. Don't rely on variable or signal initialisation in
synthesisable code. XST accepts it, but many tools don't.
In any case, variable initialisation is extremely confusing
because it can lead you to believing that the variable is
initialised every time round the process, rather than
only at startup. See below, I think you've fallen into
somesuch trap.
if rising_edge(clk) then
case state is
when wait_rfd =>
if start = '1' and
operation_rfd = '1' then

Surely you need to set i := floats'LOW here????
Otherwise it'll still be floats'HIGH, left over from the last pass.
lowest := i;
index <= lowest;
state := is_rfd;
end if;
[snip]

if (i < floats'LENGTH) then

Prefer (i < floats'HIGH) to protect yourself against arrays that
may have been declared with subscript ranges not starting at 1.

I haven't checked the rest of your code in detail, but the state
machine looks fairly sensible. These things always need
careful checking for corner cases - does it work correctly
if the lowest-valued element is the first in the array? the last?
does it work correctly if all elements have the same value?
I'm not saying your code is wrong - in fact, I suspect it isn't -
but merely asking you to check very carefully.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
A

Anon Anon

Apologies - this was an earlier attempt to try and fix the problem,
which I subsequently commented out (as shown in my first posting). In my
second posting I physically removed this line and the other kludge, with
an explanation as to what I'd done (see below).

Sorry for the confusion!

====================================================================
 
A

Anon Anon

I accept all your points which are perfectly valid, and are clearly bugs
in my code, or an indication of my lack of experience. However, I should
have made the situation a bit clearer.

The code seems to step through all of the elements successfully and
seems to present them to the comparator - at least to the extent that I
get varying outputs from the comparison. However, the comparison output
doesn't match the actual data, so I don't get a correct result. This may
be the result of several factors, including:

1) A bug or quirk in the comparator that I don't know about (I have
already found some quirks in the fixed-point to floating-point operation
that I have already used).

2) A more fundamental failure in the fix-to-float that I used to
generate the numbers that I'm using for this test. i.e. the comparison
may be working correctly, but with the wrong data.

At least you have reassured me that I am not doing anything
fundamentally wrong with the language itself - which was my main fear
(subject of course to the limitations inherent in you validating the
code by eye alone).

For my next test I'll write a float to fix operation to see if the data
*looks* ok - although of course if it's faulty in one direction it might
be faulty in the other also, sigh...

I'll also contact my supplier to see if they know of any problems in the IP.

BTW: I am mainly a S/W engineer and I've become spoilt by libraries that
just do what they say they'll do! ;-)

Ho, hum... Thanks for your kind support in any case. I'll definitely
consider Doulos when I have the time for training in this stuff!!

======

Jonathan said:
This may be down to an error in the IP, or an error in my VHDL - since I
am quite new to this area. The code is shown below - if anybody can see
the flaw could they please advise?

I think you are failing to re-initialise the array index each time the
processing state machine starts work.
variable lowest, i : integer := floats'LOW(1);

BAD IDEA. Don't rely on variable or signal initialisation in
synthesisable code. XST accepts it, but many tools don't.
In any case, variable initialisation is extremely confusing
because it can lead you to believing that the variable is
initialised every time round the process, rather than
only at startup. See below, I think you've fallen into
somesuch trap.
if rising_edge(clk) then
case state is
when wait_rfd =>
if start = '1' and
operation_rfd = '1' then

Surely you need to set i := floats'LOW here????
Otherwise it'll still be floats'HIGH, left over from the last pass.
lowest := i;
index <= lowest;
state := is_rfd;
end if;
[snip]

if (i < floats'LENGTH) then

Prefer (i < floats'HIGH) to protect yourself against arrays that
may have been declared with subscript ranges not starting at 1.

I haven't checked the rest of your code in detail, but the state
machine looks fairly sensible. These things always need
careful checking for corner cases - does it work correctly
if the lowest-valued element is the first in the array? the last?
does it work correctly if all elements have the same value?
I'm not saying your code is wrong - in fact, I suspect it isn't -
but merely asking you to check very carefully.
 
B

Ben Jones

The code seems to step through all of the elements successfully and seems
to present them to the comparator - at least to the extent that I get
varying outputs from the comparison. However, the comparison output
doesn't match the actual data, so I don't get a correct result. This may
be the result of several factors, including:
1) A bug or quirk in the comparator that I don't know about (I have
already found some quirks in the fixed-point to floating-point operation
that I have already used).

Please could you give us details of exactly what "quirks" you have found in
this operator? And could you post some more specific information of a
failing testcase, that is, "I compared floating point number 0x3f800000
against 0x40000000 and it said they were equal when they are clearly not"?

Have you checked that the latency of the operator(s) is/are what you expect?
I'll also contact my supplier to see if they know of any problems in the
IP.
BTW: I am mainly a S/W engineer and I've become spoilt by libraries that
just do what they say they'll do! ;-)

The Xilinx floating point IP is verified extensively in a large number of
configurations by means of industry standard test packages such as John
Hauser's "TestFloat" application, which provide millions of test vectors.
Apart from minor deviations from the standard in the handling of NaNs and
denormalized numbers, which are clearly explained in the datasheet, we know
of no problems. So if you have found one, we'd really like to hear about it!

Cheers,

-Ben-
 
A

Anon Anon

Ben said:
Please could you give us details of exactly what "quirks" you have found in
this operator? And could you post some more specific information of a
failing testcase, that is, "I compared floating point number 0x3f800000
against 0x40000000 and it said they were equal when they are clearly not"?

Have you checked that the latency of the operator(s) is/are what you expect?


The Xilinx floating point IP is verified extensively in a large number of
configurations by means of industry standard test packages such as John
Hauser's "TestFloat" application, which provide millions of test vectors.
Apart from minor deviations from the standard in the handling of NaNs and
denormalized numbers, which are clearly explained in the datasheet, we know
of no problems. So if you have found one, we'd really like to hear about it!

Cheers,

-Ben-
I'm happy to mail you my fixed-to-float code - could you give me your
direct e-mail address (encoded in some way to avoid spammers).

The sort of issues I've encountered are things like having to wait on a
zero-to-one transition on the rdy signal and also having to reset the
operation_nd to a low state. As I've mentioned many times, these may be
down to mistakes on my part, and I'd love to find out that that is the case!

Cheers
 
B

Brian Drummond

I accept all your points which are perfectly valid, and are clearly bugs
in my code, or an indication of my lack of experience. However, I should
have made the situation a bit clearer.

The code seems to step through all of the elements successfully and
seems to present them to the comparator - at least to the extent that I
get varying outputs from the comparison. However, the comparison output
doesn't match the actual data, so I don't get a correct result. This may
be the result of several factors, including:

1) A bug or quirk in the comparator that I don't know about (I have
already found some quirks in the fixed-point to floating-point operation
that I have already used).

You don't need a library to perform floating point comparison; (assuming
IEEE754 floats) By design, they are guaranteed monotonic (apart from the
sign bit) so if there's any doubt about the library, roll your own.

- Brian
 
A

Anon Anon

Brian said:
You don't need a library to perform floating point comparison; (assuming
IEEE754 floats) By design, they are guaranteed monotonic (apart from the
sign bit) so if there's any doubt about the library, roll your own.

- Brian

Thanks for that point - it could come in handy - although comparisons
are really the least of my problems ;-) At the end of the day I'll need
to do most of the operations you might want to perform on an Flt-Pt
value - hence my concern in getting it done correctly (and reassuring
myself that the IP is essentially correct and bug-free).
 
M

Mike Treseler

Anon said:
At the end of the day I'll need
to do most of the operations you might want to perform on an Flt-Pt
value - hence my concern in getting it done correctly (and reassuring
myself that the IP is essentially correct and bug-free).

The only way to really do this
is to own the source code.

-- Mike Treseler
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top