Hallo Leute
Sitze nun seit 3 Stunden am gleichen Code und schaffe es nicht, das
ganze korrekt zum laufen zu bringen.
Es handelt sich um einen PRN Generator. Genauer gesagt, ein
Schieberegister, der pseudozufällig '1' oder '0' rausspuckt. Der Code
ist ziemlich selbsterklärend.
Simulation und alles funktioniert problemlos, jedoch kommt immer nur der
gleiche Wert raus (lfsr_out = '0').
Code:
lfsr<=std_logic_vector(unsigned(lfsr)sll1);--shifting all bits to left by 1
78
lfsr_out<=lfsr(WIDTH-1);--MSB to output
79
lfsr<=lfsr(WIDTH-1downto1)&d0;--concatenate the feedback to the lfsr
80
else
81
lfsr<=(others=>'0');--reset state -> lfsr contains only '0'
82
lfsr_out<='0';
83
endif;
84
endprocess;
85
endarchitecture;
Wenn ich in der output_logic den lfsr_out <= '1' setze, kommt bei der
simulation immer 1 heraus. Die Testbench beginnt 1 clkzyklus lang mit
reset, danach ist reset 0 für 1024 Taktzyklen... Seht jemand grad den
Fehler?
Eren Y. schrieb:> Die Testbench beginnt 1 clkzyklus lang mit reset, danach ist reset 0 für> 1024 Taktzyklen... Seht jemand grad den Fehler?
Wie wäre es, wenn du die paar VHDL Dateien hier einfach mal anhängst?
Damit kann man sich leichter ein Projekt aufsetzen und ein Bild
machen...
BTW: Wenn deine Simulation schon läuft, dann musst du nur überlegen, was
du beim Schreiben der Zeilen gedacht hast, und kontrollieren ob genau
das passiert.
Ein Wort zum Verhalten von Signalen in Prozessen (und zum eigentlichen
Problem hier):
Eren Y. schrieb:
1
lfsr<=std_logic_vector(unsigned(lfsr)sll1);--shifting all bits to left by 1
2
lfsr_out<=lfsr(WIDTH-1);--MSB to output
3
lfsr<=lfsr(WIDTH-1downto1)&d0;--concatenate the feedback to the lfsr
lfsr behält seinen "alten" Wert während des gesamten Prozesses. Und am
Ende des Prozesses "gewinnt" die letzte Zuweisung. Also ist die erste
der obigen drei Zeilen wirkungslos, weil der in der ersten Zeile
zugewiesene Wert in der dritten Zeile wieder überschreiben wird.
BTW: zum Formatieren von VHDL-Code bitte die [vhdl] Tags verwenden.
BTW2:
Hierzu ein Wort:
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
Damit hast du doppelte Typdefinitionen und irgendwann sicher seltsame
Fehlermeldungen. Fazit: diese beiden niemals zusammen einbinden.
Siehe den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete"
Hallo Lothar
> BTW: zum Formatieren von VHDL-Code bitte die vhdl Tags verwenden.
Vielen Dank für das Bearbeiten meines Beitrages.
Lothar M. schrieb:> use ieee.std_logic_unsigned.all;> use ieee.numeric_std.all;> Damit hast du doppelte Typdefinitionen und irgendwann sicher seltsame> Fehlermeldungen. Fazit: diese beiden niemals zusammen einbinden.
Ich hatte Probleme mit "sll" in Vivado. Dieses Pkg hatte ich noch
eingefügt gehabt, da ich ungeduldig wurde. Aber war überflüssig ja,
danke!
Lothar M. schrieb:> Ein Wort zum Verhalten von Signalen in Prozessen (und zum eigentlichen> Problem hier):> lfsr behält seinen "alten" Wert während des gesamten Prozesses. Und am> Ende des Prozesses "gewinnt" die letzte Zuweisung. Also ist die erste> der obigen drei Zeilen wirkungslos, weil der in der ersten Zeile> zugewiesene Wert in der dritten Zeile wieder überschreiben wird.
Ich nehme an, zwei Zuweisungen des gleichen Signals sind in einem
Prozess also nicht zulässig, da man Hardware beschreibt und somit alles
gleichzeitig abläuft? Ich habe jetzt versucht dies zu korrigieren indem
ich die Shift-Left Anweisung und das Anhängen des Feedbacks in einem
letzten Schritt durchführe:
1
lfsr_out<=lfsr(WIDTH-1);--MSB to output
2
lfsr(WIDTH-1downto0)<=lfsr(WIDTH-2downto0)&d0;
Aber ich sehe keine Veränderung. Ich denke dass der Fehler irgendwo in
der Outputlogic liegt. Was passiert da zuerst, was danach? Der Inhalt
von lfsr bleibt doch nach dem process erhalten oder geht der wieder in
den Default-Zustand?
Eren Y. schrieb:> Ich denke dass der Fehler irgendwo in der Outputlogic liegt.
Wie kommst du darauf? Ändert sich der Wert des lfsr irgendwann? Nein?
den Grund habe ich genannt: das Verhalten von Signalen in Prozessen...
> Ich nehme an, zwei Zuweisungen des gleichen Signals sind in einem> Prozess also nicht zulässig, da man Hardware beschreibt und somit alles> gleichzeitig abläuft?
Genau andersrum: du kannst zigtausemal irgendwas an ein Signal zuweisen.
Das Signal ändert seinen Wert während des gesamten Prozesses nicht. Er
am Schluss des Prozesses (oder beim nächsten wait) übernimmt das signal
den zuletzt zugewiesenen Wert. Ein echt praktisches Verhalten, wenn
man sich dran gewöhnt hat. Mal angenommen, hier komme ich mit a=2 in den
Prozess:
1
signala:integer;
2
signalb:integer;
3
4
process(clk)begin
5
ifrising_edge(clk)begin
6
a<=5;-- a wird am Ende des Prozesses 5, behält aber vorerst den Wert 2
7
b<=a+1-- b wird am Ende des Prozesses 3, behält aber vorerst den Wert
8
a<=a+4;-- a wird am Ende des Prozesses 5, a bleibt aber vorerst 2
9
a<=b+3;-- a bleibt 2
10
a<=a+1;-- a bleibt 2
11
endif;
12
endprocess;-- jetzt "bekommt" a den zuletzut zugewiesenen Wert 3
Des Witz daran ist, dass ich bis auf die letzte Zeile alle vorigen
Zeilen ohne Funktionsänderung beliebig durcheinander mischen kann.
Und bei dir ist das die letzte Zuweisung:
lfsr <= lfsr(WIDTH - 1 downto 1) & d0;
Und nur die ist interessant. Also wird das lfsr laufend sich selber
zugewisen. nur das unterste Bit könnte mal 1 oder auch 0 sein.
Das hier ist übrigens eine kombinatorische Schleife, die du aber wegen
der unvollständigen Sensitivliste nicht bemerkst:
lfsr <= std_logic_vector(unsigned(lfsr) sll 1);
Denn ein LFSR muss getaktet sein. Und ein Takt ist immer ein
xxx_edge() oder ein 'event.
http://www.lothar-miller.de/s9y/archives/42-Kombinatorische-Schleifen.html
Mampf F. schrieb:> Für mich sieht es so aus, als würden Latche gebildet werden ...
Das ist das Problem der Zwei-Prozess-Schreibweise: der Takt wird dann
von Anfängern nur für die FSM verwendet, Zähler (oder hier das LFSR)
laufen ungetaktet als (versteckte) kombinatorische Schleife.
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html
Der Synthesizer meldet solche gegateten kombinatorischen Schleifen dann
gern als Latch.
Ich hol mal den Prozess mit der unvollständigen Sensitivliste extra raus
und kürze ihn etwas ein:
1
output_logic:process(present_state)
2
begin
3
if(present_state=state_go)then
4
caseWIDTHis--definitions for the feedback
5
when3=>d0<=lfsr(2)xnorlfsr(1);-- lfsr fehlt in der Sensitivliste, denn eine Änderung
6
when4=>d0<=lfsr(3)xnorlfsr(2);-- von lfsr müsste eine Neuberechnung des Prozesses anstoßen
7
...
8
whenothers=>null;
9
endcase;
10
lfsr<=std_logic_vector(unsigned(lfsr)sll1);-- wenn lfsr in der Sensitivliste steht, dann wird hier
11
-- bei jeder Änderung von lfsr ein neuer Wert für lfsr berechnet
12
-- und weil ein neuer Wert berechnet wird, ändert sich lfsr --> Endlosschleife
13
else
14
lfsr<=(others=>'0');--reset state -> lfsr contains only '0'
Lothar M. schrieb:> Ich hol mal den Prozess mit der unvollständigen Sensitivliste extra raus> und kürze ihn etwas ein
Deshalb hatte ich mir angwohnt, (nahezu) alles als getakteten Prozess
zu schreiben ... Dann muss ich mir auch keine Gedanken um die
Sensitivity-Liste machen.
Wenn ich kombinatorisch etwas mache, dann nicht in Prozessen :)
Bin damit bisher gut gefahren^^
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang