mikrocontroller.net

Forum: FPGA, VHDL & Co. Datenabtastung und Case-Problem


Autor: Geo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
ich programmiere zur Zeit einen CPLD in VHDL mit Quartus. Ich will einen 
Datenwandler/-buffer realisieren. Als Eingangssignal habe ich ein TTL 
Datensignal mit der dazugehörigen Clock.
Je nach Schalterstellung (3 Stellungen) soll folgendes realisiert 
werden:
1.: Buffer (IN = OUT) ohne Abtasten oder ähnliches
2.: Scrambler, als LFSR realisiert und Signale Abgetastet
3.: Descrambler, ebenfalls als LSFR realisiert und Signale abgetastet

Nun habe ich 2 Fragen:
1.:
Da ich in den meisten Anwendungsfällen nicht weiß, ob die Daten bei der 
steigenden oder fallenden Flanke gültig sind(Clock Invertiert oder 
nicht), hätte ich die Clock durch Abtasten mit CPLD-CLK um einen 1/4 
Takt verzögert. So müsste ich bei sauberen Signalen bei steigender oder 
fallender Flanke immer gültige Daten haben:
z.B.:
Clock:      __--__--__--__--__--__--__-- Daten gültig bei st. Flanke
Daten:      ___----____----____----___
1/4 verz.:  -__--__--__--__--__--__--__- Daten gültig bei st. oder 
fallender Flanke
Kann man das so realisieren oder gibt es dazu bessere Methoden? Würde 
für die Verzögerung Daten und Clocksignal mit CPLD-CLK >= 16x Datenclock 
abtasten und das Clocksignal dann entsprechend mehrere Abtasttakte 
verzögern (bei 16-facher Abtastung z.B. um 4)

2.:
Da ich den 3 Fällen bei Fall 1 (BUFFER) ohne externe Clock arbeiten 
möchte und bei Fall 2+3 die Signale mit der 16-fachen externen Clock 
noch abtasten würde, hätte ich mir ungefähr folgendes gedacht:
process(CLK,datain,clockin) -- CLK: CPLD-Clock zum Abtasten:
begin
 case switch is
   when "00" => --BUFFER
      dataout <= datain;
      clockout <= clockin;
   when "01" => --SCRAMBLER
    if(rising_edge(CLK)) then
    ...
   when others => --DESCRAMBLER
    if(rising_edge(CLK)) then
    ...
 end case;
Hier bekomme ich aber Fehlermeldungen. Ist wohl nicht möglich in einem 
process 2 mal nach rising_edge(CLK)abzufragen. Funktioniert nur, wenn 
ich Fall 1 (BUFFER) auch abtaste.
Also:
case...
if rising_edge...
when "00"...
Was gibt es hierzu für eine Programmiermethode um bei 3 Case-Fällen im 
Process, eine ohne clock abzuarbeiten?

Danke im Vorraus
Geo

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal abgesehen davon, dass das Signal switch in der Sens-List fehlen 
würde ;-)

Ein case ist ein Multiplexer, und das ist per Definition ein 
ungetaktetes Bauteil. Du kannst den Mux aber mit getakteten daten 
füttern. Also machst du 2 Prozesse, einen mit case und ungetaktet (den 
Mux), und einen getaktet zum Synchronisieren den Signals.

Ich könnte mir das auch so etwa vorstellen:
process(CLK,switch) -- CLK: CPLD-Clock zum Abtasten:
begin
 if( switch="00" ) then --BUFFER  --  kombinatorisch
      dataout <= datain;
      clockout <= clockin;
 elsif rising_edge(CLK) then    -- getaktet
   if (switch = "01") then --SCRAMBLER
    ...
   else                    --DESCRAMBLER
    ...
   end if;
 end if;
end process;

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Lothar Miller (lkmiller)

>Ich könnte mir das auch so etwa vorstellen:

Nicht gut, das erzeugt Kombinatorik am asynchronen Reset. Die einfachste 
Lösung ist auch die beste. Zwei Prozesse. Einen für die kombinatorische 
Mux, einen für die getakteten Prozesse.


process(datain, clockin, switch) -- CLK: CPLD-Clock zum Abtasten:
begin
 case switch is
   when "00" => --BUFFER
      dataout <= datain;
      clockout <= clockin;
   when "01" => --SCRAMBLER
      dataout <= scramberl_out;
      clockout <= clockin;
   when others => --DESCRAMBLER
      dataout <= descramberl_out;
      clockout <= clockin;
 end case;

process(CLK) -- CLK: CPLD-Clock zum Abtasten:
begin
 if rising_edge(CLK) then    -- getaktet
   -- scramber hier
  scrambler_out <= ???
 end if;
end process;

