Forum: FPGA, VHDL & Co. Allererster Versuch - Frequenzteiler


von Norbert S. (norberts)


Lesenswert?

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.
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity clock is
6
    Port ( clk : in  STD_LOGIC;
7
           clock_all : out  STD_LOGIC;
8
        divider : in STD_LOGIC_VECTOR (3 downto 0));
9
end clock;
10
11
architecture Divider of clock is
12
  signal count_to : integer range 0 to 2000 := 0;
13
  signal clock_counter : integer range 0 to 2000 := 0;
14
begin
15
16
  process (divider) begin
17
    case divider is
18
      when "0000" =>
19
        count_to := "1"
20
      when "0001" =>
21
        count_to := "2"
22
      when "0010" =>
23
        count_to := "5"
24
      when "0011" =>
25
        count_to := "10"
26
      when "0100" =>
27
        count_to := "20"
28
    end case
29
  end process;
30
  
31
  process (clk, count_to, clock_counter) begin
32
    wait until rising_edge(clk);
33
    if (clock_counter < count_to) then
34
        clock_counter <= clock_counter + 1;
35
      else
36
        clock_counter <= 0;
37
        clock_all <= not clock_all;
38
    end if
39
  end process;
40
41
end Divider;

Gruß,
Norbert

von Lattice User (Gast)


Lesenswert?

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.

von Norbert S. (norberts)


Lesenswert?

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

von Lattice User (Gast)


Lesenswert?

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.

von Lattice User (Gast)


Lesenswert?

Übrigens eine kleine Hausaufgabe:

Dein Frequenzteiler funktioniert zwar, teilt aber durch 4, 6, 12, 22, 
42.

von Norbert S. (norberts)


Lesenswert?

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

von Norbert S. (norberts)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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...

von Norbert S. (norberts)


Lesenswert?

Hi,

ich habs jetzt mal geändert und dann noch die ganzen Syntaxfehler 
korrigiert. Das implementiert jetzt zumindest ohne Fehlermeldungen:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity clock is
6
    Port ( clk : in  STD_LOGIC;
7
           clock_all : out  STD_LOGIC;
8
        divider : in STD_LOGIC_VECTOR (3 downto 0));
9
end clock;
10
11
architecture Divider of clock is
12
  signal count_to : integer range 0 to 2000 := 0;
13
  signal clock_counter : integer range 0 to 2000 := 0;
14
  signal clock_dvd : STD_LOGIC;
15
begin
16
  process (divider) begin
17
    case divider is
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
      when others =>
33
        count_to <= 1;
34
    end case;
35
  end process;
36
  
37
  process begin
38
    wait until rising_edge(clk);
39
    if (clock_counter < count_to) then
40
        clock_counter <= clock_counter + 1;
41
      else
42
        clock_counter <= 1;
43
        clock_dvd <= not clock_dvd;
44
    end if;
45
  end process;
46
  clock_all <= clock_dvd;
47
48
end Divider;

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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:
1
  architecture behave ... begin
2
    y <= a and b;        -- concurrent: implizite Sensitivliste
3
4
    process (a,b) begin  -- sequential: explizite Sensitivliste
5
       y <= a and b;
6
    end process;
7
  end behave;

> 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
  signal count_to : integer range 0 to 1999 := 0; 
2
  signal clock_counter : integer range 0 to 1999 := 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
  process begin
12
    wait until rising_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.

von Jonas B. (jibi)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jonas Biensack schrieb:
> Auf opencores gibt
> es ein SPI-Core der wohl ganz brauchbar zu funktionieren scheint.
Ja, nun, SPI ist kein Hexenwerk. Und ein SPI-Slave ist nur ein 
Schieberegister. Da bitte nicht gleich von einem "Core" sprechen...
http://www.lothar-miller.de/s9y/categories/17-SPI
http://www.lothar-miller.de/s9y/categories/26-SPI-Slave
http://www.lothar-miller.de/s9y/categories/45-SPI-Master

von Jonas B. (jibi)


Lesenswert?

@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

von Duke Scarring (Gast)


Lesenswert?

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

von Norbert S. (norberts)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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.

von Norbert S. (norberts)


Lesenswert?

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

von Jonas B. (jibi)


Lesenswert?

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

von Duke Scarring (Gast)


Lesenswert?

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

von Norbert S. (norberts)


Lesenswert?

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):
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
USE ieee.numeric_std.ALL;
4
 
5
ENTITY Divider_test IS
6
END Divider_test;
7
 
8
ARCHITECTURE behavior OF Divider_test IS 
9
    COMPONENT clock
10
    PORT(clk : IN  std_logic; clock_all : OUT  std_logic;
11
         divider : IN  std_logic_vector(3 downto 0));
12
    END COMPONENT;   
13
   signal clk : std_logic := '0';
14
   signal divider : std_logic_vector(3 downto 0);
15
   signal clock_all : std_logic;
