Forum: FPGA, VHDL & Co. Anfängerfrage: Compare in VHDL für FPGA


von Steffen H. (avrsteffen)


Lesenswert?

Hallo liebe Gemeinde

Seid mir bitte nicht böse, aber ich bin noch blutiger Anfänger in sachen 
FPGA und VHDL.

Aufgabe ist es für eine Triggereinrichtung zwei 8bit Werte mit einander 
zu vergleichen. Also Wert_A mit Wert_B. Allerdings muss ein Vergleich 
immer genau einen Takt zuvor geschehen und dieses Ergebnis im 
2.Taktzyklus beim zweiten Vergleich vorliegen.

Die Gleichung dazu:

Y = (A >= B) & (A' < B')
Hinweis: A' und B' sollen hier die Vergleichswerte einen Taktzyklus 
vorher darstellen.

Ich weiß gar nicht erst wie ich da anfangen soll. Wer kann helfen und 
mir einen Tip geben und mich auf die richtige Fährte führen?

Ich danke schon mal für die Hilfe
Steffen

von Markus (Gast)


Lesenswert?

Kuck dir das hier mal an:
http://www.doulos.com/knowhow/vhdl_designers_guide/an_example_design_entity/

Dann noch als Hinweis: Wenn du den alten Zustand brauchst, dann musst du 
einen getakteten Process ´ala:


process(clk)
begin
  if clk'event and clk='1' then
    ...
  end if;
end process;

bauen, sonst kannst du keine Werte speichern (Schaltwerk vs Schaltnetz).

Grüße,
Markus

von Steffen H. (avrsteffen)


Lesenswert?

Hallo Markus

Danke dir schonmal. Allerdings hilft der link mir da auch nicht weiter.

Ich hab mir jetzt schon mal einen Comparator gebastelt der greater, 
equal und less ausgibt.

Das ich hier mit Taktflanken arbeiten muss war mir schon klar. Ich hab 
auch schon etwas Logik auf dem Papier gezeichnet, wie es eigentlich 
funktionieren müsste. Allerdings möchte ich es in VHDL abbilden und kein 
Schematic nehmen.

Weitere Vorschläge?
Grüße Steffen

von Steffen H. (avrsteffen)


Angehängte Dateien:

Lesenswert?

So, hab mal den Logik-Plan mit angehangen.

von Steffen H. (avrsteffen)


Angehängte Dateien:

Lesenswert?

Hallo

Nun ein wenig bin ich jetzt schon weiter. Die funktionelle Simulation 
funktioniert. Doch wird das Design in einer timig simulation noch 
funktionieren?

Wer kann mal über diesen (Anfänger-) Code schauen?

Ich habe noch ein asyncronen Reset über "Stop" und "RESET" mit 
eingefügt. Außerdem gibt es einen Trigger-Enable Anschluss und einen zur 
Auswahl des Triggermodus, steigende oder fallende Flanke.

Ich kann mit Kritik umgehen. Also, ran an die Tasten, was könnt ich da 
noch besser machen???

Grüße
Steffen

von Steffen H. (avrsteffen)


Angehängte Dateien:

Lesenswert?

Ups, Sorry!

Das war die Testbench. Hier jetzt der richtige Code. Vieleicht kann man 
da noch was in Components machen?

Steffen

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


Lesenswert?

> Ich habe noch ein asyncronen Reset über "Stop" und "RESET" mit
> eingefügt.
Ja, böse, böse...
Wenn schon ein asynchroner Reset, dann auf jeden Fall keinen 
kombinatorischen asynchronen Reset.

> Nun ein wenig bin ich jetzt schon weiter. Die funktionelle Simulation
> funktioniert. Doch wird das Design in einer timig simulation noch
> funktionieren?
Ja. Das wird sogar sehr gut auch in einer Timing-Simulation 
funktionieren. Aber in der Realität wird das Desing herumzicken!!!
Warum? Weil du asynchrone Eingänge vergleichst:
1
        if (DATA_IN < TRIG_LEVEL) then  
