Datum:
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:
output: process(clk, count, segment7a, segment7b, segment7c, segment7d) begin if(count=1) then segment_select<="1110"; segment_output<=segment7d; end if; if (count=2) then segment_select<="1110"; segment_output<="1111111"; end if; if (count=3) then segment_select<="1101"; segment_output<=segment7c; end if; if (count=4) then segment_select<="1101"; segment_output<="1111111"; end if; if(count=5) then segment_select<="1011"; segment_output<=segment7b; end if; if (count=6) then segment_select<="1011"; segment_output<="1111111"; end if; if (count=7) then segment_select<="0111"; segment_output<=segment7a; end if; if (count=8) then segment_select<="0111"; segment_output<="1111111"; end if; end process; |
ich hab jetzt nur den process mit den beiden signalen exportiert, ich hoffe das reicht. Vielen Dank schonmal!
Datum:
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.
Datum:
...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.
Datum:
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?
Datum:
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
Datum:
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...
Datum:
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:
comb_process: process (PS,send,actual_value,biggest_value, a_sm_b, a_eq_b, a_gt_b,headroom_buffer ) begin case PS is --start when ST0 => biggest_value<=biggest_value; headroom<=headroom_buffer; headroom_buffer<=headroom_buffer; if (send ='1') then NS <=ST3; elsif (a_sm_b='1') then NS <=ST1; elsif (a_eq_b = '1' or a_gt_b='1') then NS <= ST2; else NS <= ST0; end if; --compared when ST1 => biggest_value<=biggest_value; headroom<=headroom_buffer; headroom_buffer<=headroom_buffer; if (send ='1') then NS <=ST3; else NS <= ST0; end if; --compared when ST2 => biggest_value<=actual_value; headroom<=headroom_buffer; headroom_buffer<=headroom_buffer; if (send = '1') then NS <= ST3; else NS <= ST0; end if; --send when ST3 => headroom<=biggest_value; biggest_value<=biggest_value; headroom_buffer<=biggest_value; if (send = '1') then NS <= ST3; else NS <=ST4; end if; --neustart when ST4 => biggest_value<="000000000000"; headroom<=headroom_buffer; headroom_buffer<=headroom_buffer; NS <= ST0; when others => NS <= St0; end case; end process; |
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!
Datum:
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?
Datum:
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.
Datum:
@lkmiller ich hab count so definiert:
signal count : integer range 1 to 8 :=1; |
PS ist folgendermaßen deklariert:
type state_type is (ST0,ST1,ST2,ST3,ST4); signal PS,NS : state_type; |
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:
signal biggest_value: std_logic_vector(11 downto 0):="000000000000"; signal headroom_buffer: std_logic_vector(11 downto 0):="000000000000"; |
das signal headroom kommt ja von außen, wie kann ich dem einen default geben?
Datum:
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! :-)
Datum:
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?
Datum:
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...
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.
Datum:
so, jetzt hab ich ein paar sachen geändert:
comb_process: process (PS,send,actual_value,biggest_value, a_sm_b, a_eq_b, a_gt_b,headroom_buffer ) begin case PS is --start when ST0 => headroom<=headroom_buffer; if (send ='1') then NS <=ST3; elsif (a_sm_b='1') then NS <=ST1; elsif (a_eq_b = '1' or a_gt_b='1') then NS <= ST2; else NS <= ST0; end if; --compared when ST1 => headroom<=headroom_buffer; if (send ='1') then NS <=ST3; else NS <= ST0; end if; --compared when ST2 => biggest_value<=actual_value; headroom<=headroom_buffer; if (send = '1') then NS <= ST3; else NS <= ST0; end if; --send when ST3 => headroom<=biggest_value; headroom_buffer<=biggest_value; if (send = '1') then NS <= ST3; else NS <=ST4; end if; --neustart when ST4 => biggest_value<="000000000000"; headroom<=headroom_buffer; NS <= ST0; end case; end process; |
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.
Datum:
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.
headroom_buffer <= (others <= '0'); 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.
Datum:
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?
Datum:
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!
Datum:
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
Datum:
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...
Datum:
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...
Datum:
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.
