Forum: FPGA, VHDL & Co. Kontrolle über LEs


von Klaus (Gast)


Angehängte Dateien:

Lesenswert?

Hallo miteinander,

ich verzweifle langsam ein bisschen mit meinem MAX1000 board bzw. 
Quartus. Ich wollte ein bisschen mit einer Carry-Chain 
herumexperimentieren, bekomme aber einfach nicht Quartus dazu mir die 
Logikzellen so zusammenzusetzen wie ich es haben möchte. Es geht mir 
dabei eher ums Prinzip als um eine wirkliche Anwendung.

Haben möchte ich folgendes: Eine Kette von Logikzellen bei denen nichts 
weiter passiert als den Carry-In an Carry-Out durchzuschleifen. Also so 
wie im Bild. Ich schaffe es einfach nicht Quartus zu sagen, dass er 
'einfach nur' LEs mit dieser Konfiguration erzeugen soll.

Ich habe viele verschiedene Wege über eine Addition von 'signed' bis zu 
'carry_sum' und 'carry' primitives mit allen erdenklichen Einstellungen 
der Synthese ausprobiert. Das funktioniert allerdings nur mir vielen 
Einschränkungen und ich scheine kaum Einfluss haben zu können wie und 
was Quartus wegoptimisiert. Beispielsweise werden alle Ketten kleiner 
gleich vier Elementen in eine LE zusammengefasst, und zusätzlich wird 
eine gleiche Anzahl an Konstanten benötigt.

Gibt es da eine Möglichkeit bessere Kontrolle über die Erzeugung der LEs 
zu haben?

von C. A. Rotwang (Gast)


Lesenswert?

Klaus schrieb:
> Gibt es da eine Möglichkeit bessere Kontrolle über die Erzeugung der LEs
> zu haben?

Optimierung abschalten, global und/oder lokal. Für xilinx gibt es vhdl 
attribute 'dont_touch' und 'keep' o.ä.. Bei Quartus mag es Ähnliches 
geben.

https://www.intel.com/content/www/us/en/programmable/quartushelp/17.0/hdl/vhdl/vhdl_file_dir_preserve.htm

https://stackoverflow.com/questions/24712976/prevent-compiler-from-optimizing-logic-away

Direkte Instanzierung von primitiven ist auch ne Option:
https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_low_level.pdf

https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_low_level.pdf

von ... (Gast)


Lesenswert?

Einfach die LEs im Floorplaneditor verbinden.

von Sigi (Gast)


Lesenswert?

Klaus schrieb:
> Gibt es da eine Möglichkeit bessere Kontrolle über die Erzeugung der LEs
> zu haben?

Ja, kann für Altera, Xilinx und Lattice folgendermassen gemacht werden:
Zu jeder Familie (der einzelnen Hersteller) gibt es Bibliotheken
für alle Bausteine (IO, RAM, LCELL, etc.), die sich problemlos
per Std.Instantiierung in VHDL/Verilog in ein Design einbinden
lassen. Für z.B. LEs kannst du sogar die LUT4/LUT6/etc-Funktion
frei wählen. Zusätzlich gibt es bei allen 3 Herstellern sogenannte
Location-Constraints, teils mit relativer, teils mit absoluter
Positionierung. Damit kannst du dann die Lage "deiner" LEs
relativ frei wählen.

Das ganze hatte ich in der Vergangenheit schon ofter für alle
3 Hersteller gemacht (kleine DSP-Units mit beliebigen Funktionen),
hatte immer problemlos funktioniert.

von Klaus (Gast)


Angehängte Dateien:

Lesenswert?

C. A. Rotwang schrieb:
> Optimierung abschalten, global und/oder lokal. Für xilinx gibt es vhdl
> attribute 'dont_touch' und 'keep' o.ä.. Bei Quartus mag es Ähnliches
> geben.

Das habe ich auch in allen möglichen Variationen versucht. Wenn ich im 
unteren VHDL code beispielsweise 'carry_transfer' das Attribut keep=true 
zuweise, macht Quartus aus der Carry Chain eine einfache Folge von 
Buffern.

Sigi schrieb:
> Zu jeder Familie (der einzelnen Hersteller) gibt es Bibliotheken
> für alle Bausteine (IO, RAM, LCELL, etc.)

LCELL hatte ich auch schon gesehen, allerdings gibt es da nur einen Ein- 
und Ausgang.

Ich bin mir nicht sicher, ob ich überhaupt richtig verstanden habe wie 
man die Primitives wie carry_sum benutzen soll. Folgendes versuche ich 
zu synthetisieren:
1
architecture primitive of delay_line is
2
component carry_sum
3
    port (
4
        sin : in std_logic;
5
        cin : in std_logic;
6
        sout : out std_logic;
7
        cout : out std_logic );