process(CLK) -- CLK: CPLD-Clock zum Abtasten:
begin
 if rising_edge(CLK) then    -- getaktet
   -- descramber hier
    descrambler_out <= ???
 end if;
end process;

Das mit der automatischen Flankenerkennung sollte man sehr vorsichtig 
angehen, da kann man sich fix ins Knie schiessen. Das mit der 
Verzögerung um 1/4 des Eingangstaktes klappt ggf.
Allerdings muss man nicht den Eingangstakt verzögern, sondern nur seinen 
Abtastzeitpunkt.

MFG
Falk

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Nicht gut, das erzeugt Kombinatorik am asynchronen Reset.
Ja, schon klar, aber hier handelt es sich um zeitinvariante statische 
Signale (vermutlich DIP-Schalter), da könnte man das Risiko eingehen ;-)

Autor: Geo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antworten:
@Lothar
Deine Lösung wäre jetzt auch die eine Lösung gewesen, die ich noch 
ausprobieren wollte, ansonsten hätte ich auch nichts mehr gewusst.
Beim switch-Signal handelt es sich um statische
Signale, da würde eine Übernahme der Änderung zum nächsten Takt locker 
reichen, deshalb habe ich switch nicht in der sens. list.
@Falk
Ich verzögere auch nur den Abtastzeitpunkt und nicht das Signal, habe 
ich nicht genau beschrieben:
mache ich in der Art:

clock1 <= clock;
clock2 <= clock1;
...
clock5 <= clock4;

mit 2 Processen wäre es dann etwa wie folgt:
process(CLK) -- CLK: CPLD-Clock zum Abtasten:
begin
 if rising_edge(CLK) then    -- getaktet
   clock1 <= clock;
   clock2 <= clock1;
   ...
   clock5 <= clock4;
    if clock5 = '0' and clock4 = '1' -- steigende Flanke um 4 Takte
                                     --verzögert
    -- scramber hier
    end if;
 end if;
  scrambler_out <= scrambler_ergebnis
  clock_out <= clock
end process;

process(CLK) -- CLK: CPLD-Clock zum Abtasten:
begin
 if rising_edge(CLK) then    -- getaktet
   clock1 <= clock;
   clock2 <= clock1;
   ...
   clock5 <= clock4;
    if clock5 = '1' and clock4= '0' -- steigende Flanke um 5 Takte
                                    --verzögert
     -- descramber hier
     descrambler_out <= descrambler_ergebnis
    end if;
 end if;
clock_out <= clock
end process;
Müsste ich dann mal testen, da das scrambler_ergebnis und 
descrambler_ergebnis zu unterschiedlichen Zeiten einmal vor end if; und 
einmal nach end if; (siehe Code) gültig ist.

Das das Abfragen der Daten, um 1/4 Takt verzögert, funktioniert ganz 
gut. Habe ich schon getestet. Da die Datenrate unter 10MHz liegt und das 
Signal recht sauber ist, habe ich bis jetzt keine Probleme.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Geo (Gast)

>Beim switch-Signal handelt es sich um statische
>Signale, da würde eine Übernahme der Änderung zum nächsten Takt locker
>reichen, deshalb habe ich switch nicht in der sens. list.

Ist aber dennoch falsch. Siehe VHDL

>clock1 <= clock;
>clock2 <= clock1;
>...
>clock5 <= clock4;

Schau dir mal die Verwendung von Vektoren an ;-)

>process(CLK) -- CLK: CPLD-Clock zum Abtasten:
>begin
> if rising_edge(CLK) then    -- getaktet
>   clock1 <= clock;
>   clock2 <= clock1;
>   ...
>   clock5 <= clock4;
>    if clock5 = '0' and clock4 = '1' -- steigende Flanke um 4 Takte
>                                     --verzögert
>    -- scramber hier
>    end if;
> end if;
>  scrambler_out <= scrambler_ergebnis
>  clock_out <= clock

Das ist falsch. Nach dem end if hat dort GAR NICHTS mehr zu stehen.

>Müsste ich dann mal testen, da das scrambler_ergebnis und
>descrambler_ergebnis zu unterschiedlichen Zeiten einmal vor end if; und
>einmal nach end if; (siehe Code) gültig ist.

Nöö, siehe oben.

MFG
Falk

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Beim switch-Signal handelt es sich um statische
> Signale, da würde eine Übernahme der Änderung zum nächsten Takt
> locker reichen, deshalb habe ich switch nicht in der sens. list.
Au weia.
Die Sens-List ist ausschliesslich für die Simulation interessant. 
Aktuelle Synthesewerkzeuge weisen dich einfach nur mit einer Warnung 
freundlich darauf hin, dass die nicht komplett ist. Es wird aber für die 
Synthese nichts über diese Liste gesteuert!
Das einzige was passiert, wenn die Liste nicht komplett ist, ist dass 
deine Simulation nicht mit der Realität übereinstimmt.

