Forum: FPGA, VHDL & Co. VHDL-Teile für Simulation anders behandeln als für die Synthese


von Mike (Gast)


Lesenswert?

Hallo zusammen,

Es ist ja möglich mit Generate-Anweisungen bestimmte Varianten
kompilieren zu lassen. Beispielsweise so:

code-Ausschnitt wird nur berücksichtigt wenn DEBUG = 1:
1
DEBUG_TEIL : if DEBUG = 1 generate
2
...
3
VHDL Beschreibung die genutzt wird für für den Fall DEBUG = 1
4
...
5
end generate DEBUG_TEIL;

Nun möchte ich für den Fall, dass ich eine Komponente simuliere, 
automatisch eine Abwandlung des VHDL-Designs für die Simulation nutzen. 
Für die eigentliche Synthese als Grundlage für die Implementation dann 
aber eine andere Abwandlung. Also irgendwas in dieser Art:
1
SIMU_TEIL : if SIMULATION = 1 generate
2
...
3
VHDL Beschreibung die genutzt wird für für den Fall, dass simuliert wird.
4
...
5
end generate DEBUG_TEIL;
1
IMPL_TEIL : if IMPLEMENTATION = 1 generate
2
...
3
VHDL Beschreibung die genutzt wird für für den Fall, dass implementiert wird.
4
...
5
end generate DEBUG_TEIL;

Allerdings soll das automatisch gehen, so dass ich vor der Simulation 
oder Implementation nichts händisch ändern muss.

Simulationstool (falls relevant): Model Sim

Viele Grüße,
Mike

von Vancouver (Gast)


Lesenswert?

Du kannst beim Aufruf von modelsim so etwas angeben wie 
+define+SIMULATION, dann ist dieses Symbol definiert. Ich weiß nicht 
mehr genau die Syntax ist, aber ich habe das mal benutzt vor längerer 
Zeit, allerdings in Systemverilog. Für die Synthese wertest du dann aus, 
ob das Symbol nicht definiert ist.

von Vancouver (Gast)


Lesenswert?

Ich habe gerade nochmal nachgeschaut. Das +define+SIMULATION habe ich 
als Parameter für vlog angegeben, also den Compiler. Allerdings in einem 
Script. Wie das in der GUI geht, kann ich nicht sagen.

von abc (Gast)


Lesenswert?

In vielen Tools sollte es auch möglich sein, Werte für Generics per 
Kommandozeile mitzugeben.

von Pat A. (patamat)


Lesenswert?

Es gibt auch - Tool-abhängig - die Direktiven
1
--synthesis translate_off
2
--synthesis translate_on

und
1
--pragma translate_off
2
--pragma translate_on

von Tobias B. (Firma: www.elpra.de) (ttobsen) Benutzerseite


Lesenswert?

Idealerweise wuerde ich fuer sowas VUnit nehmen um Generics fuer 
verschiedene Testszenarien zu verwalten. Macht alles viel einfacher.

Du kannst Generics beim Aufruf von vsim mitgeben, welche dann in deiner 
Testbench bis an dein HDL Modul weitergegeben werden. Der entsprechende 
CLI Switch ist -g, siehe:

http://www.pldworld.com/_hdl/2/_ref/se_html/manual_html/c_vcmds191.html#11034046

von Nick (Gast)


Lesenswert?

Macht das denn Sinn, eine Simulation anders zu formulieren?
Soweit es meine Sachen angeht, braucht es doch nur Ersatzmodule für 
PLLs, Transceiver, IOs, SERDES und alles, was irgendein wichtiges 
Zeitverhalten hat. Die kann man doch leicht austauschen, d.h. im 
Toplevel der Synthese andere Module verwenden, als in der für die 
Simulation. Das schleift man einfach durch und entscheidet innen an der 
Entity welche Module genutzt werden. So hat man immer nur ein Mapping 
drin, statt riesen Blöcke an VHDL.

von Tobias B. (Firma: www.elpra.de) (ttobsen) Benutzerseite


Lesenswert?

Jep, es gibt z.B. Faelle in denen du die Simulation beschleunigen 
willst. Ein Beispiel ist die Init Routine eines Speichers oder der 
Startup bis MGTs bereit sind.

