Hi,
wie angedroht hier eine extreme Anfängerfrage.
Ich habe zwar reichlich gelesen aber leider oft nicht alles verstanden.
Mein erster Versuch ist ein variabler Frequenzteiler.
Ich denke es geht aus dem Quellcode hervor was ich vorhabe:
"clk" ist der Systemtakt, an den 4 bits "divider" liegt der Teiler an
(von einem AVR) und auf "clock_all" soll der geteilte Takt ausgegeben
werden.
Hier habe ich das nur bis zum Teiler 20 gemacht, später soll das in den
gleichen Schritten bis 2000 gehen.
Eine Testbench zu erstellen ist für mich noch extrem mühsam, ich würde
eher gerne wissen ob das vom Prinzip her so grob hinhaut oder ob ich da
elementare Dinge noch nicht richtig verstanden habe.
Also bitte Gnade bei der Kritik.
Im Process divider sollte eine default Zuweisung an count_to enthalten
sein.
Sonst hat du da die berüchigten Latches.
Der 2. Process braucht nur clk in der Sensitivitylist.
Hi,
Lattice User schrieb:> Im Process divider sollte eine default Zuweisung an count_to enthalten> sein.> Sonst hat du da die berüchigten Latches.
Ahh ja, sowas wie:
when others =>
count_to := "1"
Ist mir tatsächlich nicht ganz neu, undefinierter Zustand muß abgefangen
werden.
>> Der 2. Process braucht nur clk in der Sensitivitylist.
Weil count_to und clock_counter sowas wie lokale Variablen der ganzen
architecture und nicht nur des process sind?
Richtig?
Danke!
Gruß,
Norbert
Norbert S. schrieb:> Weil count_to und clock_counter sowas wie lokale Variablen der ganzen> architecture und nicht nur des process sind?> Richtig?
Nein, sondern weil es ein getakteter Prozess ist.
Lattice User schrieb:> Nein, sondern weil es ein getakteter Prozess ist.
Ich habe zwar eine grobe Ahnung was das mir sagen soll aber lese lieber
noch erstmal nach bevor ich weitere dumme Fragen stelle.
Das hat mir aber schon sehr weitergeholfen!
Gruß,
Norbert
Lattice User schrieb:> Dein Frequenzteiler funktioniert zwar, teilt aber durch 4, 6, 12, 22,> 42.
Hm, (* 2 + 2), das sollte lösbar sein.
Ja ok, vielleicht passt da die Logik noch nicht aber ich bin ja
scheinbar nicht völlig auf dem falschen Dampfer. Momentan bin ich noch
froh wenn da irgendwas überhaupt funktioniert. Morgen versuche ich mal
eine Testbench zu bauen.
Einen Schritt nach dem anderen und ich bin für heute einen Schritt
weiter.
Gruß,
Norbert
Norbert S. schrieb:> process (clk, count_to, clock_counter) begin> wait until rising_edge(clk);
Ein Prozess mit einem wait darf keine Sensitivliste haben!
Denn die Sensitivliste ist ja einfach eine andere Schreibweise für ein
wait.
> auf "clock_all" soll der geteilte Takt ausgegeben werden.
Der aber dann hoffentlich "nur" als Signal nach aussen geht und nicht
als neuer Takt im Baustein verwendet wird...
> count_to := "1"
Lass da doch einfach die Hochkommas weg. Ein Integer ist keine
Zeichenkette.
Lattice User schrieb:> Dein Frequenzteiler funktioniert zwar, teilt aber durch 4, 6, 12, 22,> 42.
Allseits beliebte Anfängerfehler... ;-)
Denkfehler 1:
Ein Zähler, von 0 bis 2 braucht 3 Takte: 0, 1, 2, 0, 1, 2, 0, 1, 2, ...
Denkfehler 2:
Einen Teiler 1 kann es nicht geben, denn das wäre ja kein richtiger
Teiler. Ein Flipflop das mit jedem Takt umschaltet, teilt schon durch
2...
Hi,
ich habs jetzt mal geändert und dann noch die ganzen Syntaxfehler
korrigiert. Das implementiert jetzt zumindest ohne Fehlermeldungen:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.NUMERIC_STD.ALL;
4
5
entityclockis
6
Port(clk:inSTD_LOGIC;
7
clock_all:outSTD_LOGIC;
8
divider:inSTD_LOGIC_VECTOR(3downto0));
9
endclock;
10
11
architectureDividerofclockis
12
signalcount_to:integerrange0to2000:=0;
13
signalclock_counter:integerrange0to2000:=0;
14
signalclock_dvd:STD_LOGIC;
15
begin
16
process(divider)begin
17
casedivideris
18
when"0000"=>
19
count_to<=1;--div by 2 ->50ns
20
when"0001"=>
21
count_to<=2;--div by 4 -> 100ns
22
when"0010"=>
23
count_to<=4;--div by 8 -> 200ns
24
when"0011"=>
25
count_to<=1;--div by 20 -> 500ns
26
when"0100"=>
27
count_to<=20;--div by 40 -> 1µs
28
when"0101"=>
29
count_to<=40;--div by 80 -> 2µs
30
when"0111"=>
31
count_to<=100;--div by 200 -> 5µs
32
whenothers=>
33
count_to<=1;
34
endcase;
35
endprocess;
36
37
processbegin
38
waituntilrising_edge(clk);
39
if(clock_counter<count_to)then
40
clock_counter<=clock_counter+1;
41
else
42
clock_counter<=1;
43
clock_dvd<=notclock_dvd;
44
endif;
45
endprocess;
46
clock_all<=clock_dvd;
47
48
endDivider;
Mit der Sensitivity list und "getakteter Prozess" sehe ich jetzt langsam
etwas klarer.
Dumme Frage: was ist der Unterschied zwischen dem Code in einem Prozess
und z.B. der Zeile clock_all <= clock_dvd;, die einfach so in der
architectural steht?
Der geteilte Takt geht zwar nach draussen aber den wollte ich auch an
anderen Stellen im Baustein benutzen. Wo ist da das Problem?
Naja, wie stelle ich das in einer anderen entity an?
Wenn ich mir das Beispiel freqm in ISE ansehe, da werden die Hexcodes
für die vier Stellen der Anzeige erzeugt aber ich sehe nirgendwo, wie
die HEX-Werte in die HEX2LEDs kommen. Doch wohl nicht etwa über
Hardware-Pins?
Oder packt man das dann besser alles in eine entity?
Vielleicht hilft es, wenn ich mal beschreibe, was das mal werden soll:
Ein einfaches DSO mit nem ATMega.
Der CPLD soll den geteilten Takt erzeugen und Sram-Adressen laufend
durchzählen. Der Sram hat 32kx8, also wird das ein 15bit Zähler.
Mit dem geteilten Takt werden die Daten von externen ADC in das Sram an
die entsprechende Adresse getaktet. Gleichzeitig sollen die Daten mit
einer von aussen (AVR) angelegten Triggerschwelle verglichen werden. Bei
Trigger werden noch 16k an Daten ausgelesen. Dann soll der AVR um den
Trigger herum erstmal 1k an Daten auslesen, dann den Rest. Das geht im
AVR sicher einfacher und das wird ohnehin vergleichsweise langsam
ablaufen, da es per Bluetooth rausgeschickt werden soll (deswegen auch
erstmal 1kByte für eine schnelle Anzeige).
Nächste Woche kommt wohl meine Starterboard mit nem XC2C256 aber ich
hoffe, daß das auch in nen kleineren Coolrunner passt. Alles was geht
kann und soll der AVR machen, das ist nicht das Problem.
Sorry, da fehlen mir noch so viele Grundlagen aber ich finde auch keine
kompakte verständliche Einführung für Leute wie mich, die nur mal ein
paar Bytes schneller als mit nem AVR rumschubsen wollen. Ich will ja
nicht übermorgen ne LTE-Basisstation häkeln...
Edit:
Ach ja, die Denkfehler bei der Teilerei sind peinlich, das hat ja
weniger was mit VHDL zu tun und hätte nicht passieren dürfen. Der
Hinweis von Lattice User hätte gereicht. Trotzdem natürlich danke für
die Erklärung.
Gruß,
Norbert
Norbert S. schrieb:> Dumme Frage: was ist der Unterschied zwischen dem Code in einem Prozess> und z.B. der Zeile clock_all <= clock_dvd;, die einfach so in der> architectural steht?
Der Code, der "einfach so" in der architecture steht, nennt sich
concurrent und ist praktisch ein "verkümmerter" Prozess mit impliziter
Sesitivitylist. Das hier macht jeweils exakt das selbe:
> Ach ja, die Denkfehler bei der Teilerei sind peinlich, das hat ja> weniger was mit VHDL zu tun und hätte nicht passieren dürfen.
Nein, du hast IMMER NOCH die flasche Denkweise:
Mit deine Rücksetzerei auf 1 verschenkst du die 0 als Zählerzustand!
Halb so schlimm bei solchen unbinären werten wie 5, 20, 100... Aber was,
wenn du 128 Schritte zäahlen willst? Oder 256, oder 1024? Dein Ansatz
mit 1...1024 braucht ein Flipflop mehr als meiner mit 0...1023 (oder
1..128 vs 0..127). Überleg mal, warum die Zählbereiche auf meiner HP
meist auf -1 enden (range 0 to 25000000-1 oder auch range o to 2**8-1).
Und gerade im CPLD kommt es auf jedes Flipflop an. Da sind eh so
wenige davon da...
Ergo müsste es richtigerweise so aussehen:
1
signalcount_to:integerrange0to1999:=0;
2
signalclock_counter:integerrange0to1999:=0;
3
4
when"0000"=>
5
count_to<=1-1;--div by 2 ->50ns
6
when"0001"=>
7
count_to<=2-1;--div by 4 -> 100ns
8
:
9
:
10
11
processbegin
12
waituntilrising_edge(clk);
13
if(clock_counter<count_to)then
14
clock_counter<=clock_counter+1;
15
else
16
clock_counter<=0;
17
:
> Der geteilte Takt geht zwar nach draussen aber den wollte ich auch an> anderen Stellen im Baustein benutzen. Wo ist da das Problem?
So erzeugt man üblicherweise keine Takte. Weil diese Aussage aber
hauptsächlich für komplexere FPGAs relevant ist, kannst du sie im CPLD
vorerst ignorieren.
> Wenn ich mir das Beispiel freqm in ISE ansehe, da werden die Hexcodes> für die vier Stellen der Anzeige erzeugt aber ich sehe nirgendwo, wie> die HEX-Werte in die HEX2LEDs kommen. Doch wohl nicht etwa über> Hardware-Pins?> Oder packt man das dann besser alles in eine entity?
Kannst du machen. Aber der übliche Weg ist, einzelne Funktionsgruppen in
eigene Entities zu stecken, und diese dann als Komponenten einzubinden.
So wie dort z.B. der PWM-Generator aus einer DDFS-Einheit und einer
PWM-Einheit eine Sinus-PWM erzeugt:
http://www.lothar-miller.de/s9y/archives/57-Sinusausgabe-mit-PWM.html
So kannst du z.B. die DDFS simulieren und die PWM simulieren, die beiden
dann anschliessend einfach verbinden und sagen: es läuft.
Moin,
@Norbert: Hättest du Lust auf ein Gemeinschaftsprojekt? Ich will mich
auch mal "wieder" ins Thema fpga einarbeiten. Eval-Board liegt hier rum.
Und ein kleines DSO bräucht ich auch schon lange. schmuntzel
Deinen Plan find ich gut, gerade ein Avr als Controller ist toll. Bloss
kein Picoblaze der selbst im Core läuft, da wirst du verrückt bei. Was
hälst du von SPI als Interface zwischen Avr und fpga? Auf opencores gibt
es ein SPI-Core der wohl ganz brauchbar zu funktionieren scheint. Was
benutzt'n fürn Softwarewerkzeuge?
Gruß Jonas
@Lothar: Danke Lothar für die Links, ich hab gerade mal ISE neu
installiert und ein VHDL-Modul plus Testbench erstellt, mit deinen
Cor... eh ich meine mit deinen Schieberegistern. Simulation hat mich
begeistert. Ich bin wieder infiziert...
Ich dachte mir nun als nächsten Schritt folgendes:
Bringe die Verbindung zwischen Avr und FPGA zu laufen. Mein FPGA Board
hat 8 Leds zur Ausgabe an Bord, damit könnte ich mir ja mal zum Testen
das erste Byte aus dem Rx Register anzeigen lassen.
Ich glaub so ne Debugausgabe ist ganz brauchbar..., oder was meinste?
@Norbert: Will deinen Thread nicht "voll müllen", also wenn's dir nicht
passt, sag bitte bescheid, dann mach in nen neuen auf.
Gruß Jonas
Jonas Biensack schrieb:> Ich glaub so ne Debugausgabe ist ganz brauchbar..., oder was meinste?LEDs zum Debuggen sind besser als nix.
Für statische Pegel noch ok, aber bei den heutigen Schaltzeiten der
Signale kommt für dynamische Sachen keine echte Freude auf. Da hilft
dann nur noch ein Oszi mit vielen Kanälen oder ein Logikanalyzer (intern
oder extern).
Aber das allermeiste wird durch eine gute Testbench vorher in der
Simulation geprüft.
Duke
Hi,
hm, also kann man straflos vieles auch ohne Prozess machen? Was ist denn
wirklich anders in einem Prozess?
Lothar Miller schrieb:> Nein, du hast IMMER NOCH die flasche Denkweise:
Is ja gut, 0-basiert zählen statt 1-basiert. Solange ich nur solche
"Fehler" mache... Aber danke für den Hinweis, das muß man erstmal
verinnerlichen, daß das hier ein Unterschied ist, bei µC ist es ja
wurscht.
Ok, wird geändert.
Lothar Miller schrieb:> So erzeugt man üblicherweise keine Takte. Weil diese Aussage aber> hauptsächlich für komplexere FPGAs relevant ist, kannst du sie im CPLD> vorerst ignorieren.
Ja, sowas würde ich gerne öfter lesen. Ich komme mir so vor als wenn ich
Führerschein für PKW machen will aber die Theoriekurse gibts nur
komplett inkl. Flugschein für Passagierverkehr.
So wie ich das jetzt sehe, komme ich für alle Basteleien locker mit den
Coolrunner II hin.
Lothar Miller schrieb:> Aber der übliche Weg ist, einzelne Funktionsgruppen in> eigene Entities zu stecken, und diese dann als Komponenten einzubinden.
Dann werde ich das auch so machen. Ich werde mir Dein Beispiel mal genau
ansehen, auf den ersten Blick scheint das ja nicht zu kompliziert zu
sein.
@Jonas:
Ich teile gerne meine Pläne aber ich finde gerade das Spannende daran
alles von a-z selbst zu machen, vor allem das, was neu für mich ist.
Wenn man sich über seine ähnlichen Projekte austauscht kann man sich
natürlich gegenseitig inspirieren.
Und soweit meine Meinung in diesem Punkt von Bedeutung ist: Anderes
Thema -> anderer Thead würde ich vorziehen. Meine Probleme liegen eher
nicht bei SPI sondern bei der Umsetzung von "irgendwas" in VHDL. Es wäre
wohl sinnvoll wenn es hier bei diesem Thema bleibt, denn ich werde
sicher noch ein paar weitere grundlegende Fragen haben.
Gruß,
Norbert
Norbert S. schrieb:> Ja, sowas würde ich gerne öfter lesen. Ich komme mir so vor als wenn ich> Führerschein für PKW machen will aber die Theoriekurse gibts nur> komplett inkl. Flugschein für Passagierverkehr.
Naja, die Theorie ist aber überall gleich und hat nichts mit dem Chip an
sich zu tun. Um mal bei deinem Vergleich zu bleiben (Flugzeug mal
ausgenommen): Du musst lernen, welche Seite der Straße man benutzt, wie
man die Spur hält, wie man abbiegt und was eine rote Ampel bedeutet.
Außerdem die wichtigsten Verkehrszeichen.
So ist es bei FPGA, CPLD ebenfalls. Du musst wissen, was ein Prozess
ist, wie synchrone Designs gemacht werden und wieso und außerdem die
wichtigsten Sprachelemente. Außerdem der Unterschied zwischen Variablen
und Signalen.
> So wie ich das jetzt sehe, komme ich für alle Basteleien locker mit den> Coolrunner II hin.
Hm, naja, das würde ich nun gerade nicht machen. Gerade für ein
Experimentierboard ist man dann schnell eingeschränkt. Lieber ein
kleines FPGA, da geht ein vielfaches von dem rein, was ein CPLD fasst.
Ein CPLD verwendet man eigentlich nur dann, wann man vorher ganz genau
weiß, wieviele FlipFlops benötigt werden. Die kleinen SPartan 6
beispielsweise gibts auch als TQFP und die benötigen auch nur noch 2
Spannungen.
Hi,
Christian R. schrieb:> Naja, die Theorie ist aber überall gleich und hat nichts mit dem Chip an> sich zu tun. Um mal bei deinem Vergleich zu bleiben (Flugzeug mal> ausgenommen): Du musst lernen, welche Seite der Straße man benutzt, wie> man die Spur hält, wie man abbiegt und was eine rote Ampel bedeutet.> Außerdem die wichtigsten Verkehrszeichen.>> So ist es bei FPGA, CPLD ebenfalls. Du musst wissen, was ein Prozess> ist, wie synchrone Designs gemacht werden und wieso und außerdem die> wichtigsten Sprachelemente. Außerdem der Unterschied zwischen Variablen> und Signalen.
Ja, genau diese Dinge versuche ich gerade zu verstehen bzw. muß ich
verstehen.
Aber sieh Dir mal die Tutorials an, da wird gleich noch Kreisverkehr,
Flughöhenwechsel und Landeanflug behandelt. Im Kapitel Abbiegen. Daß ich
das nicht wissen muß, wenn ich nur von einer Strasse auf die andere
fahren will wird nicht erwähnt, ist ja alles eine Art Abbiegen.
Und alles bevor mal erklärt wird, wo die Kupplung ist und wie man einen
Gang einlegt.
Christian R. schrieb:> Hm, naja, das würde ich nun gerade nicht machen.
Mein Frequenzteiler macht gerade 5-10% vom Coolrunner II 256. Wenn ich
das grob schätze, passt mein Projekt am Ende vielleicht sogar in einen
64er.
Alles was geht wird im µC gemacht, da ist es viel bequemer und vor allem
billiger.
Fazit:
Ich brauche nur einen Ersatz für Gattergräber, vielleicht einen Tick
mehr.
Ein µC wird immer dabei sein.
Der CPLD soll nur die ganz schnellen Sachen machen.
Der Einstieg ist dafür ist unnötig hoch.
Gruß,
Norbert
Moin Norbert,
SPI ist sicher nicht mein Problem, dafür habe ich schon zu viele LCD's,
SD Karten, ADC's, etc. über diesen erschlossen. ES sollte nur ein
Beispiel sein. Ich mach meinen eigenen Thread auf. Trotzdem viel Erfolg.
Gruß Jonas
Norbert S. schrieb:>> Nein, du hast IMMER NOCH die flasche Denkweise:>> Is ja gut, 0-basiert zählen statt 1-basiert. Solange ich nur solche> "Fehler" mache... Aber danke für den Hinweis, das muß man erstmal> verinnerlichen, daß d
Du hast immer noch die falsche Denkweise ;-)
Es geht darum, das man Hardware beshcreibt. Ähnlich, wie man mit HTML
ein Webseite beschreibt. Und es geht nicht darum, zu programmieren, so
wie man einen Prozessor programmiert.
Vielleicht hilft Dir am Anfeng der RTL-View weiter, den viele
Synthesizer eingebaut haben, gerade im Hinblick auf die Tatsache, das Du
TTL-Gräber vermeiden willst.
Duke
Hi,
ich nehme ja gerne die Ratschläge von den Spezis an, ja, ich beschreibe
Hardware, nein, das ist kein Programm sondern alles passiert erstmal
gleichzeitig. Aber bitte etwas Gnade, das ist für Neueinsteiger wirklich
alles nicht einfach.
Ich hab mich jetzt wieder drangemacht nach den letzten Änderungen und
versuche mich an der Testbench.
Nach vielen selbst gefundenen Fehlern bekomme ich jetzt noch folgende,
die ich nun überhaupt nicht verstehe (jeweils als Kommantar nach der
bemeckerten Zeile):
Norbert S. schrieb:> signal divider_cnt : std_logic_vector(3 downto 0);
Dein divider_cnt ist als std_logic_vector definiert. Damit rechnet man
nicht.
Versuch es mal so:
Hi,
danke, geht! Also zumindest der Teil.
if ... then ... in einer Zeile ohne end if; war auch noch falsch.
Ich möchte mich mal für die freundliche und geduldige Hilfe hier
bedanken. Das hat man nicht überall so.
Die Testbench selbst funktioniert in der Simulation, alles (divider,
divider_cnt, counter) zählt schön hoch und läuft über wie es soll aber
die Signale der Beschreibung "clock" funktionieren allesamt nicht.
clock_dvd, clock_counter und count_to bleiben dauerhaft 0 und clock_all
ist "U" (undefined oder sowas?).
Also alles so als wenn meine Beschreibung komplett ignoriert wird.
Ja, sie steht in der Hierarchie unter der Testbench.
Sorry, was ist da jetzt wieder falsch? Ich bin alles x-fach
durchgegangen aber jetzt komme ich mal wieder nicht weiter.
Bitte auch meckern, wenn ich nicht genug Infos liefere, ich geb mir
Mühe!
Es folgen die Beschreibung und danach die Testbench.
Gruß,
Norbert
Ergänzung:
Wenn ich in der Simulation "Show drivers" wähle, kommt für die Signale
die 0 sind "... has no drivers" und für clock_all (welches "U" ist) die
Zeile "clock_all <= clock_dvd;".
Die Prozesse in der "clock" werden irgendwie komplett ignoriert.
Gruß,
Norbert
Model Technology ModelSim PE vcom 10.1 Compiler 2011.12 Dec 6 2011
5
-- Loading package STANDARD
6
-- Loading package TEXTIO
7
-- Loading package std_logic_1164
8
-- Loading package NUMERIC_STD
9
-- Compiling entity clock
10
-- Compiling architecture Divider of clock
11
12
$ vcom divider_tb.vhd
13
Model Technology ModelSim PE vcom 10.1 Compiler 2011.12 Dec 6 2011
14
-- Loading package STANDARD
15
-- Loading package TEXTIO
16
-- Loading package std_logic_1164
17
-- Loading package NUMERIC_STD
18
-- Compiling entity Divider_test
19
-- Compiling architecture behavior of Divider_test
20
###### divider_tb.vhd(23): clk <= not clk after 25ns;
21
** Warning: [4] divider_tb.vhd(23): (vcom-1207) An abstract literal and an identifier must have a separator between them.
22
23
$ vsim -gui divider_test
24
# Loading std.standard
25
# Loading std.textio(body)
26
# Loading ieee.std_logic_1164(body)
27
# Loading ieee.numeric_std(body)
28
# Loading work.divider_test(behavior)
29
# Loading work.clock(divider)
30
> add wave *
31
> run 2 ms
Sieht soweit ganz gut aus.
Norbert S. schrieb:> clock_dvd, clock_counter und count_to bleiben dauerhaft 0 und clock_all> ist "U" (undefined oder sowas?).
Du hast Dich selber ausgetrickst :-)
Die Signale, die Du Dir anschaust sind in der Testbench definiert. Das
sind natürlich andere Signale als im DUT/UUT.
Und wenn Du clock_dvd noch einen Initialwert mitgibst, klappts auch
mit der Simlation (not 'U' ergibt wieder 'U').
Duke
Hi,
danke, danke, danke, Ihr seid wirklich Gold wert!
Das mit dem Initialwert habe ich nun auch geschnallt, durch den Fehler
auf die harte Tour, dafür jetzt nachhaltig.
Duke Scarring schrieb:> Die Signale, die Du Dir anschaust sind in der Testbench definiert. Das> sind natürlich andere Signale als im DUT/UUT.
Weia, das kommt davon wenn man keine Ahnung hat was man tut.
Ok, kapiert und ich hab auch rausgefunden, wie ich mir die internen
Signale der uut in der Simulation anzeigen lassen kann :-)
Ich habe jetzt auch das
1
waituntilrising_edge(clk);
in
1
process(clk)begin
2
ifclk'eventthen
3
...
4
endif;
geändert und funzt.
Jetzt habe ich das was ich wollte und eine Menge gelernt.
Ok, soweit erstmal gut, beim nächsten Problem mache ich nen anderen Tröd
auf.
Gruß,
Norbert
Norbert S. schrieb:> Ich habe jetzt auch das> wait until rising_edge(clk);> in> process (clk) begin> if clk'event then> ...> end if;> geändert
Du willst auf jede beliebige Änderung des Taktes reagieren?
Hört sich nach "Designfehler" an...
> und funzt.
Hat das vorher nicht gefunzt, oder warum hast du es geändert?
Hi,
Lothar Miller schrieb:> Du willst auf jede beliebige Änderung des Taktes reagieren?
Vorher war das ja ein Teiler von mindestens 2 wenn ich immer nur bei
steigender Flanke des Taktes gezählt habe.
Ich möchte aber auch gar nicht teilen können, also bei jeder Flanke.
In dem Fall könnte man natürlich auch direkt den Takt nehmen aber das
kommt mir gefühlt irgendwie unschön vor.
So wie es ist funktioniert es aber wenn das besser/effizienter geht -
nur her mit den Vorschlägen.
Gruß,
Norbert
Norbert S. schrieb:> Vorher war das ja ein Teiler von mindestens 2 wenn ich immer nur bei> steigender Flanke des Taktes gezählt habe.> Ich möchte aber auch gar nicht teilen können, also bei jeder Flanke.
Das funktioniert leider nur in der Simulation. Die FFs auf dem FPGA
können nur auf eine Flanke reagieren.
> In dem Fall könnte man natürlich auch direkt den Takt nehmen aber das> kommt mir gefühlt irgendwie unschön vor.
Da wäre jetzt angesagt die sowieso bessere Clockenable Methode
anzuwenden, dann kannst du intern auch durch 1 Teilen.
Hi,
Lattice User schrieb:> Das funktioniert leider nur in der Simulation. Die FFs auf dem FPGA> können nur auf eine Flanke reagieren.
Das ist gelinde gesagt etwas frustrierend, warum macht die Simulation
das dann?
Lattice User schrieb:> Clockenable Methode
Ich habe mir den Eintrag bei Lothar angesehen, den Artikel hier und bin
immer noch nicht schlauer wie das mit Clock Enable gehen sollte.
Ernsthafte Frage: Sollte ich das als blutiger Anfänger vielleicht
erstmal links liegen lassen und es so lassen wie vorher?
Ich will mich nicht in Details verrennen und mit dem halben Takt könnte
ich durchaus leben.
Gruß,
Norbert
Norbert S. schrieb:> Ernsthafte Frage: Sollte ich das als blutiger Anfänger vielleicht> erstmal links liegen lassen und...
Ich hab hier mal ein bissel mitgelesen und finde, daß die Leute, die dir
ihre Ratschläge geben, damit nicht gerade pädagogisch umgehen.
Beispiele:
(Duke Scarring:)
> Dein divider_cnt ist als std_logic_vector definiert. Damit rechnet man> nicht.
oder
> Du hast immer noch die falsche Denkweise ;-)> Es geht darum, das man Hardware beshcreibt.
Ich würde es für besser und instruktiver halten, wenn sowas nicht
einfach nur hingehauen, sondern erklärt wird. Warum (z.B.) "rechnet
man damit nicht"? Weil der Schreiber es so geschrieben hat, oder gibt's
dafür einen sachlichen Grund (den man auch beschreiben kann..)? Und
wie geht es denn nun, daß man Hardware beschreibt? Vielleicht wäre es
einsehbarer, wenn stattdessen stände: "Schau mal, beim Atmel hast du,
wenn du 10x eine Funktion aufrufst eben 10x hintereinander das selbe
Unterprogramm durchlaufen - wenn du aber bei VHDL 10x ein "PROCESS BEGIN
... END" hinschreibst, dann macht der Compiler daraus 10 Stücke Logik,
die alle parallel laufen und du müßtest..."
Also Norbert,
ich sehe in deinem Bemühen eigentlich nicht ein sondern zwei Probleme:
1. Problem: du musst dir vorher klargemacht haben, was für ein
Verhalten deine Logik eigentlich haben soll, bevor du auch nur den PC
einschaltest und den Texteditor für's Quellfile startest:
> Ich denke es geht aus dem Quellcode hervor was ich vorhabe:> "clk" ist der Systemtakt, an den 4 bits "divider" liegt der Teiler an> (von einem AVR) und auf "clock_all" soll der geteilte Takt ausgegeben> werden.
So herum wird nur Murks draus. Der Sinn des Vorhabens erklärt sich nicht
aus dem erstellten Quellcode. Mach dir lieber zuallererst einen Schrieb
auf Papier zurecht, wo du dein gewünschtes Verhalten definierst.
Beispiel:
a) Ich hab nen Eingang, wo ein Takt ins CPLD eingespeist wird.
b) Ich will einen Ausgang, wo der geteilte Takt wieder herauskommt.
c) Den Teilerfaktor will ich mit einem Code aus 4 Bit festlegen, die ich
an 4 Eingänge lege.
d) Ich nehme mir vor: (Beispiele von W.S.)
Code 0000 --> soll durch 1 teilen, also garnicht. Ausgang = Eingang
0001 --> soll durch 5 teilen
0010 --> soll durch 10 teilen
1000 --> soll durch 153 teilen
alle anderen Codes --> Ausgang soll einfach auf low gehen
Wenn du dir dein Vorhaben so oder ähnlich definiert hast, dann wird auch
die Umsetzung erleichtert.
2. Problem: Du hast nun ein Vorhaben - hoffentlich sauber genug
definiert - und willst dieses nun in einer Programmiersprache
formulieren, die du noch nicht wirklich kennst.
(ich schreibe hier ausdrücklich und provokativ PROGRAMMIERSPRACHE denn
sowas wie VHDL ist eben auch nur eine Programmiersprache - allerdings
mit Tücken, die ganz woanders liegen als dort, wo es um das Formulieren
von Code für deinen Atmel-Controller geht)
Also löse erst mal das 1. Problem und poste dann das Ergebnis. Wenn die
anderen das lesen und nachvollziehen können, ist es auch leichter,
treffsichere Ratschläge zu geben.
W.S.
Hi,
meine Fresse, da hat sich einer Mühe gegeben.
Allerdings bin ich für die Hinweise hier durchaus dankbar und habe sie
hoffentlich auch meist verstanden
W.S. schrieb:> Damit rechnet man>> nicht.
Das ist ein gutes Beispiel. Das ist ein Signal und damit kann ich nicht
rechnen. Das kann ich lesen oder dem was zuweisen, es ist aber eben
keine Variable, wie ich es von Programmiersprachen kenne. Verstanden.
1.)
Das habe ich doch klar definiert. Wenn ich dann bei steigender Flanke
meinen Zähler toggle und mich wundere, daß das schon durch 2 teilt -
solche Banalitäten sollte ich dann schon selbst finden.
2:)
Ich habe Probleme mit Datentypen, was ist ein Signal, was ist ein
unsigned usw... Meine geplante Anwendung ist ja eher Pipifax und das
Konzept ist zwar nicht banal aber das kriege ich schon hin.
Ich denke schon, daß ich auf dem richtigen Weg bin und die Beiträge hier
haben mir enorm geholfen.
Trotzdem danke für Deinen umfangreichen Beitrag, Teile davon muß ich
auch noch erstmal verarbeiten.
Gruß,
Norbert.
Hallo, ich hab das mal für das Digilent Basys geschrieben (xc3s100e).
Als divider werden die Switches 3...0 verwendet. Wenn der divider "0000"
ist, blinken die LEDs im 2-Sekundentakt, es wird ja immer bis 1 gezählt
und dann auf 0 gesetzt, also der Takt halbiert. Ich lasse dann mit dem
neuen Takt clock_all bis 50000000 zählen (50mhz ist Eingangstakt). Die
LEDs sind aus wenn der Zähler led_counter < 25000000 ist und leuchten
wenn er größer ist.
Bei divider "0001" wird bis 2 gezählt, also blinken die im
3-Sekundentakt und bei divider "0100" wird bis 20 gezählt, also
21-Sekundentakt.
Norbert S. schrieb:> Das ist ein gutes Beispiel. Das ist ein Signal und damit kann ich nicht> rechnen. Das kann ich lesen oder dem was zuweisen, es ist aber eben> keine Variable, wie ich es von Programmiersprachen kenne. Verstanden.
Nee, darum gehts nicht. Man kann und muss mit Signalen durchaus rechnen.
Nur eben nicht mit Vektoren. Mit signed/unsigned kannst du eindeutige
Rechnungen durchführen. Ein Vektor kann ja alles mögliche darstellen. Da
ist nicht explizit angegeben, ob das eine signed oder unsigned Zahl oder
was ganz anderes sein soll.
Variablen brauchst du als Anfänger erst mal überhaupt nicht. Variablen
in VHDL machen was gänzlich anderes als in Programmiersprachen.
Und wie schon mehfach gesagt, bei weitem nicht alles, was in der
Simulation klappt, geht auch in Hardware. VHDL ist zwar sehr mächtig,
aber auf dem FPGA/CPLD läuft allenfalls 5% davon. Du musst dir immer
vorstellen, dass VHDL für FPGA/CPLD "nur" eine ascii- Beschreibung
eines Digital-Schaltplanes ist. Und in diesem Schaltplan kann es erst
mal nur FlipFlops und Logik-Gatter und Leitungen geben.
Norbert S. schrieb:> Das ist ein Signal und damit kann ich nicht rechnen.
Doch natürlich: mit Signalen kann man problemlos rechnen. Aber man
sollte es dann nicht tun, wenn diese Signale den Datentyp
std_logic_vector besitzen (genausowenig sollte man aber auch mit
Variablen rechnen, die den Typ std_logic_vector haben).
Der Hintergrund: ein std_logic_vector ist ein Zwitter (eigentlich noch
viel mehr, weil std_logic neunwertig ist), der gleichzeitig signed oder
unsigned sein kann. Je nach dem, wie man ihn ansieht kann der 8-Bit
Vektor 11111111 entweder 255 oder -1 sein...
> Weil der Schreiber es so geschrieben hat, oder gibt's> dafür einen sachlichen Grund (den man auch beschreiben kann..)?
Man könnte so eine Aussage z.B. auch als Ausgangspunkt nehmen, hier im
Forum (oder von mir aus auch wltweit) mal danach zu suchen, weil es ja
sein könnte, dass diese Frage nicht zum ersten Mal gestellt wurde...
Mit dieser Suche:
http://www.mikrocontroller.net/search?query=mit+std_logic+rechnet+man+nicht&forums[]=9&max_age=-&sort_by_date=1
findet man dann leicht den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete"
1
signalled_counter:integerrange0to50000000:=0;
2
3
elsifled_counter=50000000then
4
led_counter<=0;
1. Ich hatte es schon mal erwähnt: du zählst hier 50000001 Takte!
Das ist bei 50Mio nicht schlimm, bei einem Zähler für 8 Ereignisse macht
es aber schon 12% aus...
1
ifled_counter<50000000-1then
2
led_counter<=led_counter+1;
3
else
4
led_counter<=0;
5
endif;
2. Der GLEICH-Vergleich ist unnötig, denn wie sollte der Zähler einen
Wert über 50000000 annehmen? Ich würde es also so schreiben:
1
waituntilrising_edge(clock_all);
2
waituntilrising_edge(CLK1);
3. Es gibt in einem Anfängerdesign nur 1 (einen einzigen) Takt. Der Rest
wird mit Clock-Enables gemacht.
Wenn du das mit dem Enable nicht ganz gebucht hast, dann sieh dir mal
das an:
http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html
Dort gibt es einen Taktteiler, der ein Clock-Enable für das Lauflicht
erzeugt...
Ja, ist mir alles klar, aber es sollte schnell gehen und es
funktioniert.
Das mit den Clock-Enables verstehe ich nicht, also ich verstehe was das
ist aber was habe ich da falsch gemacht? Ich verwende das erste mal
einen getakteten Prozess mit dem Originaltakt und dann zum LED
blinkenlassen einen Weiteren mit dem neuen Takt als Eingangstakt.
Oder willst du darauf hinaus, dass ich nur einen Takt verwenden sollte?
Das geht natürlich auch, aber so war es für mich einfacher.
Das Problem mit mehreren Takten ist bei mir immer ein Problem wenn die
jeweiligen Daten nur kurzzeitig anliegen und an einen Prozess mit einem
anderen Takt übergeben werden. Dann muss man das schön synchronisieren.
Gustl Buheitel schrieb:> Oder willst du darauf hinaus, dass ich nur einen Takt verwenden sollte?
Ja, GENAU das.
> Das geht natürlich auch, aber so war es für mich einfacher.
Wenn du dir diesen falschen Designstil jetzt am Anfang beibringst, dann
machst du das später auch mal, weil es "einfacher" ist. Aber es wird
dadurch, dass es "einfacher" ist nicht automatisch auch "richtiger"! Ein
Kleiner Merksatz: innerhalb eines FPGAs werden so keine Takte erzeugt.
Wenn man dort abgeleitete Takte braucht, dann nimmt man einen
Taktmanager (DLL, PLL, DCM...).
Gustl Buheitel schrieb:> Das Problem mit mehreren Takten ist bei mir immer ein Problem wenn die> jeweiligen Daten nur kurzzeitig anliegen und an einen Prozess mit einem> anderen Takt übergeben werden. Dann muss man das schön synchronisieren.
Nicht nur dann.
Sieh dir einfach mal an, wie so ein abgeleiteter Takt intern als Takt
verwendet wird: das Taktsignal wird "händisch" durchverdrahtet, es wird
kein Taktnetz verwendet. Dadurch ergeben sich für die flipflops des
Zählers unterschiedlich lange Laufzeiten, bis der Takt am Takteingang
ankommt. Und es ist von der jeweiligen Platzierung abhängig, ob das
Design läuft oder nicht...
Hier ging es um blinkende LEDs, und den Teil mit den LEDs hab ich auch
nur gemacht um zu zeigen dass der neue Takt auch wirklich das ist was er
sein soll.
Ja, aber stimmt schon eigentlich soll man das nicht machen, vor allem
wenn es um Dinge geht die schnell sein sollen, also einen Takt für eine
RS232 runterteilen, das geht, aber ein RAM damit takten oder was das
schnell ist, das macht Probleme.
Wenn man frisch VHDL lernt sollte man es einfach komplett vermeiden. Ich
mach das jetzt seit wenigen Jahren und hab es leider nie wirklich
gelernt und auch kein Buch und auch keine Zeit das jetzt nebenher zu
lernen, da gewöhnt man sich schnell Dinge an die in Hardware im
konkreten Fall funktionieren, aber eigentlich vermieden werden sollten.
Also gleich richtig lernen.
Und vielen Dank Lothar, auch wenn du oft alles total kaputtkritisierst
und das erstmal frustrierend ist, so hat das durchaus Lernwert, auch
deine Seite mit den vielen nützlichen Beispielen.
Gustl Buheitel schrieb:> auch wenn du oft alles total kaputtkritisierst
Ja, erst mal eine volle Breitseite ...
> und das erstmal frustrierend ist
und dann, wenn sich der Rauch verzogen hat nachsehen, was noch übrig
ist.
;-)
> so hat das durchaus Lernwert
Das ist die eigentliche Absicht.
Gibt es noch was zu kritisieren?
Was auch cool wäre, wäre ein Online-Lernkurs. Also Jemand der das kann
stellt jede Woche oder so eine kleine Aufgabe die ein oder mehrere
Probleme verdeutlicht, und die wird dann gelöst von denen die mitmachen
wollen und in der darauffolgenden Woche werden alle eingeschickten
Lösungen online gestellt, verglichen, besprochen ... kostet leider Zeit
aber würde Vielen helfen.
Gustl Buheitel schrieb:> Gibt es noch was zu kritisieren?
Ja, klar... ;-)
Ich würde diesen kombinatorischen Vergleich noch in den getakteten Teil
nehmen, dann können am LED-Ausgang keine Glitches auftauchen:
Aber das ist wieder "nur" der Designstil. Bei LEDs wird es nichts
ausmachen, wenn die mal für ein paar ns flackern, für andere Signale ist
das evtl. h#ässlich...
W.S. schrieb:> Ich würde es für besser und instruktiver halten, wenn sowas nicht> einfach nur hingehauen, sondern erklärt wird. Warum (z.B.) "rechnet> man damit nicht"?
Danke für die Kritik. Ich werd mir mal ein paar Textbausteine
zurechtlegen, damit mit die Suchfunktion hier nicht so überlastet wird
;-)
Duke
Duke Scarring schrieb:> damit mit die Suchfunktion hier nicht so überlastet wird
Das ist nicht das eigentliche Thema, denn jemand, der ein Problem noch
nicht kennt, kann nach der Lösung des ihm unbekannten Problems auch
nicht suchen.
Ist doch eigentlich logisch. Gelle?
W.S.