Forum: FPGA, VHDL & Co. Counter mit Datentyp natural


von Marco (mannmitbart)


Lesenswert?

Hallo,
ich bin der aus Beitrag "Setzen einzelner Stellen eines std_logic_vector" und 
habe mir jetzt mal einen Account angelegt...
In den Lehrbüchern heißt es, dass für einen Zähler bzw. arithmetische 
Operationen am besten Signed oder Unsigned verwendet werden sollte.
In meiner Schaltung verwendete ich ausschließlich natural, was auch 
einwandfrei zu synthetisieren war. Gibt es einen Grund es nicht so zu 
machen?
1
entity Beispiel is
2
    generic (ANZAHL:natural:=10);
3
    Port
4
    
5
    (   CLK, RST  : in  STD_LOGIC;
6
        DOUT      : out STD_LOGIC);
7
end Beispiel;
8
9
architecture Behavioral of Beispiel is
10
    constant MAXCOUNT1: natural range 0 to (ANZAHL+10):= (ANZAHL+10);
11
    constant MAXCOUNT2: natural range 0 to ANZAHL:= ANZAHL;
12
    
13
    signal COUNTER1: natural range 0 to (ANZAHL+10):= 0;
14
    
15
begin
16
p1: process(CLK, RST)
17
variable COUNTER2: natural range 0 to MAX:=0;
18
begin
19
    if(RST = '1') then
20
        COUNTER1 := 0;
21
        COUNTER2 := 0;
22
    elsif rising_edge(CLK) then
23
        COUNTER1 := COUNTER1 + 1; 
24
        COUNTER2 := COUNTER2 + 1;
25
    end if;            
26
end process;
27
   
28
end Behavioral;

Der Code ist nicht vollständig und soll nur zeigen was ich meine. Mit 
unsigned hätte ich das Problem, dass zuvor die Länge des unsigned 
Vektors bekannt sein muss. Allerdings wollte ich die Parameter der 
Schaltung zentral konfigurierbar machen und bin mir nicht sicher wie 
man, ohne IEEE.math_real mit log2(real(max_val)) auf die Breite kommt. 
Vielleicht hat jemand eine Idee wie ich das lösen könnte.
Oder kann man es einfach so lassen?
Viele Grüße

: Bearbeitet durch User
von Duke Scarring (Gast)


Lesenswert?

Natural geht auch, wenn man einen range angibt. Nur falls es mal aus dem 
FPGA rausgehen soll, benötigt man zwei Umwandlungen:
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std
signed/unsigned ist eben die 'goldene Mitte'.

Die log2 aus der math_real kann man nach meiner Erfahrung problemlos 
verwenden. Die Bitbreite ist ja i.d.R. zum Synthesezeitpunkt statisch.

Duke

von Marco (mannmitbart)


Lesenswert?

Super, danke.

von Ent-Schnitzer (Gast)


Lesenswert?

Zeile 19: Die Klammern beim if sind unnötig
Zeile 20: signal velangt '<=' als Zuweisungsoperator

Zeile 3: man kann zuerst einen type definieren, dann hate man mit 'high 
und 'low Zuigriff auf die grenzen.

1
    typedef T_COUNTER1 is natural range 0 to (ANZAHL+10);
2
    signal COUNTER1: T_COUNTER1 := T_COUNTER1'low; -- unnötige signalinitialisierung, bringt Punktabzug
3
4
--im Process auch
5
6
if COUNTER1 = T_COUNTER'high then
7
 COUNTER1 <= T_COUNTER'low;
8
else
9
   COUNTER <= Counter + 1; 
10
end if;

von Marco (mannmitbart)


Lesenswert?

Ent-Schnitzer schrieb:
> Zeile 20: signal velangt '<=' als Zuweisungsoperator

Ja stimmt, habe ich hier übersehen.

Ent-Schnitzer schrieb:
> typedef T_COUNTER1 is natural range 0 to (ANZAHL+10);
>     signal COUNTER1: T_COUNTER1 := T_COUNTER1'low;

Die Konstanten sind gemeint oder? Weil das auch mit T_COUNTER'high 
angegeben werden kann.

: Bearbeitet durch User
von Ent-Schnitzer (Gast)


Lesenswert?

Marco schrieb:
> Ent-Schnitzer schrieb:
>> Zeile 20: signal velangt '<=' als Zuweisungsoperator
>
> Ja stimmt, habe ich hier übersehen.
>
> Ent-Schnitzer schrieb:
>> typedef T_COUNTER1 is natural range 0 to (ANZAHL+10);
>>     signal COUNTER1: T_COUNTER1 := T_COUNTER1'low;
>
> Die Konstanten sind gemeint oder? Weil das auch mit T_COUNTER'high
> angegeben werden kann.

