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
libraryieee;
2
3
useieee.std_logic_1164.all;
4
useieee.numeric_std.all;
5
useieee.math_real.all;
6
7
entityTopis
8
port(
9
clk:instd_logic;
10
data_select:inunsigned(2downto0);
11
data_out:outunsigned(7downto0):=(others=>'0')
12
);
13
endentity;
14
15
architecturertlofTopis
16
-- Seeds für Uniform, die Werte werden bei jedem 'Aufruf' geändert
17
sharedvariableseed_1,seed_2:natural:=1;
18
19
impurefunctionrandomreturnnaturalis
20
variablerand_real:real;
21
variableresult: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
returninteger(round(rand_real*100.0));
27
endfunction;
28
29
-- Ein Arry, das mit Zufallswerten initialisiert werden soll.
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.
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.
>> 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
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.
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.
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.
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
libraryieee;
2
useieee.std_logic_1164.all;
3
useieee.numeric_std.all;
4
useieee.math_real.all;
5
entityTopis
6
port(
7
clk:instd_logic;
8
data_select:inunsigned(2downto0);
9
data_out:outunsigned(7downto0):=(others=>'0')
10
);
11
endentity;
12
architecturertlofTopis
13
-- Ein Arry, das mit Zufallswerten initialisiert werden soll.