Forum: FPGA, VHDL & Co. Problem mit GENERATE


von Peter F. (widlarizer)


Angehängte Dateien:

Lesenswert?

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
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
entity n_bit_register is
5
  GENERIC (n : IN positive := 10);
6
  PORT (
7
    clk     : in bit;
8
    reg_in  : in bit_vector(n-1 downto 0);
9
    reg_out : out bit_vector(n-1 downto 0));
10
end n_bit_register;
11
12
architecture Structural of n_bit_register is
13
  COMPONENT d_ff
14
    PORT (
15
      data_in, clk : in bit;
16
      data_out     : out bit);
17
  END COMPONENT;
18
  
19
begin
20
  reg : FOR i IN n-1 downto 0 GENERATE
21
    d_ff_module : entity work.d_ff(Behavioral)
22
      PORT MAP (reg_in(i), clk, reg_out(i));
23
  END GENERATE;
24
25
end Structural;

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:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
entity sboxChain_mult is
5
  GENERIC (n : IN positive RANGE 2 to 64 := 4);
6
  PORT(
7
    A_first : in std_logic;
8
    B_first : in std_logic;
9
    C_first : in std_logic;
10
    D_first : in std_logic;
11
    
12
    W_last : out std_logic;
13
    X_last : out std_logic;
14
    Y_last : out std_logic;
15
    Z_last : out std_logic);
16
end sboxChain_mult;
17
18
architecture Structural of sboxChain_mult is
19
  SIGNAL intern_1 : std_logic_vector(1 to n-1);
20
  SIGNAL intern_2 : std_logic_vector(1 to n-1);
21
  SIGNAL intern_3 : std_logic_vector(1 to n-1);
22
  SIGNAL intern_4 : std_logic_vector(1 to n-1);
23
  
24
  COMPONENT sBox
25
    PORT(
26
      A, B, C, D : in std_logic;
27
      W, X, Y, Z : out std_logic);
28
  END COMPONENT;
29
  
30
begin
31
  box : FOR i IN n DOWNTO 1 GENERATE
32
-- erste S-Box in der Kette
33
  box_begin : IF i = 1 GENERATE
34
    s_box_begin : entity work.sBox(Structural)
35
      PORT MAP(A_first, B_first, C_first, D_first, intern_1(i), intern_2(i), intern_3(i), intern_4(i));
36
  END GENERATE;
37
-- mittlere S-Boxen
38
  box_middle : IF i > 1 AND i < n GENERATE
39
    s_box_middle : entity work.sBox(Structural)
40
      PORT MAP(intern_1(i-1), intern_2(i-1), intern_3(i-1), intern_4(i-1), intern_1(i), intern_2(i), intern_3(i), intern_4(i));
41
  END GENERATE;
42
-- letzte S-Box in der Kette
43
  box_end : IF i = n GENERATE
44
    s_box_end : entity work.sBox(Structural)
45
      PORT MAP(intern_1(i-1), intern_2(i-1), intern_3(i-1), intern_4(i-1), W_last, X_last, Y_last, Z_last);
46
    END GENERATE;
47
  END GENERATE;
48
49
end Structural;

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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...

: Bearbeitet durch Moderator
von bko (Gast)


Lesenswert?

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
entity n_bit_register is
2
  GENERIC (n : IN positive := 10);
3
  PORT (
4
    clk     : in bit;
5
    reg_in  : in bit_vector(n-1 downto 0);
6
    reg_out : out bit_vector(n-1 downto 0));
7
end n_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
entity n_bit_register_mit_einem_si_so is
2
  GENERIC (n : IN positive := 10);
