Forum: FPGA, VHDL & Co. [verilog] nettyp wor


von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

Hallo,

Mehrfachzuweisungen zu einem wor-Netz klappen in Quartus nicht, also der 
Compiler meckert deshalb.
Was muss ich tun, damit er es frisst?

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


Lesenswert?

> Mehrfachzuweisungen zu einem wor-Netz klappen in Quartus nicht,
Es gibt in einem aktuellen FPGA keine Komponente, die ein Wired-Or 
hardewaremässig abbilden kann. Deshalb gilt:
1
Triand, trior, wand and wor, are types of wired nets used to model wired 
2
logic configurations. Wired nets use truth tables to resolve the conflicts 
3
that result when multiple drivers drive the same net.

Du machst irgendwas, das die Auflösung verhindert...

> Was muss ich tun, damit er es frisst?
Mach ein "normales" Or daraus.

BTW:
Du kannst mit Verilog (und VHDL) Dinge beschreiben, die niemals auf ein 
FPGA abgebildet werden können.

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

bloß warum macht der compiler nicht einfach ein normales or draus?

also beispiel:

wor x;
assign y = a;
assign y = b;

ist das gleiche wie:

assign y = a || b;

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Stefan Helmert schrieb:
> bloß warum macht der compiler nicht einfach ein normales or draus?

Weil Du ihm explizit sagst, dass Du das nicht willst.

> wor x;
> assign y = a;
> assign y = b;
>
> ist das gleiche wie:
>
> assign y = a || b;

Nein, das eine ist eine Beschreibung, wie Deine Hardware aussehen
soll, das andere eine Zuweisung des Ergebnisses einer logischen(!)
Verknüpfung[1]. Außerdem sind die Wahrheitstabellen unterschiedlich. Was
Du vermutlich schreiben wolltest, war
1
assign y = a | b;

Aber auch hier ist die Tabelle anders[2]. Stell Dir mal die Umsetzung
eines wired OR vor, schreib die Tabelle auf

Den "physikalischen" Teil von Verilog sollte man bei synthetisierbaren
Designs vermeiden, da es meistens Probleme gibt. Überlass die
Umsetzung in Hardware Deinem Synthese Werkzeug.

Gruß
Marcus
http://www.doulos.com/

Footnotes:
[1]  Keine Z oder X Propagation :-)

[2]  Keine Z Propagation

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

Wenn man etwas auf diese Weiße formulieren möchte, sollte man wohl VHDL 
nehmen und dort den Datentyp std_logic?

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Stefan Helmert schrieb:
> Wenn man etwas auf diese Weiße formulieren möchte, sollte man wohl VHDL
> nehmen und dort den Datentyp std_logic?

Worauf bezieht sich diese Aussage? Mit VHDL wirst Du ebenfalls kein 
wired-OR hinbekommen, wenn die Zieltechnologie diese Option nicht 
bietet.

Was willst Du denn erreichen? Warum möchtest Du das unbedingt als 
wired-OR beschreiben und erwartest dass die Synthese das ggf. als 
normales Gatter umsetzt. Warum der Umweg?

Gruß
Marcus
http://www.doulos.com/

von Stefan H. (Firma: dm2sh) (stefan_helmert)


Lesenswert?

>Warum möchtest Du das unbedingt als
>wired-OR beschreiben und erwartest dass die Synthese das ggf. als
>normales Gatter umsetzt. Warum der Umweg?

Weil dann der Code schöner aussieht! OK klingt doof, ist aber doch bei 
Bussystemen üblich. Wenn mehrere Komponenten sich eine Bus teilen, dann 
wird nur die aktive einen Wert auf den Bus legen, die anderen eben 
High-Z. Man kann ja das High-Z auch als low interpretieren lassen. Oder 
man gibt weak-low auf den Bus und die Komponente, die sendet legt 
forcing-high für 1 an bzw. weak-low oder high-Z für 0. Das wird 
natürlich natürlich nicht physikalisch so im FPGA realisiert.

Es geht ja darum, dass man es eben nicht so schreibt, wie es tatsächlich 
realisiert wird, sondern so, dass der Code mit einem Blick durchschaubar 
ist. Natürlich könnte man die Ausgänge von mehreren Bus-Teilnehmern über

