Hallo zusammen,
in meinem ersten Thread hatte ich einige Fragen zum Spartan 3A, da ging
es in erster Linie darum wie ich den Chip gut "gefüllt" kriege. Im
gleichen Zuge wurde ich darauf hingewiesen, dass ich mich hierfür in die
GENERATE Anweisung einarbeiten soll. Gesgt, getan. Nur leider habe ich
damit ein paar Schwierigkeiten, die sich im zwei verschiedenen Projekten
kristallisierten.
Problem Nr. 1:
In meiner naiven Vorstellung wollte ich für den Anfang ein simples
Schieberegister bauen, bestehend aus einer Parralelschaltung aus D-FFs.
Der Code hierfür:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
4
entityn_bit_registeris
5
GENERIC(n:INpositive:=10);
6
PORT(
7
clk:inbit;
8
reg_in:inbit_vector(n-1downto0);
9
reg_out:outbit_vector(n-1downto0));
10
endn_bit_register;
11
12
architectureStructuralofn_bit_registeris
13
COMPONENTd_ff
14
PORT(
15
data_in,clk:inbit;
16
data_out:outbit);
17
ENDCOMPONENT;
18
19
begin
20
reg:FORiINn-1downto0GENERATE
21
d_ff_module:entitywork.d_ff(Behavioral)
22
PORTMAP(reg_in(i),clk,reg_out(i));
23
ENDGENERATE;
24
25
endStructural;
Die Komponente d_ff ist ein simples D-FF basierend auf einer einfachen
Verhaltensbeschreibung. Syntaxcheck läuft einwandfrei. Ich frage mich
aber warum das Synthesetool bzw. der RTL viewer immer nur EINE Instanz
des D-FF grafisch anzeigt und nicht alle 10 nebeneinander? Ein Blick in
die Design Summary sagt mir, dass genau NULL (!!!!) Slices genutzt
werden, dafür aber 21 IOBs. NULL Slices?? Setze ich n = 150 werden nur
mehr IOBs verwendet, die Anzahl der verwendeten Slices bleibt nach wie
vor bei 0. Also schlussfolgere ich daraus, dass dieses Vorhaben nicht
besonders gut geeignet war den Spartan 3A Chip in seinen Kapazitäten
auszureizen?
Problem Nr. 2:
Unabhängig vom ersten Projekt wollte ich eine "Dummy-Logik" entwickeln,
um den Chip auch mit etwas unregelmäßigeren Strukturen zu füllen, als
mit Schieberegistern. Herizu habe ich mich einer 4x4 S(ubstitution)-Box
aus der Kryptographie bedient, die nichts anderes als eine Look-Up Table
ist und 4 Eingangsbits kombinatorisch vertauscht um sie als 4
Ausgangsbits wieder auzugeben. Davon wollte ich einige Instanzen bilden
und sie miteinander verschalten. Der Code hierzu:
Syntaxcheck läuft einwandfrei, ABER der RTL viewer zeigt mir nur ZWEI
Instanzen grafisch an. Dabei werden die "mittleren" S-Boxen und die
letzte quasi "zusammengefasst". Was um alles in der Welt läuft hier
falsch? Auch die Ergebnisse der Design Summary sind ernüchternd: grad
mal 2 Slices genutzt und 4 LUTs :-(
Zur Verdeutlichung habe ich hierfür einen entsprechenden Screenshot des
RTL Viewers angehängt. Kann mir bitte jemand helfen? Ich bin die
Quellcodes immer und immer wieder durchgegangen und finde den Fehler
nicht.
Zum "Problem" 1: sieh dir mal an, wie ein FPGA Ausgang aussieht. Genau
dieses Flipflop, das du da siehst, wird verwendet.
Zum "Problem" 2: irgendeine beliebig komplizierte logische Funktion mit
4 Eingängen und 1 Ausgang braucht 1 LUT. Für eine Funktion mit 4
Eingängen und 4 Ausgängen braucht also 4 LUTs.
Das die Funktion dazwischen "unglaublich geheim" und kompliziert ist,
schert den Synthesizer nicht. Der ist genau dafür programmiert,
komplizierte Funktionen zu vereinfachen...
Zum "Problem" 1: willst du a) viele IOs benutzen oder b) viele Flipflops
im FPGA verwenden?
Alle Signale in der toplevel Portdeklaration werden von der Synthese
an IOs angeschlossen also in diesem Fall:
1
entityn_bit_registeris
2
GENERIC(n:INpositive:=10);
3
PORT(
4
clk:inbit;
5
reg_in:inbit_vector(n-1downto0);
6
reg_out:outbit_vector(n-1downto0));
7
endn_bit_register;
-> bei n=10 werden 10 IOs benutzt.
Wenn aber nur der serielle Ein-und Ausgang der Schieberegisterkette
verwendet werden soll (b), dann muss dies in etwas so aussehen:
1
entityn_bit_register_mit_einem_si_sois
2
GENERIC(n:INpositive:=10);
3
PORT(
4
clk:inbit;
5
ser_in:inbit;
6
ser_out:outbit;
7
endn_bit_register;
8
9
signalreg_in:inbit_vector(n-1downto0);
10
signalreg_out:outbit_vector(n-1downto0;
11
12
reg_in(0)<=ser_in;
13
ser_out<=reg_out(n-1);
14
15
...undhierderRestvomcodevonoben
dann solltens (nach Beseitigung etwaiger Syntaxfehler) viele
Flipflops und nur 3 IOs werden, meine ich.
@Lothar:
Dass genau dieses FF am Ausgang des FPGA verwendet wird, war mir nicht
klar. Danke für den Hinweis. Dennoch grübele ich noch darüber, wie ich
den Code verändern muss, damit ich das Schieberegister realisieren kann
:-( User bko hat ja schon ein paar Hinweise geliefert...
Was das zweite Problem anbelangt: Die Funktion dazwischen soll ja alles
andere als "geheim" sein. Finde es beeindruckend, dass das der
Synthesizer schlau genug ist, um komplizierte Funktionen zu
vereinfachen, welche Schritte bzw. Modifikationen müssen denn aber
unternommen werden, damit ich einen FPGA "einfach" voll kriege? :-( Habe
die Befürchtung, dass mir der gute Synthesizer alles munter
"wegoptimiert".
@bko:
Ich möchte vor allem viele FlipFlops im FPGA verwenden, am besten so
viele wie möglich! Vielen Dank für deine Vorschläge, ich habe diese in
den Code eingepflegt und danach einen erneuten Versuch gestartet, doch
leider will es noch nicht so recht fluppen:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
4
entityn_bit_registeris
5
GENERIC(n:INpositive:=10);
6
PORT(
7
clk:inbit;
8
ser_in:inbit;
9
ser_out:outbit);
10
endn_bit_register;
11
12
architectureStructuralofn_bit_registeris
13
14
signalreg_in:bit_vector(n-1downto0);
15
signalreg_out:bit_vector(n-1downto0);
16
17
COMPONENTd_ff
18
PORT(
19
data_in,clk:inbit;
20
data_out:outbit);
21
ENDCOMPONENT;
22
23
begin
24
25
reg_in(0)<=ser_in;
26
ser_out<=reg_out(n-1);
27
28
reg:FORiINn-1downto0GENERATE
29
d_ff_module:entitywork.d_ff(Behavioral)
30
PORTMAP(reg_in(i),clk,reg_out(i));
31
32
ENDGENERATE;
33
34
endStructural;
Kannst du mir sagen, wo an dieser Stelle der Hase im Pfeffer liegt? Ich
habe verschiedene Kombinationen im Quellcode versucht, eine richtige
Kette von miteinander verschalteten FlipFlops kriege ich damit aber
leider nach wie vor nicht hin.
> ... damit ich einen FPGA "einfach" voll kriege?>Ich möchte vor allem viele FlipFlops im FPGA verwenden, am besten so>viele wie möglich!
Ich bin einfach neugierig. Vielleicht magst Du mal erzählen, was der
Zweck davon ist, den FPGA voll zu kriegen.
@Logiker:
Neugier ist immer gut :-) Eigentich wollte ich mir nur das Floorplanning
bzw. Place & Route einer regelmäßigen Schaltungsstruktur (RAM Matrix) im
Vergleich zu einer relativ unregelmäßigen "Dummy-Logik"-Struktur
ansehen. Mich interessiert es einfach wie das vpm Tool gehandhabt wird.
@bko:
Es wird ein Syntaxerror ausgegeben und zwar für diese Zeile
1
reg_in(0)<=ser_in;
Die Meldung dazu: Syntax error near "reg_in". 1 error(s) found while
parsing design hierarchy.
Habe ich in dem obigen Code die beiden Zuweisungen
1
2
reg_in(0)<=ser_in;
3
ser_out<=reg_out(n-1);
denn überhaupt an die richtige Stelle gesetzt? Müsste es nicht
1
ser_in<=reg_in(0);
heißen? Dementsprechend müsste dann noch in der GENERATE Anweisung
anstelle der 0 die 1 stehen, oder?
dden schrieb:> versuch doch mal sowas,
Bitte das nächste Mal gleich mit den Tokens [vhdl ] und [/vhdl ] um den
Quelltext (ohne die Leerzeichen).
> evtl. sind noch kleiner syntaxerrors drin.
Und sicher auch der eine oder andere Denkfehler:
1
(data_in=>ser_in,
2
:
3
(data_in=>ser_in(i-1),
Ja was denn jetzt? ser_in ist doch eh' nur 1 Bit tief/breit...
Und warum eigentlich so kompliziert?
Diese Kapselung eines FF in eine Komponente dient eh' nur der Verwirrung
des geneigten Lesers. Dem Synthesizer ist das egal, der pflückt sich das
FF einfach da raus und macht es platt (flatten hierarchy). Ich würde
1000 FFs im Schieberegister einfach so beschreiben:
Lothar Miller schrieb:> Bitte das nächste Mal gleich mit den Tokens [vhdl ] und [/vhdl ] um den
sorry, hat ich auf die schnelle vergessen.
> Ja was denn jetzt? ser_in ist doch eh' nur 1 Bit tief/breit...
Ja, da hat der copyteufel zugeschlagen, soll natürlich reg_in heißen.
> Und warum eigentlich so kompliziert?> Diese Kapselung eines FF in eine Komponente dient eh' nur der Verwirrung> des geneigten Lesers. Dem Synthesizer ist das egal, der pflückt sich das> FF einfach da raus und macht es platt (flatten hierarchy). Ich würde> 1000 FFs im Scheiberegister einfach so beschreiben:
Da stimm ich dir völlig zu, aber er hat ja mit dem Generate was machen
wollen, wollte das nur ein bischen strukturierter darstellen was er
machen "wollte", und nicht nur signale ins nichts zu führen und mächtig
aufblähen und zu zerstückeln.
Um nochmehr Logik zu generieren könnte er auch einfach zwei 1000bit
lange Shift-In Register xoren,lol.
dden schrieb:> er hat ja mit dem Generate was machen wollen
Und dabei immer auf "das FPGA möglichst voll bekommen" gezielt. Ich
würde mich freuen wie ein Nasenbär, wenn ich was unglaublich Komplexes
hinschreibe (siehe Problem 2 im Anfangspost), und dann nur 4 LUTs dafür
gebraucht werden...
Wenn ich aber das FPGA voll bekommen will, dann fiele mir da schon was
ein. Deine XOR Geschichte zeigt da die Richtung... ;-)
@dden:
Syntaxfehler wurden soweit eliminiert, nach dem erfolgreichen Check
sieht der Code wie folgt aus:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useieee.std_logic_unsigned.all;
4
5
entityn_bit_registeris
6
GENERIC(n:INpositive:=10);
7
PORT(
8
ser_in:inbit;
9
clk:inbit;
10
ser_out:outbit);
11
endn_bit_register;
12
13
architectureStructuralofn_bit_registeris
14
15
signalreg_in:bit_vector(n-1downto0);
16
signalreg_out:bit_vector(n-1downto0);
17
18
COMPONENTd_ff
19
PORT(
20
data_in,clk:inbit;
21
data_out:outbit);
22
ENDCOMPONENT;
23
24
begin
25
26
reg:FORiINn-1downto0GENERATE
27
eingang:ifi=0generate
28
d_ff_module:entitywork.d_ff(Behavioral)
29
PORTMAP
30
(data_in=>ser_in,
31
clk=>clk,
32
data_out=>reg_out(i)
33
);
34
endgenerateeingang;
35
36
schieber:if(i/=0ori/=(n-1))generate
37
d_ff_module:entitywork.d_ff(Behavioral)
38
PORTMAP
39
(data_in=>reg_in(i-1),
40
clk=>clk,
41
data_out=>reg_out(i)
42
);
43
endgenerateschieber;
44
45
ausgang:ifi=(n-1)generate
46
d_ff_module:entitywork.d_ff(Behavioral)
47
PORTMAP
48
(data_in=>reg_in(i-1),
49
clk=>clk,
50
data_out=>ser_out
51
);
52
endgenerateausgang;
53
54
ENDGENERATE;
55
56
endStructural;
ABER: Der Synthesizer macht das nach wie vor nicht unbedingt mit. Die
Synthese schlägt fehl und zwar landet diese Meldung in der Konsole:
1
Index value <-1> is not in Range of array <reg_in>.
und zwar bezogen auf diese Zeile
1
d_ff_module:entitywork.d_ff(Behavioral)
. Ich dachte anfangs, dass es an der
1
reg:FORiINn-1downto0GENERATE
liegen könnte und änderte den Wert von 0 auf 1, aber das hat auch nicht
zum gewünschten Erfolg geführt. Die Synthese lief dann zwar einwandfrei
durch, es kamen aber nicht die Ergebnisse dabei raus, die ich mir
erhofft hatte. Stattdessen hagelte es Warnungen wie
1
All outputs of the instance <reg[9].schieber.d_ff_module> of the block <d_ff> are unconnected in block <n_bit_register>.
2
This instance will be removed from the design along with all underlying logic
und es wurde nur EIN FlipFlop synthetisiert.
@lothar:
Okay, ich merke schon, dass mein Wissensstand in Sachen VHDL dem der
anderen Leute hier noch ein paar Lichtjahre hinterherhinkt. Was deine
Alternativen anbelangt hätte ich eine Bitte an dich: in Bezug auf deinen
letzten Codevorschläge mit der Registerlänge, die über die Zahl 999
eingestellt wird, würde ich mich total freuen, wenn du mir einmal den
kompletten beispielhaften Code posten würdest. Dann habe ich EINMAL das
Erlebnis eine komplette, fehlerfreie und sinngemäße Synthese hier auf
dem Schirm zu haben und freue mich auch wie ein Nasenbär :-)
Peter Falk schrieb:> use ieee.std_logic_unsigned.all;
Die wird hier nicht gebraucht.
Siehe auch Beitrag "Re: IEEE.STD_LOGIC_ARITH.ALL obsolete"
Die restliche Beschreibung verschleiert sehr schön ihr Funktion.
Ich hab mir mal den Code von Beitrag #3473136 angeschaut:
1. Du verwendest den Datentyp bit statt std_logic (bzw. noch besser
std_ulogic).
Das ist erstmal kein Fehler, erschwert es aber Code auszutauschen, da
das quasi nur Akademiker verwenden.
2. Dein 1-Bit FF ist immer noch eine extra Komponente. Warum? Ziehst Du
Dir auch die Hosen mit der Kneifzange an?
Peter Falk schrieb:> Kannst du mir sagen, wo an dieser Stelle der Hase im Pfeffer liegt? Ich> habe verschiedene Kombinationen im Quellcode versucht, eine richtige> Kette von miteinander verschalteten FlipFlops kriege ich damit aber> leider nach wie vor nicht hin.
Wenn Du das Ganze mal simuliertst, würde Dir der Fehler sofort
auffallen:
Aus Deinem Modul kommt immer '0' raus...
Duke
@all:
Entschuldigt bitte, dass ich erst jetzt antworte. Bin früher leider
nicht dazu gekommen.
@Duke:
Herzlichen Dank, dass du dir die Mühe gemacht hast, das zu simulieren.
Verdammt, daran habe ich gar nicht gedacht, sollte ich in Zukunft
vielleicht mal öfter beherzigen. Sofern aus meinem Modul stets 0
rauskommt, liegt es am Design des D-FF selbst?
Das nur Akademiker den Datentyp bit verwenden war mir bis dato nicht
geläufig. Ich meine in der einschlägigen Literatur aber auch an
irgendeiner Stelle gelesen zu haben, dass in der Tat der Datentyp
std_logic in der Praxis weitaus mehr Verwendung gefunden hat. Habs mir
mal hinter die Ohren geschrieben.
Meine Hosen muss ich mir bislang noch nicht mit der Kneifzange anziehen
;-) Ich hoffe auch ganz stark, dass dieser Kelch an mir vorübergehen
wird :-D
@Lothar:
Jawoll!!! Besten Dank dafür Lothar! Himmel, was ist das für ein tolles
Gefühl, wenn ein (fehlerfries) Ergebnis bei der ganzen Aktion
herauskommt. Ich habe einige deiner Register dann noch mit XOR-Gattern
miteinander verbunden und einen LUT Fllgrad von über 85% erhalten.
Ich glaube, dass ich meine Absicht über die Verkettung der S-Boxen den
Spartan 3A voll zu kriegen einstampfen kann. Der Symthesizer ist einfach
zu gut, selbst als ich mehrere Instanzen davon serien und parallel per
XOR, XNOR usw. miteinander verbunden habe, hat das nur unwesentlich mit
LUTs verbraucht. Gibt es einen frei verfügbaren Quellcode, von dem man
weiß, dass er einen relativ "kleinen" FPGA wie den Spartan 3A im
Hinblick auf dessen Ressorucen gut beansprucht?
Hallo zusammen,
ich bin es schon wieder und möchte euch mal wieder um euren guten Rat
bitten. Ich habe in VHDL einen kleinen 4 Bit VHDL Addierer geschrieben
und zwar einmal mit manueller Instanziierung und Verdrahtung der
einzelnen Volladdierer und einmal mit Hilfe der GENERATE Anweisung
(Letzteres anhand eines Beispiels aus dem Netz).
Die VHDL Quelltexte hierzu:
Der Vollständigkeit halber noch der Volladdierer an sich:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
4
entityfull_adderis
5
PORT(
6
x,y,z:instd_logic;
7
sum,carry:outstd_logic);
8
endfull_adder;
9
10
architecturefull_adder_arch_1offull_adderis
11
12
begin
13
sum<=((xXORy)XORz);
14
carry<=((xANDy)OR(zAND(xANDy)));
15
16
endfull_adder_arch_1;
Syntaxcheck läuft einwandfrei, Synthesizer beschwert sich ebenfalls
nicht. Instanziiere ich die Komponenten des Addierers wie in der ersten
Variante manuel, sieht das Ergebnis so aus wie ich es mir vorgestellt
habe, dargestellt auf Bild 1. Schaue ich mir jedoch das Ergebnis der
Synthese mit GENERATE an, wird mir (zu meinem Erstaunen) ein anderes
Schaltungsbild geliefert, was ich noch nicht verstehen kann. Abgesehen
davon wird der carry Ausgang einfach nicht mit dem cout verbunden,
obwohl das eigentlich laut Code (nach meinem Verständnis) geschehen
sollte.
Kann mir vielleicht bitte jemand sagen, was ich hierbei falsch mache?
DANKE! :-)
Der Code schaut erst einmal ok aus, der ISE-"view-RTL-Schematic"
verwirrt
mich bei Verwendung von generates auch immer etwas.
Kämpf dich doch mal durch den "Technology-Schematic-View", hier sollte
dann alles vorhanden sein (Allerdings in Xilinx Elementen wie LUTS und
Bufxyz usw.. ).
bko schrieb:> der ISE-"view-RTL-Schematic" verwirrt> mich bei Verwendung von generates auch immer etwas.
Ja klar, weil er einfach falsch und unvollständig darstellt. Das tut er
aber auch schon ohne Generate... :-(
Hmmm okay...also liegt es dieses Mal ausnahmsweise nicht an mir? Den
"Technology-Schematic-View" habe ich mir mal angeschaut (nicht in diesem
Projekt), war ganz interessant, allerdings musste die Übersicht hierbei
arg Federn lassen :-(
Schlägt sich hier die Quartus II Entwicklungsumgebung von Altera
eigentlich besser?
Mittlerweile komme ich mit der "Technology-Schematic-view" wesentlich
besser klar und insgesamt betrachtet scheint diese Variante tatsächlich
weniger fehleranfällig zu sein als der "RTL-schematic-view".
Von daher habe ich mal mit dem Code des n_Bit_Adders ein wenig
herumgespielt und wollte daraus einen 32 Bit Adder machen, indem ich
einfach
1
GENERIC(n:integer:=32);
wie im Code dargestellt auf 32 setzte. Interessanterweise kann ich
daraus aber nicht mehr als einen 31 Bit Addierer machen..selbst wenn ich
die generische Variable n wieder z.B. auf 16 setze, bleibt es dabei,
dass es 31 Bit nach der Synthese sind (darauf lässt die Bennenung der
Eingänge im schematic und die Durchnummerierung der Pins schließen
a(30:0) sowie b(30:0).
Jedes Mal wenn ich den Viewer neu starte, zeigt er mir die gleiche
Anzahl der Eingänge an, dagegen aktualisiert sich der
"RTL-schematic-view" allerdings korrekt :-(
Kann mir jemand vielleicht sagen, woran das liegt?
EDIT:
Sobald ich ISE jedoch einmal beende und erneut starte, ist das Problem
verschwunden? Stimmt mit meiner Installation vielleicht etwas nicht?
Peter Falk schrieb:> Sobald ich ISE jedoch einmal beende und erneut starte, ist das Problem> verschwunden? Stimmt mit meiner Installation vielleicht etwas nicht?
Schonmal "Project >> Cleanup Project Files" probiert?