In umfangreichen Projekten kannst du so z.B. nicht mehr nach jedem 
Commit Regression Tests laufen lassen. Dann ueberlegst du dir das ganze 
mehrstufig zu fahren, z.B. Tests die innerhalb weniger Minuten 
durchlaufen so dass du eine "Commit early and often" Strategie fahren 
kannst. In diesen Faellen geht es oft nicht anderst.

Viele IPs bringen einen solchen Sim Speedup Switch schon mit, 
entsprechend angenehm ist die Handhabung. :-)

Andere Beispiele sind wenn du nicht synthetisierbaren Code zu 
Debugzwecke hast, z.B. Ausgabe von Logfiles. Da kann so ein Switch einem 
auch das Leben einfacher machen. :-)

von Vancouver (Gast)


Lesenswert?

Nick schrieb:
> Macht das denn Sinn, eine Simulation anders zu formulieren?

Das Problem tritt immer dann auf, wenn ein IP-Core verwendet wird, der 
nicht im RTL-Code vorliegt. Dann braucht man ein explizites 
Simulationsmodell, das auch nur bei der Simulation eingebunden wird. Bei 
der Synthese würde das einen Fehler verursachen (weil es gar nicht 
synthetisierbar ist oder extrem ineffizient für die Implementierung 
wäre).
Die Unterscheidung wird meistens in einem Wrapper getroffen. Als 
Designer muss man nur den Wrapper einbinden, aber under the hood wird 
dann jeweils das richtige Modul ausgewählt für Simulation und Synthese. 
Das ist bei fast allen kommerziellen IPs so. PLDA z.B. würde dir sicher 
nicht den  RTL-Code seiner PCIe-Bridge zur Simulation bereitstellen, 
sondern nur ein vereinfachtes Modell, das aber nicht synthetisierbar 
ist.
Beim ASIC-Design liegen die meisten IPs ohnehin schon als Hardmacros für 
die jeweilige Technologie vor, die sind dann nicht mehr simulierbar und 
werden auch nicht mehr synthetitisiert, sondern erst bei der 
Maskengenerierung in der FAB eingebaut. Da muss man entweder das 
Simulationsmodell einbauen oder einen Platzhalter.

von Martin S. (strubi)


Lesenswert?

@Mike: Wenn du nur Komponenten umschalten musst, faehrst du allenfalls 
mit einer `configuration` eleganter (und musst den Code nicht mit 
generates verunstalten).

Also was in dem Stil:
1
configuration virtualjtag of tb_breakout is
2
  use work.breakout_top;
3
4
  for sim
5
    for uut : breakout_top
6
      use configuration work.vjtag;
7
    end for;
8
  end for;
9
10
end virtualjtag;
Fuer den jeweiligen Target tauschst du dann nur noch entsprechend die 
configuration-VHDL-Files. Sollte Modelsim eigentlich auch koennen, ich 
nutze hier GHDL.

von ktorkelson (Gast)


Lesenswert?

Hallo @Mike,

ich würde die Idee von @patamat aufgreifen und mit Direktiven arbeiten.
1
constant IMPLEMENTATION : integer := 0
2
                                     -- synthesis translate_off
3
                                     + 1
4
                                     -- synthesis translate_on
5
                                     ;
6
...
7
8
SIMU_TEIL : if IMPLEMENTATION = 1 generate
9
10
  -- VHDL Beschreibung, die genutzt wird für den Fall, dass simuliert wird.
11
12
end generate SIMU_TEIL;
13
14
...
15
16
IMPL_TEIL : if IMPLEMENTATION = 0 generate
17
18
  -- VHDL Beschreibung, die genutzt wird für den Fall, dass implementiert wird.
19
20
end generate IMPL_TEIL ;
21
22
...

Gruß

von Duke Scarring (Gast)


Lesenswert?

Ich nutze seit vielen Jahren folgendes Konstrukt:
1
    function simulation_active return std_ulogic is
2
        variable result : std_ulogic;
3
    begin
4
        result := '0';
5
        -- pragma translate_off
6
        result := '1';
7
        -- pragma translate_on
8
        return result;
