Forum: FPGA, VHDL & Co. Tapped-Carry-Chain in VHDL


von Christian M. (charlie)


Lesenswert?

Hallo,

ich beschäftige mich seit kurzem wieder mit FPGA's (Virtex 5) und habe 
dazu eine Frage: Ich möchte eine Tapped-Carry-Chain realisieren, wie sie 
in auf FPGA basierten Time-to-Digital Konverter eingesetzt werden kann. 
Das Ganze ist im Prinzip nichts weiter als ein n-Bit Carry-Ripple 
Addierwerk, das asynchron zum restlichen Design

sum = 11...1 + 00...0x

berechnet. x ist dabei die Triggerleitung. Die Summe wird bei steigender 
Taktflanke in FF's geladen. Das Synthese-Tool (XST) muss die Berechnung 
als Carry-Ripple Addierer realisieren, weil die Multiplexerlaufzeiten 
der Carry-Chain (zwischen den LUT's/CLB's) gezählt werden soll. Und 
genau das ist das Problem: für x = 0 ist die Summe 11...1 und bei x = 1 
entsprechend 00...0. Dementsprechend wird der Addierer wegoptimiert und 
durch einen Inverter ersetzt.

Wenn man einen der Summanden variabel lässt, kann man das Problem 
umgehen aber das ist keine saubere Lösung... equivalent_register_removal 
und keep-Statements brachten (bisher) leider nicht das erhoffte 
Ergebnis, der Trick, wie er in 
http://www.fpgarelated.com/usenet/fpga/show/13535-1.php eingesetzt wird, 
ebenfalls nicht. Anschließend etwas Code. Die FDC's sollten den Trick 
aus dem vorhergehenden Link darstellen:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.std_logic_unsigned.all;
4
use ieee.std_logic_arith.all;
5
6
entity carry_chain_example is 
7
8
  generic(width : integer := 16); -- Width of Component, number of stages
9
  port (reset_not : in std_logic;
10
      clock : in std_logic;
11
      tdc_in : in std_logic;
12
      output : out std_logic_vector((width-1) downto 0));
13
      
14
end carry_chain_example;
15
16
architecture Arch of carry_chain_example is
17
18
-- Components 
19
  component FDC -- Rising edge FF
20
    port (d, c, clr : in std_logic;
21
        q : out std_logic );
22
  end component;
23
24
-- Signals
25
  signal sum : std_logic_vector((width-1) downto 0);
26
  signal sum_reg : std_logic_vector((width-1) downto 0);
27
  signal reset : std_logic;
28
  signal all_ones : std_logic_vector((width-1) downto 0);
29
  signal all_zeros : std_logic_vector((width-1) downto 1);
30
31
-- Attributes
32
  attribute box_type : string;
33
  attribute box_type of FDC : component is "black_box";
34
  
35
  attribute keep : string;
36
  attribute keep of sum : signal is "true";
37
  --attribute keep of all_ones : signal is "true";
38
  --attribute keep of all_zeros : signal is "true";
39
40
  begin
41
42
-- Component instantiations
43
    FDC_All:
44
    for i in 0 to (width-1) generate
45
      FDC_One: FDC port map (  c => clock,
46
                      d => sum(i),
47
                      clr => reset,
48
                      q => sum_reg(i));
49
    end generate;
50
51
52
  --  process begin
53
  --    wait until rising_edge(clock);
54
  --    output <= sum;
55
  --  end process;
56
57
-- Concurrent statements
58
    all_ones <= (others => '1');
59
    all_zeros <= (others => '0');
60
    sum <= all_ones + (all_zeros & tdc_in );
61
    reset <= not reset_not;
62
    output <= sum_reg;
63
64
end Arch;

Hat eventuell jemand eine Idee/die Lösung, wie man das Synthese-Tool 
dazu zwingen kann, den Addierer beizubehalten? Ich verwende übrigens 
Xilinx ISE 12.2.

Gruß

von CLB Friend (Gast)


Lesenswert?

Hi,

statt nur die FFs von Hand zu generieren: Generiere doch statt
dessen einfach die komplette Kette inkl. LUT6s, CARRY4s und FFDs.
Die Verdrahtung ist relativ einfach, bei Problemen kannst du ja
einfach mal einen Adder synthetisieren und die Schaltung in
PlanAhead oder FPGA-Editor anschauen. Und damit in deinem Fall
nichts wegoptimiert wird, musst du z.B. alle Signale ziwschen
CARRY4s und FFDs mit KEEP=TRUE versehen.

Evtl. muss du alle LUT6s, CARRY4s und FFDs noch mit RLOC Constraints
positionieren, wegen den CARRY4s ist dass aber glaube ich überflüssig.


Gruss

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

Ich habe so etwas mit einem anderen Baustein realisiert.
Versuche mal mit dem Begriff "puls catch" was zu finden.

von Christian M. (charlie)


Lesenswert?

Hallo zusammen,

vielen Dank für die Antworten und Ratschläge.

@CLB Friend: Warum ich diese Möglichkeit nicht gleich versucht habe, 
kann ich nicht sagen aber es funktioniert tatsächlich wir du geschrieben 
hast. Ich habe als einfachen Test einzelne Carry4's und Fdc's 
miteinander "verdrahtet" und das reicht schon aus, um die gewünschte 
Tapped-Line zu generieren. Die Belegungen der LUT's kann man dem 
Synthese-Tool überlassen und manuelles Positionieren der einzelnen 
Komponenten war bisher nicht notwendig.

@ René D.: Ich werde nach dem Begriff suchen. Vielleicht ergibt sich 
eine Alternative.

Gruß

von Duke Scarring (Gast)


Lesenswert?

@Christian M.:

Den Addierer-Ansatz hatt ich auch kurz versucht und bin an dem selben 
Punkt wie Du hängengeblieben.

Die Positionierung habe ich mit einer for-generate-Schleife erzeugt. 
Sonst kommt der Placer möglicherweise auf die Idee die Chain zu 
splitten. Und dann sind die Laufzeiten zwischen den Taps noch ungenauer, 
als sie so schon sind.

Testen kann man das Ding übrigens ganz gut mit einem freilaufenden 
Ringszillator (Forumssuhce).

Duke

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.