XST vhdl adder with carry out : broken carry chain
Jul 29, 2004 15 Replies
B
Bart De Zwaef
Hi all,
I need some help here for implementing an efficient adder with carry out. Target : V2Pro System : WinXP, ISE 6.2.03 sp3
I am trying to implement a 16 bit adder with carry out. I use the vhdl description for this as stated in the XST user guide (see src code added at the bottom of this post):
q
Didn't find your answer? Ask the community — no account required.
A
Allan Herriman
Hi Bart,
I have observed exactly the same symptoms, but with another synthesiser (Synplify Pro). I think the problem is with MAP rather than the synthesiser. MAP doesn't seem to handle the last bit in an odd length carry chain well.
My solution (as usual) was to create a module that instantiated the unisim components directly (with RLOC attributes), so that I got exactly what I wanted.
BTW, this bug has been around for at least three years. At the time, I was having a lot of trouble implementing a 17 and 33 bit adders. I came to the conclusion that Xilinx's test suite probably only has even length adders.
Regards, Allan.
S
Symon
R
rickman
Rick "rickman" Collins
rick.collins@XYarius.com
Ignore the reply address. To email me use the above address with the XY
removed.
Arius - A Signal Processing Solutions Company
Specializing in DSP and FPGA design URL http://www.arius.com
4 King Ave 301-682-7772 Voice
Frederick, MD 21701-3110 301-682-7666 FAX
S
Symon
Adding
to
it
A
Allan Herriman
Rick, it was a timing issue due to poor mapping, rather than a functional issue.
Regards, Allan.
R
rickman
That would be the problem the OP had. But the problem Symon described is a coding issue. But then he replied to my post and I may not have understood what he meant.
Rick "rickman" Collins
rick.collins@XYarius.com
Ignore the reply address. To email me use the above address with the XY
removed.
Arius - A Signal Processing Solutions Company
Specializing in DSP and FPGA design URL http://www.arius.com
4 King Ave 301-682-7772 Voice
Frederick, MD 21701-3110 301-682-7666 FAX
S
Symon
B
Bart De Zwaef
Thanks for the help guys.
I agree with Symon : it's a timing issue, functionality is 100% ok. And yes, it only happens when the carry out is the odd bit, not even. I also believe that the problem is MAP related, not XST (although I can not prove this). I tried with the "KEEP" attribute (which is XST equivalent of the synplify "syn_keep") : unfortunately this does not change anything. Also USE_CARRY_CHAIN and some other attributes I tried didnt do the trick. I was hoping there would be a clean and simple workaround, because I have a design with some 120 - 140 adders in it, I would hate to give up on readable code. But right now I would be happy with something that would work at all.
If I do find some solution I will surely post it here.
Bart.
A
Allan Herriman
You don't need to change a line of your HDL source.
Write a (e.g. Perl) script to read the EDIF and locate the carry chains. From that you can generate a UCF which has an RPM for each carry chain. This will force MAP to do the right thing.
Regards, Allan.
B
Bret Wade
Hello Bart,
We've run your code and there is indeed a map packing problem. The MSB is simply a FF driven by COUT of the previous slice. I see two related problems with the packing:
FF "tmp1_16" should be packed into a slice utilizing the CIN pin through the XORCY BEL as an extension of the carry chain but is not.
Instead, FF "tmp1_16" is being packed into the FFY BEL of the carry chain slice that is driving it, displacing "tmp1_15" from its correct packing location.
I've logged CR 192265 for these issues. Meanwhile, I don't see a work around for first issue except to extend the carry chain by one bit as you mentioned or possibly by instantiating an XORCY and FF to terminate the carry chain. The second issue can be controlled with a map packing constraint such as:
INST "tmp1_16" XBLKNM = XLNX_WA ;
I'll post again when we have a fix date scheduled.
Regards, Bret Wade Xilinx Product Applications
S
Symon
Thanks Bret, makes you wonder why Allan or I never opened a webcase about this rather than work around the problem. Could've been fixed years ago. Bloody hardware engineers! Cheers, Syms.
B
Bret Wade
Just to follow up on this issue, it has been fixed for the next service pack, 6.3i SP2 which will become available in mid October.
Bret
G
glen herrmannsfeldt
I am not sure about verilog. If I assign to a variable the same width as the operands of +, I get warnings about truncated bits.
One book says that {cout, sum} = in1 + in2 + cin; will generate a full adder.
Another book says that the width for + is maximum of the width of the two operands.
cross posted to comp.lang.verilog, to see if anyone there can say.
-- glen
A
A Beaujean
Hello Bart,
Please find hereafter a piece of code that works for an incrementer. I had exactly the same problem as you have until I finally coded that way. I am not sure that works for A + B as it does for A + 1.
Hope it can help.
A. Beaujean
Library ieee ; Use ieee.std_logic_1164.all ; Use ieee.std_logic_unsigned.all ; Use ieee.std_logic_arith.all ;
-- Package TDC Is -- Package for Time to Digital Conversion
-- Component TDC_SUM_RE Is -- Builds the sum of all ones and ((all ones -
1) + Tdc_In -- to force the mapper to use the carry chain. -- Outputs of the carry chain are registered in the same slice -- (Rising Edge) Generic(Width : integer) ; -- Width of Component, nbr of stages Port (Reset_Not : in std_logic ; Clock : in std_logic ; -- Clock Tdc_In : in std_logic ; Output : out std_logic_vector((Width-1) downto 0)) ;
-- End Component ;
-- Component TDC_SUM_FE Is -- Builds the sum of all ones and ((all ones -
1) + Tdc_In -- to force the mapper to use the carry chain. -- Outputs of the carry chain are registered in the same slice -- (Falling Edge) Generic(Width : integer) ; -- Width of Component, nbr of stages Port (Reset_Not : in std_logic ; Clock : in std_logic ; -- Clock Tdc_In : in std_logic ; Output : out std_logic_vector((Width-1) downto 0)) ;
-- End Component ;
-- End TDC ;
-- Library ieee ; Use ieee.std_logic_1164.all ; Use ieee.std_logic_unsigned.all ; Use ieee.std_logic_arith.all ;
-- Entity TDC_SUM_RE Is -- Builds the sum of all ones and ((all ones -
1) + Tdc_In -- to force the mapper to use the carry chain. -- Outputs of the carry chain are registered in the same slice -- (Rising Edge) Generic(Width : integer) ; -- Width of Component, nbr of stages Port (Reset_Not : in std_logic ; Clock : in std_logic ; -- Clock Tdc_In : in std_logic ; Output : out std_logic_vector((Width-1) downto 0)) ;
-- End TDC_SUM_RE ;
Architecture Arch_Of_TDC_SUM_RE Of TDC_SUM_RE Is
--
-- Components declarations
-- Component FDC -- Rising edge FF Port (D,C,CLR: in std_logic ; Q : out std_logic ); End Component ;
--
-- Signals
-- Signal Chain : std_logic_vector((Width-1) downto 0); Signal Regs : std_logic_vector((Width-1) downto 0); Signal Reset : std_logic ; Signal All_Ones : std_logic_vector((Width-1) downto 0) ; Signal All_Zeroes_M1 : std_logic_vector((Width-1) downto 1) ;
--
-- Attributes
-- Attribute KEEP : string ; Attribute KEEP of Chain : signal is "true" ;
-- Begin
--
-- Components instantiation
-- FDC_All: For I in 0 to (Width-1) Generate FDC_One: FDC Port Map (C => Clock, D => Chain(I), CLR => Reset, Q => Regs(I)); End Generate ;
-- The trick used is to generate a sum of all ones and the concatenation of
-- (all ones minus 1) and the input signal.
-- All_Ones '1') ; All_Zeroes_M1 '0') ; Chain
S
Shalom Bresticker
In verilog,
{cout, sum} = in1 + in2 + cin;
will perform an addition of width max({cout, sum}, in1, in2, cin).
The statement that "the width for + is maximum of the width of the two operands" is true if "a+b" is in isolation ('self-determined' in Verilog terms).
However, for c = a+b, then the operands are extended to width max(a,b,c), and only then is the addition performed.