Die ganze typedekleration ist die 'Konstante'. Da haste alles an einer 
Code-Stelle, obere wie untere Grenze und musst nicht mit zwei Constanten 
arbeiten.
Siehe VHDL-Attribute: 
https://redirect.cs.umbc.edu/portal/help/VHDL/attribute.html


Wobei subtype statt typedef die korrekte Wahl ist. Etwa wie in: 
https://www.mikrocontroller.net/attachment/581236/single_led-cynchron.vhd

von Hallooooo (Gast)


Lesenswert?

Es ist in der Tat möglich, dass "natural" die bequemste Wahl für 
arithmetische Operationen in einem Zähler ist, da es keine Begrenzungen 
auf die maximale Anzahl der Bits hat und es automatisch die richtige 
Anzahl der Bits für den Zähler berechnet. Es gibt jedoch auch Nachteile 
bei der Verwendung von "natural", da es möglicherweise zu Überläufen 
führen kann, falls die maximale Anzahl der Bits nicht korrekt berechnet 
wurde.

Da du die Schaltung zentral konfigurierbar machen wollen, könnsten du 
die Breite des Zählers auf Basis des generischen Parameters ANZAHL 
berechnen. Hier ist ein Beispiel, wie du das tun kannst:


constant MAXCOUNT: natural range 0 to ANZAHL:= ANZAHL;
constant ZAEHLERBREITE: integer:=ceil(log2(real(MAXCOUNT)));
signal COUNTER: unsigned(ZAEHLERBREITE-1 downto 0) := (others => '0');

Dieser Code berechnet die Breite des Zählers basierend auf dem 
generischen Parameter ANZAHL und deklariert den Zähler als "unsigned" 
mit der berechneten Breite. Beachten Sie, dass ich hier die 
VHDL-Funktion "ceil" verwendet habe, die den nächst höheren ganzzahligen 
Wert zurückgibt, um sicherzustellen, dass die Zählerbreite groß genug 
ist, um alle möglichen Zählerwerte aufzunehmen.

Letztlich hängt die Wahl zwischen "natural" oder "unsigned" von deinen 
spezifischen Anforderungen und Bedenken ab. Wenn du sicher bist, dass 
deine Schaltung korrekt funktionieren wird, wenn du "natural" verwenden, 
kannst du es einfach so lassen. Andernfalls kannst du die Breite des 
Zählers berechnen und ihn als "unsigned" deklarieren, um 
sicherzustellen, dass es keine Überläufe gibt.

von Markus F. (mfro)


Lesenswert?

Hallooooo schrieb:
> Es ist in der Tat möglich

Typische ChatBot AI-Antwort.

Episches Rumgelabere und am Ende ist die Antwort eben doch 
grottenfalsch.

Natural kann man tatsächlich prima als Zähler einsetzen, aber der 
Datentyp hat nun mal keineswegs "keine Beschränkung in der Anzahl der 
Bits". Im Gegenteil - bei praktische allen Tools ist beim Wertebereich 
bei 2 ** 31 - 1 Schluss (und das ist auch der Grund dafür, warum 
UNSIGNED oft die bessere Wahl ist)..

von ENT-schnitzer (Gast)


Lesenswert?

Markus F. schrieb:
> (und das ist auch der Grund dafür, warum
> UNSIGNED oft die bessere Wahl ist)..

Und wer weiterdenkt kommt auf "ganz wilde" Zähler, die nicht wie die 
dummen Hühner 1,2,3,4,5,6 .... die Körner wegpicken, sondern bspw. 
1,3,7,5,4 . Brauchen die selben ressourcen aber weniger Strom und sind 
Fehlertoleranter. (Gray-encoded counter). Oder LFSR basierte Counter als 
Schnellläufer, ...

https://hackaday.com/2014/06/29/counting-really-really-fast-with-an-fpga/

Das macht man dann eher mit std_logic_vector.

von ... (Gast)


Lesenswert?

> Im Gegenteil - bei praktische allen Tools ist beim Wertebereich
> bei 2 ** 31 - 1 Schluss (und das ist auch der Grund dafür, warum
> UNSIGNED oft die bessere Wahl ist)..

Danke fuer die schnelle Korrektur.
Ich dachte schon ich bin im falschen Film.

von ENT-schnitzer (Gast)


Lesenswert?

Markus F. schrieb:
> Natural ... aber der
> Datentyp hat nun mal keineswegs "keine Beschränkung in der Anzahl der
> Bits". Im Gegenteil - bei praktische allen Tools ist beim Wertebereich
> bei 2 ** 31 - 1 Schluss

Weil natural ein subtype von Integer ist:
https://www.allaboutcircuits.com/technical-articles/integer-and-its-subtypes-in-vhdl/

In der letzte Fassung von VHDL, VHDL-2019, soll der integer auf 64 bit 
aufgepumpt wurden sein: https://vhdlwhiz.com/vhdl-2019/#long-integers

Ich kenne kein Tool, was diesen neumodischen Geschiss unterstützt.

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.