Servus!
Ich habe hier ein stück Code bei dem mir zwei Latches erzeugt werden.
Einmal durch das Signal "segment_select" und durch "segment_output".
Kann mir jemand von euch bitte sagen, wie ich das beheben kann? Leider
kenne ich mich in VHDL noch nicht gut genug aus.
Hier ist der code:
Das passiert, weil nicht in jedem Fall eine Zuordnung an segment_select
und segment_output geschieht. Des weiteren wird die Synthese sich wohl
darüber beschweren, dass die beiden Signale 'multiple drivers' haben -
nämlich in jedem der if-Statements.
Du kannst beide Probleme lösen, indem du obigen Code durch eine
if-elsif-...-elsif-else-Konstruktion ersetzt.
...oder noch besser: Benutze "case" und am Schluss "when others =>" für
die Default-Festlegung. Das wird dann in einem Mux realisiert. Bei der
"elsif"-Kette hast Du tendenziell mehr Logiklevels (aneinander gereihte
AND), was zum Problem werden kann, wenn der Pfad zeitkritisch ist.
Oli schrieb:> Du kannst beide Probleme lösen, indem du obigen Code durch eine> if-elsif-...-elsif-else-Konstruktion ersetzt.
Aber nur, wenn Count nicht noch größer als 8 werden könnte... :-o
Stephan S. schrieb:> ich hab jetzt nur den process mit den beiden signalen exportiert, ich> hoffe das reicht.
Mir nicht. Was hat in diesem Prozess der clk zu suchen?
So wie das hier aussieht, machst du was einfaches unglaublich
kompliziert. Denn das, was da steht, ist ein ganz hübsch großer
Multiplexer. Wolltest du sowas?
Oli schrieb:> Des weiteren wird die Synthese sich wohl> darüber beschweren, dass die beiden Signale 'multiple drivers' haben -> nämlich in jedem der if-Statements.
Bullshit!
Dafür steht es ja im process.
Duke
Duke Scarring schrieb:>> nämlich in jedem der if-Statements.> Bullshit!> Dafür steht es ja im process.
Und der Trick am Prozess ist, dass die letzte Signalzuweisung "gewinnt".
Wenn man das weiß, dann kann man das auch gewinnbringend verwenden...
Das CLK in der sensitivitylist ist nicht beabsichtigt... wahrscheinlich
stammt das aus irgendeiner uralten version des codes
der count ist nur von 1 bis 8 deklariert, daher hatte ich mir gedacht da
müsste er doch sehen, dass es andere möglichkeiten nicht gehen.
Ich hab das jetzt jetzt in ein case statement mit others umgeschrieben
und er meckert nicht mehr. Danke!
In dem Fall habe ich jetzt verstanden, warum er gemeckert hat, aber ich
habe hier noch einen anderen Fall, bei dem auch latches erzeugt werden:
in diesem fall werden drei latches erzeugt für: biggest_value,
headroom_buffer und headroom.
zum Code:
Es geht darum, während einer bestimmten Zeitspanne (deren Ende mit
send=1 signalisiert wird), den größten werd zu messen und diesen für
eine spätere Ausgabe zu speichern. Es wird der Eingang(=actual_value)
mit dem biggest_value verglichen. Dies geschieht über einen Komparator,
der entsprechend a<b (a_sm_b), a=b (a_eq_b) und a>b (a_gt_b) auf eins
setzt. Falls der wert größer oder gleich groß ist, wird er in
biggest_value abgespeichert und dann im nächsten Durchgang wieder
verglichen. Wenn nun das Signal zum senden kommt, wird der größte wert
in headroom und headroom_buffer abgespeichert. dann geht wieder alles
von vorne los.
Der wert headroom wird immer ausgegeben.
Ich hoffe ihr könnt mir helfen und schon mal Danke im voraus!
Stephan S. schrieb:> der count ist nur von 1 bis 8 deklariert, daher hatte ich mir gedacht da> müsste er doch sehen, dass es andere möglichkeiten nicht gehen.
Und wie ist der Count da definiert? Als Integer?
> in diesem fall werden drei latches erzeugt für: biggest_value,> headroom_buffer und headroom.
Wieso gibt es da ein
when others =>
NS <= St0;
Wie ist PS definiert?
Die Latches sind weg, sobald Du für die betreffenden Werte ein Default
setzt. Entweder vor dem "case"-Statement (bevorzuge ich persönlich),
oder aber im "when others". Im Moment ist weder noch der Fall.
soll das when others bei einer statemachine nicht verwendet werden? oder
worauf ziehlt deine frage ab?
@pek
die signale werden von mir am anfang deklariert:
Lothar Miller schrieb:> Duke Scarring schrieb:>>> nämlich in jedem der if-Statements.>> Bullshit!>> Dafür steht es ja im process.> Und der Trick am Prozess ist, dass die letzte Signalzuweisung "gewinnt".> Wenn man das weiß, dann kann man das auch gewinnbringend verwenden...
Ok, nicht gewusst, thx! :-)
Stephan S. schrieb:> @pek> die signale werden von mir am anfang deklariert: signal biggest_value:
std_logic_vector(11 downto 0):="000000000000";
>> signal headroom_buffer: std_logic_vector(11 downto 0):="000000000000";
Das reicht eben nicht (Initialwert != Default in einem sequentiellen
Prozess). Was ist ein Latch? Eigentlich nichts anderes als ein Speicher,
um einen Wert zu speichern. Genau das passiert in Deinem Fall in dem
sequentiellen Prozess, wenn nicht für jeden Clockzyklus definiert ist,
was das Signal für einen Wert annehmen soll. Dann geht der Synthesizer
davon aus, dass Du den alten Wert beibehalten willst => Latch.
> das signal headroom kommt ja von außen, wie kann ich dem einen default> geben?
Bist Du sicher?
Stephan S. schrieb:> soll das when others bei einer statemachine nicht verwendet werden?
Es ist bei vollständig auscodierten FSM unnötig:
http://www.lothar-miller.de/s9y/categories/25-when-others> das signal headroom kommt ja von außen, wie kann ich dem einen default> geben?
Ein Initialisierungswert ist was anderes als ein Defaultwert!
Ich dein Problem erkannt: du beschreibst ein Latch. Dann muss der
Synthesizer das auch machen...
1
headroom_buffer<=headroom_buffer;-- das ist ein klassisches explizites Latch!
Und in so einem Fall wird auch ein Defaultwert nichts helfen, denn: die
letzte Signalzuweisung im Prozess gewinnt. Und die sagt headroom_buffer
muss gespeichert werden.
jetzt wird für headroom kein latch mehr erzeugt, aber für
headroom_buffer und biggest_value immer noch.
wie gebe ich denen jetzt nen default wert? einfach im process vor dem
case statement einen wert zuweisen? falls ja, dann hab ich eine
Verständnisfrage zu dem process:
durch das hinzufügen des default wertes, wird doch dann bei jedem aufruf
der process funktion diese wieder neu angewandt, oder? dadürch würde ja
immer anfang der default wert zugewiesen werden und es sich ja dann
keinen wert merken. in meinem fall muss ja das signal biggest_value und
headroom_buffer gemerkt werden, bis sie bei einem sendebefehl neu
beschrieben werden.
Stephan S. schrieb:> dadürch würde ja> immer anfang der default wert zugewiesen werden und es sich ja dann> keinen wert merken.
Wenn Du Dir einen Wert _merken_ willst, dann brauchst Du dazu
natürlich ein Register.
Falls es nur kombinatorische Verknüpungen sein sollen, dann brauchst Du
vor dem "case"-Staement Default-Zuweisungen, z.B.
1
headroom_buffer<=(others<='0');
2
biggest_value<=(others<='0');
ode im "case"-Statement ein "when others =>". Auch wenn Du alle Zustände
auflistest, sind es nicht 2^^N, es bleiben also nach wie vor 3
unbenutzte bis 2^^3 = 8.
Peter K. schrieb:> Auch wenn Du alle Zustände> auflistest, sind es nicht 2^^N, es bleiben also nach wie vor 3> unbenutzte bis 2^^3 = 8.
Du gehst offenbar von einer binär codierten FSM aus. Bei einer
One-hot-FSM stimmt das sicher nicht mehr. Und: hast du meinen Link von
weiter oben schon gesehen?
Stephan S. schrieb:> wie gebe ich denen jetzt nen default wert? einfach im process vor dem> case statement einen wert zuweisen? falls ja, dann hab ich eine> Verständnisfrage zu dem process:> durch das hinzufügen des default wertes, wird doch dann bei jedem aufruf> der process funktion diese wieder neu angewandt, oder? dadürch würde ja> immer anfang der default wert zugewiesen werden und es sich ja dann> keinen wert merken. in meinem fall muss ja das signal biggest_value und> headroom_buffer gemerkt werden, bis sie bei einem sendebefehl neu> beschrieben werden.
also nimm's mir nicht uebel, aber du hast kein Problem mit VHDL. Dein
Problem scheint mir zu sein, dass du nicht weisst was
a) kombinatorische Logik
b) Latch
c) Flip-Flop
jeweils ist und wie man das in einer HDL beschreibt! Du hast oben
geantwortet, dass du es jetzt verstanden haettest. Aber trotzdem baust
du dir ein Latch nach dem anderen ein...
Vielleicht mal als Hinweis:
1.) Kombinatorik schreibt man am besten als 'concurrent statement'
2.) Ein Latch entsteht, wenn man ohne Takt/Clock einem Signal entweder
gar nix zuweist oder eben den alten Wert (Latch: Zustandsgesteuerter
Speicher!)
3.) Ein FF uebernimmt einen Logikwert aus der Prozessbeschreibung oder
einem concurrent assignment
PS: Und lies dir mal die Antworten hier durch, da steht das auch schon
alles!
berndl schrieb:> jeweils ist und wie man das in einer HDL beschreibt! Du hast oben>> geantwortet, dass du es jetzt verstanden haettest. Aber trotzdem baust>> du dir ein Latch nach dem anderen ein...
Hallo Bernd,
der TO ist doch einen Schritt weiter.
Am Anfang hat er die Latches nur implizit erzeugt.
Zum Schluß schon explizit.
Das ist doch schon ein Fortschritt mit Lerneffekt für Ihn und andere die
diesen Thread lesen.
Wo Du natürlich recht hast, ist dass der TO wohl den Unterschied
ziwschen Register, Latches und kombinatorischer Logik noch nicht
vollumfänlglich verinnerlicht hat.
Aber klar ist dass er ein Latch haben will , auch wenn er es sich noch
nicht eingestanden hat...
Sein Problem im Moment ist, dass Ihm die Toolchain sagt, Latches sind
böse und sein Code enthällt Latches.
@Stephan S
Du möchtest bei einer bestimmten Eingangskombination einen Zustand am
ausgang festhalten?!
Das ist ein Speicherelement.
Wenn Du einen Clock hernehmen kannst um das zu synchronisieren, bist Du
raus aus dem Schneider indem Du das ganze als (clock)synchronen Prozess
beschreibst.
Sollte das nicht gehen, dann greift die Warnung deiner Toolchain:
Weißt Du auf was Du dich einlässt? Wenn ja dann beschreibe deine Logik
mit einem Latch.
Hierzu musst Du allerdings einiges an Erfahrung und Wissen über den
inneren Aufbau deines FPGAs kennen um zu wissen, was da dann draus
synthetisiert wird...
Gruß
Vanilla
Vanilla schrieb:> Aber klar ist dass er ein Latch haben will , auch wenn er es sich noch> nicht eingestanden hat...
Aber unklar ist, ob er überhaupt eines braucht!
> Weißt Du auf was Du dich einlässt?
Lass mich mal schätzen: Nein, das weiss er nicht.
> dass Ihm die Toolchain sagt, Latches sind böse
Klar, weil sie die Laufzeiten nicht mehr zuverlässig berechnen kann, und
weil aus einem solchen Latch gern mal eine (versteckte) kombinatorische
Schleife wird...
lkmiller schrieb:> Peter K. schrieb:>> Auch wenn Du alle Zustände>> auflistest, sind es nicht 2^^N, es bleiben also nach wie vor 3>> unbenutzte bis 2^^3 = 8.> Du gehst offenbar von einer binär codierten FSM aus. Bei einer> One-hot-FSM stimmt das sicher nicht mehr. Und: hast du meinen Link von> weiter oben schon gesehen?
Ja, ich ging von einer binär codierten FSM aus. Bei One-hot stimmt die
Rechnung natürlich nicht, da hast Du noch einige unbenutzte Zustände
mehr (alle wo mehr als ein FF den Wert 1 hat).
Bei Leuten, die ausschliesslich in FPGA zuhause sind vermutlich kein
Problem. Verlässt man die (heile) FPGA-Welt, vielleicht weil der Code
auch in einem ASIC zum Einsatz kommen könnte, und ist zudem "graceful
recovery" ein Thema, macht das "when others" durchaus Sinn. Sicher
nicht, um dort ein Error-Signal zu setzen das sonst immer '0' ist,
sondern um z.B. eine Statemachine in einen sinnvollen Zustand
zurückzuführen (e.g. nach IDLE).
Verlieren tut man damit auf jeden Fall sicher nichts...
Peter K. schrieb:> Verlieren tut man damit auf jeden Fall sicher nichts...
Platz? Silizium?
> Verlässt man die (heile) FPGA-Welt, vielleicht weil der Code> auch in einem ASIC zum Einsatz kommen könnte, und ist zudem "graceful> recovery" ein Thema, macht das "when others" durchaus Sinn.
Es gibt aber in einer FSM, bei der alle definierten States verwendet
wurden, keine anderen Zustände mehr. Es müssen also zusätzliche, nicht
in VHDL abhandelbare Konstrukte her, die so etwas steuern könnten...
Bei Xilinx ist das in den Syntheseoptinen versteckt und heißt "Implement
Failsafe FSM". Damit wird sichergestellt, dass unabhängig von der
tatsächlichen Implementierung (Binär, Gray, One-Hot, ...)
ausschliesslich die definierten Zustände auftauchen können. Von einem
solchen Verhalten geht aber ein Simulator auf VHDL-Ebene sowieso
zwingend aus.