VHDL XST not synthesizing correctly

回眸只為那壹抹淺笑 提交于 2019-12-12 03:28:53

问题


I've been working on a packet sorting pipeline in VHDL using Xilinx ISE 14.2. In order to make the structure generic I wrote a few algorithms in a package that will determine how to connect sorting nodes. Interestingly when I design a test bench around the functions the results are correct. When I simulate my design in the project using a combination of generates and functions the hardware is wired correctly. (used 'assert false report " & integer'image(layer);' to validate in simulation) However when I generate the RTL schematic I can see that some nodes AREN'T connected correctly.

I'm 90% sure this is a bug but saying that I'm no veteran with this software. Functions works, at this stage maybe 2% of the available resources have been used. Are there any secret flags or peculiarities anyone knows of?

Thanks a mil' everyone. Regards, Steve


回答1:


XST is pretty reliable.

The only genuine wrong-hardware bug I have seen in XST has to do with signals passed as OUT parameters to procedures within a process... the signals were assigned using variable assignment (immediate assignment) semantics!

In ISE14 this bug is still present - when targeting Spartan-3 and older devices, but not when targeting Spartan-6 and newer devices. It turns out that XST has two different VHDL parsers, the newer one seems to be better.

So you can try again, using the other parser (either by changing target family, or the "use_new_parser" setting or command line option)- see Xilinx docs for details.

You can also plug the post-synth netlist into your testbench and reproduce (or not!) the errors in simulation. (IMO the only practical use for post-synth and post-PAR simulation is confirming or eliminating possible tool bugs!)

And - as Phillippe says - divide and conquer the design until you either have a tiny demonstrator - or find out what the real problem is!

EDIT :

Added to demonstrate a couple of points...

Given the correct integer values for l,n we can characterise this problem more closely... From the asserts above, we can deduce that n=8, l=3.

    library IEEE;
    use ieee.math_real.all;

    entity count is
    end count;

    architecture Behavioral of count is

    constant n : integer := 8;
    constant l : integer := 3;

    begin

       report "n: " & integer'image(8) severity Note;
       assert false report "r: " & real'image(8.0) severity Note;
       report "Border a: " & real'image(real(n) + ( real(n) mod 2.0)) severity Note;
       report "Border b: " & real'image(2.0**(real(l+1) - 1.0)) severity Note;
       report "Border a/b: " & real'image((real(n) + ( real(n) mod 2.0))/(2.00 ** (real(l+1) - 1.0))) severity Note;
       report "Ceil a/b: " & real'image(ceil((real(n) + ( real(n) mod 2.0))/(2.00 ** (real(l+1) - 1.0)))) severity Note;
       report "Residual a/b: " & real'image((real(n) + ( real(n) mod 2.0))/(2.00 ** (real(l+1) - 1.0)) - 1.0 ) severity Note;

    end Behavioral;

1) "Assert False" is not necessary (since 1993)

2) Contrary to popular myth, asserts CAN be synthesised provided their conditions are statically determinable. Thus in the above code, where l,n are constants, XST synthesises, reporting ...

Targetting Spartan-3 we get:

INFO:Xst:1749 - "count.vhd" line 15: note: n: 8
INFO:Xst:1749 - "count.vhd" line 16: note: r: 0

so using the old parser, using Math.Real in synthesis was not well supported. Specifically, real'image returned 0!

Targetting Spartan-6,

Elaborating entity <count> (architecture <Behavioral>) from library <work>.
Note: "n: 8"
Note: "r: 8.0"
Note: "Border a: 8.0"
Note: "Border b: 8.0"
Note: "Border a/b: 1.0"
Note: "Ceil a/b: 2.0"
Note: "Residual a/b: 2.22044604925031E-16"

so we have reproduced the "error". But crucially, if I subtract 1.0 from the expression instead of taking its ceiling, we can see the residual (introduced through rounding). And we can see that, though it is tiny, it is positive.

Therefore Ceil() is behaving correctly in returning 2.0 and this is definitively NOT a synthesis tool bug.