>>clock1 <= clock;
>>clock2 <= clock1;
>>...
>>clock5 <= clock4;
> Schau dir mal die Verwendung von Vektoren an ;-)
Insbesondere als Schieberegister.
Das Schlüsselwort heisst Concatenation, der Operator ist das '&'.

>>    end if;
>> end if;
>>  scrambler_out <= scrambler_ergebnis
>>  clock_out <= clock
> Das ist falsch. Nach dem end if hat dort GAR NICHTS mehr zu stehen.
Und falls doch, dann sollte das entsprechende Signal wenigstens in der 
Sens-List stehen. Aber vermutlich sollte das Ganze sowieso Concurrent 
(Stichwort) beschrieben werden. So etwa:
:
process(CLK) -- CLK: CPLD-Clock zum Abtasten:
begin
 if rising_edge(CLK) then    -- getaktet
   clock1 <= clock;
   clock2 <= clock1;
   ...
   clock5 <= clock4;
    if clock5 = '0' and clock4 = '1' -- steigende Flanke um 4 Takte
                                     --verzögert
    -- scramber hier
    end if;
 end if;
end process;
:
:
scrambler_out <= scrambler_ergebnis;
clock_out <= clock;
:

Autor: Geo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Als Vektor meint ihr wohl in etwa so:
clock : std_logic_vector(5 downto 0);  -- shift register
...
clock <= shift_reg(4 downto 0) & clockin;
...
Die Verzögerte Flankenabfrage dann wohl so:
if clock(5) = '0' and clock(4) = '1'...

Ist in Hardware später normal eh das gleiche. Für meine Tests hab ich 
statt Vektoren die einzellnen Bits geschrieben.

@Lothar
Wenn ich alles auf eine CLK synchronisiere, brauche ich doch switch 
nicht
in der Sens Liste. Ist ja als Vergleich wie beim synchronen Reset. Da 
schreib ich ja auch nur:
process(CLK)...
 if rising_edge(CLK)
   if reset...
oder täusche ich mich da?

Wenn ich schreibe:
scrambler_out <= scrambler_ergebnis;
   end if;
 end if;
end process;...

bzw.

--schrambler
   end if;
 end if;
(hier vor end process)scrambler_out <= scrambler_ergebnis;
end process;
(bzw. nach end process)scrambler_out <= scrambler_ergebnis;
bekomme ich unterschiedliche Ergebnisse, auch beim Descrambler.
Was ist dann hier der Fehler, wenn nach dem end if; nichts stehen soll? 
Beim Scrambler sind die Daten richtig, wenn ich
scrambler_out <= scrambler_ergebnis; nach den end if's schreibe.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn ich alles auf eine CLK synchronisiere, brauche ich doch switch
> nicht in der Sens Liste. Ist ja als Vergleich wie beim synchronen
> Reset. Da schreib ich ja auch nur:
>>process(CLK)...
>> if rising_edge(CLK)
>>   if reset...
> oder täusche ich mich da?

Mein Bezug war auf den ersten Post:
process(CLK,datain,clockin) -- CLK: CPLD-Clock zum Abtasten:
begin
 case switch is
   when "00" => --BUFFER
      dataout <= datain;
      clockout <= clockin;
   when "01" => --SCRAMBLER
    if(rising_edge(CLK)) then
    :
Die Synthese brauch überhaupt keine Senitivity-List. Die holt sich alle 
Signale automatisch ins Design. Also auch die Schalter.

Aber die Simulation rechnet den Prozess nur dann durch, wenn sich eines 
der Signale in der Liste ändert. Ergo wird der Prozess aber nicht neu 
simuliert, wenn sich am switch was ändert, weil der nicht in der Liste 
steht.

Fazit: die Simulation macht alles richtig (so wie du es beschrieben 
hast),
und die Realität macht auch alles richtig (so wie du es beschreiben 
wolltest), aber zwischen Simulation und Realität ist ein Unterschied. 
Das ist zumindest unschön, denn weshalb hättest du es denn sonst 
simulieren wollen?

Mit dem synchronen Reset
>>process(CLK)...
>> if rising_edge(CLK)
>>   if reset...
stimmt die Sens-List, denn hier kannst du (sowohl in der Simulation als 
auch in der Realität) solange am reset herumwackeln wie du willst. Es 
wird nichts passieren. Erst, wenn du am CLK wackelst (und deshalb in der 
Simulation der Prozess neu berechnet wird) wird auch der Pegel von reset 
interessant. Also ist für alle getakteten Signale der CLK in der 
Sens-List ausreichend.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.