Forum: FPGA, VHDL & Co. Frage zu Register und Clock


von Thomas P. (pototschnig)


Lesenswert?

Hallo,

angenommen ich hab einen asynchronen Adress/Datenbuss und will mit der 
negativen Flanke von WR ein 8Bit Datum zwischenspeichern, dann sieht das 
ja so aus:

process (wr)
begin
    if falling_edge(wr) then
        temp := din;
    end if;
end process;

In dem Beispiel wurde wr als clock verwendet und wenn ich versuche bei 
der implementierung den Pin an einen normalen I/O zu binden, dann 
meckert das Synthesetool, weil es den Pin gerne an einem der 
CLK-Eingänge hätte und verweigert mit den weiteren Fortgang.

Ich habs dann eigentlich so gemacht, dass ich dann auch wirklich einen 
der CLK-Eingänge verwendet habe, aber was ist wenn ich da mal mehr 
solche Signale hab als ich Clockeingänge hab?

Mfg
Thomas Pototschnig

von Jörn K. (joern)


Lesenswert?

Ich würde es so machen:

mittels einer Flankenerkennung die fallende Flanke des wr Signals 
ermitteln. Dieses Signal als Enablesignal für die Daten-FF verwenden.

process sync(clk, reset)
begin
     if (reset='0') then
      sync  <='1';
      sync1 <='1';
     elsif rising_edge(clk) then
      sync <= wr;
      sync1<= sync;
     end if;
end;

wr_fe <= '1' when sync1 = '1' and sync = '0' else '0';

process save(clk,reset)
begin
     if (reset='0') then
      temp <= (others=>'0');
     elsif rising_edge(clk) then
      if (wr_fe = '1') then
        temp <= din;
      end if;
     end if;
end;

Am besten die Daten auch noch mit einsychronisieren.

Gruß Jörn



von ----- (Gast)


Lesenswert?

Solche Abfragen sollte man vermeiden. Wenn es irgend wie geht, solltest 
du das so implementieren.

process (clk)
begin
    if rising_edge(clk) then
        temp <= wr;
        wr_pulse <= temp and not wr;
    end if;
end process;

process (clk)
begin
    if rising_edge(clk) then
      if wr_pulse = '1' then
        reg <= din;
      end if;
    end if;
end process;

von ----- (Gast)


Lesenswert?

zu spät

von lolli (Gast)


Lesenswert?

die daten brauchen nicht einsynchroniiert werden, da sie ja zum 
Zeitpunkt der WR stbil sind / sein muessen.

von Morpheuz (Gast)


Lesenswert?

Okay alles klar!

Mfg
Thomas

von Falk (Gast)


Lesenswert?

@Thomas Pototschnig

>process (wr)
>begin
>    if falling_edge(wr) then
>        temp := din;
>    end if;
>end process;

Nimm Signale, keine Variablen. Das geht manchmal schief (Das Modell von 
Variablen und Signalen in VHDL ist bisweilen knifflig).

>Ich habs dann eigentlich so gemacht, dass ich dann auch wirklich einen
>der CLK-Eingänge verwendet habe, aber was ist wenn ich da mal mehr
>solche Signale hab als ich Clockeingänge hab?

1.) Das möglichst beim Hardwaredesign vermeiden
2.) Man kann die Software auch überreden, normale IOs als Takteingänge 
zu verwenden. Dann sollte man aber nur wenig Logik dort dranhängen und 
möglichst schnell die Daten auf ein solides Taktnetz synchronisieren.

MFG
Falk

P.S. Ich hab jetzt nicht die genauen Einstellungen dafür im Kopf. Muss 
mal zuhause auf meinem Rechner schauen wie das gemacht wird.

von Falk (Gast)


Lesenswert?

Im VHDL muss folgendes eingefügt werden

attribute clock_buffer: string;
attribute clock_buffer of my_clock_signal signal is "ibuf";

damit wird für das Taktsignal my_clock_signal ein normaler IO als 
Takteigang verwendet (und nicht ein globaler Taktpuffer wie es 
normalerweise implizit getan wird).

