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
caseswitchis
4
when"00"=>--BUFFER
5
dataout<=datain;
6
clockout<=clockin;
7
when"01"=>--SCRAMBLER
8
if(rising_edge(CLK))then
9
...
10
whenothers=>--DESCRAMBLER
11
if(rising_edge(CLK))then
12
...
13
endcase;
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
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:
@ 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
caseswitchis
4
when"00"=>--BUFFER
5
dataout<=datain;
6
clockout<=clockin;
7
when"01"=>--SCRAMBLER
8
dataout<=scramberl_out;
9
clockout<=clockin;
10
whenothers=>--DESCRAMBLER
11
dataout<=descramberl_out;
12
clockout<=clockin;
13
endcase;
14
15
process(CLK)-- CLK: CPLD-Clock zum Abtasten:
16
begin
17
ifrising_edge(CLK)then-- getaktet
18
-- scramber hier
19
scrambler_out<=???
20
endif;
21
endprocess;
22
23
process(CLK)-- CLK: CPLD-Clock zum Abtasten:
24
begin
25
ifrising_edge(CLK)then-- getaktet
26
-- descramber hier
27
descrambler_out<=???
28
endif;
29
endprocess;
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
> 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 ;-)
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
ifrising_edge(CLK)then-- getaktet
4
clock1<=clock;
5
clock2<=clock1;
6
...
7
clock5<=clock4;
8
ifclock5='0'andclock4='1'-- steigende Flanke um 4 Takte
9
--verzögert
10
-- scramber hier
11
endif;
12
endif;
13
scrambler_out<=scrambler_ergebnis
14
clock_out<=clock
15
endprocess;
16
17
process(CLK)-- CLK: CPLD-Clock zum Abtasten:
18
begin
19
ifrising_edge(CLK)then-- getaktet
20
clock1<=clock;
21
clock2<=clock1;
22
...
23
clock5<=clock4;
24
ifclock5='1'andclock4='0'-- steigende Flanke um 5 Takte
25
--verzögert
26
-- descramber hier
27
descrambler_out<=descrambler_ergebnis
28
endif;
29
endif;
30
clock_out<=clock
31
endprocess;
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.
@ 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
> 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
ifrising_edge(CLK)then-- getaktet
5
clock1<=clock;
6
clock2<=clock1;
7
...
8
clock5<=clock4;
9
ifclock5='0'andclock4='1'-- steigende Flanke um 4 Takte
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:
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.
> 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
caseswitchis
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.