Forum: FPGA, VHDL & Co. Initialwert und Reset


von Jan K. (frittenfett)


Lesenswert?

Hallo zusammen,

ich habe auf meinem DE0-Nano Board einen kleinen Test geschrieben, um 
ein bisschen mit Initialwerten und dem Reset herumzuspielen. Dabei ist 
mir eine, für mich überraschende, Sache aufgefallen:

Wenn ich ein Zählerregister mit einem Initialwert ungleich 0 versehe und 
im asynchronen Reset einen Wert ungleich dem Initialwert setze, dann 
wird der Initialwert ignoriert und beim Power On der Resertwert geladen. 
Dabei kommt in Quartus die Meldung:
1
Critical Warning (18061): Ignored Power-Up Level option on the following registers
2
  Critical Warning (18010): Register r_counter[0] will power up to Low
3
  Critical Warning (18010): Register r_counter[1] will power up to Low
4
  Critical Warning (18010): Register r_counter[2] will power up to Low
5
  Critical Warning (18010): Register r_counter[3] will power up to Low

Die Warnung ist verständlich, da er den Initialwert nicht verwendet.

Ich dachte, dass der Initialwert beim Power On gesetzt wird und der 
Resetwert erst beim Drücken der Resettaste.

Hier mein Testcode:
1
library IEEE;
2
use IEEE.std_logic_1164.all;
3
use IEEE.numeric_std.all;
4
5
entity chip_top is
6
port(
7
    clk50mhz            : in std_logic                              := '0';
8
    reset_n             : in std_logic                              := '0';
9
    
10
    key                 : in std_logic                              := '0';
11
    
12
    led                 : out std_logic_vector(7 downto 0)          := (others => '0')
13
);
14
end chip_top;
15
16
architecture chip_top_behavioral of chip_top is
17
signal r_counter        : unsigned(7 downto 0)                      := x"0F";
18
signal r_key_prev       : std_logic                                 := '0';
19
20
begin
21
22
counter_process : process(clk50mhz, reset_n)
23
begin
24
    if reset_n = '0' then
25
        r_counter <= x"FF";
26
    elsif rising_edge(clk50mhz) then
27
    if r_key_prev = '1' and key = '0' then
28
            r_counter <= r_counter + 1;
29
        end if;
30
        r_key_prev <= key;
31
    end if;
32
end process;
33
34
led <= std_logic_vector(r_counter);
35
36
end chip_top_behavioral;

Wenn ich den Reset synchron verwende, ist das Verhalten so wie ich es 
oben erwarte. Der Initialwert liegt beim Power On an und beim Drücken 
der Resettaste liegt der Resetwert an.

Meine Frage ist jetzt: Erkennt Quartus automatisch den asynchronen Reset 
und reagiert entsprechend? Gibt es dazu ein Paper oder eine andere 
Quelle?

Ich danke Euch für Eure Hilfe.

Liebe Grüße
Jan

von Wort Kauer (Gast)


Lesenswert?

Jan K. schrieb:
> Ich dachte, dass der Initialwert beim Power On gesetzt wird und der
> Resetwert erst beim Drücken der Resettaste.

Nein, der Initialwert ist i.A. nur für die Simu, aber nicht fürs real 
life.
Bei Xilinx ist das anders, bei altera (wie bei deinem Board) gilt die 
Regel, das PowerOnWerte (nur) durch einen Reset zu erreichen sind.

https://www.xilinx.com/support/documentation/white_papers/wp272.pdf



Ich plädiere dafür, den begriff 'Initialwert' aus den Bereich Hardware 
zu verbannen und nur von Reset- resp. PowerOn-Wert zu sprechen.
Und in einer Signaldeklaration keine init-zuweisung zu verwenden.

von FPGAzumSpass (Gast)


Lesenswert?

Ich verwende Initialwerte seit 10 Jahren bei Altera(Cyclone 2-5) und 
Xilinx(Virtex E bis 7er Series) ohne Probleme.
Benutze oft gar keine Resets, wenn überhaupt, dann immer synchrone 
Resets.

Kann mir vorstellen, das der asynchrone Reset für den Power On Reset mit 
verwendet wird und deswegen nicht unterschiedliche Werte geladen werden 
können.

von Sigi (Gast)


Lesenswert?