Im UCF sollte man noch der Software sagen, dass diese Taktsignal auf 
Leitungen mit wenig Skew geroutet werden soll.

NET my_clock_signal_ibuf USELOWSKEWLINES;

Das Suffix _ibuf generiert der Synthesizer, da intern ja nicht direkt 
das Taktsignal verwendet wird, sondern erst nachdem es über einen Ibuf 
gelaufen ist.
Man sollte sich aber im klaren darüber sein, dass so ein Taktpuffer ganz 
und gar nicht mit einem richtigen, globalen Taktpuffer vergleichbar ist. 
Man sollte also höchstens 20..30 FlipFlops dort dranhängen. Das gilt für 
alle "alten" FPGAs bis einschliesslich Virtex-IIPRO bzw. Spartan3. Bei 
Virtex4/5 sieht das schon wieder anders aus, die haben local clocking. 
Allerdings kann ich dazu nicht viel sagen, da ich damit bisher (leider) 
noch nicht gearbeitet habe.

Alles nachlesbar im Xilinx Constraint Guide, gibts als PDF auf der 
xilinx Homepage.

MfG
Falk

von Thomas P. (pototschnig)


Lesenswert?

Danke für die ausführlichen Erklärungen!

Ich werds jetzt erstmal mit dem samplen von WR versuchen und wenn ich 
irgendwo Probleme mit dem Write-Timing krieg, dann versuch ich es dann 
anders.

Mfg
Thomas Pototschnig

von ChrisV (Gast)


Lesenswert?

> die daten brauchen nicht einsynchroniiert werden, da sie ja zum
> Zeitpunkt der WR stbil sind / sein muessen.

Oh doch, die Daten sollten ebenfalls synchronisiert werden. Erstens 
liegen die Daten ansonsten um die Takte früher an, die für das 
synchronisieren des wr Signals nötig sind, und zweitens sollte, wenn 
möglich, und das ist es fast immer,, jedes Signal dass von außen kommt 
zum Takt synchronisiert werden. Andernfalls kann es ganz schnell zu sehr 
unschönen Effekten kommen, wenn die Signale mal nicht wie eine 1 
anstehen und etwas "glitschig" sind.

von Joerg W. (joergwolfram)


Lesenswert?

Vielleicht ist es gar nicht notwendig, beim WR die Flanke zu erkennen. 
Indem man, ähnlich wie bei einem Speicherbaustein, Anforderungen an die 
externe Ansteuerlogik vorgibt. Das wären Setup, Hold und minimale 
Pulsbreite. Bei WR=Low werden die Daten in ein Zwischenregister 
geschrieben und bei WR=High aus dem Zwischenregister in das eigentliche 
Datenregister. Die minimale Pulsbreite sollte dann etwas länger als die 
Taktperiode sein, Setup und Hold ergeben sich aus den Verzögerungen von 
den Eingängen zum Zwischenregister.
Über ein "9.Datenbit" kann damit gleich noch festgestellt werden, ob ein 
Schreibzugriff erfolgt ist. Vorteil ist, dass alles synchron bleibt, 
Nachteile könnten sich eventuell aus den Anforderungen für die 
Ansteuerung ergeben.
1
signal t_data,data: std_logic_vector(7 downto 0);
2
signal t_write,write,done: std_logic;
3
4
process (clk) is
5
begin
6
   if (rising_edge(clk)) then
7
      if (wr='0') then
8
         t_data <= din;
9
         t_write <= '1';
10
      elsif (done='1') then
11
         t_write <= '0';
12
       end if;
13
   end if;
14
end process;
15
16
process (clk) is
17
begin
18
   if (rising_edge(clk)) then
19
      if (wr='1') then
20
         data <= t_data;
21
         write <= t_write;
22
      end if;
23
   end if;
24
end process;

(write and t_write) zeigt an, dass ein Schreibzugriff ausgelöst wurde, 
mit done wird das Ganze wieder zuückgesetzt.

Gruß Jörg

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.