Hallo zusammen, ich bin relativ neu hier - entschuldigt bitte wenn ich so etwas banales frage, aber ich konnte hier im Forum und mit google nichts finden was mir weiterhilft... Ich habe zum spielen ein Spartan 3A DSP 1800 Board bekommen. Jetzt möchte ich den 125 MHz Systemtakt "einstellbar" runtertakten. Hierzu möchte ich die 8 DIP-Schalter auslesen um mir so eine Frequenz zwischen 1 Hz und 256 Hz einstellen zu können. Aber wie errechne ich mir in VHDL die entsprechenden Werte für meinen Zähler? Ich benutze zur Zeit nur Std_Logic_Vektoren - da ich mit integer range xxx to yyy große Probleme hatte. Ich habe mir gedacht dass ich einen Zähler benutze - von der ersten Taktflanke (der 125 MHz Clock)bis zur Taktflanke für die halbe gewünschte Frequenz soll er das "neue" Taktsignal auf '0' setzten und von da bis zur Taktflanke bei der gewünschten Frequenz soll er das Taktsignal auf '1' setzten. (Ich hoffe ich konnte mich verständlich ausdrücken!) Hierzu müsste ich dann aber für jede Frequenz mit Potenzen rechnen - das scheint mir aber viel zu unübersichtlich (oder ich kenne die Befehle einfach nicht). Alternativ habe ich an einen Automaten gedacht - der wird aber riesig groß... Bin für jede Hilfe (auch Links) dankbar... Gruß Boris
Mach doch einfach einen counter der alle halbe Sekunde einen hochzählt. Immer wenn der Zählerstand XOR deinen Dipswitches 0 ergibt toggelst du deinen Ausgang und resetest den Timer.
Ich würde mal empfehlen mit dem unsigned Datentyp aus der numeric_std zu arbeiten. Das ist standardisiert und jedenfalls eher richtig als andere Dinge. Zur Aufgabe: Vielleicht könntest du den Zähler mit dem 8 bit Wert der sich aus den DIP-Switches ergibt erhöhen, dann musst du dir einmal den Wert für 1 Hz ausrechnen und der Rest sollte sich von selbst ergeben. Dann vergleichen ob der Zählerwert größer-gleich dem Maximalwert ist und in Abhängigkeit davon togglen und den Zähler zurücksetzen. Aber da gibts sicher schönere Lösungen. Und daran denken dass während dem Umschalten der Dipswitches das ganze vmtl mal für kurze Zeit nicht ganz so glatt funktioniert hat. Aber das bleibt dir eh nicht erspart, wenn du die Switches nicht entprellst.
> um mir so eine Frequenz zwischen 1 Hz und 256 Hz einstellen zu können. Das ist gar nicht mal sooo trivial wie es auf den ersten Blick aussieht, denn es sollen ja vermutlich die Frequenzen 1Hz, 2Hz, 3Hz, 4Hz, 5Hz ... 256Hz erzeugt werden? Es reicht nicht aus, einfach den Binärwert auf einen Reloadwert hochzumultiplizieren. Du brauchst eigentlich den Kehrwert des eingestellten DIP-(Frequenz-)Wertes. Ich könnte mir vorstellen, dass eine Lookup-Tabelle für die Reload-Werte Sinn machen könnte. > da ich mit integer ... große Probleme hatte. Wie Matthias schon sagte: die numeric_std bietet schöne (und definierte) Umrechnungen und Casts zwischen den Datentypen
1 | integer <-> (un)signed <-> und std_logic_vector |
an.
Vielen Dank für eure Antworten!!! Werde mich jetzt gleich mal an die Sache ran machen...
ich halte auch eine Lookup-Tabelle für das Einfachste. Einfach einmalig für jede DIP-Einstellung den etnsprechenden Reload oder Overflow Wert berechnen und dann den Counter immer mit diesem Wert laufen lassen. Oder du berechnest den Overflow-Wert zur Laufzeit. 125 000 000 / (Dip-switch * 2) - 1 Die Multiplikation kannst auch durch ein "Schieben" ersetzen. Also auf den so errechneten Wert zählen, dann ausgang toggeln, Zähler zurücksetzen und wieder von vorne anfangen, zu zählen.
> 125 000 000 / (Dip-switch * 2) - 1 > Die Multiplikation kannst auch durch ein "Schieben" ersetzen. Ja, aber das mit der Division wird lustig ;-)
ja ich kenn jetzt den Spartan nicht und weiss nicht, ob der Multiplizierer hat. Dann wäre das kein Problem ist ja kein Fliesskomma und nix. Also ich seh die Divishon nicht als soo stressig. Und selbst, wenn man sie "konventiell" durchführen muss, da keine Multiplizierer vorhanden, kann man ja nen langsamen Takt wählen oder in merhreren Zyklen durchführen. Ich hab hier in meinem aktuellen Design ne fixed-point Multiplikation drin (32 Bit x 16 Bit) und die läuft in konventioneller Hardware ohne Probleme mit 50 MHz auf einem Lattice XP Und hier wäre es ja nur ne Multiplikation mit 8 Nachkommastellen (8 Bit Dip-switch) Also ich seh in dem Multiplizierer/ Dividierer gar kein Problem.
> Also ich seh die Divishon nicht als soo stressig. Du solltest da schon den bisherigen Wissenstand unseres Delinquenten in Betracht ziehen: >> Ich habe zum spielen ein Spartan 3A DSP 1800 Board bekommen. >> Bin für jede Hilfe (auch Links) dankbar... > ... ob der Multiplizierer hat. Multiplizierer gibts. Die laufen mit +100MHz. Aber du mußt durch die DIP-Schalter teilen. Wie würdest du deine Berechnung durchführen? > Also ich seh in dem Multiplizierer/ Dividierer gar kein Problem. Ich bei den Multiplizierern auch nicht. Das kann ich in VHDL einfach so hinschreiben y <= a*b; Dazu brauche ich noch nicht mal einen Takt, denn die Multiplikation ist eine rein kombinatorische Angelegenheit. Aber zeig mir doch mal eine Division, die genauso einfach geht. y <= a/b; Allerdings gilt als Rahmenbedingung: Zweierpotenzen (2,4,8,16...) kann das Tool schon von alleine ;-)
> Dazu brauche ich noch nicht mal einen Takt, denn die Multiplikation ist eine rein kombinatorische Angelegenheit. Richtig, ich wollte damit nur ausdrücken, dass die kombinatorische "Tiefe" so gering ist, dass der Pfad durch den Multiplizierer in einem 50MHz Desing läuft. Also kein Pfad im Multiplizierr länger als 20 ns ist > Aber zeig mir doch mal eine Division, die genauso einfach geht. Recht hast, da war ich etwas vorschnell. Ne Division durch 5 wird schon echt bescheiden gg
Eine Division durch einen festen Wert lässt sich schön auf eine Multiplikation zurückführen: z.B. 1/5 ~ 1/4 ~ 2/8 ~ 3/16 ~ 6/32 ~ 13/64 ~ 26/128 ~ 51/256 Man muss nur nach der benötigten Genauigkeit gucken. Duke
Dann braucht Boris aber Sekundenkleber für die DIP-Schalter, denn die bleiben ja im Nenner... ;-) 1/6 ~ 43/256 1/7 ~ 37/256 1/9 ~ 28/256 1/10 ~ 26/256 Auch mit diesen Zahlen gibt es nicht die direkte Zuordnung von DIP-Schalter zu Faktor.
Hallo nochmal... Hab da nochmal eine Anfängerfrage. Wenn ich die IEEE's NUMERIC_STD benutze kann ich (wenn ich dass richtig verstanden habe) folgende Operationen durchführen (+,-,*,/,rem,mod) jedoch nur wenn ich unsigned und signed Variblen benutze. Jetzt habe ich aber das Problem, dass ich meine DIP-Schalter als STD_LOGIC_Vector(7 downto 0) declariert habe. Wie wandele ich die um? Meine Versuche in VHDL enden leider mit einer Fehlermeldung: FATAL_ERROR:Xst:Portability/export/Port_Main.h:143:1.17 - This application has discovered an exceptional condition from which it cannot recover. Process will terminate. For technical support on this issue, please open a WebCase with this project attached at http://www.xilinx.com/support. Liegt dass an meinem Code (siehe Anhang)???
>Wie wandele ich die um?
unsigned(signalname) bzw. in die andere Richtung
std_logic_vector(signalname)
Der Error ist wohl eher ein Fehler von ISE, vielleicht mal ein Cleanup
Project Files machen, oder das Programm neu starten...
1 | if count < ((125000000 / signed_DIP) - 1) then |
Das wird nicht gehen. Eine Division wird in dieser Art von der Synthese nicht unterstützt. Nur Divisionen durch konstante Zweierpotenzen werden synthetisiert.
Hallo Jan, danke für deine schnelle Antwort... Cleanup Project Files hat leider nicht geholfen... Durch Probieren habe ich herausgefunden dass es wohl an dieser Zeile liegt: if count < (125000000 / signed_DIP) then wenn ich hier signed_DIP durch eine Zahl (z.B. 10 ersetze) klappt alles wunderbar. Nur ist es ja mein Ziel den Divisor über die DIP-Schalter einzulesen... Oder kann ich die DIP-Schalter schon als SIGNED bzw. UNSIGNED einlesen? Hab den aktuellen Code als .txt mal angehängt - vielleicht mache ich ja etwas Grundsätzliches falsch... Meine ISE kennt wohl kein UNSIGNED? Ist im Code nicht farbig Dargestellt... Oder fehlt mir hierzu eine Bibliothek?
Hallo Lothar... Da war ich wohl zu langsam... Schade dann war mein Gedanke mal wieder falsch... Habe noch die Idee die Division durch eine Schleife an Subtraktionen durchzuführen und mit einem Zähler hoch zu zählen. Das Ergebnis wird zwar nicht sehr genau - aber ich denke dass wird mir für den Anfang erstmal reichen...
@Boris wieviel DIP-Schalter hast Du denn? Zur Not eine Funktion schreiben, die für alle möglichen Werte von "signed_DIP" eine Näherung für "125000000 / signed_DIP" errechnet, dann ein ROM deklarieren, dessen Inhalt sich durch Aufruf der o.a. Funktion ergibt: in einem BlockRAM lassen sich immerhin 18kBits speichern - z.B: 1024 x 18 Bit oder 2048 x 9 Bit Gruß Jochen
> Habe noch die Idee die Division durch eine Schleife an Subtraktionen > durchzuführen und mit einem Zähler hoch zu zählen. Ja, der pragmatiche Ansatz, so wird es gehen. > Das Ergebnis wird zwar nicht sehr genau ... Das Ergebnis wird genauso genau, wie bei einer integer-Division zu erwarten. 1 / 2 = 0 Rest 1 234566 / 234567 = 0 Rest 234566
anbei ein Beispiel zur Umrechnung DIP => 1/DIP via BlockRAM PAR-Ergebnis auf Spartan3: Device Utilization Summary: Number of BUFGMUXs 1 out of 8 12% Number of External IOBs 21 out of 124 16% Number of LOCed IOBs 0 out of 21 0% Number of RAMB16s 1 out of 4 25% gut - es könnte auch noch 'generisch' gemacht werden, aber immerhin... Gruß Jochen
Hallo Joko, ich werde mir mal deinen Code anschauen - mal sehen ob ich da mit meinem bisschen VHDL noch mitkomme. Habe bis jetzt nur mal kurz mit einem XC9572 gearbeitet. Demnächst soll ich aber mit dem Spartan 3A bzw. einem Virtex zu recht kommen. Deshalb hat mir mein Kollege - der mir das alles bei bringen soll ein paar Aufgaben gegeben bis er aus dem Urlaub wieder da ist...(siehe Anhang - für die die es interessiert). Habe mal meine Idee programmiert, bekomme aber eine Fehlermeldung die da lautet: ERROR:Place:1018 - A clock IOB / clock component pair have been found that are not placed at an optimal clock IOB / Hier der Code dazu: library IEEE; use IEEE.STD_LOGIC_1164.ALL; --use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.NUMERIC_STD.all; ---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity toplevel is Port ( LEDs_out : out Std_Logic_Vector (7 downto 0); DIP_Switches : in Std_Logic_Vector (7 downto 0); -- Push_Button_Reset : in Std_Logic; reset : in Std_Logic; -- RS232 : inout Std_Logic_Vector (xxx); CLK : in Std_Logic); end toplevel; architecture Behavioral of toplevel is signal LEDs_in : Std_Logic_Vector (7 downto 0) := (others => '0'); signal count : integer range 0 to (125000000/2-1); signal frequenz_zaehler : integer range 0 to (125000000/2-1); --für die Schleife der Subtraktion signal x : integer range 0 to (125000000); signal y : integer range 0 to (125000000); signal A : integer range 0 to (125000000); signal B : integer range 0 to (125000000); signal sub_fertig : STD_LOGIC := '0'; begin process(reset,CLK) begin if reset = '1' then count <= 0; LEDs_in <= DIP_Switches; sub_fertig <= '0'; A <= 125000000; --Clock 125MHz B <= 2; --doppelte gewünschte Frequenz hier 1 Hz y <= 0; --Schleifenzähler x <= A; --Abbruchkriterium für die Schleife (x>=A) elsif rising_edge(CLK) then if sub_fertig = '0' then if x >= B then y <= y + 1; x <= A - B; A <= x; else sub_fertig <= '1'; frequenz_zaehler <= y ; end if; elsif sub_fertig = '1' then if count < frequenz_zaehler then count <= count +1; else LEDs_in <= LEDs_in(6 downto 0) & LEDs_in(7); count <= 0; end if; end if; end if; end process; LEDs_out <= LEDs_in; end Behavioral;
Hallo Jochen, vielen dank für dein Beispiel Divide_ROM aber das ist glaube ich noch etwas zu hoch für mich...
So nicht:
1 | use IEEE.STD_LOGIC_1164.ALL; |
2 | --use IEEE.STD_LOGIC_ARITH.ALL;
|
3 | |
4 | use IEEE.STD_LOGIC_UNSIGNED.ALL; -- nicht beide |
5 | use IEEE.NUMERIC_STD.all; -- Libs parallel verwenden |
Eher so:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.numeric_std.ALL; |
> ERROR:Place:1018 - A clock IOB / clock component pair have been found > that are not placed at an optimal clock IOB / Erst danach wirds interessant ;-) Wo ist dein Takteingang? Eine Suche im Forum ergibt z.B. den Beitrag "ERROR:Place:1018"
letzlich 'löst' dieses Schnipsel auch eine andere Aufgabe als die, die Du (nachträglich) veröffentlicht hast... Was in meinem Bespiel gemacht wird, ist einfach eine 'vorab-Berechnung' von einer Funktion - hier - Nenner: konstanter, zur Synthesezeit einstellbarer Wert - Zähler: alle möglichen Werte von 0..2047 (11 Bit) - Ausgabe: 9-Bit Wert mit Zähler/Nenner Innerhalb der Funktions-Deklaration kann man (fast) jede beliebige Funktion implementieren, die zur Lösung einer Umrechnung benötigt wird (hier wurde der Einfachheit halber nur Zähler/Nenner berechnet... Viel Erfolg Jochen
@Lothar: vor meiner nächsten Frage möchte ich mich erstmal bei Dir für die vielen Antworten DANKEN ! ! ! Gerade als Anfänger macht man häufig fehler die nicht passieren sollten oder fragt das ein oder andere mehrmals bevor man es richtig versteht... >library IEEE; >use IEEE.STD_LOGIC_1164.ALL; >use IEEE.numeric_std.ALL;< Habe die IEEE.STD_LOGIC_UNSIGNED.ALL jetzt auskommentiert. >Wo ist dein Takteingang? Mein Takteingang ist CLK (auf dem Board F13) >Erst danach wirds interessant ;-) Habe gerade erst rausgefunden, dass ich immer nur einen Teil der Warnings und Errors gesehen habe. Mal sehen ob ich das Problem nicht selbst lösen kann. Liest sich eigentlich recht einfach... Hier die komplette Fehlermeldung: ERROR:Place:1018 - A clock IOB / clock component pair have been found that are not placed at an optimal clock IOB / clock site pair. The clock component <reset_IBUF_BUFG> is placed at site <BUFGMUX_X2Y11>. The IO component <reset> is placed at site <J17>. This will not allow the use of the fast path between the IO and the Clock buffer. If this sub optimal condition is acceptable for this design, you may use the CLOCK_DEDICATED_ROUTE constraint in the .ucf file to demote this message to a WARNING and allow your design to continue. However, the use of this override is highly discouraged as it may lead to very poor timing results. It is recommended that this error condition be corrected in the design. A list of all the COMP.PINs used in this clock placement rule is listed below. These examples can be used directly in the .ucf file to override this clock rule. < NET "reset" CLOCK_DEDICATED_ROUTE = FALSE; >
Was passiert, wenn du den Reset synchron machst?
1 | process(reset,CLK) |
2 | begin
|
3 | if rising_edge(CLK) then |
4 | |
5 | if sub_fertig = '0' then |
6 | if x >= B then |
7 | :
|
8 | :
|
9 | end if; |
10 | end if; |
11 | |
12 | if reset = '1' then -- RESET Synchron |
13 | count <= 0; |
14 | :
|
15 | :
|
16 | x <= A; --Abbruchkriterium für die Schleife (x>=A) |
17 | end if; |
18 | |
19 | end if; |
20 | end process; |
>Was passiert, wenn du den Reset synchron machst?
Jetzt funktioniert es ohne die Fehlermeldung.
DAnn kann ich ja die DIP_Schalter zum einstellen jetzt hinzufügen:)
Das Problem, dass ich meist zuviele IF-Anweisungen verschachtel hatte
ich schon bei meinem XC9572...
> dass ich meist zuviele IF-Anweisungen verschachtel hatte
Der Fehler kommt nicht vom "Verschachteln", sondern von der ungünstigen
Eingangs-Pin-Position des Reset-Signals. Aber mach ruhig auch in Zukunft
den Reset synchron, am besten vor Verwendung das Reset-Signal noch über
2 FFs durchtakten.
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.