Hi,
ich schreibe grade an einer VDHL für einen FPGA und bin auf folgendes
Problem gestossen:
Ich habe einen längeren Vektor mit 1 und 0 und will diesen über einen
Ausgang ausgeben. Die Ziffern müssen also mit einem bestimmten
Zeitabstand hintereinander ausgegeben werden. Wie kann ich dies
realisieren (wait-Anweisung?).
Danke schonmal für die Antworten.
Gruß Martin
ich würd über nen zähler, der aufgrund des bekannten taktes eine
definierte zeit zählt, ein enable erzeugen womit dann nach und nach 1
bit aus deinem vektor dem ausgang übergeben wird.
> Wie kann ich dies realisieren (wait-Anweisung?).
In der Simulation: Ja.
In einer realen Hardware: Nein.
> Ich habe einen längeren Vektor...
Wie lang? Welche Zielplattform hast du? Hersteller?
Was du brauchst, ist ein Zähler (für die Zeit zwischen zwei Bits) und
ein Schieberegister.
Das lässt sich in 20 Zeilen VHDL-Code beschreiben ;-)
> Der Vektor ist etwa 550 Ziffern lang.
Was ist das für ein Monstervektor.... :-o
From the Scratch:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.NUMERIC_STD.ALL;
4
5
entityPar2Seris
6
Port(clk:inSTD_LOGIC;-- z.B. 10MHz
7
serout:outSTD_LOGIC;
8
frame:outSTD_LOGIC;-- '1' solange Daten übertragen werden
9
load:inSTD_LOGIC;-- Bitvektor laden
10
parin:inSTD_LOGIC_VECTOR(549downto0));
11
endPar2Ser;
12
13
architectureBehavioralofPar2Seris
14
signaldelaycnt:integerrange0to9999;-- 1ms/Bit
15
signalbitcnt:integerrange0to550;
16
signalbits:STD_LOGIC_VECTOR(549downto0);
17
begin
18
processbegin
19
waituntilrising_edge(clk);
20
if(load='1')then
21
delaycnt<=0;-- Bitdelay zurücksetzen
22
bitcnt<=550;-- 550 Bits sind zu übertragen
23
bits<=parin;-- Daten zur internen Verarbeitung übernehmen
24
else
25
if(delaycnt/=9999)then-- 1 ms vorbei?
26
delaycnt<=delaycnt+1;-- nein: weiterzählen
27
else
28
if(bitcnt/=0)then-- sind noch Bits übrig?
29
delaycnt<=0;-- ja: Bitdelay zurücksetzen
30
bits<='0'&bits(550downto1);-- das Schieberegister eins weiterschieben
31
bitcnt<=bitcnt-1;
32
endif;
33
endif;
34
endif;
35
endprocess;
36
serout<=bits(0);
37
frame<='1'whenbitcnt/=0else'0';
38
endBehavioral;
Mangels besser definierter Rahmenbedingungen soll gelten:
- 10MHz FPGA Takt
- ein Lade-Signal zur Übernahme des Vektors (load)
- das load-Signal soll nur für 1 Taktzyklus aktiv sein
(sonst müsste die Handhabung des frame-Signals überarbeitet werden)
- ein Frame-Signal, das die Übertragung umrahmt (frame)
- jede ms wird ein Bit ausgegeben
- die Daten werden mit dem LSB voran ausgegeben.
Und ja, ich gebs zu, wegen der unklaren Aufgabenstellung sinds etwas
mehr geworden als 20 Zeilen ;-)
BTW:
Ich möchte ohne weitere Synchronisationsmaßnahmen keinen 550 Bit Vektor
empfangen müssen. Wehe, die Quarzfrequenz weicht nur einen Hauch ab...
Normalerweise wird da (wie bei SPI) ein Takt pro Bit mitgegeben, oder
ein Bit-Stuff-Mechanismus eingeführt (wie bei CAN), damit sich der
Empfänger wieder aufsynchronisieren kann.
Oder (jenachdem wie hoch die Datenrate sein muss und wer empfängt)
einfach das Bit 3 Takte lang senden mit Start und Stoppbit dann sollte
auch das syncen nicht mehr so tragisch sein.
> Bit 3 Takte lang senden mit Start und Stoppbit dann sollte> auch das syncen nicht mehr so tragisch sein.
Rechne das mal durch mit Start-Bit, dann 550 Datenbits mit
1
bits<='1'&(548downto1=>'0')&'1';-- nur das erste und letzte Bit ist gesetzt
und dann einem Stoppbit. Wann wird hier bei 100ppm-Quarzen bei Sender
und Epmfänger die Synchronisation verloren sein? Wirst du das letzte Bit
und das Stop-Bit immer korrekt zuordnen können? Wie machst du das mit
dem Einsynchronisieren beim Empfänger?
Nein, da muss ganz einfach eine Art von Synchronisation her. Am
einfachsten wäre es, das Ganze mit einem begleitenden Takt zu
übertragen:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.NUMERIC_STD.ALL;
4
5
entityPar2Seris
6
Port(clk:inSTD_LOGIC;-- z.B. 10MHz
7
serout:outSTD_LOGIC;
8
frame:outSTD_LOGIC;-- '1' solange Daten übertragen werden
bits<=parin;-- Daten zur internen Verarbeitung übernehmen
25
else
26
if(bitcnt/=0)then-- sind noch Bits übrig?
27
if(phase='1')then
28
bits<='0'&bits(549downto1);-- das Schieberegister eins weiterschieben
29
bitcnt<=bitcnt-1;
30
endif;
31
phase<=notphase;
32
endif;
33
endif;
34
endprocess;
35
serout<=bits(0);
36
frame<='1'whenbitcnt/=0else'0';
37
sclk<=phase;
38
endBehavioral;
Hier die Stimuli der Testbench
1
clk<=notclkafter50ns;
2
3
tb:PROCESSBEGIN
4
waitfor270ns;
5
parin<='1'&(548downto1=>'0')&'1';
6
parin<=(others=>'0');
7
parin(0)<='1';
8
parin(5)<='1';
9
parin(9)<='1';
10
parin(15)<='1';
11
load<='1';
12
waitfor320ns;
13
load<='0';
14
wait;-- will wait forever
15
ENDPROCESS;
und im Anhang (Screenshot) die ersten paar Bits der Übertragung.
Wenn das Frame-Signal jetzt noch invertiert wird, haben wir ein
lupenreines SPI-Protokoll...
Lothar Miller schrieb:
>> Bit 3 Takte lang senden mit Start und Stoppbit dann sollte>> auch das syncen nicht mehr so tragisch sein.> Rechne das mal durch mit Start-Bit, dann 550 Datenbits mit>
1
bits<='1'&(548downto1=>'0')&'1';-- nur das erste und letzte Bit
2
>istgesetzt
und dann einem Stoppbit. Wann wird hier bei
> 100ppm-Quarzen bei Sender und Epmfänger die Synchronisation verloren> sein? Wirst du das letzte Bit und das Stop-Bit immer korrekt zuordnen> können? Wie machst du das mit dem Einsynchronisieren beim Empfänger?>
Mit 550 Bit hab ichs nicht durchgerechnet aber beim PCI-Bus mit 33 MHz
zur Uebertragung von 8 bit Woertern mit 2 Bitseriellenkarten von einem
PC zum anderen klappt das. Muesste ich jetzt die Formel rauskramen evtl
muss man dann halt 4 oder 5 Takte uebertragen.
Start-Bit = 1 und Stopp-Bit = 0 dann erkennt man zum Synchronisieren
dass sobald eine positive Flanke auf der Leitung ist dass eine
Uebertragung beginnt. Wenn nichts uebertragen wird liegt eben 0 an.
Ich habe deine Antwort nicht ganz verstanden, aber
> ein PCI-Bus mit 33 MHz
ist absolut synchron, und bei der
> Uebertragung von 8 bit Woertern mit 2 Bitseriellenkarten
wird nach jedem Byte neu synchronisiert
(Startbit + 8 Datenbits + Stopbit).
Alle Protokolle, die ich kenne, die nur auf 1 Datenleitung aufgebaut
sind, geben auf dieser Datenleitung implizit auch den Takt mit (CAN,
Sercos, Ethernet...) damit sich der Empfänger an den Sender
aufsynchronisieren kann.
Hi,
ich programmiere auch grade an einem ähnlichen Code.
Mich würde mal die Zeile interessieren:
1
processbegin
2
waituntilrising_edge(clk)
Dies bedeutet ja, dass ich auf eine steigende Flanke von clk warte. Das
clk ist doch intern in meinem FPGA mit einer festen Frequenz drin oder?
Also kann ich es dann dem entsprechnden Pin zuweisen. Es wäre aber somit
kein in bit, weil ich es nicht von außen anlege.
Ist dies so oder hab ich da was flasch verstanden. Sorry für die Frage,
bin aber noch Anfänger was das programiieren angeht.
Grüße
> Das clk ist doch intern im FPGA mit einer festen Frequenz drin oder?
Der Takt ist genau mit der Frequenz drin, die du von Aussen am
entsprechenden Clock-Pin eingibst. In der Regel ist das ein externer
Takt von 30-100MHz, auf den (im Idealfall) alle Prozesse im FPGA
sensitiv sind.
So ist es (besonders für Anfänger) am einfachsten, wirklich synchrone
und damit definierte Designs zu machen. Später kommt dann schon mal der
eine oder andere Takt dazu.
> bin aber noch Anfänger was das programiieren angeht.
Wie gesagt, sorg dafür, dass in jedem getakteten Prozess der gleiche
Takt drin steht. Ob das jetzt mit der traditionellen
Lehrbuch-Schreibweise
1
process(clk)begin
2
ifrising_edge(clk)then
3
if(reset='1')then-- Reset synchron
4
:
5
else-- die eigentliche Arbeit
6
:
7
endif;
8
endif;
9
endprocess;
oder mit der Schreibweise, die keine Sensitivity-Liste braucht
1
processbegin
2
waituntilrising_edge(clk);
3
if(reset='1')then-- Reset synchron
4
:
5
else-- die eigentliche Arbeit
6
:
7
endif;
8
endprocess;
das ist egal, aber so bekommst du auf jeden Fall definierte Laufzeiten
und prüfbare Designs hin.
Schlimm wird es, wenn in deinem FPGA-Design z.B. sowas steht:
1
ifrising_edge(Taster)then...
2
3
iffalling_edge(ChipSelect)then...
4
5
ifrising_edge(PS2CLK)then...
6
7
ifrising_edge(clk)then...
Lauter verschiedene Takte in einem (1) Design, das kann nur schiefgehen.
Und das Blöde daran ist, dass die daraus resultierenden Fehler nur
manchmal auftreten, mal ganz selten, dann wieder öfter....
Ok Vielen Dank für die Antwort
Ich schreibe an einem Programm,an einem Test-Sender für die digitale
Übertragung des Mehrfrequenzwahlverfahren.
Ich habe dieses mal angehängt.
x: 4bit Eingangsvector um die Taste zu wählen
y: 260bit Vector in dem die einzelnen Bits (0,1) drin stehen, welche
nacheinander ausgegben werden sollen.
Sie sollen mit einem Abstand von 0.125 ms hintereiander ausgeben werden,
die Frequenz des FPGAs beträgt 50 Mhz.
In dem Programm hab ich den Teil von oben einfach übernommen. Ich habe
es dann mit dem FPGA in einem Digilabor getestet und wollte das Ergebins
auf einem Oszi ausgeben, leider hat dies nicht funtioniert.
Wo liegt den der Fehler? Kann es an dem zweiten clk liegen?
Grüße
> Kann es an dem zweiten clk liegen?
In diesem Fall eher nicht, aber der clk ist unnötig. du braichst nicht
erst den Vektor x eintakten, sondern du könntest den select gleich auf
dem x machen.
> die Frequenz des FPGAs beträgt 50 Mhz.
Welche Frequenz? clk oder clk2?
> Sie sollen mit einem Abstand von 0.125 ms hintereiander ausgeben werden,> die Frequenz des FPGAs beträgt 50 Mhz.
Dann solltest du mit dem Zähler 0.125ms/20ns = 6250 Takte zählen (und
den Kommentar mit der 1ms/Bit löschen). Wie kommst du eigentlich auf
6144 (das sind 122,8us)?
> leider hat dies nicht funtioniert.
Bei mir gehts (in der Simulation mit der angehängten Source) ;-)
Stimmt bei dir alles mit den Takten, Pinzuordnung....
Die Testbench ist eigentlich nur eine Stimuli mit dem Takt:
1
LIBRARYieee;
2
USEieee.std_logic_1164.ALL;
3
USEieee.numeric_std.ALL;
4
5
ENTITYtb_MFW_vhdIS
6
ENDtb_MFW_vhd;
7
8
ARCHITECTUREbehaviorOFtb_MFW_vhdIS
9
10
-- Component Declaration for the Unit Under Test (UUT)
BTW:
>>> x: in bit_vector(1 to 4);
Diese Schreibweise ist unüblich und bringt früher oder später Probleme.
Mach daraus einen "normalen" 4-Bit Vektor vom Typ std_logic mit dem MSB
links. Sowas also std_logic_vector(3 downto 0);
Vergiss die ganzen bit und bit_vector Definitionen und arbeite nur
mit std_logic (oder std_ulogic). Sonst klemmt es jedesmal an der
Schnittstelle, weil die ganze restliche Welt kein bit verwendet.
Danke für die Hilfe
Sorry muss mich korrigieren, es sind genau 49,152 Mhz, daher die 6144
Takte :-)
Der Ozillator im FPGA hat die Frequenz von 49,152 Mhz, dass giilt dann
laut Datneblatt für GCLK0 von dem FPGA.
Hirt könnte es sein, dass ich ihn damals flasch angeschlossen hatte.
Mit der Testbench kenn ich mich nicht aus.
Hab das ganze mit Modelsim simuliert, da hatte es funtioniert. Dann im
Labor mit dem FPGA aber nicht mehr.
Arbeite für die Aufgabe das erste mal mit vdhl-Code und mit einem FPGA,
fällt nicht leicht, da gleich den Überblick zu haben.
Grüße
> Arbeite für die Aufgabe das erste mal mit vdhl-Code und mit einem FPGA,> fällt nicht leicht, da gleich den Überblick zu haben.
Ja, das ist, wie wenn du das Autofahren gleich mit dem "Rückwärts
Einparken" beginnen würdest. So ein bisschen "Lauflicht mit
Tastenabfrage" usw. usf. ist anschaulicher und sollte vorher schon mal
gemacht werden...
> 49,152 Mhz, daher die 6144 Takte :-)
Rechne das mal mit /allen Nachkommastellen nochmal durch:
Ich komme auf 6140,625 :-o
Du darfst trotzdem nicht von 0 bis 6144 zählen, denn das sind 6145
Takte, also einer zuviel. Denn die 0 ist ja auch einen ganzen Takt lang
aktiv. Also müsstest du mit deiner Formel von 0 bis 6143, nach meiner
Berechnung eher von 0 bis 6139 (oder doch 6140 wegen der 0,625) zählen.
Am Ende hab ich im Labor auch noch mal was leichteres ausprobiert um den
FPGA zu testen.
Wenn ich es dirket in den Taschenrechner eingebe, kommt 6144 raus. Hab
es jetzt nochmal genauer gerechnet, kommt dann auch auf 6140,625.
Werde dann mal bis 6139 zählen. Falss es funtioniert, kann ich ja dann
im Oszi schauen, ob die 0.125 ms hinkommen.
Grüße
Anfänger schrieb:
> Wenn ich es dirket in den Taschenrechner eingebe, kommt 6144 raus. Hab> es jetzt nochmal genauer gerechnet, kommt dann auch auf 6140,625.
Diesen Taschenrechner würde ich wegwerfen.
Ähm grad eine Frage für verwirrte Dumme:
Sind das 50 MHz
Lothar Miller schrieb:
>> clk <= not clk after 10 ns;> Das sind 50 MHz, denn der Takt ist für 10ns low, dann für 10ns high.> In der Summe 20ns = 50MHz ;-)
Ich danke dir, mich hat das Quick Start Tutorial von Xilinx immer
verwirrt warum die Low und High 20ns Sekunden haben obwohl das Startan3
Eval Board nen 50MHz Oszi hat bis ich gerade gesehen habe dass deren
Design (bzw. Simulation) im QST auf 25MHz ausgelegt ist fuer das
Spartan-3 Demo Board mit 50MHz .,,. so ein Kack
Mein Gott manchmal dieses Brett vorm Kopf...