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


von Geo (Gast)


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:
1
process(CLK,datain,clockin) -- CLK: CPLD-Clock zum Abtasten:
2
begin
3
 case switch is
4
   when "00" => --BUFFER
5
      dataout <= datain;
6
      clockout <= clockin;
7
   when "01" => --SCRAMBLER
8
    if(rising_edge(CLK)) then
9
    ...
10
   when others => --DESCRAMBLER
11
    if(rising_edge(CLK)) then
12
    ...
13
 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

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


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:
1
process(CLK,switch) -- CLK: CPLD-Clock zum Abtasten:
2
begin
3
 if( switch="00" ) then --BUFFER  --  kombinatorisch
4
      dataout <= datain;
5
      clockout <= clockin;
6
 elsif rising_edge(CLK) then    -- getaktet
7
   if (switch = "01") then --SCRAMBLER
8
    ...
9
   else                    --DESCRAMBLER
10
    ...
11
   end if;
12
 end if;
13
end process;

von Falk B. (falk)


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.

1
process(datain, clockin, switch) -- CLK: CPLD-Clock zum Abtasten:
2
begin
3
 case switch is
4
   when "00" => --BUFFER
5
      dataout <= datain;
6
      clockout <= clockin;
7
   when "01" => --SCRAMBLER
8
      dataout <= scramberl_out;
9
      clockout <= clockin;
10
   when others => --DESCRAMBLER
11
      dataout <= descramberl_out;
12
      clockout <= clockin;
13
 end case;
14
15
process(CLK) -- CLK: CPLD-Clock zum Abtasten:
16
begin
17
 if rising_edge(CLK) then    -- getaktet
18
   -- scramber hier
19
  scrambler_out <= ???
20
 end if;
21
end process;
22
23
process(CLK) -- CLK: CPLD-Clock zum Abtasten:
24
begin
25
 if rising_edge(CLK) then    -- getaktet
26
   -- descramber hier
27
    descrambler_out <= ???
28
 end if;
29
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

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


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 ;-)

von Geo (Gast)


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:
1
process(CLK) -- CLK: CPLD-Clock zum Abtasten:
2
begin
3
 if rising_edge(CLK) then    -- getaktet
4
   clock1 <= clock;
5
   clock2 <= clock1;
6
   ...
7
   clock5 <= clock4;
8
    if clock5 = '0' and clock4 = '1' -- steigende Flanke um 4 Takte
9
                                     --verzögert
10
    -- scramber hier
11
    end if;
12
 end if;
13
  scrambler_out <= scrambler_ergebnis
14
  clock_out <= clock
15
end process;
16
17
process(CLK) -- CLK: CPLD-Clock zum Abtasten:
18
begin
19
 if rising_edge(CLK) then    -- getaktet
20
   clock1 <= clock;
21
   clock2 <= clock1;
22
   ...
23
   clock5 <= clock4;
24
    if clock5 = '1' and clock4= '0' -- steigende Flanke um 5 Takte
25
                                    --verzögert
26
     -- descramber hier
27
     descrambler_out <= descrambler_ergebnis
28
    end if;
29
 end if;
30
clock_out <= clock
31
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.

von Falk B. (falk)


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

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


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:
1
:
2
process(CLK) -- CLK: CPLD-Clock zum Abtasten:
3
begin
4
 if rising_edge(CLK) then    -- getaktet
5
   clock1 <= clock;
6
   clock2 <= clock1;
7
   ...
8
   clock5 <= clock4;
9
    if clock5 = '0' and clock4 = '1' -- steigende Flanke um 4 Takte
10
                                     --verzögert
11
    -- scramber hier
12
    end if;
13
 end if;
14
end process;
15
:
16
:
17
scrambler_out <= scrambler_ergebnis;
18
clock_out <= clock;
19
:

von Geo (Gast)


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:
1
scrambler_out <= scrambler_ergebnis;
2
   end if;
3
 end if;
4
end process;...
5
6
bzw.
7
8
--schrambler
9
   end if;
10
 end if;
11
(hier vor end process)scrambler_out <= scrambler_ergebnis;
12
end process;
13
(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.

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


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:
1
process(CLK,datain,clockin) -- CLK: CPLD-Clock zum Abtasten:
2
begin
3
 case switch is
4
   when "00" => --BUFFER
5
      dataout <= datain;
6
      clockout <= clockin;
7
   when "01" => --SCRAMBLER
8
    if(rising_edge(CLK)) then
9
    :
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.

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.