Try the same in simulation and you will probably find a similarly small but negative number, therefore it is also correct...

See this and other papers by Professor Kahan about floating point - this isn't a tool problem or even a VHDL problem but a much much bigger can of worms...

So the final word is : if you can find any way of accomplishing the same task in integer arithmetic, it will be a better solution.




回答2:


It is possible you're not understanding the generated RTL schematic properly. Modern synthesis tools for FPGAs do a LOT of optimizations, including pushing logic around across flip-flop boundaries, replicating logic, and various other tricks to improve speed & reduce the size of the compiled logic. While it is possible there is a bug in this optimization logic, I suspect if your design is at all non-trivial, you're just not fully understanding the mangling the synthesis tool did to 'improve' things. If there is a difference in behavior, there's either a bug in the tools, or your code is ambiguous and the synthesizer and simulator are doing different things...you'd have to post some code for us to help with this one.




回答3:


Thanks guys for well your time and thoughts. In the end it came down to a 'glitch' with the CEIL function in IEEE.MATH_REAL as it behaves differently in Simulation and Synthesis.

I solved this by plastering my code with ASSERT statements (note: these only work in SIMULATION). I had an idea where it could have potentially gone wrong and thus disected one of the functions with such ASSERT statements as shown below. So the aim of this debugging approach is to compare pre-synth function output with post synth output, I used the normal Behavioral simulation and then the "Generate Post-Synth Simulation" Using assert statements will output the values to the console window during the simulation initialisation period.

Assert code example: (note: integer'image converts number to string. assert false forces to print statement (needed in earlier VHDL versions))

assert false report "Border Value: " & integer'image(Border(l+1, n));
assert false report "Border a: " & real'image(real(n) + ( real(n) mod 2.0));
assert false report "Border b: " & real'image(2.0**(real(l+1) - 1.0));
assert false report "Border a/b: " & real'image((real(n) + ( real(n) mod 2.0))/(2.00 ** (real(l+1) - 1.0)));
assert false report "Ceil a/b: " & real'image(ceil((real(n) + ( real(n) mod 2.0))/(2.00 ** (real(l+1) - 1.0))));

Results:

Here is the pre synth output, look at the ceil function

Error: ""
Error: "(3,8)"
Error: "Node Port-ID (In.Port 0 then 1): 46 - 47"
Error: "Next Node (Out.Port 0 then 1): 4 - 8"
Error: "Dst Port: 1"
Error: "Border Value: 4"
Error: "Border a: 8.0"
Error: "Border b: 8.0"
Error: "Border a/b: 1.0"
Error: "Ceil a/b: 1.0"
Error: "Next Node Port-ID(Out.Port 0 then 1): 55 - 63"
Error: ""

Here is the post synth output, again look at the ceil function

Error: "(3,8)"
Error: "Node Port-ID (In.Port 0 then 1): 46 - 47"
Error: "Next Node (Out.Port 0 then 1): 8 - 12"
Error: "Dst Port: 0"
Error: "Border Value: 12"
Error: "Border a: 8.0"
Error: "Border b: 8.0"
Error: "Border a/b: 1.0"
Error: "Ceil a/b: 2.0"
Error: "Next Node Port-ID(Out.Port 0 then 1): 62 - 70"
Error: ""

Conclusion:

In simulation if a whole number such as 1.0 is fed to CEIL, it will return 1.0. During synthesis however 1.0 is rounded to the next integer (2.0) as it strips the non-integer part and adds 1 (e.g. 0.75 -> 0 -> 1) The resolution (at least in my case) is to subtract 0.01 from the value fed to ceil (e.g 1 -> 0.99 -> 1) This wasnt noted in any of the documenation I came across nor do I believe this is intended. Verilog supports $display command which would have been very helpful in this case, what I did is create a work around.

If no one has anything to add I will raise this with XILINX support team.

Thanks again. Steve



来源:https://stackoverflow.com/questions/14069229/vhdl-xst-not-synthesizing-correctly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!