2
        less <= '1';
3
        equal <= '0';
4
        greater <= '0';
Und dann die kombinatorisch ermittelten Werte (less..greater) ohne 
weitere Synchronisation direkt weiterverwendest:
1
      if falling_edge (CLK) then
2
         q_dff_3 <= (greater or equal or out_trig_hi);
3
      end if;
Das muß und wird irgendwann schief gehen.

Was, wenn kurz vor der nächsten fallenden Flanke ein neues DATA_IN 
kommt. Sind dann für diese Abfragen die 3 Komparatorausgänge garantiert 
alle richtig und stabil?
Nein. Du kannst das nicht garantieren, solange DATA_In zum Takt keinen 
Bezug hat. Das Stichwort und die Problematik dahinter heißt 
"Einsynchronisieren":
http://www.lothar-miller.de/s9y/categories/35-Einsynchronisieren


BTW:
> comperator:  process(DATA_IN,TRIG_LEVEL)
Das sollte eher comparator heißen. Komperatoren gibt es nicht.

von Steffen H. (avrsteffen)


Lesenswert?

Hallo Lothar

Danke für die Hinweise. Genau sowas hab ich auch befürchtet. Aber bitte 
nicht vergessen, das ist mein erster Versuch und ich bin blutiger 
Anfänger in Sachen VHDL und FPGA.

>Ja. Das wird sogar sehr gut auch in einer Timing-Simulation
>funktionieren. Aber in der Realität wird das Desing herumzicken!!!
>Warum? Weil du asynchrone Eingänge vergleichst:
1
        if (DATA_IN < TRIG_LEVEL) then  
2
        less <= '1';
3
        equal <= '0';
4
        greater <= '0';

Wie kann ich den denn einsynchronisieren? Zum Beispiel mit einer 
fallenden Flanke von CLK?