FPGAzumSpass schrieb:
> Ich verwende Initialwerte seit 10 Jahren bei Altera(Cyclone 2-5) und
> Xilinx(Virtex E bis 7er Series) ohne Probleme.
> Benutze oft gar keine Resets, wenn überhaupt, dann immer synchrone
> Resets.

Selbst bei älteren Altera-Produkten (APEX etc.) lassen sich
Initialwerte ohne Probleme verwenden, bei alten
Xilinx-FPGAs/CPLDs genauso. (ich glaube, schon bei den
XC2000ern liessen sich INIT-Werte definieren). Das Problem
bei älteren war aber, das da teils VHDL/Verilog erst in z.B.
ABEL oÄ übersetzt werden musste und dort dann kein INIT-Wert
unterstützt wurde.

Das Problem Oben ist leicht zu verstehen: der TO versucht
zum einen, einen INIT-Wert in der Definition zu setzen,
aber dann im Reset-Teil einen anderen Reset-Wert zu verwenden.
Es ist aber je FF nur ein INIT-Werte=Reset-Wert zugelassen.
Daraus folgt also der Konflikt.

von Jan K. (frittenfett)


Lesenswert?

Guten Morgen,

vielen Dank für Eure Antworten.

Ich habe die Implementierungen mal im RTL Viewer verglichen. Beim 
asynchronen Reset legt Quartus das reset_n Signal auf den CLR Eingang 
der Register. Beim synchronen Reset wird reset_n als Enable Signal 
verwendet.

Des Weiteren ist mir aufgefallen, dass Initialwerte zusätzliche 
Kombinatorik benötigen. Das ist eigentlich logisch, ich habe es nur 
nicht bedacht.

Nochmals vielen Dank. Jetzt bin ich schon wieder ein ganzes Stück 
weiter.

von Sigi (Gast)


Lesenswert?

Jan K. schrieb:
> Des Weiteren ist mir aufgefallen, dass Initialwerte zusätzliche
> Kombinatorik benötigen. Das ist eigentlich logisch, ich habe es nur
> nicht bedacht.

Nein, total falsch: INIT-Werte, egal welcher Pegel,
werden im Configurationstream abgelegt und beim
Start entsprechend gesetzt, und zwar ohne zusätzliche
Logik.

von Jan K. (frittenfett)


Lesenswert?

Sigi schrieb:
> Nein, total falsch: INIT-Werte, egal welcher Pegel,
> werden im Configurationstream abgelegt und beim
> Start entsprechend gesetzt, und zwar ohne zusätzliche
> Logik.

Ich verwende diesen Code:
1
library IEEE;
2
use IEEE.std_logic_1164.all;
3
use IEEE.numeric_std.all;
4
5
entity chip_top is
6
port(
7
    clk50mhz                        : in std_logic;
8
    reset_n                         : in std_logic;
9
    
10
    key                             : in std_logic;
11
    
12
    led                             : out std_logic_vector(7 downto 0)
13
);
14
end chip_top;
15
16
architecture chip_top_behavioral of chip_top is
17
signal r_counter                    : unsigned(7 downto 0)          := x"00";
18
--signal r_counter                    : unsigned(7 downto 0)          := x"FF";
19
signal r_key_prev                   : std_logic;
20
21
begin
22
23
counter_process : process(clk50mhz, reset_n)
24
begin
25
    if rising_edge(clk50mhz) then
26
        if r_key_prev = '1' and key = '0' then
27
            r_counter <= r_counter + 1;
28
        end if;
29
        r_key_prev <= key;
30
    end if;
31
end process;
32
33
led <= std_logic_vector(r_counter);
34
35
end chip_top_behavioral;

Im ersten Fall setze ich für r_counter einen Initialwert von x"00". 
Quartus liefert mir in der Zusammenfassung:
1
Flow Status                 Successful - Thu Mar 19 08:20:08 2020
2
Quartus Prime Version       15.1.2 Build 193 02/01/2016 SJ Standard Edition
3
Revision Name               chip_top
4
Top-level Entity Name       chip_top
5
Family                      Cyclone IV E
6
Device                      EP4CE22F17C6
7
Timing Models               Final
8
Total logic elements        9 / 22,320 ( < 1 % )
9
Total combinational functions    9 / 22,320 ( < 1 % )
10
Dedicated logic registers   9 / 22,320 ( < 1 % )
11
Total registers             9
12
Total pins                  11 / 154 ( 7 % )
13
Total virtual pins          0
14
Total memory bits           0 / 608,256 ( 0 % )
15
Embedded Multiplier 9-bit elements    0 / 132 ( 0 % )
16
Total PLLs                  0 / 4 ( 0 % )