9
    end function simulation_active;

Wahlweise geht auch das, was ja der Idee von ktorkelson entspricht:
1
    constant simulation_active : boolean := false
2
    -- pragma translate_off
3
        or true
4
    -- pragma translate_on
5
        ;

Eigentlich sind die VHDL-configurations dafür gedacht, aber irgendein 
Tool kam damals, wo ich das gebraucht habe, nicht klar damit. ModelSim 
war es nicht, das unterstützt configurations.

In einem CI-System würde ich die Parameter eher per Generics + 
Kommandozeile mitgeben.

Duke

von Mike (Gast)


Lesenswert?

@All

ein ganz dickes Dankeschön für die vielen Tips und Vorschläge. Das hilft 
mir auf jeden Fall schonmal weiter!

Viele Grüße,
Mike

von Nick (Gast)


Lesenswert?

Vancouver schrieb:
> Das Problem tritt immer dann auf, wenn ein IP-Core verwendet wird, der
> nicht im RTL-Code vorliegt. Dann braucht man ein explizites
> Simulationsmodell, das auch nur bei der Simulation eingebunden wird.

Ist mir alles klar, nur die Frage ist, WIE man das einbindet.
Wenn ich eine Simulation habe, instanziiere ich direkt nur die Modelle 
(egal, woher sie kommen).

Ich denke, es geht wohl darum, wie man das in der Tiefe des Designs 
macht. Ich habe bisher einfach einen std_logic mitgegeben, z.B. 
"design_confing_vector (15 downto 0" der an alle entities geht und 
durchgereicht wird. An den kann ich dann "unten" anschließen was ich 
will. Als Beispiel bezieht ein Design unten drin bei der Simulation 
seine Takte dann aus einem einfachen not-Konstrukt statt einer echten 
PLL und das Ergebnis einer umfangreichen Berechnung wird als Ersatzwert 
ausgegeben (mit Latenz) statt es alles zu berechnen.

von Vancouver (Gast)


Lesenswert?

Nick schrieb:
> Wenn ich eine Simulation habe, instanziiere ich direkt nur die Modelle


Genau das soll automatisiert werden. Man möchste einfach keine zwei 
Designs pflegen, eins für die Simulation und eins für Synthese. Das ist 
bei größeren Projekten eine erhebliche Fehlerquelle. Überall dort, wo 
Synthese- und Simulationsmodell verschieden sind, soll automatisch das 
richtige Modell ausgewählt werden. Wenn du das manuell machst, kommst 
irgendwann in Teufels Küche (ich war mehrmals dort...)
In deinem Fall würde man einen Wrapper für die Taktgenerierung bauen, in 
dem entweder ein rückgekoppelter Inverter oder eine echte PLL 
instanziiert wird. Das erspart dir den config-vector, du musst nichts 
mehr "umklemmen" für die Synthese.

von Nick (Gast)


Lesenswert?

Vancouver schrieb:
> Das erspart dir den config-vector,

Dann muss ich in einer anderen Weise definieren, welches der VHDL Module 
eingebunden werden soll.

Den Vektor benutze ich auch für die Instanzierung unterschiedlicher 
Versionen von VHDL-Modulen für verschiedene Versionen der Software (also 
der synthetisierten Software).

Die Quelle dieses Vektors ist ein Version-Modul (ein VHDL) in dem ein 
Versions-Code hinterlegt ist.
Dieser Versions-Code ist von der Software auslesbar. Damit lässt sich in 
jedem Gerät eindeutig erkennen, welche Module an sind und welche Version 
sie haben.

Man muss also nur im Versionsmodul einen Code ändern. Z.B. so:

VersionCode <= "001" & "101" & x"210402" & "0010" & "0101" & "0110";

Heisst:  Version 1.5 - vom 2.APR.2021 mit den SW-Versionen 2,5,6 für die 
SW-Teile, die austauschbare Versionen haben. Eine 1 vorne ist eine 
Simulationsversion. Dazu gibt es Schalter für Debug-Versionen. Dann 
kommen nur Module hinein, die zum Debuggen gebraucht werden.

Der Tipp kam so von einem Typen auf einem PLC2-Seminar.

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.