Hi,
da ich noch Anfängerin bin und mich Schritt für Schritt durch den VHDL
Jungle kämpfe, bin ich nun am Schieberegister angelangt. Ich habe mir
vorgenommen ein Schieberegister aufzubauen welches parallel zwei 8Bit
Zeichen einliest und anschließend diese Seriell ausgibt. Später will ich
diese 8 Bit Zeichen an meinem Nexys Board einlesen welche dann von
meinem µC kommen. Deshalb habe ich wie @Lothar Miller es beschrieben hat
den Enable und und Reset einsynchronisiert. Theoretisch müsste ich Load0
und Load1 auch einsynchronisieren, oder?
Das Einsynchroniseren habe ich versucht wie beschrieben umzusetzten,
weis aber nicht ob das so komplett passt wie ich das aufgefasst und
umgesetzt habe. Der Reset muss laut Ihm auch auf jedenfall
einsynchronisiert werden da dieser von einem Taster kommt und daher
komplett asynchron wäre.
Nun gut, es funktioniert auch eigentlich alles auch so halbwegs.
Probleme sind das mein Schieberegister die Werte einliest, aber diese
nicht ausgibt. Was habe ich falsch verstanden? Habe ein Bild von meiner
Simulation angehangen.
Auch habe ich bei meinen eingelesen werten einen Taktversatz. Ich lese
doch parallel ein, warum ist da ein Versatz drinnen?
Vicky M. schrieb:> (...)> process(clk) -- Schieberegister> beginviel zu viel asyncrones
> if (enablesync = '1') and (resetsr(0) = '0') then> sr <= load0;> elsif (enablesync = '0') and (resetsr(0) = '0') then> sr <= load1;> elsif (resetsr(0) = '1') then> sr <= "00000000";> elsif rising_edge(clk) then> sr <= sr (6 downto 0) & '0';> end if;> end process;
Probier es erstmals so:
1
process(clk)
2
ifrising_edge(clk)then
3
if(enablesync='1')and(resetsr(0)='0')then
4
sr<=load0;
5
elsif(enablesync='0')and(resetsr(0)='0')then
6
sr<=load1;
7
elsif(resetsr(0)='1')then
8
sr<="00000000";
9
else
10
sr<=sr(6downto0)&'0';
11
endif;
12
endif
13
endprocess;
AAAAber: >sr <= sr (6 downto 0) & '0';< kann rein logisch nie erreicht
werden!
> Theoretisch müsste ich Load0 und Load1 auch einsynchronisieren, oder?
Nein, da die zwei intern und konstant sind.
Erst einmal vielen Dank dir. Aber leider bleibt mein y Ausgang immer
noch auf Null.
Bernhard K. schrieb:> AAAAber: >sr <= sr (6 downto 0) & '0';< kann rein logisch nie erreicht> werden!
Das verstehe ich nicht ganz was du damit meinst?
mach einfach eine Tabelle:
wenn enablesync und resetsr(0) dann macht dein VHDL-code
1 0 sr <= load0
0 0 sr <= load1;
- (=egal) 1 sr <= "00000000";
Mit welchen Logikwerten kommt man nun
zu "sr <= sr (6 downto 0) & '0'" ??
Evtl mit einem zusätzlichen Steuersignal:
Wozu hat reset_sr eigentlich 2 Bits, wenn das zweite davon niemals
benutzt wird?
Vicky M. schrieb:> deshalb habe ich wie @Lothar Miller es beschrieben hat den Enable und und> Reset einsynchronisiert.
Das solltest du dir nochmal genauer ansehen und vor allem: versuchen zu
verstehen, warum da 2 Flipflops hintereinander kommen sollten...
> Der Reset muss laut Ihm auch auf jedenfall einsynchronisiert werden da> dieser von einem Taster kommt und daher komplett asynchron wäre.
Meine Worte sind: ein Reset ist unnötig, weil im echten Leben ein
Resettaster niemals gedrückt wird. Nur vermurkste Designs und Anfänger
brauchen sowas.
BTW: deine Simulation ist FALSCH, weil die Sensitivliste nicht
komplett ist. Da fehlen enablesync und reset_sr. Deshalb ist der
Screenshot auch teilweise so schön synchron zum fallenden(!!)
Taktflanke, obwohl die Signale asynchron sind...
Bernhard K. schrieb:> mach einfach eine Tabelle:> wenn enablesync und resetsr(0) dann macht dein VHDL-code> 1 0 sr <= load0> 0 0 sr <= load1;> - (=egal) 1 sr <= "00000000";>> Mit welchen Logikwerten kommt man nun> zu "sr <= sr (6 downto 0) & '0'" ??>> Evtl mit einem zusätzlichen Steuersignal:>
Ok, ich hoffe ich habe es verstanden. Ich glaube du möchtest mir damit
sagen das ich immer in den ersten drei if hängenbleibe und nie in die
else Bedingung komme. Somit wird nie der Befehl
1
sr<=sr(6downto0)&'0‘;
ausgeführt. Somit müsste das letzte else eigentlich ein elsif mit
Bedingung sein damit ich da rein komme.
Jo da stehe ich dann aber vor dem Problem was für eine Bedingung das
sein soll. Theoretisch ein writeout. Theoretisch könnte ich es auch
Taktgesteuert herausführen und aus der elsif herausnehmen sobal das
Schieberegister geladen ist?
1
2
process(clk,enablesync,resetsr)-- Schieberegister
3
begin
4
ifrising_edge(clk)then
5
if(enablesync='1')and(resetsr(0)='0')then
6
sr<=load0;
7
writeout<='1';
8
elsif(enablesync='0')and(resetsr(0)='0')then
9
sr<=load1;
10
writeout<='1';
11
elsif(resetsr(0)='1')then
12
sr<="00000000";
13
writeout<='1';
14
elsif(writeout='1')then
15
sr<=sr(6downto0)&'0';
16
writeout<='0';
17
endif;
18
endif;
19
endprocess;
20
21
y<=sr(0);
22
23
endBehavioral;
Nachtrag: Dieser Versuch führte auch nicht zum gewünschten Ziel. Ich
habe es wohl doch falsch verstanden.
Lothar M. schrieb:> Wozu hat reset_sr eigentlich 2 Bits, wenn das zweite davon niemals> benutzt wird?
Da muss ich ehrlich zugeben das ich es nicht vollständig verstanden
habe. Ich habe mich auch gewundert. Damit ich keine Fehler mehr bekommen
habe habe ich dann ein Bit ausgewählt.
Lothar M. schrieb:> BTW: deine Simulation ist FALSCH, weil die Sensitivliste nicht> komplett ist. Da fehlen enablesync und reset_sr. Deshalb ist der> Screenshot auch teilweise so schön synchron zum fallenden(!!)> Taktflanke, obwohl die Signale asynchron sind...
Habe die Sensitivliste vervollständigt.
Des Weiteren meinst du ich sollte den Reset heraus nehmen. Ich wusste
nicht das dieser besser weggelassen wird. Ich dachte das wenn mal ein
Fehler auftaucht das ein Reset gedrückt werden kann :D .
Vicky M. schrieb:
> (...)>Ich habe es wohl doch falsch verstanden.
ja, dennwie soll "sr <= sr (6 downto 0) & '0';" erreicht werden, ohne
neues Signal in den ersten if-abfragen ?
Ich meine etwa so:
1
process(clk)
2
-- Schieberegister
3
begin
4
ifrising_edge(clk)then-- -----> hier das neue Signal
Und lass den reset einfach erstmal drin, wenn dann das Beispiel geht
könntest du bei FPGAs den reset auch rauslassen, mach aber erst mal
den ersten Schritt mit reset!
Also so sehr ich es auch versuche und weitere Variablen einführe usw.
will der Ausgang einfach nichts ausgeben. So langsam glaube ich der
Hunde liegt noch wo anders begraben.
Ich habe auch diesen Betrag von Lothar Miller gefunden.
https://embdev.net/topic/348169
Ganz am Anfang meines Post habe ich es doch so ähnlich gemacht.
Sodelle ich habe nun nochmals alles aufgeräumt und getestet. Ich habe
ein Timingproblem! In meiner Testbench habe ich meine Zeiten und Enables
usw. nicht im Griff. Deshalb kommt beim Seriellen Ausgang nur Müll raus.
Wie gehe ich da am besten vor?
Ich habe 8Bit die Parallel zu Seriell gewandelt werden. das bedeutet, 8*
CLK ist die Zeit die das Schieberegister benötigt die Bits auszugeben
bevor neue hinein geladen werden dürfen. Stimmt das?
Jetzt muss ich schauen wie ich meine loadenable und shift richtig setze
damit es funktioniert. Aus Einfachheitsgründen habe ich den Reset mal
weggelassen.
Programm:
Vicky M. schrieb:> 8* CLK ist die Zeit die das Schieberegister benötigt die Bits> auszugeben bevor neue hinein geladen werden dürfen. Stimmt das?
Und zudem brauchst du noch mindestens 1 Taktzyklus zur Übernahme des
nächsten Datenworts.
BTW: das was du da machst wird bei SPI im Grunde auch gemacht...
Vicky M. schrieb:> Programm:
Dir sollte klar werden, dass du da nicht programmierst, denn sonst hieße
es ja VHPL.
Vicky M. schrieb:> In meiner Testbench habe ich meine Zeiten und Enables usw. nicht im> Griff. Deshalb kommt beim Seriellen Ausgang nur Müll raus.> Wie gehe ich da am besten vor?
Was macht nun diese Beschreibung mit dieser Testbench? Woher kommen im
"echten Leben" diese Signale? Wie sieht dort das zeitliche Verhalten
aus? Denn im besten Fall ist die Testbench eine Nachbildung der
Realität...
Lothar M. schrieb:> Vicky M. schrieb:>> 8* CLK ist die Zeit die das Schieberegister benötigt die Bits>> auszugeben bevor neue hinein geladen werden dürfen. Stimmt das?> Und zudem brauchst du noch mindestens 1 Taktzyklus zur Übernahme des> nächsten Datenworts.
Wenn ich dann aber meine parallel eingeschobene Bits seriell ausgeben
möchte, habe ich dann immer einen Takt Versatz von load0 zu load1. Das
macht mir ja meine serielle Bitkette kaputt?
> Vicky M. schrieb:>> In meiner Testbench habe ich meine Zeiten und Enables usw. nicht im>> Griff. Deshalb kommt beim Seriellen Ausgang nur Müll raus.>> Wie gehe ich da am besten vor?> Was macht nun diese Beschreibung mit dieser Testbench? Woher kommen im> "echten Leben" diese Signale? Wie sieht dort das zeitliche Verhalten> aus? Denn im besten Fall ist die Testbench eine Nachbildung der> Realität...
Projekt 1.)
Wie oben beschrieben ist es ein Eigenprojekt die ich mir ausgedacht habe
um ein besseres Verständnis für alles zu bekommen. Load0 und Load1 sind
noch Konstanten, welche ich aber später mit einem STM Board zu meinem
FPGA sende. Dort will ich diese einlesen und anschließend Parallel
Seriell Wandeln um eine schöne Bitkette zu bekommen.
Projekt 2.)
STM Board sendet die serielle Bitkette zum FPGA und soll diese Parallel
Wandeln um wieder Load0 und Load1 zu erkennen. Theoretisch versuche ich
eine sehr einfache Übertragung aufzubauen. Theoretisch das oben
rückwärts.
Aber zu aller erst muss es in der Simulation mit festen Werten
funktionieren, anschließend schau ich weiter wie es mit den externen
Signalen funktioniert. Somit muss ich mir jetzt eine Frequenz aussuchen
wo mit die 8Bit+ Taktversatz rein passt damit mein Ausgangssignal
vollständig abgebildet wird.
100MHz ist vom Nexys der Grundtakt. Das bedeutet ja das 10ns eine
Periode vom Takt ist. Dann brauche ich 90ns (8Bit+ Taktversatz) für
meine Bitkette (z.b. load0) aber nur beim ersten mal, oder? Wie verhält
sich es mit dem Taktversatz beim Wechsel von load0 zu load1?
Sollte ich andere, tiefere Frequenzen wählen? Theoretisch kann ich diese
ja später immer noch mit einem Zähler langsamer machen, oder? Wie macht
man das in der Paxis?
Vicky M. schrieb:> Wenn ich dann aber meine parallel eingeschobene Bits seriell ausgeben> möchte, habe ich dann immer einen Takt Versatz von load0 zu load1. Das> macht mir ja meine serielle Bitkette kaputt?
Ja nun, wenn du alle 8 Bits ein neues Wort einlesen und nahtlos
ausgeben willst, dann musst du da ein wenig mehr Gehirnschmalz
reinstekcne und praktisch schon am vorhergehenden Takt alles für Laden
vorbereiten. Es ist dann ja nichts zufällig, sondern es muss einfach
einen Takt früher passieren...
> Load0 und Load1 sind noch Konstanten, welche ich aber später mit einem> STM Board zu meinem FPGA sende. Dort will ich diese einlesen und> anschließend Parallel Seriell Wandeln um eine schöne Bitkette zu bekommen.
Wenn in deinem Bitstrom ausschließlich Datenbits kommen, wie kann sich
der Empfänger dann synchronisieren? SPI verwendet zum Synchronisieren
z.B. den SlaveSelect.
> Sollte ich andere, tiefere Frequenzen wählen?
Du solltest die Frequenz maximal so hoch wählen, dass du deine Daten
ausreichend schnell übertragen kannst. Wenn du die beiden 8 Bit Worte
100000 mal pro Sekunde übertragen musst (! Achtung: es zählt nur das,
was du musst, nicht das, was du willst), dann reichen dir 2 MHz Takt
locker aus.
> Theoretisch versuche ich eine sehr einfache Übertragung aufzubauen.
Praktisch wirst du sehen, dass dir da der angesprochene
Synchronisationsmechanismus fehlt. Denn wenn da nur 1 kleine Störung
auftritt und der Empfänger einen Taktimpuls doppelt oder gar nicht
erkennt, dann läuft deine gesamte Kommunikation von da an um 1 Bit
versetzt.
Lothar M. schrieb:> Vicky M. schrieb:>> Wenn ich dann aber meine parallel eingeschobene Bits seriell ausgeben>> möchte, habe ich dann immer einen Takt Versatz von load0 zu load1. Das>> macht mir ja meine serielle Bitkette kaputt?> Ja nun, wenn du alle 8 Bits ein neues Wort einlesen und nahtlos> ausgeben willst, dann musst du da ein wenig mehr Gehirnschmalz> reinstekcne und praktisch schon am vorhergehenden Takt alles für Laden> vorbereiten. Es ist dann ja nichts zufällig, sondern es muss einfach> einen Takt früher passieren...
Mach ich das mit einem Zähler? Sozusagen alles fängt an mit Zählerstand
10 außer das Laden das wird schon ab Takt 9 ausgeführt? Also benötigt
man hierfür zwei Zähler? Oder gibts eine einfachere Lösung?
Lothar M. schrieb:>> Theoretisch versuche ich eine sehr einfache Übertragung aufzubauen.> Praktisch wirst du sehen, dass dir da der angesprochene> Synchronisationsmechanismus fehlt. Denn wenn da nur 1 kleine Störung> auftritt und der Empfänger einen Taktimpuls doppelt oder gar nicht> erkennt, dann läuft deine gesamte Kommunikation von da an um 1 Bit> versetzt.
Also müsste ich ein weiteres load „load2" einführen mit fest definierten
Datenbits, welche immer an einer gewissen Stelle vorkommen. Und beim
Empfänger eine Biterkennung aufbauen. Theoretisch ein MUX der immer
schaltet wenn eine gewisse Folge anliegt.
Ziemlich komplex finde ich gerade. Gibts hier irgendwo ein Beispiel für
so etwas?
Vicky M. schrieb:> Also müsste ich ein weiteres load „load2" einführen mit fest definierten> Datenbits, welche immer an einer gewissen Stelle vorkommen. Und beim> Empfänger eine Biterkennung aufbauen. Theoretisch ein MUX der immer> schaltet wenn eine gewisse Folge anliegt.
Du musst noch weiter denken, denn wenn dieses
"Synchronisations-Bitmuster" zufällig mal durch andere Daten erzeugt
wird, dann machst du ebenfalls einen Resync. Denn mal angenommen, dein
Synchronisationspattern ist 01010101, dann sag mir mal, wo du bei dieser
Bitfolge neu aufsetzen würdest:
Ein Tipp: das sind tatsächlich immer die selben 3 Bytes, die
nacheinander gesendet werden. Und eines davon ist das "Sync-Byte"
01010101
Sag mir jetzt, welches die beiden anderen Bytes sind. Ich sage dir dann
hinterher, welche ich tatsächlich gesendet habe...
Aber wie schon erwähnt: das Rad ist bereits erfunden. Du kannst dir
einfach mal anschauen, wie andere das machen: RS232, SPI, Microwire,
usw. usf.
> Mach ich das mit einem Zähler? Sozusagen alles fängt an mit Zählerstand> 10 außer das Laden das wird schon ab Takt 9 ausgeführt? Also benötigt> man hierfür zwei Zähler? Oder gibts eine einfachere Lösung?
Ein Zähler reicht aus. Und den nimmst du dann gleich als Basis für einen
Multiplexer, der diese Bits auf den Ausgang durchschaltet...
Also bei einem Datenstrom übertrage ich viele bytes aber bei jedem byte
ist das letzte bit reserviert. Ist das das erste byte in einem Paket so
ist das bit 1 und bei allen weiteren bytes im Paket 0. also kostet zwar
Datenrate aber funktioniert super.
Gustl B. schrieb:> Ist das das erste byte in einem Paket so ist das bit 1 und bei allen> weiteren bytes im Paket 0. also kostet zwar Datenrate aber funktioniert> super.
Es funktioniert aber auch nur dann, wenn du weißt, welches das "erste"
Bit ist. Du brauchst also noch einen weiteren
Synchronisationsmechanismus, der anzeigt, wo denn so ein Datenwort
anfängt.
Bei der RS232 z.B. muss mindestens einmal eine Pause von mindestens
einem ganzen Byte eingelegt werden, sonst hast du ständig falsch
empfangene Bytes zusammen mit irgendwelchen Framing- oder
Parity-Fehlern...
Ach so, ja. Also ich habe das nur um Pakete aus mehreren Byte zu
erkennen. Übertragen wird das über UART oder parallel FIFO da ist immer
klar wo ein Byte anfängt und wo es endet.
Also ich verstehe nicht wieso hier nicht auch einfach UART oder so
genommen wird. Kann man ja schneller laufen lassen als Daten nachkommen
und hat so eitwas Pausezeiten dazwischen.