16
  signal divider_cnt : std_logic_vector(3 downto 0);
17
  signal counter : integer range 0 to 999;
18
BEGIN
19
   uut: clock PORT MAP (clk => clk, clock_all => clock_all, divider => divider);
20
   clk <= not clk after 25ns;
21
  divider <= divider_cnt;
22
  process begin
23
    wait until rising_edge(clk);
24
    if  counter < 999 then
25
      counter <= counter + 1;
26
    else
27
      counter <= 0;
28
      divider_cnt <= divider_cnt + 1;
29
-- found '0' definitions of operator "+", cannot determine exact overloaded matching definition for "+"
30
    end if;
31
    if divider_cnt = "1000" then divider_cnt <= "0000";  
32
  end process;
33
-- Syntax error near "process".
34
END;

Es wäre toll, wenn ich noch ein paar Tips bekäme was da ev. sonst noch 
falsch ist.

Gruß,
Norbert

von Duke Scarring (Gast)


Lesenswert?

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:
1
signal divider_cnt : unsigned(3 downto 0);
2
...
3
BEGIN
4
...
5
divider <= std_logic_vector( divider_cnt);

Duke

von Norbert S. (norberts)


Lesenswert?

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
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity clock is
6
    Port ( clk : in  STD_LOGIC;
7
           clock_all : out  STD_LOGIC;
8
        divider : in STD_LOGIC_VECTOR (3 downto 0));
9
end clock;
10
11
architecture Divider of clock is
12
  signal count_to : integer range 0 to 1999 := 0;
13
  signal clock_counter : integer range 0 to 1999 := 0;
14
  signal clock_dvd : STD_LOGIC;
15
begin
16
  process (divider) begin
17
    case divider is
18
      when "0000" =>
19
        count_to <= 1-1;      --div by 2 ->50ns
20
      when "0001" =>
21
        count_to <= 2-1;       --div by 4 -> 100ns
22
      when "0010" =>
23
        count_to <= 4-1;       --div by 8 -> 200ns
24
      when "0011" =>
25
        count_to <= 10-1;       --div by 20  -> 500ns
26
      when "0100" =>
27
        count_to <= 20-1;     --div by 40 -> 1µs
28
      when "0101" =>
29
        count_to <= 40-1;     --div by 80 -> 2µs
30
      when "0111" =>
31
        count_to <= 100-1;     --div by 200 -> 5µs
32
      when others =>
33
        count_to <= 1-1;
34
    end case;
35
  end process;
36
  
37
  process begin
38
    wait until rising_edge(clk);
39
    if (clock_counter < count_to) then
40
        clock_counter <= clock_counter + 1;
41
      else
42
        clock_counter <= 0;
43
        clock_dvd <= not clock_dvd;
44
    end if;
45
  end process;
46
  clock_all <= clock_dvd;
47
48
end Divider;
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
USE ieee.numeric_std.ALL;
4
 
5
ENTITY Divider_test IS
6
END Divider_test;
7
 
8
ARCHITECTURE behavior OF Divider_test IS 
9
    COMPONENT clock
10
    PORT(clk : IN  std_logic; clock_all : OUT  std_logic;
11
         divider : IN  std_logic_vector(3 downto 0));
12
    END COMPONENT;   
13
   signal clk : std_logic := '0';
14
   signal divider : std_logic_vector(3 downto 0);
15
   signal clock_all : std_logic := '0';
16
  signal clock_dvd : std_logic := '0';
17
  signal divider_cnt : unsigned(3 downto 0) := (others=>'0');
18
  signal counter : integer range 0 to 999 :=0;
19
  signal clock_counter : integer range 0 to 1999 := 0;
20
  signal count_to : integer range 0 to 1999 := 0;
21
BEGIN
22
   uut: clock PORT MAP (clk => clk, clock_all => clock_all, divider => divider);
23
   clk <= not clk after 25ns;
24
  divider <= std_logic_vector(divider_cnt);
25
  process begin
26
    wait until rising_edge(clk);
27
    if  counter < 999 then
28
      counter <= counter + 1;
29
    else
30
      counter <= 0;
31
      divider_cnt <= divider_cnt + 1;
32
    end if;
33
    if divider_cnt = "1000" then
34
      divider_cnt <= "0000";
35
    end if;
36
  end process;
37
END;

von Norbert S. (norberts)


Lesenswert?

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

von Duke Scarring (Gast)


Angehängte Dateien:

Lesenswert?

1
$ vlib work
2
3
$ vcom divider.vhd
4
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

von Norbert S. (norberts)


Lesenswert?

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
wait until rising_edge(clk);
in
1
process (clk) begin 
2
if clk'event then
3
...
4
end if;
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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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?

von Norbert S. (norberts)


Lesenswert?

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

von Lattice User (Gast)


Lesenswert?

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.

von Norbert S. (norberts)


Lesenswert?

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

