Forum: FPGA, VHDL & Co. Taktfrequenzerhöhung


von Johann (Gast)


Lesenswert?

Hallo,

bei folgendem Beispiel komme bei "Simulate Post-Fit Model" (ISE 10.1) 
auf maximalen Takt von ca. 12MHz, in Timing Report steht:

Max. Clock Frequency (fSYSTEM) 100.000 MHz
Clock to Setup (tCYC)    10.000 ns.
Setup to Clock at the Pad (tSU)   6.500 ns.
Clock Pad to Output Pad Delay (tCO)   14.500 ns.

Ich verwende XC95144XL, wie kann ich Takt erhöhen ?

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
entity tap_ctl is
7
Port (          DATA : inout  STD_LOGIC_VECTOR (15 downto 0);
8
                BUSY : out  STD_LOGIC;
9
                WR : in  STD_LOGIC;
10
                CMD : in  STD_LOGIC;
11
                CS : in  STD_LOGIC;
12
                RESET : in  STD_LOGIC;
13
                -- Clocks GCLK0, faster clock - GCLK0 --
14
                GCLK0 : in  STD_LOGIC
15
);
16
end tap_ctl;
17
18
19
architecture Behavioral of tap_ctl is
20
21
signal tmp_data : STD_LOGIC_VECTOR (15 downto 0) := (others => '0');
22
type cmd_states is ( IDLE, DATA_CMD, DATA_WRITE, DATA_READ );
23
signal cmd_state : cmd_states := IDLE;
24
25
begin
26
        uc_iface: process(GCLK0, RESET)
27
        begin
28
                if RESET = '1' then
29
                        cmd_state <= IDLE;
30
                        tmp_data <= (others => '0');
31
                elsif rising_edge(GCLK0) then
32
                        case cmd_state is
33
                        when IDLE =>
34
                                cmd_state <= IDLE;
35
                                if CS='1' and CMD='1' and WR='0' then
36
                                        cmd_state <= DATA_CMD;
37
                                        tmp_data <= DATA;
38
                                elsif CS='1' and CMD='0' and WR='1' then
39
                                        cmd_state <= DATA_WRITE;
40
                                        tmp_data <= DATA;
41
                                elsif CS='1' and CMD='0' and WR='0' then
42
                                        cmd_state <= DATA_READ;
43
                                end if;
44
45
                        when DATA_CMD =>
46
                                cmd_state <= IDLE;
47
48
                        when DATA_WRITE =>
49
                                cmd_state <= IDLE;
50
51
                        when DATA_READ =>
52
                                cmd_state <= IDLE;
53
                        end case;
54
                end if;
55
        end process uc_iface;
56
        DATA <= tmp_data when cmd_state = DATA_READ else (others => 'Z');
57
        BUSY <= '0' when cmd_state = IDLE else '1';
58
59
end Behavioral;

von Georg A. (Gast)


Lesenswert?

Wie kommst du denn auf die 12MHz bzw. wer sagt das? Das wären ja ca. 
80ns Periodendauer. Das kann ich mir bei den dünnen kombinatorischen 
Pfaden gar nicht vorstellen...

von Johann (Gast)


Angehängte Dateien:

Lesenswert?

Durch Timing Einstellungen in testbench.tbw (ist für mich als Anfänger 
einfacher). Ab ca. 12 MHz funktioniert die Simulation nicht mehr.

Sim Console meldet auch:
at 176.800 ns(3), Instance /testbench/UUT/tmp_data_11_REG/ : Warning: 
/X_FF SETUP High VIOLATION ON I WITH RESPECT TO CLK;
  Expected := 3 ns; Observed := 1.5 ns; At : 176.8 ns

und so weiter.

von Oliver N. (neufranke)


Lesenswert?

wo kommen denn die timings her, die da verletzt sein wollen?

von Georg A. (Gast)


Lesenswert?