8
end component;
9
signal carry_transfer: std_logic_vector(LINE_WIDTH downto 0); 
10
begin
11
  carry_transfer(0) <= INPUT;
12
  
13
  f: for i in 1 to LINE_WIDTH generate
14
    c: carry_sum port map (sin => '1',
15
                    cin => carry_transfer(i-1),
16
                    cout => carry_transfer(i));
17
  end generate;
18
  
19
  OUTPUT <= carry_transfer(LINE_WIDTH);
20
end;

Im RTL-Viewer sieht es wie im angehängten Bild aus, in det Technology 
Map ist es dann vollständig verschwunden. Ich habe alle auswählbaren 
Optimisierungseinstellungen durchprobiert, nichts hat geholfen. Gibt es 
noch andere außer denen unter "Settings->Compiler Settings->Advanced 
Settings"?

... schrieb:
> Einfach die LEs im Floorplaneditor verbinden.

So habe ich das mit dem Bild im ersten Post gemacht, allerdings ist dann 
nach erneutem Kompilieren alles wieder weg.

von C. A. Rotwang (Gast)


Angehängte Dateien:

Lesenswert?

Klaus schrieb:
> Gibt es
> noch andere außer denen unter "Settings->Compiler Settings->Advanced
> Settings"?

Da gibt es zwei Klassen, Fitter und Synthesis, da muss man wohl beide 
durchklopfen. (Screenshots als 'Inspiration' im Anhang).

