Ich hab in meiner architecture vor dem begin einige Funktionen definiert, die dazu dienen ein array mit Werten aus einer Textdatei zu initialisieren. Im Simulator läuft das einwandfrei, aber XST meckert wenn ich das 'length Attribut einer line (nach readline()) auslesen will und sagt mir "VHDL source expression not yet supported: 'DerefOp'.". Wie kann ich festlegen, dass diese Funktion nicht als Komb. Logik synthetisiert werden soll sondern nur einmal vor der Synthese zur Berechnung der Initialwerte ausgeführt werden soll?
Daniel R. schrieb: > Im Simulator läuft das einwandfrei Man kann 100% (naja, fast) von VHDL simulieren. Aber bestenfalls 95% synthetisieren. > aber XST meckert wenn ich das 'length Attribut einer line > (nach readline()) auslesen will Das File-Handling ist nicht primäre Aufgabe eines Synthesizers. Welche 5% synthetisierbar sind, steht im Handbuch zum Synthesizer. In deinem Fall zum XST-Users Guide. > ein array mit Werten aus einer Textdatei zu initialisieren. Dafür gibt es andere Wege. Hier kocht jeder seine eigene Suppe. Ich habe ein externes C-Programm, das mir einen VHDL-Frame generiert, das Arrays mit Werten füllt und das Ande anhängt. Letztlich bekomme ich dan eine VHDL-Datei mit den gewünschten Werten. Du kannst das Textfile auch parsen und als Initwerte für ein BRAM in die Bitstromerzeugung einfließen lassen.
Lothar Miller schrieb: > Das File-Handling ist nicht primäre Aufgabe eines Synthesizers. Richtig. Obwohl da erstaunlich viel geht... Daniel R. schrieb: > einige Funktionen > definiert, die dazu dienen ein array mit Werten aus einer Textdatei zu > initialisieren. Wie oft rufst Du denn Deine Funktion auf? Und an welcher Stelle? > 'length Attribut Laut UG627 sollte das funktionieren, offenbar aber nicht bei readline. Vielleicht findest Du einen Workaround? > Wie kann ich festlegen, dass diese Funktion nicht als Komb. Logik > synthetisiert werden soll sondern nur einmal vor der Synthese zur > Berechnung der Initialwerte ausgeführt werden soll? Hier ein Beispiel aus dem UG627:
1 | ...
|
2 | architecture syn of rams_20c is |
3 | |
4 | type RamType is array(0 to 63) of bit_vector(31 downto 0); |
5 | |
6 | impure function InitRamFromFile (RamFileName : in string) return RamType is |
7 | FILE RamFile : text is in RamFileName; |
8 | variable RamFileLine : line; |
9 | variable RAM : RamType; |
10 | begin
|
11 | for I in RamType’range loop |
12 | readline (RamFile, RamFileLine); |
13 | read (RamFileLine, RAM(I)); |
14 | end loop; |
15 | return RAM; |
16 | end function; |
17 | |
18 | signal RAM : RamType := InitRamFromFile("rams_20c.data"); |
19 | |
20 | begin
|
21 | ...
|
Duke
Ok die Datei außerhalb zu parsen wäre auch möglich. Ich hab das so gemacht: Vor begin steht die Zuweisung
1 | signal RAM : rom_type := rom_init("C:\Modelsim_Projects\file.txt"); |
Die rom_init() Funktion ist gleich darüber definiert und wird nirgendwo sonst aufgerufen. Aus der Datei liest sie eine Zeile von unbekannter Länge. Die Länge entnehme ich dann line_v'length
1 | line_length_v := line_v'length; --hier Problem |
und kopiere dann entsprechend viele Zeichen in den 20 Zeichen großen String Vector
1 | read(line_v, str_line_v(1 to line_length_v)); |
Den String Vektor gehe ich dann in einer Schleife durch und wandel jedes Zeichen in einen std_logic_vector um. Meckern tut XST beim Speichern der length in einer Variablen oben. Der Unterschied zu dem Beispiel oben ist lediglich, dass die Zeilenlänge bei mir variabel sein soll (begrenzt auf maximal 20 Zeichen). Wenn ich die Zeilenlänge nicht angeb ist das ein Typkonflikt und erzeugt eine Warnung. Außerdem brauch ich die Länge um die Gesamtzahl der belegten Arrayfelder zu berechnen.
:
Bearbeitet durch User
Daniel R. schrieb: > Der Unterschied zu dem Beispiel oben ist lediglich, dass die Zeilenlänge > bei mir variabel sein soll (begrenzt auf maximal 20 Zeichen). Vielleicht hilft es die Datei zeichenweise zu lesen? Duke
Naja, aber ich seh da nur die Funktionen: readline() zum holen der kompletten nächsten Zeile und read() zum auslesen der Zeile in eine Variable der passenden Größe. Vielleicht geht es irgendwie, dass man eine Zeile zeichenweise ausliest bis man was ungültiges zurück kriegt, aber ich wüsste jetzt nicht mit welchen Funktionen das gehen würde. Möglicherweise könnte man
1 | procedure READ (L: inout LINE; VALUE: out CHARACTER; |
2 | GOOD: out BOOLEAN); |
Immer wieder aufrufen bis GOOD = false ist (falls es da intern einen Iterator gibt der aufs nächste Zeichen springt).
:
Bearbeitet durch User
Daniel R. schrieb: > Vielleicht geht es irgendwie, dass man eine Zeile zeichenweise ausliest > bis man was ungültiges zurück kriegt Im Anhang ist ein Stück Code, welches eine Textdatei einliest. Ich hab das jetzt nur im Simulator getestet, aber es sollte auch im Synthesizer funktionieren:
1 | vcom test_vhdl_read.vhd |
2 | # Model Technology ModelSim SE-64 vcom 10.3d Compiler 2014.10 Oct 7 2014 |
3 | # vcom -reportprogress 300 test_vhdl_read.vhd |
4 | # -- Loading package STANDARD |
5 | # -- Loading package TEXTIO |
6 | # -- Loading package std_logic_1164 |
7 | # -- Loading package NUMERIC_STD |
8 | # -- Compiling entity test_vhdl_read |
9 | # -- Compiling architecture test of test_vhdl_read |
10 | # Errors: 0, Warnings: 0 |
11 | vsim -novopt test_vhdl_read |
12 | # vsim |
13 | # |
14 | # Loading std.standard |
15 | # Refreshing work.test_vhdl_read(test) |
16 | # Loading std.textio(body) |
17 | # Loading ieee.std_logic_1164(body) |
18 | # Loading ieee.numeric_std(body) |
19 | # Loading work.test_vhdl_read(test) |
20 | # ** Note: read 6 bytes from ram_data.txt |
21 | # Time: 0 ps Iteration: 0 Instance: /test_vhdl_read File: test_vhdl_read.vhd |
22 | # ** Note: read 3 lines from ram_data.txt |
23 | # Time: 0 ps Iteration: 0 Instance: /test_vhdl_read File: test_vhdl_read.vhd |
24 | run -all |
25 | # ** Note: 0 --> 65 |
26 | # ** Note: 1 --> 66 |
27 | # ** Note: 2 --> 66 |
28 | # ** Note: 3 --> 67 |
29 | # ** Note: 4 --> 67 |
30 | # ** Note: 5 --> 67 |
31 | # ** Note: 6 --> 0 |
32 | # ** Note: 7 --> 0 |
33 | # ** Note: 8 --> 0 |
34 | # ** Note: 9 --> 0 |
35 | # ** Note: 10 --> 0 |
Duke
Vielen Dank für die ausführliche Antwort. Im Simulator läuft meine Lösung auch, wenn ich die line so wie in deinem Beispiel zeichenweise einlese. Aber im Synthesetool leider nicht! Es lässt einfach nicht zu, dass die line-Attribute 'range oder 'length abgefragt werden. Frage ich 'length ab sagt XST: "VHDL source expression not yet supported: 'DerefOp'." Und frage ich 'range ab sagt XST: "Bad object specification in qualified expression." Wie auch immer, wenn ich die Attribute nicht benutze sondern mir einenn End-Marker in jeder Zeile definier z.B. ';' dann läuft die Schleife zwar an aber nur für 64 Iterationen. Danach kommt die Meldung "Loop has iterated 64 times. Use "set -loop_iteration_limit XX" to iterate more." Ich finde es unschön soeinen Parameter per Hand in die .xst Datei schreiben zu müssen. Außerdem soll die Funktion ja gar nicht synthetisiert werden. Kann man nicht irgendwie Sachen markieren, die nicht synthetisiert werden sollen?
:
Bearbeitet durch User
Daniel R. schrieb: > Es lässt einfach nicht zu, dass die line-Attribute 'range oder 'length > abgefragt werden. Eigentlich schon: im XST Users Guide zur Version 14 steht:
1 | VHDL Specifications |
2 | • Supported for some predefined attributes only: |
3 | – HIGHLOW |
4 | – LEFT |
5 | – RIGHT |
6 | – RANGE |
7 | – REVERSE_RANGE |
8 | – LENGTH |
9 | – POS |
10 | – ASCENDING |
11 | – EVENT |
12 | – LAST_VALUE |
> Es lässt einfach nicht zu, dass die line-Attribute 'range oder 'length > abgefragt werden. WIE frägst du die denn exakt ab? Im Beispiel von Duke kommt kein 'length vor... > Und frage ich 'range ab sagt XST: "Bad object specification in qualified > expression." Zeig DEN Code, der diesen Fehler hervorruft. Ein 'range ist selbstverständlich synthetisierbar. Fast jede Konvertierungsfunktion verwendet das... Die Funktion TO_01 in der numeric_std sieht z.B. so aus:
1 | -- function TO_01 is used to convert vectors to the
|
2 | -- correct form for exported functions,
|
3 | -- and to report if there is an element which
|
4 | -- is not in (0,1,h,l).
|
5 | -- Assume the vector is normalized and non-null.
|
6 | -- The function is duplicated for SIGNED and UNSIGNED types.
|
7 | |
8 | function TO_01(S : SIGNED ; xmap : STD_LOGIC:= '0') return SIGNED is |
9 | variable RESULT: SIGNED(S'length-1 downto 0); |
10 | variable bad_element : boolean := FALSE; |
11 | alias xs : SIGNED(s'length-1 downto 0) is S; |
12 | begin
|
13 | for i in RESULT'range loop --- 'RANGE |
14 | case xs(i) is |
15 | when '0' | 'L' => RESULT(i):='0'; |
16 | when '1' | 'H' => RESULT(i):='1'; |
17 | when others => bad_element := TRUE; |
18 | end case; |
19 | end loop; |
20 | if bad_element then |
21 | assert NO_WARNING |
22 | report "numeric_std.TO_01: Array Element not in {0,1,H,L}" |
23 | severity warning; |
24 | for i in RESULT'range loop --- 'RANGE |
25 | RESULT(i) := xmap; -- standard fixup |
26 | end loop; |
27 | end if; |
28 | return RESULT; |
29 | end TO_01; |
Und die Funktion ist tadellos synthetisierbar.
> Außerdem soll die Funktion ja gar nicht synthetisiert werden.
Warum ist sie dann da drin? Die sollte dann doch eher zur Testbench nach
ausserhalb gehören....
:
Bearbeitet durch Moderator
Naja aber XST beschwert sich bei der Verwendung von 'range einer line
1 | variable line_v : line; |
2 | begin
|
1 | readline (rom_file, line_v); |
2 | for j in line_v'range loop --Zeile 132 |
Und ich krieg die Meldung: "... line 132: Bad object specification in qualified expression. INTERNAL_ERROR:Xst:cmain.c:3464:1.56 - Process will terminate. For technical support on this issue, please open a WebCase with this project attached at http://www.xilinx.com/support." Ich umgehe das Problem dann gezwungenermaßen mit einem Trennzeichen am Ende um die Abfrage zu vermeiden.
Oh man, XST sagt zu meinen Initialisierungsschleifen "Loop body will iterate zero times" und "Index value(s) does not match array range, simulation mismatch." Dabei stimmt das gar nicht.
:
Bearbeitet durch User
Daniel R. schrieb: > XST beschwert sich bei der Verwendung von 'range einer linevariable > readline (rom_file, line_v); > for j in line_v'range loop --Zeile 132 Nein. Der Synthesizer kann einfach nur nichts mit dynamischen Grenzen bei einer for-Schleife anfangen. Das braucht er im restlichen Leben auch nie... Daniel R. schrieb: > "Loop body will iterate zero times" Gleicher Fall: der Synthesizer kann nichts mit variablen Grenzen bei einer for-Schleife anfangen... Das steht aber ganz klar&deutlich im bereits des öfteren erwähnten XST Users Guide:
1 | VHDL For-Loop Statements |
2 | XST supports VHDL for-loop statements for: |
3 | • Constant bounds |
4 | ... |
Wie Lothar Miller schrieb: >>>> Welche 5% synthetisierbar sind, steht im Handbuch zum Synthesizer. In >>>> deinem Fall im XST Users Guide.
:
Bearbeitet durch Moderator
Ok, aber selbst wenn ich die dynamischen durch feste Grenzen ersetze kommt es zur selben Meldung.
1 | for i in 0 to 50 loop |
2 | for j in 0 to 50 loop |
3 | if count_v < x and ... then |
4 | count_v := count_v + 1; |
5 | end if; |
6 | end loop; |
7 | end loop; |
Außerdem beißt er sich ziemlich lange daran fest.
:
Bearbeitet durch User
Durch die Ausgabe auf dem Display habe ich festgestellt, dass XST anscheinend irgendwelche Fehler bei der Verwendung der TextIO Methoden macht. Im Simulator enthält mein array alle Werte, wie gewünscht. Bei XST nicht (da sind die verschoben und unvollständig). Der Übersichtlichkeit halber tendiere ich nun zum erstgenannten Vorschlag, nämlich in C++ einen Textfile-Parser zu schreiben, der eine vhdl Datei ausspuckt, die das fertige Array bzw. spezifischen Adressdekoder enthält.
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.