hallo.
ich habe zwar gelesen, das signalinitialisierungen im sinne der
synthetisierung manchmal nicht realisierbar sind, aber es schien mit die
einzige lösung für mein problem.
ich möchte einen frequenzteiler programmieren, der einen basistakt
entsprechende einer variablen frequenz an diese anpasst.
hier der code:
1
library IEEE;
2
use IEEE.std_logic_1164.all;
3
use ieee.std_logic_arith.all;
4
5
entity Teiler_Motor is
6
7
port (
8
CLK: in STD_LOGIC;
9
clk_m: out STD_LOGIC;
10
drehzahl: in STD_LOGIC_VECTOR(7 downto 0)
11
);
12
end Teiler_Motor ;
13
14
architecture behavior of Teiler_Motor is
15
16
signal n : integer :=13; -- standart-teilerverhätlnis
17
18
begin
19
20
process(drehzahl) -- wenn sich drehzahl ändert, wird teiler verhätlnis über for-schleife neu berechnet
process (CLK) -- frequenzteiler; gibt neue frequenz clk_m aus
48
49
variable Z : integer range 0 to 32000000;
50
51
begin
52
53
54
55
if CLK='1' and CLK'event then -- L/H-Flanke
56
57
if Z < n-1 then
58
Z := Z+1;
59
else
60
Z := 0;
61
end if;
62
63
if Z = 0 then
64
clk_m <= '1';
65
end if;
66
if Z = n/2 then
67
clk_m <= '0';
68
end if;
69
70
end if;
71
72
end process;
73
end behavior;
das standard-teiler verhältnis soll 13 sein.
daher die signalinitialisieren für n.
beim simulieren mit isim hat n allerdings den wert n.
woran kann das liegen?
grüße
weisti
process(drehzahl)-- wenn sich drehzahl ändert, wird teiler verhätlnis über for-schleife neu berechnet
Dass du dich da mal nicht täuschst. Was meinst du, wie dieser Prozess
umgesetzt wird? Sieh dir mal die Kombinatorik dazu an...
> if 1/n*takt = takt_d then
Willst du das nur simulieren, oder soll das mal in der Realität laufen?
> beim simulieren mit isim hat n allerdings den wert n.
Wie?
> woran kann das liegen?
Seis drum: dieser Wert 13 wird SOFORT bei Simulationsstart
überschrieben, weil dann jeder Prozess einmal aufgerufen wird. Und dann
passiert das:
1
n<=i;
BTW: Warum verwendest du so abartig viele Variablen?
danny w. schrieb:> if CLK='1' and CLK'event then -- L/H-Flanke>> if Z < n-1 then> Z := Z+1;> else> Z := 0;> end if;>> if Z = 0 then> clk_m <= '1';> end if;> if Z = n/2 then> clk_m <= '0';> end if;>> end if;
So werden im FPGA keine Takte erzeugt.
Mach dich mal schlau zum Thema "Clock-Enable"
> if CLK='1' and CLK'event then -- L/H-Flanke
Nein, das ist noch keine steigende Flanke. Da fehlt noch CLK'last='0'...
Oder nimm besser gleich die Funktion rising_edge(CLK).
danke fürdie antwort.
habe mich verschrieben.
ich wollte erklären, dass in der simulation n den wert 10 hat anstatt
13.
Das müsste doch auch so sein, denn der process danach wird ja nur
ausgeführt wenn sich das signal drehzahl ändert uund das tut es ja in
der simulation nicht.
Lothar Miller schrieb:>> if 1/n*takt = takt_d then> Willst du das nur simulieren, oder soll das mal in der Realität laufen?
das soll inder realität so laufen.
weiß noch nich ob es synthetisierbar ist.
Wieso wird bei simulaitonsbeginn jeder process gestartet? dann wäre die
simulation ja nich reßpärsentativ.
Ansonsten ist das natürlich die erklärung für n=10.
danny w. schrieb:> Wieso wird bei simulaitonsbeginn jeder process gestartet? dann wäre die> simulation ja nich reßpärsentativ.
Nein, nur DESHALB kann die Simulation zur Hardware passen. Denn aus
einem nicht getakteten Prozess kann nur Kombinatorik herauskommen. Und
die reagiert in der Realität auch nicht erst auf den ersten
Pegelwechsel!
> Ansonsten ist das natürlich die erklärung für n=10.
So ist es.
danny w. schrieb:> das soll inder realität so laufen.> weiß noch nich ob es synthetisierbar ist.
Da sehe ich Probelme auf dich zukommen...
Du kannst in VHDL nicht einfach mathematische Operationen wie * und /
hinschreiben. Das MUSS in Hardware umgesetzt werden, und zwar JEDE
einzelne Multiplikation. Wenn da 4 mal * steht, dann brauchst du 4
Multiplier GLEICHZEITIG in der Hardware. Divisionen können sowieso nur
mit extrem großem Hardwareaufwand realisiert werden (ausgenommen
Divisionen durch Zweierpotenzen 2,4,8,16,32...)
> > if CLK='1' and CLK'event then -- L/H-Flanke> Nein, das ist noch keine steigende Flanke. Da fehlt noch CLK'last='0'...
Der Gerechtigkeit halber muss man sagen, dass das aus historischer
Kompatibilität alle Synthese-Tools als rising_edge interpretieren und
man in der Simulation bei Takten eher selten U->1-Flanken hat, die da
Fehlauslösungen produzieren könnten. D.h. das könnte man ruhig lassen,
aber der Rest ist natürlich ziemlicher Käse...
danke für die antworten.
mal sehen was ich damit anfangen kann.
Lothar Miller schrieb:> Du kannst in VHDL nicht einfach mathematische Operationen wie * und /> hinschreiben. Das MUSS in Hardware umgesetzt werden, und zwar JEDE> einzelne Multiplikation. Wenn da 4 mal * steht, dann brauchst du 4> Multiplier GLEICHZEITIG in der Hardware. Divisionen können sowieso nur> mit extrem großem Hardwareaufwand realisiert werden (ausgenommen> Divisionen durch Zweierpotenzen 2,4,8,16,32...)
ja is schon klar, dass das umgesetzt werden muss. aber für einen teiler
brauch ich nun mal einen teiler ; ) ich kann nur zusehen das ich diese
operatoren nich so oft benutze.
und wenn schon was kann passieren, außer das die signallaufzeit steigt?
bin für aufklärungen offen.
Du willst wohl nicht unendlich viele Teiler, oder? Ich würde das Problem
für die benötigten Teiler mit einer Tabelle lösen. Einfach und in einem
Taktzyklus erledigt.
>ja is schon klar, dass das umgesetzt werden muss. aber für einen teiler>brauch ich nun mal einen teiler ; ) ich kann nur zusehen das ich diese>operatoren nich so oft benutze.
Was soll man sagen? Es gibt im Deutschen Großschreibung, verdammt
nochmal!
danny w. schrieb:> aber für einen teiler brauch ich nun mal einen teiler ; )> ich kann nur zusehen das ich diese operatoren nich so oft benutze.
Du brauchst nicht für jede Division gleich eine eigene Divisionseinheit.
In einem uC ist ja auch nur 1 Recheneinheit da, und die wird von einigen
Teilnehmern nacheinander benutzt.
> ja is schon klar, dass das umgesetzt werden muss.
Die Frage ist, ob die Synthese es umsetzen kann. Altera macht es (auf
Kosten der Ressourcen), Xilinx lässt dich (m.M. zu Recht) auflaufen,
Lattice genauso.
> und wenn schon was kann passieren, außer das die signallaufzeit steigt?
Dein FPGA wird wegen solcher unnötiger Berechnungen zu schnell zu klein.
> bin für aufklärungen offen.
Man vermeidet für solche stupiden Skalierungsaufgaben so weit wie
möglich eine Division.
Man arbeitet nicht mit uneingeschränkten Integern (denn dann macht die
Synthese immer 32Bit Berechnungen, und erst die Optimierungsschritte
später müssen mühsam herauspfriemeln, was eigentlich wirklich nötig
ist).
Man macht sich vorher Gedanken, wie eine Aufgabe effizient lösbar ist.
Man beachtet (inbesondere als Anfänger) meine Postulate:
1
Ein Design (insbesondere ein Anfängerdesign) hat genau 1 Takt,
2
der immer auf dieselbe Flanke aktiv ist.
3
Es gibt keinen (und schon gar keinen asynchronen) Reset.
4
Externe Signale werden über 2 Flipflops einsynchronisiert.
5
Jede Abweichung von diesen Regeln muß fundiert begründet werden können.
pedro schrieb:> Du willst wohl nicht unendlich viele Teiler, oder? Ich würde das Problem> für die benötigten Teiler mit einer Tabelle lösen. Einfach und in einem> Taktzyklus erledigt.
du meinst so eine lookup-tabelle?
aber das is doch ein rießiger code- und datenaufwand. ich kann mir das
nich so recht vorstellen. Es geht ja um teilerverhältnisse von 1 bis
32000000.
Oder wie meinst du das?
danny w. schrieb:> Es geht ja um teilerverhältnisse von 1 bis 32000000.
Ich frage dich, ob du das brauchst, wenn dein Eingangswort sowieso nur
256 verschiedene Stufen zulässt...
Also kann die Lookup Tabelle auch nur maximal 256 Einträge haben.
Bastian schrieb:> Vielleicht geht es ihm um die Rundung der Werte?
Auch dann kann die Tabelle nur 256 Einträge haben. Weil der
Eingangsvektor nur 256 Auswahlmöglichkeiten bietet.
ok.
aber ist nicht trotzdem zu aufwendig eine tabelle für 256 fälle zu
implementieren?
Wenn nicht:
Würde ich dann eine case verzeigung für 256 fälle schreiben?
danny w. schrieb:> Würde ich dann eine case verzeigung für 256 fälle schreiben?
Das kannst du machen.
Weil ausser dir immer noch keiner weiß, welche zeilplattform du
verwendest, Hier die Reglen für Xilinx:
Der Synthesizer macht dann ein distributed RAM wenn du das einfach so
als kombinatorisches case hinschreibst (weil asynchron). Wenn du die
Adresse getaktet ans RAM anlegst, gibts ein BRAM:
http://www.lothar-miller.de/s9y/archives/20-RAM.html#extended
Mehr dazu im XST User Guide (such nach XST.PDF)
der FPGA kriegt durch einen Quarz den basistakt 32MHz.
is doch aus meinen obigen ausführungen zu entehmen.
und die ermittlung des Teilerverhältnisses kann denke ich durchaus
asynchron sein.
Was wäre denn die alternative zu einer case anweisung oder einfach nur
bedingten signalzuweisungen?
tatsache ist ja wohl das ich die ganzen 256 fälle einhacken muss. und
das führt dmich zu der überlegung ob des dann nich auch sehr viel daten-
oder verzweigungsaufand im fpga ist.
apropos: es soll auf einem spartan3 implementiert werden.
danny w. schrieb:> und die ermittlung des Teilerverhältnisses kann denke ich durchaus> asynchron sein.
Kann schon. Dann wird sie aber auch ständig auf Werte warten, die neu zu
berechnen sind. Das kostet Hardware und damit Geld.
Stell dir die Frage: ist das nötig?
> Was wäre denn die alternative zu einer case anweisung oder einfach nur> bedingten signalzuweisungen?> tatsache ist ja wohl das ich die ganzen 256 fälle einhacken muss.
Du könntest ein RAM mit einer Formel initialisieren, so wie ich es dort
unten mit dem Sinus mache:
http://www.lothar-miller.de/s9y/archives/37-DDFS-mit-BROM.html> das führt dmich zu der überlegung ob des dann nich auch sehr viel daten-> oder verzweigungsaufand im fpga ist.
Probier verschiedene Konfigurationen aus und sieh dir den Ressourcen-
verbrauch an. Diesen Vorgang nennt man "Lernen"... ;-)
hallo nochmal bzw. guten abend.
ich habe mir jetz folgendes überlegt:
ich addiere die gewünschte taktfrequenz so oft mit sich selbst bis sie
größer als die maximale frequenz (basistakt) ist, und zähle über eine
for-schleife die additionsschritte.
Die Anzahl der Schritte ist dann das zu berechnende Teilerverhältnis.
so habe ich auf jeden fall keine schleife mit divisionen.
das ganze sieht dann so aus.
1
libraryIEEE;
2
useIEEE.std_logic_1164.all;
3
useieee.std_logic_arith.all;
4
USEieee.std_logic_unsigned.ALL;
5
6
entityTeiler_Motoris
7
8
port(
9
CLK:inSTD_LOGIC;
10
clk_m:outSTD_LOGIC;
11
drehzahl:inSTD_LOGIC_VECTOR(7downto0)
12
);
13
endTeiler_Motor;
14
15
architecturebehaviorofTeiler_Motoris
16
17
signaltakt_d:integerrange0to850;
18
signaln:integer:=0;
19
signalloop_dz:integerrange0to32000850;
20
21
begin
22
takt_d<=conv_integer(drehzahl)*200/60;
23
24
process(takt_d)-- wenn sich drehzahl ändert, wird teiler verhätlnis über for-schleife neu berechnet
25
26
variabletakt:integer:=32000000;
27
variablei:integerrange0to256;
28
29
begin
30
31
foriin1to256loop
32
33
ifloop_dz<taktthen
34
35
loop_dz<=loop_dz+takt_d;
36
n<=n+1;
37
38
endif;
39
40
endloop;
41
endprocess;
42
43
44
process(CLK)-- frequenzteiler; gibt neue frequenz clk_m aus
45
46
variableZ:integerrange0to32000000;
47
48
begin
49
50
51
52
ifCLK='1'andCLK'eventthen-- L/H-Flanke
53
54
ifZ<n-1then
55
Z:=Z+1;
56
else
57
Z:=0;
58
endif;
59
60
ifZ=0then
61
clk_m<='1';
62
endif;
63
ifZ=n/2then
64
clk_m<='0';
65
endif;
66
67
endif;
68
69
endprocess;
70
endbehavior;
das eingangssignal drehzahl hat den wert 222. Es soll eine drehzahl pro
minute sein. kurz nebenbei: es soll ein schrittmotor mit dieser frequenz
angesteuert werden. Für diese Drehzahl ist dann ein Takt von 740Hz
notwendig (222*200/60).
Der basistakt clk hat 32MHz.
leider funkioniert auch das nicht.
In der Simulation bleibt n, also das teilerverhältnis, welches ich
berechnen möchte, bei 2, und loop_dz bei 740.
Eigtl. sollte n bis 43244 zählen und loop_dz auf bis ungefähr 32000000.
Nachvollziehbar? Wenn nein: bitte details erfragen. Würde mich freuen
wenn ich das mal hinbekomme.
Mir scheint, du verwechselst die FOR Anweisung in VHDL mit der
for-Schleife in C. Was in VHDL über for gemacht wird, wird parallel in
den Chip abgebildet. In deinem Fall hast du 256 parallel arbeitende
Vergleicher erzeugt. Löse dich bitte komplett von C und sequenziellem
Abarbeiten, wenn du mit VHDLHardware beschreibst. Das ist was völlig
anderes.
mein professor hat mir das so erklärt, dass über eine for schleife in
einem process einfach der jeweilige logik-block mehrmals benutzt wird,
da in einem process die anweisung sequentiell abgearbeitet werden.
hab ichs falsch verstanden? Es muss doch möglich sein auf hohe zahlen
hochzuzählen..
oder kann man das in der schaltungstechnik einfach nicht realisieren?
Klar geht das. Aber alles, was nacheinader ablaufen soll, musst du durch
eine State Machine und/oder Zähler beschreiben. So wie du die
for-schleife hingeschrieben hast, bedeutet das, dass der Vergleicher 256
mal parallel abgebildet wird. Du hast deinen Prof falsch verstanden. C
und VHDL sind was völlig anderes. In VHDL beschreibst du nur
Logik-Elemente und FlipFlops.
Christian R. schrieb:> Mir scheint, du verwechselst die FOR Anweisung in VHDL mit der> for-Schleife in C.
Mir auch: Beitrag "Re: CONV_INTEGER"danny w. schrieb:> mein professor hat mir das so erklärt
Wenn jemand nur einen Hammer hat/kennt, dann sieht die ganze Welt wie
ein Nagel aus. Blöd nur, wenn dann eine Schraube zu verarbeiten ist, und
dafür ein Schraubendreher das passende Werkzeug wäre. Man könnte
natürlich versuchen, die Schraube mit dem Hammer reinzudreschen...
Setze jemand=du, Hammer=C, Nagel=uC, Schraube=FPGA, Schraubendreher=VHDL
Lothar Miller schrieb:> Man könnte> natürlich versuchen, die Schraube mit dem Hammer reinzudreschen...
Geht. BTDT. Besser als man denkt. Zwar war der Schraubendreher
vorhanden, aber meinem Kollegen ging's zu langsam. :-)
Duke