Forum: FPGA, VHDL & Co. VHDL: Zufallswerte für die Initialisierung erzeugen


von Florian (flori_n)


Lesenswert?

Moin,

ich sitze gerade an einem kleinen Problem.
In VHDL sollen für die Initialisierung, das heißt zur Synthesezeit, 
Zufallswerte erzeugt werden.
Es gibt die Standardprozedur uniform. Ist es möglich, die für die 
Initialisierung zu nutzen?
Unten steht ein kurzer Code dazu. Der funktioniert in der Simulation wie 
erwartet, aber bei der Synthese gibt es Probleme.
Quartus gibt den Fehler
"Error (10372): VHDL error at Top.vhdl(19): item cannot be assigned 
value
"
aus (Zeile 19 ist der Beginn der Funktionsdefinition).
Vivado ist bei einem ähnlichen Code (den ich jetzt nicht hier habe) 
etwas genauer und gibt an, dass irgendwo in math_real ein 
nicht-konstantes real-Signal benutzt wird, das nicht synthetisiert 
werden kann.
Ist es möglich, uniform oder eine andere Standardfunktion für 
Zufallszahlen in der Synthese zu nutzen?

Ich könnte ein LFSR benutzen oder die Zufallswerte extern erzeugen und 
im Code als Werte speichern. Darum geht es aber nicht.
Und noch ganz klar: Es geht nicht darum, einen Zufallszahlengenerator zu 
synthetisieren. Es sollen einfach nur bei der Synthese pseudozufällige 
Initialisierungswerte erzeugt werden.

[Bearbeitung: Es geht auch nicht darum, dass die Werte bei jedem 
Synthesedurchlauf unterschiedlich sind.]
1
library ieee;
2
3
use ieee.std_logic_1164.all;
4
use ieee.numeric_std.all;
5
use ieee.math_real.all;
6
7
entity Top is
8
  port(
9
    clk           : in  std_logic;
10
    data_select   : in  unsigned(2 downto 0);
11
    data_out      : out unsigned(7 downto 0) := (others => '0')
12
  );
13
end entity;
14
15
architecture rtl of Top is
16
  -- Seeds für Uniform, die Werte werden bei jedem 'Aufruf' geändert
17
  shared variable seed_1, seed_2  : natural := 1;
18
19
  impure function random return natural is
20
    variable rand_real  : real;
21
    variable result    : integer;
22
  begin
23
    -- rand_real ist ein Zufallswert zwischen 0 und 1
24
    uniform(seed_1, seed_2, rand_real);
25
    -- Auf den Bereich 0 bis 100 abbilden
26
    return integer(round(rand_real * 100.0));
27
  end function;
28
  
29
  -- Ein Arry, das mit Zufallswerten initialisiert werden soll.