Im zweiten Fall setze ich für r_counter einen Initialwert von x"FF". 
Quartus liefert mir in der Zusammenfassung:
1
Flow Status                 Successful - Thu Mar 19 08:24:22 2020
2
Quartus Prime Version       15.1.2 Build 193 02/01/2016 SJ Standard Edition
3
Revision Name               chip_top
4
Top-level Entity Name       chip_top
5
Family                      Cyclone IV E
6
Device                      EP4CE22F17C6
7
Timing Models               Final
8
Total logic elements        16 / 22,320 ( < 1 % )
9
Total combinational functions    16 / 22,320 ( < 1 % )
10
Dedicated logic registers   9 / 22,320 ( < 1 % )
11
Total registers             9
12
Total pins                  11 / 154 ( 7 % )
13
Total virtual pins          0
14
Total memory bits           0 / 608,256 ( 0 % )
15
Embedded Multiplier 9-bit elements    0 / 132 ( 0 % )
16
Total PLLs                  0 / 4 ( 0 % )

Kann der Cyclone IV es nicht im Configurationstream oder denke ich nur 
komplett falsch?

von Wort Kauer (Gast)


Lesenswert?

Sigi schrieb:
> Jan K. schrieb:
>> Des Weiteren ist mir aufgefallen, dass Initialwerte zusätzliche
>> Kombinatorik benötigen. Das ist eigentlich logisch, ich habe es nur
>> nicht bedacht.
>
> Nein, total falsch: INIT-Werte, egal welcher Pegel,
> werden im Configurationstream abgelegt und beim
> Start entsprechend gesetzt, und zwar ohne zusätzliche
> Logik.

Nicht bei Altera, bei xilinx ja. Siehe Generic Init im Template


Xilinx
1
-- FDCE: Single Data Rate D Flip-Flop with Asynchronous Clear and -- Clock Enable (posedge clk). -- Spartan-6 -- Xilinx HDL Libraries Guide, version 14.7
2
  FDCE_inst : FDCE generic map
3
    (INIT => '0')                       -- Initial value of register ('0' or '1')
4
    port map (
5
      Q   => Q,                         -- Data output
6
      C   => C,                         -- Clock input
7
      CE  => CE,                        -- Clock enable input
8
      CLR => CLR,                       -- Asynchronous clear input
9
      D   => D                          -- Data input
10
      );


Altera:
1
COMPONENT DFFEAS
2
   PORT (d        : IN STD_LOGIC;
3
        clk       : IN STD_LOGIC;
4
        clrn      : IN STD_LOGIC;
5
        prn       : IN STD_LOGIC;
6
        ena       : IN STD_LOGIC;
7
        asdata    : IN STD_LOGIC;
8
        aload     : IN STD_LOGIC;
9
        sclr      : IN STD_LOGIC;
10
        sload     : IN STD_LOGIC;
11
        q         : OUT STD_LOGIC );
12
END COMPONENT;

von Wort Kauer (Gast)


Lesenswert?

Jan K. schrieb:
> Kann der Cyclone IV es nicht im Configurationstream oder denke ich nur
> komplett falsch?

Meines Wissens kann es das FF im Cyclone nicht, das FF in xilinx dagegen 
schon. Damit der HDL Code architekturunabhängig ist, sollte man zum init 
allein das reset/set Netzwerk verwenden, dan passt es auch mit dem ASIC.


Und auch da kann man 'fehler' machen, die zu zusätzlichen Kombinatorik 
führen, wie Ken Chapman für Xilinx gut erklärt: 
https://www.xilinx.com/support/documentation/white_papers/wp275.pdf

von FPGAzumSpass (Gast)


Lesenswert?

Wenn man einen Reset statt Initwerte verwenden will, dann aber bitte 
auch darauf achten, dass man als Reset den Startup Reset verwendet.
(z.b. Element ROC bei Xilinx)

Und nicht einfach eine globale Resetleitung, am besten noch direkt vom 
Pin kommend.