von W.S. (Gast)


Lesenswert?

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.

von Norbert S. (norberts)


Lesenswert?

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.

von Gustl B. (-gb-)


Angehängte Dateien:

Lesenswert?

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.
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use IEEE.numeric_std.all;
4
5
6
entity divider is
7
port (CLK1: in std_logic; --50mhz
8
    sw  : in std_logic_vector(7 downto 0);
9
    led : out std_logic_vector(7 downto 0));
10
end divider;
11
12
architecture behav of divider is
13
14
signal count_to     : integer range 0 to 20:=0;
15
signal clock_counter: integer range 0 to 20:=0;
16
signal divider        : std_logic_vector (3 downto 0);
17
signal clock_all      : std_logic;
18
19
signal led_counter  : integer range 0 to 50000000:=0;
20
21
begin
22
23
divider <= sw(3 downto 0);
24
25
process begin
26
    wait until rising_edge(CLK1);
27
  
28
  if    divider = "0000" then
29
    count_to <= 1;
30
  elsif divider = "0001" then
31
    count_to <= 2;
32
  elsif divider = "0010" then
33
    count_to <= 5;
34
  elsif divider = "0011" then
35
    count_to <= 10;
36
  elsif divider = "0100" then
37
    count_to <= 20;
38
  end if;
39
40
  if clock_counter < count_to then
41
    clock_counter <= clock_counter+1;
42
    clock_all <= '0';
43
  else
44
    clock_counter <= 0;
45
    clock_all <= '1';
46
  end if;    
47
end process;
48
49
process begin
50
    wait until rising_edge(clock_all);
51
   
52
  if led_counter < 50000000 then
53
    led_counter <= led_counter + 1;
54
  elsif led_counter = 50000000 then
55
    led_counter <= 0;
56
  end if;
57
   
58
end process;
59
60
led <= "00000000" when led_counter < 25000000 else "11111111";
61
62
end behav;

von Christian R. (supachris)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
signal led_counter  : integer range 0 to 50000000:=0;
2
3
  elsif led_counter = 50000000 then
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
  if led_counter < 50000000-1 then
2
    led_counter <= led_counter + 1;
3
  else
4
    led_counter <= 0;
5
  end if;
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
    wait until rising_edge(clock_all);
2
    wait until rising_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...

von Gustl B. (-gb-)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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...

von Gustl B. (-gb-)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von Gustl B. (-gb-)


Lesenswert?

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.
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use IEEE.numeric_std.all;
4
5
6
entity divider is
7
port (CLK1: in std_logic; --50mhz
8
    sw  : in std_logic_vector(7 downto 0);
9
    led : out std_logic_vector(7 downto 0));
10
end divider;
11
12
architecture behav of divider is
13
14
signal count_to     : integer range 0 to 20:=0;
15
signal clock_counter: integer range 0 to 20:=0;
16
signal divider        : std_logic_vector (3 downto 0);
17
signal clock_all      : std_logic;
18
19
signal led_counter  : integer range 0 to 50000000 - 1:=0;
20
21
begin
22
23
divider <= sw(3 downto 0);
24
25
process begin
26
    wait until rising_edge(CLK1);
27
  
28
  if    divider = "0000" then
29
    count_to <= 1;
30
  elsif divider = "0001" then
31
    count_to <= 2;
32
  elsif divider = "0010" then
33
    count_to <= 5;
34
  elsif divider = "0011" then
35
    count_to <= 10;
36
  elsif divider = "0100" then
37
    count_to <= 20;
38
  end if;
39
40
  if clock_counter < count_to then
41
    clock_counter <= clock_counter + 1;
42
    clock_all <= '0';
43
  else
44
    clock_counter <= 0;
45
    clock_all <= '1';
46
  end if;  
47
end process;  
48
49
process begin
50
    wait until rising_edge(CLK1);
51
  if clock_all = '1' then
52
    if led_counter < 50000000 - 1 then
53
      led_counter <= led_counter + 1;
54
    else
55
      led_counter <= 0;
56
    end if;
57
  end if;
58
  
59
end process;
60
61
led <= "00000000" when led_counter < 25000000 else "11111111";
62
63
end behav;

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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:
1
  led <= "00000000" when led_counter < 25000000 else "11111111";
-->
1
process begin
2
    wait until rising_edge(CLK1);
3
  if clock_all = '1' then
4
    if led_counter < 50000000 - 1 then
5
      led_counter <= led_counter + 1;
6
    else
7
      led_counter <= 0;
8
      
9
    end if;
10
    
11
    if (led_counter < 25000000) then 
12
       led <= x"00";
13
    else 
14
       led <= x"ff";
15
    end if;
16
  end if;
17
  
18
end process;
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...

von Duke Scarring (Gast)


Lesenswert?

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

von W.S. (Gast)


Lesenswert?

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.

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
Noch kein Account? Hier anmelden.