3
  PORT (
4
    clk     : in bit;
5
    ser_in  : in bit;
6
    ser_out : out bit;
7
end n_bit_register;
8
9
signal reg_in  : in bit_vector(n-1 downto 0);
10
signal reg_out : out bit_vector(n-1 downto 0;
11
12
reg_in(0) <= ser_in;
13
ser_out <= reg_out(n-1);
14
15
... und hier der Rest vom code von oben
dann solltens (nach Beseitigung etwaiger Syntaxfehler) viele
Flipflops und nur 3 IOs werden, meine ich.

von Peter F. (widlarizer)


Lesenswert?

@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
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
entity n_bit_register is
5
  GENERIC (n : IN positive := 10);
6
  PORT (
7
       clk     : in bit;
8
       ser_in  : in bit;
9
       ser_out : out bit);
10
end n_bit_register;
11
12
architecture Structural of n_bit_register is
13
14
signal reg_in  : bit_vector(n-1 downto 0);
15
signal reg_out : bit_vector(n-1 downto 0);
16
17
  COMPONENT d_ff
18
    PORT (
19
      data_in, clk : in bit;
20
      data_out     : out bit);
21
  END COMPONENT;
22
  
23
begin
24
25
        reg_in(0) <= ser_in;
26
        ser_out <= reg_out(n-1);
27
  
28
  reg : FOR i IN n-1 downto 0 GENERATE
29
    d_ff_module : entity work.d_ff(Behavioral)
30
      PORT MAP (reg_in(i), clk, reg_out(i));
31
  
32
  END GENERATE;
33
34
end Structural;

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.

von Logiker (Gast)


Lesenswert?

> ... 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.

von bko (Gast)


Lesenswert?

@ Peter Falk
Was sagt die Simulation?

von Peter F. (widlarizer)


Lesenswert?

@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?
1
reg : FOR i IN n-1 downto 0 GENERATE

Fragen über Fragen, sorry :-(

von dden (Gast)


Lesenswert?

Hallo,
versuch doch mal sowas, evtl. sind noch kleiner syntaxerrors drin.
1
reg : FOR i IN n-1 downto 0 GENERATE
2
  eingang: if i=0 generate
3
    d_ff_module : entity work.d_ff(Behavioral)
4
      PORT MAP 
5
      ( data_in  => ser_in, 
6
        clk      => clk, 
7
        data_out => reg_out(i)
8
      );
9
  end generate eingang;
10
  ausgang: if i=(n-1) generate
11
    d_ff_module : entity work.d_ff(Behavioral)
12
      PORT MAP 
13
      ( data_in  => ser_in(i-1), 
14
        clk      => clk, 
15
        data_out => ser_out
16
      );
17
  end generate ausgang;
18
  schieber: if (i/=0 or i/=(n-1)) generate
19
    d_ff_module : entity work.d_ff(Behavioral)
20
      PORT MAP 
21
      ( data_in  => reg_in(i-1), 
22
        clk      => clk, 
23
        data_out => reg_out(i)
24
      );
25
  end generate schieber;
26
END GENERATE;

: Bearbeitet durch Moderator
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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:
1
  signal sr : std_logic_vector (999 downto 0) := (others=>'0');
2
  :
3
  sr <= sr(998 downto 0) & ser_in when rising_edge(clk);
4
  ser_out <= sr(999);

Oder über eine Konstante:
1
  contant srlen : integer := 999;
2
  signal sr : std_logic_vector (srlen downto 0) := (others=>'0');
3
  : 
4
  sr <= sr(srlen -1 downto 0) & ser_in when rising_edge(clk);
5
  ser_out <= sr(srlen );

Oder generisch mit Attributen, dann wird die Registerlänge über eine 
Änderung der Zahl "999" eingestellt (das gefällt mir am besten):
1
  signal sr : std_logic_vector (999 downto 0) := (others=>'0');
2
  : 
3
  sr <= sr(sr'left-1 downto 0) & ser_in when rising_edge(clk);
4
  ser_out <= sr(sr'left);

Oder, oder, oder...

: Bearbeitet durch Moderator
von dden (Gast)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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... ;-)

: Bearbeitet durch Moderator
von Peter F. (widlarizer)


Lesenswert?

@dden:

Syntaxfehler wurden soweit eliminiert, nach dem erfolgreichen Check 
sieht der Code wie folgt aus:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use ieee.std_logic_unsigned.all;
4
5
entity n_bit_register is
6
  GENERIC (n : IN positive := 10);
7
  PORT (
8
      ser_in  : in bit;
9
     clk     : in bit;      
10
       ser_out : out bit);
11
end n_bit_register;
12
13
architecture Structural of n_bit_register is
14
15
  signal reg_in  : bit_vector(n-1 downto 0);
16
  signal reg_out : bit_vector(n-1 downto 0);
17
18
  COMPONENT d_ff
19
    PORT (
20
      data_in, clk : in bit;
21
      data_out     : out bit);
22
  END COMPONENT;
23
    
24
begin
25
  
26
  reg : FOR i IN n-1 downto 0 GENERATE
27
  eingang: if i=0 generate
28
    d_ff_module : entity work.d_ff(Behavioral)
29
      PORT MAP 
30
      ( data_in  => ser_in, 
31
        clk      => clk, 
32
        data_out => reg_out(i)
33
      );
34
  end generate eingang;
35
36
  schieber: if (i/=0 or i/=(n-1)) generate
37
    d_ff_module : entity work.d_ff(Behavioral)
38
      PORT MAP 
39
      ( data_in  => reg_in(i-1), 
40
        clk      => clk, 
41
        data_out => reg_out(i)
42
      );
43
  end generate schieber;
44
  
45
  ausgang: if i=(n-1) generate
46
    d_ff_module : entity work.d_ff(Behavioral)
47
      PORT MAP 
48
      ( data_in  => reg_in(i-1), 
49
        clk      => clk, 
50
        data_out => ser_out
51
      );
52
  end generate ausgang;
53
  
54
END GENERATE;
55
56
end Structural;
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 : entity work.d_ff(Behavioral)
. Ich dachte anfangs, dass es an der
1
reg : FOR i IN n-1 downto 0 GENERATE
 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 :-)

von Duke Scarring (Gast)


Angehängte Dateien:

Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Peter Falk schrieb:
> wenn du mir einmal den kompletten beispielhaften Code posten würdest.
Kein Problem:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
entity n_bit_register is
5
  GENERIC (n : IN positive := 1000);
6
  PORT (  ser_in  : in std_logic;
7
          clk     : in std_logic;      
8
          ser_out : out std_logic);
9
end n_bit_register;
10
11
architecture Structural of n_bit_register is
12
13
signal sr : std_logic_vector (n-1 downto 0) := (others=>'0');
14
15
begin
16
17
  sr      <= sr(n-2 downto 0) & ser_in when rising_edge(clk);
18
  ser_out <= sr(n-1);
19
20
end Structural;
Der Xilinx Synthesizer sagt dazu:
1
Final Register Report
2
Macro Statistics
3
# Shift Registers                                      : 1
4
 1000-bit shift register                               : 1
Und der Schaltplan sieht (auszugsweise die ersten zehn und letzten zehn 
Flipflops) so aus wie die Screenschots im Anhang...

: Bearbeitet durch Moderator
von Peter F. (widlarizer)


Lesenswert?

@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?

von Peter F. (widlarizer)


Angehängte Dateien:

Lesenswert?

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:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
entity adder_bits_4_new is
5
  PORT(
6
    cin : in std_logic;
7
    a0, b0, a1, b1, a2, b2, a3, b3 : in std_logic;
8
    s0, s1, s2, s3 : out std_logic;
9
    cout : out std_logic);
10
end adder_bits_4_new;
11
12
architecture ripple_4_arch_new of adder_bits_4_new is
13
  COMPONENT full_adder
14
    PORT (x, y, z: in std_logic; sum, carry: out std_logic);
15
  end COMPONENT;
16
  
17
  signal t0, t1, t2 : std_logic;
18
19
begin
20
  FA0 : full_adder
21
    PORT MAP(cin, a0, b0, s0, t0);
22
  FA1 : full_adder
23
    PORT MAP(t0, a1, b1, s1, t1);  
24
  FA2 : full_adder
25
    PORT MAP(t1, a2, b2, s2, t2);
26
  FA3 : full_adder
27
    PORT MAP(t2, a3, b3, s3, cout);
28
29
end ripple_4_arch_new;

Hier nochmal mit GENERATE:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
entity adder_bits_n is
5
  GENERIC (n : integer := 4);
6
  PORT(
7
    cin  : in std_logic;
8
    a, b : in std_logic_vector(n-1 downto 0);
9
    s    : out std_logic_vector(n-1 downto 0);
10
    cout : out std_logic);
11
end adder_bits_n;
12
13
architecture ripple_n_arch of adder_bits_n is
14
  
15
  COMPONENT full_adder 
16
    PORT (x, y, z: IN std_logic; sum, carry: OUT std_logic);
17
  END COMPONENT;
18
  
19
  SIGNAL t: std_logic_vector(n downto 0); 
20
  
21
    begin
22
      t(0)  <= Cin;  Cout <= t(n); 
23
      FA: for i in 0 to n-1 generate
24
        FA_i: full_adder PORT MAP (t(i), a(i), b(i), S(i), t(i+1)); 
25
      end generate;
26
27
end ripple_n_arch;

Der Vollständigkeit halber noch der Volladdierer an sich:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
entity full_adder is
5
  PORT(
6
    x, y, z    : in std_logic;
7
    sum, carry : out std_logic);
8
end full_adder;
9
10
architecture full_adder_arch_1 of full_adder is
11
12
begin
13
  sum <= ((x XOR y) XOR z);
14
  carry <= ((x AND y) OR (z AND (x AND y)));
15
16
end full_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! :-)

von bko (Gast)


Lesenswert?

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.. ).

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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...  :-(

von Peter F. (widlarizer)


Lesenswert?

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?

von Peter F. (widlarizer)


Lesenswert?

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?

: Bearbeitet durch User
von Duke Scarring (Gast)


Lesenswert?

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?

von Peter F. (widlarizer)


Lesenswert?

Jupp, habe ich. Hat aber unmittelbar danach nicht zum gewünschten Erfolg 
geführt. Erst nach dem Neustart. Es ist mir ein Rätsel :-(

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.