Naja, die Ursache ist Pad-In to Setup, weil wohl du die Daten (und 
auch WR etc.) in der Testbench zu kurz vor der steigenden Taktflanke 
draufgibst. Das sieht aus, als wäre das Timing fest kodiert, mit dem 
Takt scheint das nicht viel zu tun zu haben. Wenn es in der Realität 
auch so asynchron ist, hast du ein ganz anderes Problem, was sich auch 
mit nur 100kHz Takt nicht löst...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

@  Johann
Georg hat es schon gesagt, du wirst das Problem mit der Warning 
niemals lösen können. Das ist eine Verletzung der Setup-Zeit 
(alternativ könntest du auch die Hold-Zeit verletzen), die in einem 
metastabilen Verhalten der betroffenen FFs resultieren wird. Bei deinem 
Design sind das die FFs der State-Machine, die kann dann beligib hin und 
her hüpfen.... :-o

Dein Problem lässt sich nicht sicher lösen, weil du 3 Steuersignale 
gleichzeitig hast: CS, WR und CMD.
1
     when IDLE =>
2
        cmd_state <= IDLE;
3
        if    CS='1' and CMD='1' and WR='0' then
4
           cmd_state <= DATA_CMD;
5
        elsif CS='1' and CMD='0' and WR='1' then
6
           cmd_state <= DATA_WRITE;
7
        elsif CS='1' and CMD='0' and WR='0' then
8
           cmd_state <= DATA_READ;
9
       end if;
Was passiert hier, wenn du ausgehend von CS='0', CMD='0' und WR='0' auf
CS='1', CMD='0' und WR='1' umschaltest und dabei das WR='1' nur eine 
Nanosekunde später (und dazwischen der Takt) kommt?
Richtig: du bekommst über CS='1', CMD='0' und WR='0' zwischendurch den 
Zustand DATA_READ. Und das dauert...., bis der beendet ist.
Zudem hast du in diesem Augenblick eine Buskollision, weil gleichzeitig 
der uC und dein CPLD Daten auf den Bus legen.


Üblicherweise ist CS low-aktiv und pegelgesteuert, und WR low-aktiv und 
flankengesteuert (steigende Flanke übernimmt Daten). Dann könntest du 
das Design anders aufsetzen und die Daten synchron zum WR-Impuls 
übernehmen und erst danach verarbeiten.
Die Richtung des Bustreibers wird direkt vom externen Steuersignal 
umgeschaltet, denn der hat die Kontrolle über den Bus.

Du solltest auch die Daten innerhalb deines Designs in zwei Richtungen 
auftrennen: data_in und data_out, dann wird das mit dem Mux einfacher.

Du wechselst von einer Taktdomäne (deine externe Signale) in eine andere 
Taktdomäne (der CPLD-Takt). Dazwischen müssen 2 FF-Stufen zur 
Synchronisation eingefügt werden.
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
entity tap_ctl is
7
Port (          DATA : inout  STD_LOGIC_VECTOR (15 downto 0);
8
                BUSY : out  STD_LOGIC;
9
                WR : in  STD_LOGIC;
10
                CMD : in  STD_LOGIC;
11
                CS : in  STD_LOGIC;
12
                RESET : in  STD_LOGIC;
13
                -- Clocks GCLK0, faster clock - GCLK0 --
14
                GCLK0 : in  STD_LOGIC
15
);
16
end tap_ctl;
17
18
19
architecture Behavioral of tap_ctl is
20
21
signal CSsr : STD_LOGIC_VECTOR (1 downto 0) := (others => '0'); -- Synchronisations-Schieberegister für CS
22
signal data_in : STD_LOGIC_VECTOR (15 downto 0) := (others => '0');
23
signal data_out : STD_LOGIC_VECTOR (15 downto 0) := (others => '0');
24
type cmd_states is ( IDLE, DATA_CMD, DATA_WRITE, DATA_READ );
25
signal cmd_state : cmd_states := IDLE;
26
27
begin
28
        process(GCLK0) begin
29
           if rising_edge(GCLK0) then
30
              CSsr <= CSsr(0) & CS;
31
           end if;
32
        end process;
33
34
        uc_iface: process(GCLK0, RESET)
35
        begin
36
                if RESET = '1' then
