Forum: FPGA, VHDL & Co. 1 kleines VHDL Rätsel


von Gustl B. (-gb-)


Lesenswert?

Unter welchen Umständen sind concurrent Zuweisungen wie
1
a <= b when c = '1' else d;
innerhalb eines getakteten Prozesses, also innerhalb des
1
if rising_edge(clock) then
2
  *hier*
3
end if;
erlaubt?

Bonuspunkte gibt es für die Begründung, weil ich die selber noch nicht 
kenne (-:

: Bearbeitet durch User
von Superbus (Gast)


Lesenswert?


von Achim M. (minifloat)


Lesenswert?

Vielleicht wenn sich die Zuweisung in reine Kombinatorik auflösen lässt, 
hier eben ein Demux, bestehend aus Invertern und AND-Gattern.

Ist lang her und ich bin auf die Lösung gespannt.

mfg mf

von Gustl B. (-gb-)


Lesenswert?

Argh, es gibt wohl sehr viele Lösungen ...

Ich hatte irgendwie geglaubt (warum auch immer), dass man innerhalb von 
getakteten Prozessen keine concurrent statements schreiben darf. Aber 
siehe da, das scheint generell erlaubt.

von Markus F. (mfro)


Lesenswert?

Einzige Voraussetzung ist VHDL 2008 Unterstützung.
(Zumindest) ältere Quartus-Versionen z.B. können das (wegen eben 
unvollständiger VHDL 2008 Implementierung) nicht.

Ansonsten ist es genau dasselbe wie
1
if c = '1' then a <= b; else a <= d; end if;

von M. N. (bmbl2)


Lesenswert?

Markus F. schrieb:
> Einzige Voraussetzung ist VHDL 2008 Unterstützung.
> (Zumindest) ältere Quartus-Versionen z.B. können das (wegen eben
> unvollständiger VHDL 2008 Implementierung) nicht.

Richtig. Das kam alles mit VHDL2008. Der Support dafür sieht aber i. d. 
R. schlecht aus. Die Asic Synthesen können sowas zum Beispiel gar nicht. 
Da kann man schon froh sein, wenn VHDL93 halbwegs funktioniert.

Schön zu sehen, dass so etwas immerhin von den FPGA Toolings (teilweise) 
unterstützt wird.

von M. N. (bmbl2)


Lesenswert?

Man kann es auch andersrum machen und ein FlipFlop ohne Prozess 
inferieren:
1
q <= d when rising_edge(clk) else q;

Das geht soweit ich sehe auch erst seit 2008.

von Markus F. (mfro)


Lesenswert?

M. N. schrieb:
> Das geht soweit ich sehe auch erst seit 2008.

Du siehst falsch. Das geht schon immer.

von M. N. (bmbl2)


Lesenswert?

Markus F. schrieb:
> Du siehst falsch. Das geht schon immer.
1
dcnxt_shell> read_vhdl flop.vhd 
2
Loading vhdl file '/tmp/tmp.czjuGaFtUy/flop.vhd'
3
Running PRESTO HDLC
4
Warning: Can't read link_library file 'your_library.db'. (UID-3)
5
Compiling Entity Declaration FLOP
6
Compiling Architecture RTL of FLOP
7
Error:  /tmp/tmp.czjuGaFtUy/flop.vhd:20: An if statement containing a clock event has an illegal else branch and is not supported for synthesis. (ELAB-928)
8
Error:  /tmp/tmp.czjuGaFtUy/flop.vhd:20: An if statement containing a clock event has an illegal else branch and is not supported for synthesis. (ELAB-928)
9
Error:  /tmp/tmp.czjuGaFtUy/flop.vhd:20: An if statement containing a clock event has an illegal else branch and is not supported for synthesis. (ELAB-928)
10
*** Presto compilation terminated with 3 errors. ***
11
Error: Can't read 'vhdl' file '/tmp/tmp.czjuGaFtUy/flop.vhd'. (UID-59)
12
No designs were read
13
dcnxt_shell>

flop.vhd sieht so aus:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
4
entity flop is
5
6
  port (
7
    clk : in  std_logic;
8
    d   : in  std_logic;
9
    q   : out std_logic);
10
11
end entity flop;
12
13
architecture rtl of flop is
14
  signal q_reg : std_logic;
15
begin  -- architecture rtl
16
17
  -- Signal needed due to VHDL'93. Not necessary in VHDL2008
18
  q <= q_reg;
19
20
  q_reg <= d when rising_edge(clk) else q_reg;
21
22
end architecture rtl;

von Markus F. (mfro)


Lesenswert?

Ich korrigiere: das sollte schon immer gehen.

Dann hast Du's hier halt mit einer unvollständigen VHDL-Implementierung 
zu tun...

[edit: das Ding scheint das Statement ja zu erkennen, hat "nur" keinen 
Synthese-Support dahinter]

: Bearbeitet durch User
von Mampf F. (mampf) Benutzerseite


Lesenswert?

Gustl B. schrieb:
> nter welchen Umständen sind concurrent Zuweisungen wie

Oh, auf die Idee wäre ich ja niiiiiiiiiiiiiiie gekommen, das überhaupt 
auszuprobieren 🤯

Damals ging das noch nicht und ich hab das dann auch nie wieder 
versucht.

von Bernd G. (Gast)


Lesenswert?

Für mich ist das hier relevant:
1
you can carefuly use block statement and when sequential needed use guarded. I've asked my colleagues who have huge background in FPGA design and they told that block is kinda anachronism, almost nobody use it, but it still in standard to give some choice for designers.

von Kay-Uwe R. (dfias)


Lesenswert?

Interessehalber nachgehakt:
1. Gilt das hier gesagte auch für verkettete with/select/when- bzw. 
when/else-Konstrukte vs. case/is/when im Prozess?
2. Den else-Zweig beim if kann man als einzelne Zuweisung auch vor das 
if-Statement setzen:
1
  b <= '1';
2
  ...
3
  if a = '1' then
4
    b <= '0';
5
  end if;
Gibt es das außerhalb der Prozesse auch, also z. B. when ohne else?

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Kay-Uwe R. schrieb:
> Gibt es das außerhalb der Prozesse auch, also z. B. when ohne else?

Ich habe es mir so gemerkt, dass in Prozessen "if" und außerhalb 
Prozessen "when".

Damals ging es andersrum auch garnicht. Glaub ich werde es auch nie 
wieder anders machen 🤔

: Bearbeitet durch User
von J. S. (engineer) Benutzerseite


Lesenswert?

Mampf F. schrieb:
> Ich habe es mir so gemerkt, dass in Prozessen "if" und außerhalb
> Prozessen "when".

Die Sache wird dann spannend, wenn sich die IFs und WHENs funktionell 
überlappen und es echte exklusive IF-ELSE sind, bzw wie verschachtelt 
sie sind. Als Beispiel könnte man auf die ersten 3 Bits eines Verktors 
checken und parallel noch auf die ersten 2. Das ergibt einen parallelen 
Konstrukt, der einen Vorrang braucht um eindeutig aufgelöst zu werden. 
Dann gilt nämlich die Reihenfolge der Codierung und das noch im Bezug 
auf das Auftreten von Signalen. Besonders in der Simulation macht sich 
das dann bemerkbar. Wenn z.B. eine FSM läuft, die an zwei Stellen 
zeitversetzt auf kombinatorische Signale prüft, dann würde eine Änderung 
von Signalen zwischen den beiden Abfragen zu einem varianten Ergebnis 
führen. Je nachdem, wie man die Process-Liste ausführt, bekommt man z.B. 
3 mögliche Verhaltensfälle, von denen 2 nichts mit dem gemein haben, was 
der synthetisierte Code macht.

Beitrag #7622616 wurde vom Autor gelöscht.
von Gerda M. (gerda11)


Lesenswert?

Also, check’s mal: Wenn du in VHDL abgehen willst und so a <= b when c = 
'1' else d; direkt im Prozess droppen willst, dann ist das klar machbar. 
Aber das musst du außerhalb von den krassen if-Statements machen, die 
auf den Clock abfahren, weißt du?

Hier mal ein Beispiel, wie das fresh aussehen könnte:

process(clock)
begin
  if rising_edge(clock) then
    -- Hier kommen die getakteten Moves
  end if;

  -- Und hier ballerst du die concurrent Zuweisung rein, easy.
  a <= b when c = '1' else d;
end process;

Die Sache ist die: Concurrent Zuweisungen sind wie die Party, die 
nebenan abgeht, während du in deinem Zimmer chillst. Die laufen parallel 
und jucken sich nicht daran, was in deinem sequentiellen Flow abgeht. 
Also kannst du die einfach nebenbei laufen lassen, solange sie nicht in 
den if-Statement-Vibe reinkrachen, der auf den Clock reagiert. Voll 
logisch, oder?

von Gustl B. (gustl_b)


Lesenswert?

Gerda M. schrieb:
> Aber das musst du außerhalb von den krassen if-Statements machen

Eben genau nicht. Ich dachte auch, dass das so wäre, aber es 
funktioniert auch im getakteten Teil eines Prozesses.

von J. S. (engineer) Benutzerseite


Lesenswert?

Gerda M. schrieb:
> process(clock)
> begin
>   if rising_edge(clock) then
>     -- Hier kommen die getakteten Moves
>   end if;
>
>   -- Und hier ballerst du die concurrent Zuweisung rein, easy.
>   a <= b when c = '1' else d;
> end process;
>
> Die Sache ist die: Concurrent Zuweisungen sind wie die Party, die
> nebenan abgeht,

Da sehe ich keinen Sinn drin. Das "a <= b when c = '1' else d;" gehört 
raus aus dem process statement, wenn nicht irgendwelche Abhängigkeiten 
nötig sind. Soweit sie sinnvoll sind, um die Simulation zu optimieren, 
gehört das in einen eigenen Prozess, wo die SENS-Liste von (nur) diesen 
Signalen abhängig ist.

Hier steckt auch wieder ein wenig die Strategie mancher Entwickler drin, 
dass man alle getakteten Signale in einen process stopfen 
kann/sollte/darf. Davon halte ich sehr wenig!

Ich tendiere lieber zu einer Einzelbeschreibung der relevanten 
Ausgangssignale mitsamt dem Managment dessen, was dafür nötig ist. Das 
vereinfacht die Verschachtelungen bei IF-THENs und auch eventuell WHENs.

Das Ziel sollte Übersichtlichkeit sein und nicht das Ausreizen von 
Codierungs-Optionen. Weil immer viel historisches mitgeschleppt wird, 
herrscht bei VHDL eine große Redundanz und ein Wildwuchs bei der 
Möglichkeit, exakt Dasselbe zu beschreiben, dass es angezeigt ist, das 
zu simplifizieren und zu vereinheitlichen.

> VHDL Rätsel
Wenn bei solchen Beschreibungen "gerätselt" werden muss und man die 
Simulation braucht, um einen Konstrukt zweifelsfrei und vollständig zu 
verstehen, ist er fehl am Platze.

VHDL ist eine Bauanleitung für eine virtuelle Elektronik und solche 
Anleitungen sollten klar formuliert sein, damit sie gut und effektiv 
überprüfbar sind. Das ist bei wachsender Schaltungskomplexität zunehmend 
wichtiger und in vielen Branchen, in denen Code gereviewd werden muss 
und Standards zu erfüllen hat, einfach unerlässlich. Es hat niemand 
etwas davon, wenn ein Entwickler perfektionierte und selten genutzte 
Konstrukte benutzt, die ihm Zeit ersparen, sehr elegant sind, von 
anderen aber nur durch Analyse verstanden werden. Am Ende muss man X 
Kommentare und Doku nachrüsten, was jeden Vorteil einer möglichen 
Zeiteinsparung pulverisiert.

Auch in Sachen Code-Pflege ist es viel einfacher und durchsichtiger, 
wenn beim Vergleich zweier eingecheckter Versionen nicht an 
allenmöglichen Stellen aufgeblusterte und immer komplizierter werdende 
FSMs und Prozesse auftauchen, sondern das einmal Gemachte in Ruhe bleibt 
und neue Funktionen wirklich einfach nur zu einigen neuen Prozessen und 
Zeilen führen, die im Compare-Fenster direkt aufpoppen. Die 
Compare-Funktion profitiert massiv davon, wenn Code entsprechend 
blockorientiert erstellt wurde. Auch lassen sich solche nachgerüsteten 
Code-Fragmente viel einfacher per COPY und PASTE in andere Projekte 
verfrachten und alter Code manuell nachpflegen. Das Automerge bei 
gleichzeitiger Codebearbeitung von zwei Leuten funktioniert dann auch 
unfallfreier.

von Gustl B. (-gb-)


Lesenswert?

J. S. schrieb:
> Das "a <= b when c = '1' else d;" gehört
> raus aus dem process statement, wenn nicht irgendwelche Abhängigkeiten
> nötig sind.

Darum geht es nicht. Es ging mir nur um die Tatsache, dass solche 
concurrent Zuweisungen möglich sind - und zwar nicht nur in einem 
Prozess, sondern auch in dem getakteten Teil vom Prozess. Das war mir 
neu, scheint aber standardkonform zu sein. Man kann jetzt also statt
1
process(clock)
2
begin
3
if rising_edge(clock) then
4
   if c = '1' then
5
      a <= b;
6
   else
7
      a <= d;
8
   end if;
9
end if;
10
end process;
ganz einfach
1
process(clock)
2
begin
3
if rising_edge(clock) then
4
   a <= b when c = '1' else d;
5
end if;
6
end process;
schreiben.

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.