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ß