Wie kann ich das mit dem RESET lösen?
Also "RESET" soll der interne Reset sein. Und STOP kommt von außerhalb ( 
aber immer noch innerhalb der FPGA von einem anderen Component.

Grüße
Steffen

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


Lesenswert?

Steffen H. schrieb:
> Also "RESET" soll der interne Reset sein.
Dann ist der also taktsynchron...

> Und STOP kommt von außerhalb
> aber immer noch innerhalb der FPGA von einem anderen Component.
... und der auch?
Dann sollte das keine Probleme geben.

Aber: wenn der Reset und der Stop taktsynchron sind, warum nimmst du sie 
dann nicht in den getakteten Teil des Prozesses?
So etwa:
1
  process (CLK) begin
2
   if falling_edge (CLK) then
3
     if (stop ='1' or RESET ='0') then
4
       q_dff_1 <= '0';
5
     else
6
       q_dff_1 <= less;
7
     end if;
8
   end if;
9
  end process;
Dann ist das wesentlich klarer, dass alles vom Takt abhängt.

> Wie kann ich das mit dem RESET lösen?
Stell dir die Frage: "Wofür brauche ich einen Reset?"
Wenn die Antwort ist: "Für den Reset-Knopf!"
Dann lass den Reset weg.

Welche Zielplattform (welches FPGA) verwendest du? Wenn es Xilinx ist, 
dann lies zum Thema asynchroner Reset mal den 
Beitrag "Xilinx und die Resets"
Und die Links, die darin auftauchen.

von Harald F. (hfl)


Lesenswert?

Hallo Steffen,

Lothar ist hier im Forum einer der Großen. Was der schreibt, hat immer 
Hand und Fuß. Oder fast immer, manchmal gibt es auch abweichende 
Meinungen. So auch hier. Lothar Miller schrieb:

> Ja. Das wird sogar sehr gut auch in einer Timing-Simulation
> funktionieren. Aber in der Realität wird das Desing herumzicken!!!
> Warum? Weil du asynchrone Eingänge vergleichst:
> if (DATA_IN < TRIG_LEVEL) then
>     less <= '1';
>     equal <= '0';
>     greater <= '0';
> Und dann die kombinatorisch ermittelten Werte (less..greater) ohne
> weitere Synchronisation direkt weiterverwendest:
>     if falling_edge (CLK) then
>         q_dff_3 <= (greater or equal or out_trig_hi);
>     end if;
> Das muß und wird irgendwann schief gehen

Hier muss ich Lothar leider punktuell widersprechen. Er hat sicher 
Recht, wenn er schreibt, dass Signale, die in das FPGA von außen 
eingegeben werden, entweder als taktsynchron bekannt sein oder 
einsynchronisiert werden müssen. Aber es ist durchaus erlaubt, aus diese 
Signalen kombinatorische Verknüpfungen zu bilden und die Ergebnisse 
daraus weiter kombinatorisch zu verarbeiten, bevor das finale Signal in 
ein Flipflop übernommen wird.

Harald

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


Lesenswert?

Harald Flügel schrieb:
> Aber es ist durchaus erlaubt, aus diese Signalen kombinatorische
> Verknüpfungen zu bilden und die Ergebnisse daraus weiter kombinatorisch
> zu verarbeiten, bevor das finale Signal in ein Flipflop übernommen wird.
Du hast mit der allgemeinen Betrachtung natürlich recht, aber ich hatte 
(in Unkenntniss des hoffentlich synchronen Umfelds) angemäkelt, dass 
Signale ohne weitere Synchronisation taktsynchron weiterverarbeitet 
wurden:
>> Warum? Weil du asynchrone Eingänge vergleichst:
>> if (DATA_IN < TRIG_LEVEL) then
>>     less <= '1';
>>     equal <= '0';
>>     greater <= '0';
>> Und dann die kombinatorisch ermittelten Werte (less..greater) ohne
>> weitere Synchronisation direkt weiterverwendest:
>>     if falling_edge (CLK) then
>>         q_dff_3 <= (greater or equal or out_trig_hi);
>>     end if;
Da unten könnte gleichwertig auch stehen:
1
     if falling_edge (CLK) then
2
         q_dff_3 <= (DATA_IN > TRIG_LEVEL or out_trig_hi);
3
     end if;
Und wenn dann DATA_IN oder TRIG_LEVEL asynchron wären...  :-o


Fazit: wie Harald sagt dürfen natürlich alle Signale auch schon vor dem 
Einsynchronisieren logisch verknüpft werden. Nur braucht dann auch 
dieses kombinierte Signal irgendeine Validierung, bevor es taktsynchron 
verwendet werden darf.

von Steffen H. (avrsteffen)


Lesenswert?

Hallo

Danke für eure Antworten und Tips. Hab gestern sehr lange Lothar seine 
Seite besucht und gelesen und gelesen.. Sehr, sehr interressant!

Nun nochmal zu meiner Teilkomponente "Trigger".
DATA_IN kommt von einem ADC, der mit CLK getaktet wird. Ich weiß nicht, 
ob man da sagen kann, die Daten kommen Taktsyncron. Denn laut Datasheet 
des ADC stehen die Daten "typischer Weise" nach 5.9ns nach der L->H 
Flanke des Taktes bereit. Dies kann allerdings auch schon mal 12ns 
dauern. Der CLK für den ADC ist der selbe wie für den Trigger 
(Comparator).

Das Stop-Signal soll später mal von dem Adresszähler ( den ich noch 
nicht einmal angefangen hab zu schreiben) erzeugt werden, und zwar dann, 
wenn ein bestimmter Zählerstand erreicht ist, und nichts mehr in den 
internen BRAM gespeichert werden soll. Zähler soll sozusagen Stop 
ausgeben und seinen Zählerstand auf "0000000000" zurücksetzen. Bis 
irgendwann der Trigger wieder frei gegeben wird. Dies soll von außerhalb 
des FPGA´s durch irgendeine MCU via serielle Schnittstelle zum FPGA 
geschehen. Soweit eigentlich mein Vorhaben.

Als internen Reset bezeichne ich leider doch den RESET der von außerhalb 
über einen RESET Taster erzeugt wird. Ist auf meinen Board halt so 
vorgegeben und ich weiß nicht, ob ein FPGA bei seiner Initialisierung 
einen Internen Reset in irgend einer Weise durchführt.

Ich verwende übrigens einen LATTICE FPGA vom Typ XP3 (LFXP3C) Speedgrad 
-3. War letztens auf der Electronica in München und da wurde mir LATTICE 
empfohlen für mein Vorhaben.

Hatte eigentlich vorgehabt mit Xillix Spartan3 zu arbeiten, aber da gab 
es dieses unwiederstehliche Angebot einer Platine mit dem LFXP3C als 
FPGA im Internet unter: http://www.hardware-design.de/ das HWD-LFXP3C 
Eval_board für unschlagbare 24€. Da hab ich natürlich zugeschlagen!


Wo ich jetzt gerade hänge ist die Verwendung der internen Block-RAMs als 
Speicher, die Generierung des Adresszählers für die Speicherung und die 
Clock-Generierung für den ADC (bis 80Mhz) aus dem auf dem Board zur 
Verfühgung stehenden 25Mhz Oszilators (werd ihn wohl eher auf 40Mhz 
umrüsten).

Die serielle Schnittstelle, ähnlich SPI hab ich schon fertig. Die 
liefert mir übrigens auch den Vergleichswert TRIG_LEVEL für den 
Comparator. Die Übernahme eines neuen TRI_LEVEL Wertes geschieht jetz 
noch über einen Impuls (Länge: mindestens 60ns) von LOAD_Data von der 
seriellen Schnittstelle von außen.

Sollte ich den auch einsyncronisieren über den CLK des ADC?


Grüße
Steffen

von Steffen H. (avrsteffen)


Lesenswert?

Ach ja, über Block-RAM Impementierung hab ich inzwischen schon viel 
gefunden im WWW. Aber wie ich den Adresszähler gestalte leider noch 
nicht. Ist wahrscheinlich nur ein ganz einfacher Zähler/Counter der noch 
den BRAM_ENable und BRAM_WR generiert.

Ist das so einfach???

Doch dieser sollte doch irgendwie gesteuert werden, oder?

Gerade wenn man nur Daten aufzeichnen will, wenn ein "JetztZähle"-Signal 
anliegt. Und dann selbstständigt stoppt wenn die maximale 
Speicheradresse erreicht ist und sich selbstädigt wieder rücksetzt.

Da seh ich gerade den Wald vor Bäumen nicht.

Muss mich noch ein wenig belesen und auf eure Hilfe, Tips, Denkanstöße 
warten..

Steffen

von Christian R. (supachris)


Lesenswert?

Wie wäre es mit einem Blockram FIFO? Oder brauchst du nach der Aufnahme 
wahlfreien Zugriff auf die Samples? Den FIFO könntest du einfach so 
lange beschrieben, bis er voll ist. Daszu gibts das Full Flag. Ist 
natürlich die einfachste Lösung, aber wenn die Aufnahmlänge erst mal fix 
ist...wieso nicht?

von Steffen H. (avrsteffen)


Lesenswert?

Hallo Christian

Ich würde lieber einen normalen RAM bauen, damit eventuell noch mit 
einem PRE-Trigger arbeiten kann
.
Mir reicht es jetzt allerdings erst einmal aus, wenn bei ausgelöstem 
Trigger (TRIG_OUT) der BRAM mit den Daten gefüllt wird bis er voll ist. 
Ich denk mal es werden eher 2-3 verschaltete BRAM´s werden.

Ist der BRAM also voll, wird der Trigger gestoppt (TRIG_EN =0 und 
TRIG_OUT =0) und ein weiteres Signal (SAMPLE_READY) generiert um dem MC 
anzuzeigen, dass er die DATEN nun auslesen kann.

Ist der MC mit der Aufbereitung der Daten fertig, gibt er den Trigger 
wieder frei. (TRIG_EN =1)


Grüße
Steffen

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.