assign daten_bus = speicher_do | cpu_do | dma_unit_do | interface_do;
assign speicher_di = daten_bus;
assign cpu_di = daten_bus;
assign dma_unit_di = daten_bus;
assign interface_di = daten_bus;

beschreiben. Aber es wäre doch besser, wenn man eine "normale" 
schreibweise anwenden könnte:

dma dma_unit1(daten_bus);
interface interface1(daten_bus);
speicher speicher1(daten_bus);
cpu cpu1(daten_bus);

zweitere sieht doch viel übersichtlicher aus. Das ist das was ich meine. 
Was muss ich dann tun, dass der Compiler nicht herummeckert, es sei mehr 
als ein Treiber auf dem Bus, sondern stattdessen diese Struktur zu der 
ersten Variante intern auflöst?

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Stefan Helmert schrieb:
>>Warum der Umweg?
>
> Weil dann der Code schöner aussieht! OK klingt doof, ist aber doch bei
> Bussystemen üblich.

Nein. Seit langer Zeit schon vermeidet man solche Strukturen aus
verschiedensten Gründen, vor allem Testbarkeit.

> Wenn mehrere Komponenten sich eine Bus teilen, dann wird nur die
> aktive einen Wert auf den Bus legen, die anderen eben High-Z.

Was zu verifizieren wäre. Kein Spaß in hinreichend komplexen Systemen
falls jede Komponente das selbständig tun soll. Schaltet der Arbiter
die Treiber, dann gehts bequemer und sicherer mit dem unten
beschriebenen Beispiel.

> Man kann ja das High-Z auch als low interpretieren lassen. Oder man
> gibt weak-low auf den Bus und die Komponente, die sendet legt
> forcing-high für 1 an bzw. weak-low oder high-Z für 0. Das wird
> natürlich natürlich nicht physikalisch so im FPGA realisiert.  Es
> geht ja darum, dass man es eben nicht so schreibt, wie es
> tatsächlich realisiert wird, sondern so, dass der Code mit einem
> Blick durchschaubar ist.

Die Beschreibung mit wor gibt aber eben eine genaue Implementierung
vor. Außerdem ist ist sie logisch nicht identisch mit dem was Du haben
möchtest. Willst Du wirklich, dass die Synthese Annahmen trifft?

> Natürlich könnte man die Ausgänge von mehreren Bus-Teilnehmern über
>
> assign daten_bus = speicher_do | cpu_do | dma_unit_do | interface_do;

Nein, es sei denn, Du schaltest irgendwelche Treiber ab
(s.o.). Grundsätzlich will man auf dem Chip aber keine Tri-state
buffer haben. Und auch keine High-Z "Pegel".

Viel einfacher (und geläufiger) ist daher ein multiplexed Bus. Du
wirst ohnehin einen Arbiter implementieren, und der schaltet einfach
die Signale durch, die gerade benötigt werden:
1
always @* begin
2
   case (grant)
3
      SPEICHER: daten_bus <= speicher_do;
4
      CPU:      daten_bus <= cpu_do;
5
      DMA:      daten_bus <= dma_unit_do;
6
      IFACE:    daten_bus <= interface_do;
7
      default:  daten_bus <= 32'bx;
8
   endcase
9
end

> Aber es wäre doch besser, wenn man eine "normale"
> schreibweise anwenden könnte:
>
> dma dma_unit1(daten_bus);
> interface interface1(daten_bus);
> speicher speicher1(daten_bus);
> cpu cpu1(daten_bus);
>
> zweitere sieht doch viel übersichtlicher aus.

Sieht aus wie SystemVerilog Interfaces. Auch hier wird Dir die
Implementierung nicht abgenommen, aber sie wird zentralisiert und ist
dann in der strukturellen Beschreibung nicht mehr sichtbar. Zudem kann
die Beschreibung mehrmals instanziiert werden, so dass man die Logik
nur einmal schreibt. Ist aber zur Zeit auch nicht ganz ohne
Tücken. Sieh auch diesen Artikel:
http://www.doulos.com/knowhow/sysverilog/DVCon07/DVCon07_SysVlog.php

Gruß
Marcus
http://www.doulos.com/

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.