Hi Leute, wenn ich in VHDL einen Counter mit signal Counter: integer range 0 to 115; definiere und diesen nun im VHDL mit if Clock'Event and Clock = '1' then Counter <= Counter + 1; end if; inkrementiere, bei welchem Wert läuft der Zähler über ? Bei 115 +1 auf 0 oder erst bei 255 +1 = 0 weil ja dieser Counter mit 8 FF's realisiert werden muß. Gruß Hagen
Soweit ich weiß, müsste der counter den Wert 115 noch annehmen und dann erst auf 0 gehen. Der range-Befehl müsste sich nicht nur auf die Anzahl der FF's auswirken, sondern auch auf die Übergangslogik im Zähler (vermute ich mal). Wenn nicht, so sollte beim Compilieren zumindest eine Warnung kommen. Gruß Henrik
Fehler kommt nicht, und logisch wäre ein Überlauf beim Maximum der Range. Allerdings die Zähler selber können nur bis 2^Anzhal FF -1 zählen, also immer eine Potenz von 2 an Schritten. Sogesehen müsste der Fitter das berücksichtigen und einen Comparator nachschalten. Nungut, meine Frage war nur um mir Zeit zu sparen, ich werden es ja eh noch verifizieren müssen. Bis jetzt weis ich nur das die Anzahl der benötigten Makrozellen sich nicht verändert hat, egal ob man im VHDL den Zähler explizit per Comparator zurücksetzt oder bei Range beschränkt. Schon mal ein gutes Zeichen und ich bin happy das sich hier das VHDL/Fitter wenigsten logisch verhält. Wenn ich es verifiziert habe melde ich mich nochmal. Gruß Hagen
Hallo, ich bin relativ neu im umgang mit Programmierbaren logikbausteinen, daher kann es gut sein das das was ich schreib nicht recht zu der Fragestellung passt. Ich kann leider kein VHDL, ich nehme bis jetzt den leichten weg über Schaltplaneingabe. Aber wenn man einen Zähler von 0-115 braucht, so benötigt man doch nur 7 FFs, und somit eine Makrozelle weniger. Das rücksetzen würde ich per Festverdrahteter Logik bei 116 machen, bzw zusammen mit dem Ausdekodierten Signal bei Zählerstand 115 über ein AND mit dem Takt auf den Rücksetzeingang der FFs. mfg Stefan
Das ist schon richtig was du sagst. In VHDL sähe es eben so aus signal XYZ: integer range 0 to 115; Thats all, und wäre das was du im Schematic machen würdest. Die Frage war/ist nun folgende: So ein Integer benötigt immer 7 FF's, logisch es gibt keine 1/2 FF's oder so. Somit geht der Wertebereich hardwaretechnisch immer von 0 bis 127 = 2^7-1, auch logisch. Generiert nun das VHDL für obige Deklaration automatisch einen Comparator der beim Inkrementieren überprüft ob Werte > 115 erreicht wurden und setzt den Zähler auf XYZ = XYZ mod 116, zurück. Normalerweise (händisch) würde es in VHDL so aussehen: signal XZY: integer range 0 to 127; XZY <= XYZ +x; if XYZ >= 116 then XZY <= XYZ - 116; end if; Übrigens, empfinde ich die Programmierung in VHDL wesentlich einfacher als die Schematas. Gruß Hagen
@Stefan: "Das rücksetzen würde ich per Festverdrahteter Logik bei 116 machen" wieso? Das ist doch nur ein kleiner Eingriff in die interne Tabelle für den nächsten Zustand. Das extern zu machen kostet eine Macrozelle mehr. @Hagen: Beide Möglichkeiten brauchen 7 Macrozellen (=>Anhang). Meine bevorzugte Variante ist zwar länger aber wie ich meine auch besser zu verstehen. Du solltest den Speicher für den Wert(Counter) nicht als Signal deklarieren, sondern als variable, wenn du kurz darauf auf ihn zugreifst. Bsp: Signal A integer ...; ... (Annahme: A=5) Process... begin ... A<=A+1; if (A=6) then ... (wird nicht ausgeführt, da A erst am Prozessende aktualisiert wird!) end if; end Process... Das ist zwar in erster Linie ein Problem der Simulation, man sollte es aber trotzdem vermeiden. Gruß Henrik
Ob Variable oder Signal war für meine Frage erstmal unwichtig :) Klar in meinem konkreten Fall MUSS es ein Signal sein, einfach weil es per externem Takt inkrementiert werden soll. Es sei denn ich hätte da eine Lücke in meinem VHDL Wissen und man kann Variablen (nicht shared Variablen) global im behavioral benutzen und per externem Clock inkrementieren ?? Gruß Hagen
Geht doch einfach mal von einem SImulator wie Modelsim aus. Da würdest du einen Fehler bekommen, da wenn der Zählerstand 115 ist beim nächsten Inkrement 116 nicht mehr im Range deines Subtypes ist. Die besten Erfahrungen hab ich mit folgender Beschreibung. if(rising_edge(clk)) then if(counter < 115) then counter <= counter +1; else counter <= 0; end if; end if; Dann stimmt das ganze beim Simulieren und wird auch richtig syntetisiert. Gruß Max
Das kannst du!(Über einen kleinen Umweg) In dem Prozess in meinem Code steht: "output<=counter;". Es ist egal, ob output ein Ausgang der Entity oder ein internes Signal ist. Damit ist der Wert des Zählers überall (im Behavorial) verfügbar. Natürlich ist das auch ein wenig umständlicher, aber es vereinfacht das Nachvollziehen des Codes, wenn man sicher sein kann, dass man ein Signal immer wie eine Leiterbahn ansehen kann. Bei diesem Problem kann man es am besten wie Max mit einer einfachen if-Schleife machen. Wenn die Anforderungen anden Zähler aber wachsen und man z.B. einen ladbaren Up-Down-BCD-Zähler mit Set und Reset haben will, hat man irgendwann soviele if-Schleifen, dass es vielleicht den beliebten "bad decription error" gibt. Dann ist das Problem sehr einfach mit einer case-Anweisung zu lösen (Das Thema hatten wir hier kürzlich sogar 2 mal). Gruß Henrik
Hi Henrik, ok anbei mal mein akademisches Testprojekt. Im speziellen ging es mir um HCounter und VCounter des VHDL's. Ich wüsste jetzt nicht wie man diese in Variablen statt Signale umwandeln könnte, zumindestens meckert Xilinx's WEBPack wenn ich dies versuche. Aus "Sicherheitsgründen" habe ich mich nun doch für normale std_logic_vector für die Zähler entschieden. Achso, nicht lachen über den Source, ich bin noch am üben :=) Gruß Hagen
Warum sollte ich lachen? "ich bin noch am üben :=)" da sind wir ja schon zu zweit. Habe nur minimale Änderungen vorgenommen. Die Zähler laufen jetzt über Variablen. Als ich VCount als Variable mit der Breite 7Bit (Vorgabe) initialisierte und am Ende mit VCounter verband, kam beim Compilieren eine seltsame Warnung, die vorher nicht kam: "VCountER assigned, but never used!". Das habe ich überprüft und es stimmte nicht. VCounter wurde benutzt! Dann bemerkte ich, dass die 7Bit Variable mit einem Wert von 506 verglichen wurde (wozu man ja mindestens 9 Bit braucht!). Als ich daraufhin die Variable und das Signal auf 9 Bit erweiterte verschwand diese Meldung wieder. Scheint ein kleiner Fehler im Webpack zu sein, dass hier die falsche Warnung erscheint. Gruß Henrik
Nee diese "Warnung" ansich war schon gut den es war ja schließlich definitiv ein Programmfehler. Ich habe auch lange überlegt was der "Fehler" bedeutete und schlußendlich meinen Fehler so gefunden. Das man Variablen so innerhalb eines Prozesse benutzen kann war mir schon klar. "-- das ist NICHT wie bei C-Variablen, wo diese nach dem verlassen der Schleife gelöscht würden!" Das aber die "lokale" Variable eines Prozesses ihren "Zustand" Prozessübergreifend speichern kann aber nicht. Danke für diese Info, das werde ich nochmal verifizieren. Denn schlußendlich würde das ja bedeuten das ich die komplette Logik des HCounter/VCounter in einen eigenen Prozess packen könnte und so die externen Signal wegrationalisieren kann. Allerdings ganz so sicher bin ich mir da noch nicht, ich hatte die VHDL Dokus anders interpretiert (aus Sicht eines Programmieres auf PC's) Gruß Hagen
"Das aber die "lokale" Variable eines Prozesses ihren "Zustand" Prozessübergreifend speichern kann aber nicht." Wie ist das gemeint? Gruß Henrik
Ok es geht um zwei Punkte in deinen Änderungen: variable HCount: std_logic_vector(9 downto 0); -- das ist NICHT wie bei C-Variablen, wo diese nach dem verlassen der Schleife gelöscht würden! -- horizontal sync begin if Enable = '0' then HCount := (others => '0'); else if Clock'Event and Clock = '1' then if HCount < 824 then HCount := HCount + 1; -- bereits hier darst du auf den neuen Wert von HCount zugreifen, da dieser bei Variablen sofort -- aktualisiert wird, im Gegensatz zu einem Signal! 1.) das lokale Variablen ihren Zustand innerhalb des Prozesses beibehalten. Gut das ist einfach ein "Denkfehler" von mir der einen Process als langjähiger "sequentiell" denkender Programierer eher als Funktion betrachtet, statt einem parallel laufendem Thread (im übertragenem Sinne). 2.) dein zweiter Kommentar das man bei Veränderungen von Variablen sofort danach "sequentiell" weitere Berechnungen durchführen darf. Dieser Kommantar macht mich ziemlich stutzig da ich davon ausging das dies auch auf Signale zutrifft. ich habe mein Design nun mal in verschiedenen Konfigurationen verändert. Benutze ich Variablen so verbrauche ich die gleichen Resourcen es ändert aber sich das maximale Timing zu Ungunsten, es wird ca. 50% langsammer. Dann habe ich einfach mal wieder mit Signalen für HCounter/VCounter benutzt aber diesemal in nur zwei Prozessen berechnet. Dieses Design verbraucht die gleichen Resourcen ist aber wieder genauso schnell wie das alte. Immerhin komme ich bei einem XC95144 auf 133 Makrozellen und einem maximalem Clock von 83 MHz das wären 161Hz Framerate des VGA Controllers. Die Reduktion auf max. 34Mhz Clock wenn ich Variablen benutze könnte störedn sein beim multiplexten Zugriff auf das externe 10ns SRAM. Gruß Hagen
Hallo leute.Ich muss ein counter als endliche automaten realisieren.Wer könnte mir dabei helfen?? danke
Na da können wir dir bestimmt helfen. Du sollst eine State Machine basteln? Wo hängst du fest? Was klappt nicht? Schilder dein problem mal etwas genauer bitte.
Ich muss ein Zähler entwickeln,der auf Tastesndruck gestartet und gestoppt wird.Weiterhin soll dieser Zäler durch betätigen einer weiteren taste zurückgesetzt werden können.der wert des zählers soll in hexadezimaler darstellung gegeben werden Ich soll also das modul counter als endliche automaten realisieren.Ich weiss wie ein endlichen automaten lauft,und wie ein counter lauft,aber hänge trotzdem fest. danke
Du programmierst einen normalen Zähler mit Reset und Enable. Dann deklarierst du inder architecture "type Zustaende is (Zaehle, Warte, Null); signal Zustand : Zustaende;" Wenn jetzt irgendwas ausserhalb passiert setzt du diese Zustände mit "Zustand<=Zaehle ;--(oder Warte oder Null)". Dieser Zustand wird vom Zähler dann bei jeder Takt-Flanke abgefragt und die entsprechende Aktion ausgeführt. Was soll denn "...wert des zählers soll in hexadezimaler darstellung gegeben werden" bedeuten? Logikbausteine können nur Bitmuster rausgeben. Decodieren mußt du das schon selbst. Gruss Henrik
Hi @ Hagen Ich würde das mit den Counter anders machen. Zähl doch einfach von 115 auf 0. Ich denke mal das spart noch mal Logik, da der Vergleich jetz nicht mehr if(x < 115) lautet, sondern (if x = 0). Ich glaube das benötigt weniger Logik, habe es selber aber noch nicht ausprobiert. Besonders wenn die Zähler größer werden, ist dies sicherlich eine sinvolle Lösung. if(rising_edge(clk)) then if(counter = 0) then counter <= counter - 1; else counter <= 115; end if; end if; oder eine andere sehr interessante Lösung: Stellt Dir mal die Zahl in Binär vor (sagen wir mal 2765)Dies entspricht binär "101011001101" Dann machst Du folgendes testsignal <= Counter(11) & Counter(9) & Counter(7) & Counter(6) & Counter(3) & Counter(2)& Counter(0); Somit wird das Signal "testsignal" nur dann '1' wenn der Zähler das richtige Binärmuster besitzt. Die Abfrage lautet dann so: if(testsignal = '1') then Counter <= (others => '0'); else Counter <= Counter + 1; end if; Gruss Michael
@Michael: ich weis, aber leider hilft dieser Trick nicht immer :) Das liegt aber daran das die Fitter im WebPack und Quartus bei solchen Sachen echt clever sind. Man kann eine AND/OR/XOR/Komparator Abfrage so kompliziert wie möglich machen, die beiden Fitter finden meistens das entsprechende Optimum. Zumindestens ist das meine Erfahrung mit der Software. Nun, warum ich aber aufwärts zähle hat einen anderen Grund. Der HCounter und VCounter dienen als Pixel-Address-Counter. Besonders wenn man zb. mit Auflösungen von 256,512,1024 Pixel pro Zeile arbeitet ist das ideal. Desweiteren würde ein Downcounter zwar die eine Abfrage vereinfachen, aber normalerweise muß man diesen Counter an mehreren Punkten abfragen. Eben zum Zeitpunkt des Front Porch, Back Porch, Sync Pulses und des sichtbaren Pixelbereiches. Würde man einen Downcounter benutzen so wird zwar an einer Stelle alles einfacher dafür aber an anderen Stellen eben komplizierter. Davon absehen, ich habe es probiert :) Es brachte exakt die gleichen Fitting Ergebnisse. Wichtiger nach meiner Erkenntisse ist der Unterschied zwischen Abfragen wie if Counter >= x then oder if Counter <= x then ; zu Abfragen wie if Counter > x then oder if Counter < x then ; da konnte ich Unterschiede im Resourcenverbrauch feststellen, obwohl ich mir diese nicht so recht erklären kann. Gruß Hagen
Hi Hagen Meine Erfahrungen haben gezeigt, dass man bei sehr großen Zählern sehr viele Ressourcen einsparen kann, wenn man es mit der Verknüpfung macht. Jedoch ist das auch schon zwei Jahre her. Vielleicht sind die Tools jetzt besser geworden. Ich werde gleich mal ein Beispiel ausprobieren und dann posten. Bin selber mal gespannt. Ich merke schon Du steckst sehr tief in dem Thema, das finde ich sehr gut, denn ich arbeitet auch schon etwas länger mit VHDL und genau dann stellt man sich die Fragen, wie kann ich das Design optimierern um mehr Geschwindigkeit aus dem Design zu holen. Nur leider gibt es noch zu wenig Fachleute in Deutschland. Ich hatte Vorlesungen über VDHL, aber über einfache Beispiele ist man leider nicht hinausgekommen. Das Problem ist halt, dass man einfach kaum Literatur findet, die einem da weiterhilft. Sag mal in welcher Stadt wohnst Du. (nicht zufällig in Lübeck) Gruss Michael
So habe mal als erstes folgendes erstellt: signal COUNTER : std_logic_vector(11 downto 0); signal S_NEW_CLK : std_logic; begin NEW_CLK <= S_NEW_CLK; process (CLR,CLK,COUNTER,S_NEW_CLK) begin if(CLR = '1')then COUNTER <= (others => '0'); S_NEW_CLK <= '0'; elsif(CLK'event and CLK = '1')then if(COUNTER = "100111111100")then -- 2556 COUNTER <= (others => '0'); S_NEW_CLK <= not S_NEW_CLK; else COUNTER <= COUNTER + 1; end if; end if; end process; Diese Variante benötigt 27 4-Input-LUTs und 13 Slice FF. Es ist eine maximale Frequenz von 115,44 MHz möglich. Ich habe ISE auf "Speed" gestellt und er soll die optimale Lösung finden. Danach habe ich zum Vergleich die andere Variante getestet. signal COUNTER : std_logic_vector(11 downto 0); signal S_NEW_CLK : std_logic; signal TEST : std_logic; begin TEST <= COUNTER(11) and COUNTER(8) and COUNTER(7) and COUNTER(6) and COUNTER(5) and COUNTER(4) and COUNTER(3) and COUNTER(2); NEW_CLK <= S_NEW_CLK; process (CLR,CLK,COUNTER,S_NEW_CLK) begin if(CLR = '1')then COUNTER <= (others => '0'); S_NEW_CLK <= '0'; elsif(CLK'event and CLK = '1')then if(TEST = '1')then -- 2556 100111111100 COUNTER <= (others => '0'); S_NEW_CLK <= not S_NEW_CLK; else COUNTER <= COUNTER + 1; end if; end if; end process; Die zweite Variante benötigt 25 4-Input-LUTs und 13 Slice FF. Es ist eine maximale Frequenz von 109,9 MHz möglich. So was aber auch. Ich denke mal das der Zähler noch zu klein ist, Aber wenn man einen sehr großen Teiler benötigt, dann ist diese Variante sicherlich besser. :-) Vielleicht kann man die "ANDs" noch zusammenfassen, so dass vielleicht noch mehr speed drin ist. Gruss Michael
>> Sag mal in welcher Stadt wohnst Du. (nicht zufällig in Lübeck) nee auf halber Strecke zum anderen Ende der Republik, in Eisenach. Ich mache es bei der Optimierung immer so das verschiedene Sachen austeste. Zum Glück ist es nur Hobby, professionell könnte man sich nicht so viel Zeit nehmen. Aber meistens sitze ich an ganz anderen Problemen: sowas wie "verdammt die funktionale Simulation macht alles richtig, aber die Timing Simulation ist komplett verhunzt". Besonders wenn es um BiDir TriState Sachen geht scheint es sehr große Unterschiede zwischen Altera/Xilinx - ModelSim/Altera Simulator - CPLD's und FGPA's zugeben. Ich habe einige kleinere Sache mit CPLD's gemacht, bin aber immer wieder zu schnell an die Grenzen gestossen. Ehrlich gesagt: sobald die Logik/FSM ein bischen komplizierter wird reichen CPLD's nicht mehr aus. Den Schritt hin zu FPGA wage ich aber noch nicht, kostet ja noch mehr Zeit und Geld und selber dann was bauen ist mit BGA nun auch nicht so einfach. Von daher reichen CPLD's für mich um simple Addressdekoder, Memory Mapped Controller und Taktteiler zu programmieren. Ne I2C Slave Porterweiterung wäre noch denkbar, da ich noch zu viele CPLD's rumliegen habe. Zur Zeit versuche ich anscheindend das unmögliche, ich möchte einen simplen Level-Shifter hinbekommen, sprich zwei Pins sind intern miteinander verbunden aber beide sind inout und TriState. Sinn und Zweck der Sache ist es bei meinem aktuellen Projekt die 4 noch freien Pins als Level-Shifter von 5V auf 3.3V zu benutzen. Für SPI/TWI ja kein Problem da das alles unidirekional ist, aber schön wäre es eben wenn man's für I2C auch hinbekäme. Gruß Hagen
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.