Forum: FPGA, VHDL & Co. vhdl: signalinitialisierung funktioniert nicht


von danny w. (weisti)


Lesenswert?

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
21
  
22
  variable dez_dz : integer := conv_integer(unsigned(drehzahl));
23
  variable takt_d : integer := dez_dz*200*60;
24
  variable takt : integer := 32000000;
25
  variable i : integer range 0 to 32000000;
26
  
27
  begin
28
  
29
  for i in 1 to 10 loop
30
    n<=i;
31
    if 1/n*takt = takt_d then
32
      exit;
33
    else
34
      if 1/n*takt < takt_d then
35
        exit;
36
        if 1/n*takt-takt_d>1/(n+1)*takt-takt_d then
37
          n<=n+1;
38
        
39
        end if;
40
      end if;
41
    end if;
42
  end loop;
43
  
44
  end process;
45
46
    
47
  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

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


Lesenswert?

danny w. schrieb:
1
 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).

von danny w. (weisti)


Lesenswert?

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.

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


Lesenswert?

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

von Georg A. (Gast)


Lesenswert?

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

von danny w. (weisti)


Lesenswert?

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.

von pedro (Gast)


Lesenswert?

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.

von Hip (Gast)


Lesenswert?

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

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


Lesenswert?

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.
Man verwendet Variablen nur, wenn man genau weiß, was man da tut.
Siehe dazu den Beitrag "Variable vs Signal"

von danny w. (weisti)


Lesenswert?

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?

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


Lesenswert?

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.

von Bastian (Gast)


Lesenswert?

Vielleicht geht es ihm um die Rundung der Werte?

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


Lesenswert?

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.

von danny w. (weisti)


Lesenswert?

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?

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


Lesenswert?

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)

von danny w. (weisti)


Lesenswert?

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.

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


Lesenswert?

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"...  ;-)

von danny w. (weisti)


Lesenswert?

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
library IEEE;
2
use IEEE.std_logic_1164.all; 
3
use ieee.std_logic_arith.all;
4
USE ieee.std_logic_unsigned.ALL;   
5
6
entity Teiler_Motor is
7
  
8
  port (
9
    CLK: in STD_LOGIC;
10
    clk_m: out STD_LOGIC;
11
    drehzahl: in STD_LOGIC_VECTOR(7 downto 0)
12
  );
13
end Teiler_Motor ;
14
15
architecture behavior of Teiler_Motor is
16
17
signal takt_d : integer range 0 to 850;
18
signal n : integer :=0;
19
signal loop_dz : integer range 0 to 32000850;
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
  variable takt : integer := 32000000;
27
  variable i : integer range 0 to 256;
28
  
29
  begin
30
  
31
  for i in 1 to 256 loop
32
  
33
    if loop_dz<takt then
34
  
35
      loop_dz<=loop_dz+takt_d;
36
      n<=n+1;
37
    
38
    end if;
39
      
40
  end loop;
41
  end process;
42
43
    
44
  process (CLK) -- frequenzteiler; gibt neue frequenz clk_m aus
45
  
46
  variable Z : integer range 0 to 32000000;
47
  
48
  begin
49
   
50
   
51
    
52
    if CLK='1' and CLK'event then     -- L/H-Flanke
53
54
      if Z < n-1 then
55
        Z := Z+1;
56
      else
57
      Z := 0;
58
      end if;
59
60
    if Z = 0 then 
61
        clk_m <= '1';
62
    end if;
63
    if Z = n/2 then 
64
      clk_m <= '0';    
65
    end if;   
66
    
67
    end if;
68
69
  end process;
70
end behavior;

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.

von Christian R. (supachris)


Lesenswert?

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 VHDL Hardware beschreibst. Das ist was völlig 
anderes.

von danny w. (weisti)


Lesenswert?

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?

von Christian R. (supachris)


Lesenswert?

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.

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


Lesenswert?

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

von Duke Scarring (Gast)


Lesenswert?

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

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.