37
                        cmd_state <= IDLE;
38
                        tmp_data <= (others => '0');
39
                elsif rising_edge(GCLK0) then
40
                        case cmd_state is
41
                        when IDLE =>
42
                                cmd_state <= IDLE;
43
                                if    CSsr(1)='1' and CMD='1' and WR='0' then
44
                                        cmd_state <= DATA_CMD;
45
                                elsif CSsr(1)='1' and CMD='0' and WR='1' then
46
                                        cmd_state <= DATA_WRITE;
47
                                elsif CSsr(1)='1' and CMD='0' and WR='0' then
48
                                        cmd_state <= DATA_READ;
49
                                end if;
50
51
                        when DATA_CMD =>
52
                                data_out <= irgendwas;
53
                                cmd_state <= IDLE;
54
55
                        when DATA_WRITE =>
56
                                cmd_state <= IDLE;
57
58
                        when DATA_READ =>
59
                                data_out <= irgendwasanderes;
60
                                cmd_state <= IDLE;
61
                        end case;
62
                end if;
63
        end process uc_iface;
64
65
        process (WRn) begin
66
           if rising_edge(WRn) then
67
              data_in <= DATA;
68
           end if;
69
        end process;
70
71
        DATA <= data_out when WRn='1' else (others => 'Z');  -- Der Datenbus wird direkt vom externen signal kontrolliert
72
        BUSY <= '0' when cmd_state = IDLE else '1';
73
74
end Behavioral;

BTW:
Am einfachsten wäre es allerdings, wenn du den Takt vom uC auf das CPLD 
geben würdest, denn dann ist dein Design synchron zur Taktdomäne des uC.

von Johann (Gast)


Lesenswert?

Danke Lothar für deine Hilfe.

Es ist nur ein Auszug aus meinem Design. Eigentlich habe ich 2 Takte. 
Ersten zur Kommunikation mit uC(AVR32) und zweiten - variablen Takt(frei 
einstellbar) - für so was wie serielle Schnittstelle. Wenn die erste FSM 
in z.B. Zustand DATA_CMD geht dann übernimmt die zweite FSM(GCLK2) die 
Daten und verarbeitet die. Ich hatte die Idee auch den CS als GCLK0 zu 
benutzen, also so was wie:
1
elsif rising_edge(CS) then
Kann es funktionieren ? Vorausgesetzt WR und CMD sind stabil zu dem 
Moment.

Ich werde deine Änderungen heute Abend ausprobieren.
Johann.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

>  Vorausgesetzt WR und CMD sind stabil zu dem Moment.
Ja, das ist gut so.

Aber du mußt jetzt noch einen ähnlichen sicheren Übergang ind die zweite 
Taktdomäne machen: erst die Daten stabilisieren, und dann das 
Übergabesignal aktivieren und vor der Übernahme einsynchronisieren.

von Johann (Gast)


Lesenswert?

Nach langem durchprobieren, eine Variante:
1
begin
2
3
        uc_iface: process(CS, RESET)
4
        begin
5
                if RESET = '1' then
6
                        data_out <= (others => '0');
7
                elsif rising_edge(CS) then
8
                        if CMD='0' and WR='1' then
9
                                data_out <= data_in; -- nur als Beispiel
10
                        end if;
11
                end if;
12
        end process uc_iface;
13
14
        DATA <= data_out when WR = '0' else (others => 'Z');
15
        data_in <= DATA;
16
        BUSY <= '0' when WR = '0' else '1';

Performance Summary
Min. Clock Period   14.000 ns.
Max. Clock Frequency (fSYSTEM)   71.429 MHz.
Limited by Clock Pulse Width for CS
Pad to Pad Delay (tPD)   11.000 ns.
Setup to Clock at the Pad (tSU)   2.100 ns.
Clock Pad to Output Pad Delay (tCO)   10.200 ns.

Hier muss ich nach WR = '1' Setup Time von 11 ns einhalten. Bekomme ich 
bei dem CPLD überhaupt bessere Zeiten? (Speed 10ns)

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.