30
  type array_t is array (0 to 2**data_select'length) of integer;
31
  constant const_array  : array_t := (others => random);
32
  
33
begin
34
35
  -- Damit nicht alles wegoptimiert wird
36
  data_out <= to_unsigned(const_array(to_integer(data_select)), data_out'length);
37
    
38
end architecture;

: Bearbeitet durch User
von Martin S. (strubi)


Lesenswert?

Die Synthese unterscheidet allgemein bei VHDL nicht zwischen 
'Ausfuehrung von VHDL' und 'Umsetzung in Hardware'. Leider.
Ob es in Verilog mit '$random' in der Initialisierung geht, weiss ich 
nicht.

Demnach ist dein Ansinnen in der Form vermutlich nicht umsetzbar, so 
dass es wohl das einfachere ist, die Initialwerte explizit mit einem 
Script zu generieren und dann die Synthese anzuwerfen. Oder du nutzt 
gemischt gut dokumentierte Mechanismen (je nach Vendor), um die 
Initialwerte nachtraeglich fuer entsprechende Location-Constraints ins 
BIT-File zu patchen.
Bei Xilinx gibt es sonst noch einige ICAP-Hacks zur 
in-system-Rekonfiguration, falls es um Serien-Produktion ginge.

Nachtrag: Was du noch probieren koenntest: Die Zufalls-Sequenz als 
Generic von der Synthese aus uebergeben.

: Bearbeitet durch User
von Florian (flori_n)


Lesenswert?

Martin S. schrieb:
> Die Synthese unterscheidet allgemein bei VHDL nicht zwischen
> 'Ausfuehrung von VHDL' und 'Umsetzung in Hardware'.
Grundsätzlich ist ja sowas wie
[vhdl]constant WIDTH : natural := 
integer(ceil(log2(real(DATA_RANGE))));[vhdl]
möglich, auch wenn die Formel nicht synthetisierbar ist. Deshalb habe 
ich mich gefragt, ob auch die Zufallsinitialisierung irgendwie geht.
Allerdings müsste ja für die Zufallswerte bei der Synthese tatsächlich 
eine Funktion mit Variablen ausgeführt werden. Daran scheitert es 
wahrscheinlich.

von Bradward B. (Firma: Starfleet) (ltjg_boimler)


Lesenswert?

>> Die Synthese unterscheidet allgemein bei VHDL nicht zwischen
>> 'Ausfuehrung von VHDL' und 'Umsetzung in Hardware'.
> Grundsätzlich ist ja sowas wie ... ob auch die Zufallsinitialisierung
> irgendwie geht.

Aehm, räusper, der Grundsatz in digitaler Logik wie FPGA als 
deterministisches System ist gerade, das es sowas wie "zufällige 
Anfangs-Speicherwerte nicht gibt, respektive bei PowerUp eine 
systemweite Initialisierung durchzuführen ist.

Das ist eben der Reset, den man entweder explizit im FPGA als POR 
(PowerOn Reset) definiert oder über die Konfiguration (Download 
Configurations bitstream) erreicht.

Bei Xilinx-FPGA's ist die zweite Methode möglich, manche Synthesetools 
vwerwenden den Initi-wert bei der Signaldeclaration dafür; bei 
Altera-Typen ist oft nur die "reset-Methode" anwendbar.

* https://hardwarebee.com/fpga-power-on-reset-design-and-implementation/
* https://de.wikipedia.org/wiki/Reset

Wenn man den Zufall hier verwenden will, dann nennt man das 
"Fehler-injektion":

* 
https://www.studysmarter.de/ausbildung/ausbildung-in-it/fachberater-integrierte-systeme/fehlerinjektion/
* https://www.fernuni-hagen.de/pv/docs/97-08/fi-rekonf-hardw_1_.pdf

: Bearbeitet durch User
von Florian (flori_n)


Lesenswert?

Bradward B. schrieb:
> der Grundsatz in digitaler Logik wie FPGA als
> deterministisches System ist gerade, das es sowas wie "zufällige
> Anfangs-Speicherwerte nicht gibt, respektive bei PowerUp eine
> systemweite Initialisierung durchzuführen ist.
Richtig. Deshalb schrieb ich:
Florian schrieb:
> In VHDL sollen für die Initialisierung, das heißt zur Synthesezeit,
> Zufallswerte erzeugt werden.
Florian schrieb:
> Es sollen einfach nur bei der Synthese pseudozufällige
> Initialisierungswerte erzeugt werden.

von Martin S. (strubi)


Lesenswert?

Florian schrieb:
> Allerdings müsste ja für die Zufallswerte bei der Synthese tatsächlich
> eine Funktion mit Variablen ausgeführt werden. Daran scheitert es
> wahrscheinlich.

Die Synthese kann das nur aufloesen, wenn es sich um Konstanten handelt.
A priori versucht sie, Hardware aus einem Ausdruck zu erzeugen. Mit real 
und random ist das nicht eindeutig aufloesbar, somit Bumm.
Mit Verilog koenntest du mehr Glueck haben, da 'initial' in den meisten 
Faellen ausgefuehrt wird und teils sogar Einschleifen externer 
Routinen erlaubt.
Portabel ist das sonst nur, wenn du dein Seed als Konstante explizit vor 
der Synthese extern generierst und uebergibst.

von Rick D. (rickdangerus)


Lesenswert?


von Florian (flori_n)


Lesenswert?

Martin S. schrieb:
> Die Synthese kann das nur aufloesen, wenn es sich um Konstanten handelt.
> A priori versucht sie, Hardware aus einem Ausdruck zu erzeugen. Mit real
> und random ist das nicht eindeutig aufloesbar
Eindeutig auflösbar ist es ja schon. Zur Synthesezeit sind grundsätzlich 
alle notwendigen Informationen da.
Aber ja, es wird nur berechnet, nicht ausgeführt. Da war mein Brett vor 
dem Kopf.

Es gibt ja auch noch andere Wege.

Danke für die Denkhilfe.

von Christoph Z. (christophz)


Lesenswert?

Salü Florian

Ich hab mir deinen Code angesehen und gedacht, das müsste eigentlich 
gehen. Ich hätte das sehr ähnlich geschrieben und wie andere schon 
bestätigt haben, funktioniert dieser Ansatz auch (Ich meine den Teil mit 
Initialisierung per Funktionsaufruf "constant const_array  : array_t := 
(others => random);" )

Habe darum deinen Code mal genommen und bei mir in Synplify gesteckt. 
Dieser Synthesizer versteht oft etwas mehr als andere Synthesizer und 
versteht auch oft stärker abstrahierten Code als andere.

Dein Code hat aber auch in Synplify genau die gleiche Fehlermeldung wie 
bei dir erzeugt.

Man muss dem Synthesizer in diesem Fall einfach ein bisschen auf die 
Sprünge helfen und in der Funktion das ganze Array erzeugen und nicht 
nur die einzelnen Werte.

Dieser Code wird von Synplify 2020.03M erfolgreich für einen PolarFire 
FPGA synthesisiert:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
use ieee.math_real.all;
5
entity Top is
6
  port(
7
    clk           : in  std_logic;
8
    data_select   : in  unsigned(2 downto 0);
9
    data_out      : out unsigned(7 downto 0) := (others => '0')
10
  );
11
end entity;
12
architecture rtl of Top is
13
  -- Ein Arry, das mit Zufallswerten initialisiert werden soll.
14
  type array_t is array (0 to 2**data_select'length) of integer;
15
16
  -- Seeds für Uniform, die Werte werden bei jedem 'Aufruf' geändert
17
  impure function random return array_t is
18
    variable seed_1, seed_2  : natural := 1;
19
    variable rand_real  : real;
20
    variable result    : array_t;
21
  begin
22
    for i in 0 to result'high loop
23
      -- rand_real ist ein Zufallswert zwischen 0 und 1
24
      uniform(seed_1, seed_2, rand_real);
25
      -- Auf den Bereich 0 bis 100 abbilden
26
      result(i) := integer(round(rand_real * 100.0));
27
    end loop;
28
    return result;
29
  end function;
30
31
  constant const_array  : array_t := random;
32
  
33
begin
34
  -- Damit nicht alles wegoptimiert wird
35
  data_out <= to_unsigned(const_array(to_integer(data_select)), data_out'length);
36
    
37
end architecture;

von Florian (flori_n)


Lesenswert?

Es sieht in der Simulation gut aus und es synthetisiert in Quartus.

Vielen Dank. Ich bin positiv überrascht.

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.