Ich ermittle für ein paar Frequenzen, die Takteiler automatisch. Dafür
gebe ich über generic die Frequenz mit und der Fitter ermittelt die
Werte für den Taktteiler. Das funktioniert soweit gut.
So muss ich mich nicht bei verschiedenen Boards die Teiler von Hand
ausknobeln und hart in den Code eintragen.
Bringt etwas Flexibilität ins System.
Jetzt hatte ich einen Fall, da reichte die Breite des tickcounter nicht
aus, weil die Frequenzen zu weit auseinander lagen.
Große Frage:
Gibt es eine Möglichkeit die Zählerbreite automatisch zu setzen?
Ich schreibe es mal so und hoffe auf Vorschläge.
René D. schrieb:> Fangen wir mit dem Codesegment an.> entity ....> generic(clk_freq : integer);> ...> architecture ..........> signal tickcounter : unsigned (8 downto 0) := (others => '0');> constant tick : integer := (clk_freq/10E6);> signal tick_event : std_logic := '0';>> begin>> process(clk)> begin> if rising_edge(clk) then> if (tickcounter = tick) then> tickcounter <= (others => '0');> tick_event <= '1';> else> tickcounter <= tickcounter+1;> tick_event <= '0';> end if;> end if;> end process;>> Ich ermittle für ein paar Frequenzen, die Takteiler automatisch. Dafür> gebe ich über generic die Frequenz mit und der Fitter ermittelt die> Werte für den Taktteiler. Das funktioniert soweit gut.> So muss ich mich nicht bei verschiedenen Boards die Teiler von Hand> ausknobeln und hart in den Code eintragen.> Bringt etwas Flexibilität ins System.> Jetzt hatte ich einen Fall, da reichte die Breite des tickcounter nicht> aus, weil die Frequenzen zu weit auseinander lagen.>> Große Frage:> Gibt es eine Möglichkeit die Zählerbreite automatisch zu setzen?>> Ich schreibe es mal so und hoffe auf Vorschläge. signal tickcounter :> unsigned (needed range for clk_freq/10E6)
Hallo Rene,
also ob du den Logarithmus Dualis in VHDL so einfach berechnen kannst,
weiss ich nicht und wage es mal zu bezweifeln...
Ich helfe mir immer damit, dass ich die Breite des unsigned auch als
Generic mitgebe. Damit ist meine Component generisch, beim instanzieren
wird dann alles festgelegt. Ist mein workaround fuer sowas...
Gruss,
- berndl
>> Hallo Rene,> also ob du den Logarithmus Dualis in VHDL so einfach berechnen kannst,> weiss ich nicht und wage es mal zu bezweifeln...
es gibt tatsächlich die Logfunktion in VHDL.
package math_real
1
functionlog2(x:inrea)returnreal;
Doch wie weiter?
> Ich helfe mir immer damit, dass ich die Breite des unsigned auch als> Generic mitgebe. Damit ist meine Component generisch, beim instanzieren> wird dann alles festgelegt. Ist mein workaround fuer sowas...
Das wollte ich gerade vermeiden. Für ein Problem zwei Werte durch die
Hierarchie durchcoden und dann sind die Werte wieder von Hand zu
setzen.
Mal sehen ob sich doch eine Lösung ergibt.
Warum benutzt du für "tickcounter" nicht integer bzw.
"integer range 0 to tick-1", dann wird die Weite
autom bestimmt.
Und: du vergleichst "tickcount" mit "tick" statt mit "tick-1".
Fragezeichen nicht auf deiner Tastatur?
Sigi schrieb:> Warum benutzt du für "tickcounter" nicht integer bzw.> "integer range 0 to tick-1", dann wird die Weite> autom bestimmt.
Ich arbeite ungern mit Integer in Signalen. Aus folgenden Grund.
Die Simulation mach was anderes als die Hardware bei fehlerhaften
Überläufen.
In diesem Fall wäre es noch überschaubar und würde den Code lesbarer
machen.
> Und: du vergleichst "tickcount" mit "tick" statt mit "tick-1".
Du hast recht, dass ich auf tick-1 vergleichen muss, da ich auf Null
zurücksetze und das ein Zählerwert entspricht.
Lothar Miller schrieb:> Ich hätte da ein (tick_WIDTH-1 downto 0) erwartet...
Hatte ich auch erwartet. Bei genauerer mathematischer Betrachtung
errechnet der Log2 wieviele Zustände ich abbilden kann. Und die Zahl 0
darf man als Zustand nicht vergessen.
Bsp:
log2(4)=2
Ergebnis für vier Zustände brauche ich zwei Leitungen.
Damit kann ich die Zahlen von 0...3 abbilden.
Die vier ist außerhalb des Wertebereiches.
Deshalb passt dein Vorschlag nicht.
>Wenn du beim Berechnen der Tick-Breite noch eins dazu gibst, dann klappt>es auch an den Grenzen der Zweierpotenzen,
vermutlich meinst du hier dasgleiche, da ich nicht wie du vorgeschlagen
hast mit tick_width-1 arbeite.
René D. schrieb:>> Wenn du beim Berechnen der Tick-Breite noch eins dazu gibst, dann klappt>> es auch an den Grenzen der Zweierpotenzen,> vermutlich meinst du hier dasgleiche, da ich nicht wie du vorgeschlagen> hast mit tick_width-1 arbeite.
Was ich meine, ist, dass du den halben Wertebereich des Vektors
verschenkst. Denn wenn dein Zähler 7 Schritte (also von 0 bis 6) zählen
soll, dann bekommst du einen Vektor ceil(log2(7)) = 3 downto 0. Und das
sind 4 Bit statt der tatsächlich nötigen 3 Bit.
Oder wenn du 100MHz Taktfrequenz hast, dann bekommst du einen Vorteiler
von 100, das ergibt mit deiner Formel dann einen Vektor
ceil(log2(100)) = 7 downto 0.
Wieder ein Bit zuviel: 6 downto 0 würden hier reichen.
BTW: ich würde in diesem Fall hier den Vorteiler tickcounter sowieso
einfach als integer durchgehen lassen. Da spart man sich die ganze
Rechnerei... ;-)
Lothar du hast mich überzeugt.
constant tick : integer := (clk_freq/10E6);
signal tickcounter : integer range 0 to tick-1;
Synthesizing Unit <i2c_master>.
Related source file is
"/home/red/softcore/mais2/rtl/device/i2c_master/I2C_master.vhd".
clk_freq = 80000000
Found 1-bit register for signal <start_A_d1>.
Found 3-bit register for signal <tickcounter>.
Found 1-bit register for signal <tick_event>.
Found 1-bit register for signal <SCL_falling>.
Found 8-bit register for signal <SCL_counter>.
Found 4-bit register for signal <bit_counter>.
80E6/10E6=8
0...7 Zählerwerte braucht 3 Signalleitungen
Und die ISE kapiert es auch.
Der Code sieht auch schöner aus.
René D. schrieb:> Der Code sieht auch schöner aus.
So ist es.
Nur, wenn du den impliziten Zählerüberlauf z.B. eines 4-Bit Zäahlers von
15 nach 0 haben möchtest, ist die unsigned Variante schöner zu lesen.
Aber auch ein integer Zähler, der explizit von 15 auf 0 gesetzt werden
muss, ergibt den selben Ressourcenbedarf:
1
signalcntu:unsigned(3downto0):=(others=>'0');
2
signalcnti:integerrange0to15:=0;
3
4
:
5
:
6
7
processbegin
8
waituntilrising_edge(clk);
9
10
-- unsigned Zähler mit implizitem Überlauf
11
cntu<=cntu+'1';
12
13
-- integer Zähler mit explizitem Überlauf
14
ifcnti<15then
15
cnti<=cnti+1;
16
else
17
cnti<=0;
18
endif;
19
20
--> beide Varianten bringen das selbe Synteseergebnis