Hallo zusammen,
ich möchte selber einen differentiellen Manchester Encoder / Decoder in
VHDL schreiben. Ich weiss, wie der differentielle Manchester Code
funktioniert, aber irgendwie fehlt es mir jetzt grade an einem Ansatz,
dies in VHDL umzumünzen :-( kann mir einer ein wenig auf die Sprünge
helfen?
zumindest der Codierer ist doch eigentlich total einfach:
- wenn eine 1 kommt, den nicht invertierten Takt raus geben.
- wenn nochmal eine 1 kommt, den invertierten Takt raus geben.
- wenn eine 0 kommt, das selbe raus geben wie vorher.
Stimmt doch oder? Das klingt irgendwie einfach, aber hier:
http://electronicsinourhands.blogspot.ch/2012/10/manchester-encoder.html
wird (allerdings für einfachen Manchestercode) mit einem
Zustandsautomaten gearbeitet, ich erkenne aber nicht wieso :-(
Dann noch der Decoder, irgendwie kann ich ja noch eine Taktrückgewinnung
machen aus dem Manchester-Datenstrom... nur wie jetzt genau? hier fehlt
mir der Ansatz komplett.
Ich hoffe ihr könnt mir ein paar Tipps geben :-)
Gruss
Tobias schrieb:> aber irgendwie fehlt es mir jetzt grade an einem Ansatz, dies in VHDL> umzumünzen
Wie würdest du den Coder mit Hardwarebausteinen aufbauen? Wenn du das
kannst, dann ist es leicht, diese Hardware mit VHDL zu beschreiben
(daher kommt der Begriff Hardwarebeschreibungssprache).
Tobias schrieb:> wird mit einem Zustandsautomaten gearbeitet, ich erkenne aber nicht wieso
Weil du dir den vorherigen Zustand merken musst. Du selber schreibst
ja:
> - wenn eine 1 kommt ...> - wenn nochmal eine 1 kommt
Und um etwas zu "Merken" und auf ein "Vorher" reagieren zu können, ist
ein Zustandsautomat (in welcher Form auch immer) nötig.
Das RC-5 Fernbedienungsprotokoll ist auch Manchestercodiert:
http://www.lothar-miller.de/s9y/categories/50-RC-5
Hi Lothar,
also gewöhnliche Manchestercodierung ist einfach, da dürfte wohl ein XOR
genügen, ja? aber in dem Link den ich noch gepostet habe, wird das
wesentlich komplizierter gemacht, und ich verstehe nicht warum. Er
benötigt da 5 verschiedene Zustände!
Wie sieht es denn beim Decoder aus, wie macht man es "richtig" ?
nehmen wir an ich möchte mit einem 50 MHz Clock arbeiten, dann kann ich
mit einem gewöhnlichen FPGA wohl nicht "einfach so" eine klassische
Flankendetektion machen mit
if input_old = '0' and input_new = '1' then
...
end if;
oder? jetzt mal gesetzt den Fall dass mein FPGA auch nur 50..100 MHz
Clock hat. Ich bin noch ein wenig verwirrt :-)
Gruss:
Tobias
Tobias schrieb:> Wie sieht es denn beim Decoder aus, wie macht man es "richtig" ?
Man sieht nach, ob in einem "Erwartungsfenster" eine Flanke kommt...
Tobias schrieb:> nehmen wir an ich möchte mit einem 50 MHz Clock arbeiten
Also als "Manchestertakt"...
> mal gesetzt den Fall dass mein FPGA auch nur 50..100 MHz Clock hat.
Dann wird das nichts mit der Taktrückgewinnung ohne externe Bausteine.
Denn der von mir verlinkte RC5 Decoder macht diese Aufsynchronisierung
ja durch Überabtastung.
Aber prinzipiell ist es immer so, dass du nAch jeder Flanke ein (oder
zwei) Fenster definierst, in denen was passieren muss. Und abhängig
davon, was
Tobias schrieb:> also gewöhnliche Manchestercodierung ist einfach, da dürfte wohl ein XOR> genügen, ja?
Jein.
Ja, weil es tatsächlich so aussieht.
Und nein, weil in einem FPGA wird nichts mit einem Takt logisch
verknüpft wird...
> aber in dem Link den ich noch gepostet habe, wird das wesentlich> komplizierter gemacht, und ich verstehe nicht warum. Er benötigt da 5> verschiedene Zustände!
Eigentlich nur 4 Zustände (und damit 2 FFs), denn der "Z"-Zustand ist
ein Ausnahmezustand und "Kür"...
Aber dafür ist eben nicht mehr der Takt direkt mit dem Ausgangssignal
kombinatorisch verknüpft. Und wenn du das mit deiner Art auch so machen
willst, dann brauchst du 1 FF zum Speichern des vorherigen Wertes und 1
FF zum Takten des Ausgangssignals. Und schon hast du gleich viele
Ressourcen verbraucht...
Hi Lothar,
danke für die Ausführungen. Das heisst also, dass ich meinen
Manchesterencoder eigentlich mit mehr als 50 MHz laufen lassen muss
(z.B. 100 MHz) und dann in dem Zustandsautomaten wirklich die Bits
einzeln erzeuge, ohne mit dem Takt zu verXORen ja?
Tobias schrieb:> ohne mit dem Takt zu verXORen ja?
Erst mal ja. Du könntest allerdings noch was mit DDR-FFs tricksen, die
mit jeder steigenden 50MHz Flanke geladen werden, und dann mit der
"fallenden" Flanke den jeweils anderen Wert ausgeben. Das wäre auch ein
sauberes kalkulierbares Design...
Was willst du denn mit 50MHz biphase codieren?
Ich habe nichts bestimmtes vor, ich will nur als Übung mal eine solche
Übertragungsstrecke bauen zwischen zwei FPGA Evalboards. Der eine FPGA
soll einen Datenstrom mit differentieller Manchestercodierung senden,
dann will ich es über ein Kabel leiten und am zweiten FPGA-Board
empfangen. Dann die Adern vertauschen und sich freuen, dass immer noch
die richtigen Bits empfangen werden ;-) Es ist also ein reines
Bastelprojekt. 50 MHz war einfach mal ein Wert, weil ich einen solchen
Quarz auf dem Board habe. Man könnte auch 10 MHz oder wasauchimmer
nehmen, das ist im Prinzip wurst....
Ich bin mir grade nochmals am Aufzeichnen als Timing Diagram, wie die
Signale ausschauen sollen. Ich teile einfach den FPGA-Clock durch 2,
also 50/2=25 MHz, dann ist mein "Manchesterclock" halt 25 MHz, und mit
diesem Signal darf ich dann was logisch verknüpfen, oder? das wäre dann
im Prinzip so eine Art "Datenclock" oder wie man es auch immer nennen
möchte...
Hi Lothar, ich nochmal :-)
bin mir grade einen Zustandsautomaten am überlegen für den Coder.
Kann es sein, dass es recht aufwendig wird? meiner hat jetzt 8 Zustände.
Man muss eigentlich drei Dinge wissen:
- was für ein Bit habe ich zuletzt ausgegeben, 0 oder 1
- was für ein Bit soll ich jetzt ausgeben, 0 oder 1
- welche Flanken soll ich ausgeben, fallend oder steigend
und dann gibt es eigentlich 8 Zustände:
vorher 0, jetzt 0, fallend
vorher 0, jetzt 0, steigend
vorher 0, jetzt 1, fallend
vorher 0, jetzt 1, steigend
vorher 1, jetzt 1, fallend
vorher 1, jetzt 1, steigend
vorher 1, jetzt 0, fallend
vorher 1, jetzt 0, steigend
richtig? und diese 8 Zustände kann man dann in einen Automaten
verbasteln... irgendwie.
allerdings kämpfe ich grade noch sehr mit ModelSim. Es sieht manchmal so
aus, als ob es funtionieren würde, aber irgendwie doch nicht so
richtig... Was mache ich falsch? wo in dem obigen Code liegt meine
fehlüberlegung.
Gruss
Reicht die Sensitivity-Liste des Prozesses zum Simulieren?
Ich hatte damit letzens auch Probleme, dass ich ein paar Signale
vergessen hatte. (Für die Synthese war es ja egal)
Tobias schrieb:> Es sieht manchmal so aus, als ob es funtionieren würde, aber irgendwie> doch nicht so richtig... Was mache ich falsch?
Ich tippe auf einen Takt Latency. Woher kommt das Datenbit? Wann
wechselt das? Kannst du mal den Screenshot einer Waveform posten?
PittyJ schrieb:> Reicht die Sensitivity-Liste des Prozesses zum Simulieren?
Ja, da ist alles drin: reset und clk
Hallo Lothar,
ohje, dass ich das so vereinfacht schreiben könnte, darauf bin ich nicht
gekommen :-)
Das mit dem einen Takt latency könnte stimmen. Ich kann es jetzt grad
nicht anschauen, ich brauche jeweils circa 30 Minuten, bis ich Modelsim
gestartet habe und wieder herausgefunden habe, wie man es bedient. (Ich
benutze Altera Quartus II, dort ist jetzt nur noch Modelsim zum
Simulieren vorhanden, früher ging es noch etwas einfacher mit dem Vector
Waveform Simulator oder wie der hiess).
Gruss Tobias
Tobias schrieb:> Ich kann es jetzt grad> nicht anschauen, ich brauche jeweils circa 30 Minuten, bis ich Modelsim> gestartet habe und wieder herausgefunden habe, wie man es bedient.
Modelsim startet man (imho) am besten mit einer .do Datei, also z.B.:
1
vsim -do tb_xyz.do
wobei tb_xyz.vhd eben auch der Name deiner Testbench ist. In der
tb_xyz.do wuerde z.B. stehen:
1
# Kompilate landen im Subdirectory 'work'
2
vlib work
3
# Wir wollen 'work' fuer die Simulation verwenden
4
vmap work work
5
#
6
# Wir kompilieren alle Teile des Designs
7
vcom -explicit -93 "xyz.vhd"
8
vcom -explicit -93 "tb_xyz.vhd"
9
#
10
# Wir laden den gewuenschten Design in den Simulator
11
vsim -lib work tb_xyz
12
#
13
# evtl hier noch die gewuenschten Signale anzeigen lassen oder
14
# eine 'wave.do' im Simulator abspeichern
15
#
16
# run -all wuerde die Simulation laufen lassen (bis Ende/keine Clock)
17
#run -all
Deine Testbench musst du halt schreiben. Dafuer ist's dann immer wieder
das gleiche um die Simulation zu starten...
Hmm geht das auch wenn Modelsim mit Quartus zusammen installiert wurde?
Irgendwie kann ich das gar nicht aufrufen aus einer Shell heraus,
sondern ich kann es nur starten indem ich in Quartus ein Projekt öffne
und dann "RTL Simulation" anklicke. Was mahce ich falsch? :-/
Tobias schrieb:> Hmm geht das auch wenn Modelsim mit Quartus zusammen installiert wurde?> Irgendwie kann ich das gar nicht aufrufen aus einer Shell heraus,> sondern ich kann es nur starten indem ich in Quartus ein Projekt öffne> und dann "RTL Simulation" anklicke. Was mahce ich falsch? :-/
evtl. fehlende Pfadangabe? "Damals" mit ModelSimXE (Xilinx) und "heute"
mit ModelSimPE funktioniert das bei mir genau so. Mit Altera und deren
verkrueppeltem ModelSim habe ich aber noch nix zu tun gehabt...
Hast du die o.g. Programme (vlib, vmap, vcom, vsim) bei dir auf der
Platte liegen?
In der Zwischenzeit habe ich rausgefunden wie es geht :-)
Hatte einen Pfad falsch angegeben. Jetzt läuft es!
Was allerdings nicht geht:
dun -all lässt ihn unendlich lange simulieren....
habe mal als einfachen Test folgendes in VHDL geschrieben:
-- list connections between master ports and signals
25
clk=>clk,
26
a=>a,
27
b=>b,
28
c=>c
29
);
30
init:PROCESS
31
-- variable declarations
32
BEGIN
33
clk<='0';
34
waitfor10ns;
35
clk<='1';
36
waitfor10ns;
37
ENDPROCESSinit;
38
39
40
always:PROCESS
41
-- optional sensitivity list
42
-- ( )
43
-- variable declarations
44
BEGIN
45
46
a<='0';
47
b<='0';
48
waitfor100ns;
49
50
a<='0';
51
b<='1';
52
waitfor100ns;
53
54
a<='1';
55
b<='1';
56
waitfor100ns;
57
58
a<='1';
59
b<='0';
60
waitfor100ns;
61
62
WAIT;
63
ENDPROCESSalways;
64
ENDgatetest_arch;
und das sim file:
1
# Kompilate landen im Subdirectory 'work'
2
vlib work
3
# Wir wollen 'work' fuer die Simulation verwenden
4
vmap work work
5
#
6
# Wir kompilieren alle Teile des Designs
7
vcom -explicit -93 "gatetest.vhd"
8
vcom -explicit -93 "tb_gatetest.vhd"
9
#
10
# Wir laden den gewuenschten Design in den Simulator
11
vsim -lib work gatetest_vhd_tst
12
#
13
# evtl hier noch die gewuenschten Signale anzeigen lassen oder
14
# eine 'wave.do' im Simulator abspeichern
15
#
16
# run -all wuerde die Simulation laufen lassen (bis Ende/keine Clock)
17
#run -all
18
19
add wave -position insertpoint \
20
sim:/gatetest_vhd_tst/a \
21
sim:/gatetest_vhd_tst/b \
22
sim:/gatetest_vhd_tst/c \
23
sim:/gatetest_vhd_tst/clk
mit run -all simuliert er einfach bis zum geht nicht mehr, obwohl die
Signale schon lange sich nicht mehr ändern aufgrund des wait Statement.
Aber der clock clockt natürlich noch immer, weiss nicht obs da dran
liegt...
berndl schrieb:> Du musst also in der TB explizit alle Takte stoppen. Dann haelt auch der> Simulator automatisch an...
Oder du kippst was in dieser Art an geeigneter Stelle rein:
1
assertfalse
2
report" ===== Verification run 'TESTBENCH' finished ====="
3
severityfailure;
Dann ist es egal, wenn irgendwo noch ein Clock aktiv sein sollte.