von Duke Scarring (Gast)


Lesenswert?

Oh, mal wierder eine schöne FPGA-Reset-Diskussion!

Wort Kauer schrieb:
> Damit der HDL Code architekturunabhängig ist, sollte man zum init
> allein das reset/set Netzwerk verwenden, dan passt es auch mit dem ASIC.
Ja, aus wievielen FPGA-Designs werden ASICs gemacht?

Wo kann ich mir die ASICs günstig machen lassen, ohne 1 Mio. 
Geldeinheiten mitbringen zu müssen? Schick wäre auch eine FAB für den 
Keller. 130 nm würden mir für den Einstieg reichen...

Zurück zum Thema: Der Cyclone III konnte m.E. nur auf '0' initialisieren 
und hat die Logik automatisch invertiert, wenn man doch eine '1' haben 
wollte. Oder war es andersrum?
Auf jeden Fall musste man dann im Reveal sehr aufpassen, welche 
Darstellungsweise man verwendet (physisch/logisch).

Duke

von C. A. Rotwang (Gast)


Lesenswert?

Duke Scarring schrieb:
> Oh, mal wierder eine schöne FPGA-Reset-Diskussion!

Nein, die Urschleimdiskussion hinter dem TO-Problem ist nicht (nur) die 
mit dem Slogan "To reset or not to reset" sondern "Ist VHDL eine 
Programmiersprache oder eine Modellierungssprache?"

Nur wer VHDL mit eine Programmiersprache verwechselt, glaubt die Tools 
werden aus der Signaldeklaration genau das Gewünschte - eine 
Initialsierung zum Beginn der "Programmausführung" mit dem gewünschten 
definierten Wert realisieren. Dabei können die tools nur aus den 
vorhandenen Eigenschaften der Hardware auswählen und da ist 
Initialisierung bei Power Up nicht in jedem IC eingebaut.

Also schreibt man den Code so, das da genau ein Verhaltensmodel aus dem 
"Real life" entsteht. Und das sind 4 reproduzierbare Möglichkeiten:

Nach dem PowerUp stehen in den FF
a) zufällige/Unbekannte Werte  ('U')
b) alle '0' und nichts anderes
c) alle '1' und nichts anderes
d) der, der Uservorgabe, der user kann entweder '0' oder '1' vorgeben
d1) macht der User keine Angabe werden alle mit dem selben default-Wert 
(i.e. '0') initialisiert.

Und wie bekommt man raus welche Optionen bzgl Initialisiserung der IC 
bietet?
Nun, der TO macht es richtig, er liest die Reports. Alternativ, das 
Datasheet über den Aufbau der Logigcells oder den Synthesis Style guide 
der toolchain. Und naturlich sollte man sich besonders die Warnings mit 
dem O-Ton "Die tools machen jetzt was anderes als du mglw. gewollt hast" 
anschauen. Genau dieser O-Ton hat nämlich die vom TO zitierte Warning:
1
"Ignored Power-Up Level option on the following registers ..."
(BTW, dickes Lob an den TO für die detailierte Problembeschreibung, da 
kommt man ohne grosses Nachstochern und Nachfragen auf des Pudels Kern)

Weiss man nichts um die Init-Optionen beim vorliegenden IC, wählt man 
Variante a (zufällige Werte nach PowerUp) und baut eine 
Initialisierungsschaltung aka Reset (auch POR Power-On-Reset oder auch 
ROC (Reset-On-Configuration) mit den im FPGA vorhandenen Ressourcen ein.
--
BTW:
Dem aufmerksamen Leser wird nicht entgangen sein, das sich die Antworten 
nur auf eine Teilmenge der VHDL-Fragestellung beziehen.

Eine Signaldeklaration wird nicht ausschließlich zu einem FF/Register 
umgesetzt, es kann (je nach weiterer Beschreibung im Code) auch eine 
simple Leitung an einem Kombinatorikgatterausgang sein, ein fixer Wert 
('0' oder '1' also GND oder Vcc), eine Leitung zum I/O-PAD oder eine RAM 
Zelle oder ein Schieberregister (ohne bit-load-Schaltung) oder .... Und 
bei denen stellt sich die Eingangsfrage, wie nun das PoweUp Verhalten 
mit/ohne Initialisierungszuweisung bei Deklaration beschrieben wird, 
neu.

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.