Und dann gibt es noch die tcl command line scripts (quartus_map, 
Quartus_fit, die sollten, müßen aber nicht gleich mit denen von der GUI 
sein.

https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/manual/tclscriptrefmnl.pdf

Mit der script-sprache könnte es möglich sein Verbindungen und cells 
anzulegen (connect_chain) repektive zu ändern (ohne VHDL und Co) und 
dann die Netzliste rauszuschreiben. Das ist dann aber richtig Low level 
FPGA-designen. Fast sowie damals Hexcodes im Memory per System-Monitor 
zu hacken.

Darüberhinaus ist Quartus nicht das einzige synthese-tool für Cyclone, 
allerdings wohl das einzig kostenlose.

von ich (Gast)


Lesenswert?

Nimm die fiftyfivenm_lcell_comb, mit dont_touch => "on" wird die nicht 
wegoptimiert:
1
component fiftyfivenm_lcell_comb
2
  generic (
3
    dont_touch  :  string := "off";
4
    lpm_hint  :  string := "UNUSED";
5
    lpm_type  :  string := "fiftyfivenm_lcell_comb";
6
    lut_mask  :  std_logic_vector(15 downto 0) := "0000000000000000";
7
    sum_lutc_input  :  string := "datac"  );
8
  port(
9
    cin  :  in std_logic := '0';
10
    combout  :  out std_logic;
11
    cout  :  out std_logic;
12
    dataa  :  in std_logic := '0';
13
    datab  :  in std_logic := '0';
14
    datac  :  in std_logic := '0';
15
    datad  :  in std_logic := '0'
16
  );
17
end component;
bzw.
1
library wysiwyg;
2
use wysiwyg.fiftyfivenm_components.all;
Damit kann man wunderbar Delay-Lines bauen, Ergebnis war ein TDC mit 
niedrigen 2stelligen Picosekunden RMS. Bei den Details begibst Du dich 
da aber auf undokumentiertes Low-Low-(Low-)Level Gebiet, aber es geht 
dir ja nur ums Prinzip... (Der FAE sagte das geht nicht...)

von Sigi (Gast)


Lesenswert?

Klaus schrieb:
> LCELL hatte ich auch schon gesehen, allerdings gibt es da nur einen Ein-
> und Ausgang.

... und natürlich noch eine Hand voll Generics.
Was hast du denn noch erwartet? Die Bausteine werden
wie Komponenten in VHDL/Verilog in dein Design eingebunden,
mehr als IOs (+Generics) sind also nicht erforderlich.

Vlt aber eine kleine Übung für dich, damit du dir eine
Kette im ChipPlanner/Floorplanner/etc. anschauen kannst:
Setze ein neues Projekt auf, schreib eine kleine Komponente
mit 2*4 Input Pins (für Input-Vektoren din1,din2 der Länge 4)
und 5 Output Pins (für Output-Vektor dout der Länge 5) und
addiere dout=din1+din2. Im ChipPlanner siehst du dann schon
mal die LEs mit den Verbindungen untereinander und den
entsprechenden Settings für eigene Generics in den
LCELL-Komponenten.

Was bei deinem Beispiel auch wichtig ist: du verwendest
keine LCELL-Ausgaben wie z.B. REGOUT/COMBOUT (ausser COUT),
von daher sieht der Synthesizer nur eine lange Signalkette,
die er durch Wegoptimieren zu einer kurzen/direkten
Verbindung macht. Von daher sind deine Komponenten
wegoptimiert.

Um wie Oben von mir beschrieben die Komponenten zu instantiieren
und per Location-Constraints einzubinden sind nur die
Instatiierungen in HDL und die Constraints in den entsprechenden
Constraints-Files (z.B. QSF-File) notwendig, die Beschreibung
dazu steht in den Manuals. Komplizierte Settings in Quartus
(oder auch ISE/LatticeDiamond) habe ich nie gemacht.

von ... (Gast)


Lesenswert?

> allerdings ist dann nach erneutem Kompilieren alles wieder weg.

Das muss man als Fieldchange per Changemanagement hinzufuegen.

von Klaus (Gast)


Lesenswert?

ich schrieb:
> Nimm die fiftyfivenm_lcell_comb, mit dont_touch => "on" wird die
> nicht
> wegoptimiert:

Oh man, du bist mein Held! Genau das habe ich gesucht. Puhh, wie viele 
Stunden ich mich deswegen schon durch das Internet gewühlt habe.

Sigi schrieb:
> ... und natürlich noch eine Hand voll Generics.
> Was hast du denn noch erwartet? Die Bausteine werden
> wie Komponenten in VHDL/Verilog in dein Design eingebunden,
> mehr als IOs (+Generics) sind also nicht erforderlich.
>
> Vlt aber eine kleine Übung für dich, damit du dir eine
> Kette im ChipPlanner/Floorplanner/etc. anschauen kannst:
> Setze ein neues Projekt auf, schreib eine kleine Komponente
> mit 2*4 Input Pins (für Input-Vektoren din1,din2 der Länge 4)
> und 5 Output Pins (für Output-Vektor dout der Länge 5) und
> addiere dout=din1+din2. Im ChipPlanner siehst du dann schon
> mal die LEs mit den Verbindungen untereinander und den
> entsprechenden Settings für eigene Generics in den
> LCELL-Komponenten.

Ich weiß nicht, ob ich dich richtig verstehe. Meinst du die Settings wie 
aus dem Bild in meinem ersten Post? Ich hatte nur die LCELL von der 
Intel Webseite gefunden, die nur einen Ein- und Ausgang hat, aber keine 
Generics. Oder meinen wir verschiedene LCELLs?

von Sigi (Gast)


Lesenswert?

Klaus schrieb:
> Ich hatte nur die LCELL von der
> Intel Webseite gefunden, die nur einen Ein- und Ausgang hat, aber keine
> Generics. Oder meinen wir verschiedene LCELLs?

Ah, ok, daher unser Missverständnis. Ich hatte mich
schon über deine "kurze" PortMap-Liste gewundert.
Hier mal, wie von "ich", eine LCELL vom CycloneV
(aus QuartusII 13.1,wysiwyg Verzeichnis):
1
component cyclonev_lcell_comb
2
  generic (
3
    dont_touch  :  string := "off";
4
    extended_lut  :  string := "off";
5
    lpm_hint  :  string := "UNUSED";
6
    lpm_type  :  string := "cyclonev_lcell_comb";
7
    lut_mask  :  std_logic_vector(63 downto 0) := "1111111111111111111111111111111111111111111111111111111111111111";
8
    shared_arith  :  string := "off"  );
9
  port(
10
    cin  :  in std_logic := '0';
11
    combout  :  out std_logic;
12
    cout  :  out std_logic;
13
    dataa  :  in std_logic := '0';
14
    datab  :  in std_logic := '0';
15
    datac  :  in std_logic := '0';
16
    datad  :  in std_logic := '0';
17
    datae  :  in std_logic := '0';
18
    dataf  :  in std_logic := '0';
19
    datag  :  in std_logic := '0';
20
    sharein  :  in std_logic := '0';
21
    shareout  :  out std_logic;
22
    sumout  :  out std_logic
23
  );
24
end component;

Du siehst ja den Unterschied zu "fiftyfivenm_lcell_comb",
von daher, nimm immer die Componente deiner Familie.
Die Properties/Settings/Modes im Bild aus deinem ersten
Posting lassen sich damit sofort in den Generics
wiederfinden. (noch kleiner Tipp: wenn du "deine"
Wunsch-LUT-Maske setzt, dann kann Quartus deine Ports
A,B,C,D,etc und die zugehörige Maske permutieren. Als
Folge siehst du dann unter Properties eine scheinbar
komplett andere Maske, also nicht wundern)

Und deswegen habe ich dir ja das kleine Projekt empfohlen.
Öffne dieses in einem 2. QUartus-Fenster, dann hast du
zu deinem eigentlichen Projekt immer eine schnelle
Vergleichsmöglichkeit.

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.