mikrocontroller.net

Forum: FPGA, VHDL & Co. Verilog bedingte Zuweisung


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: freduardo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich brauche Hilfe beim "Übersetzen" einer Verilog Zuweisung. Wie lässt 
sich diese Zuweisung:
set_mtr_lb <= (axi_config_cs == SETSLAVELOOPBACK) ? 0 : (axi_config_cs == SETMASTERLOOPBACK) ? 1 : set_mtr_lb;

in VHDL beschreiben?


Meine Vermutung ist:
 set_mtr_lb <= '0' when (axi_config_cs = SETSLAVELOOPBACK) else '1' when (axi_config_cs = SETMASTERLOOPBACK) else set_mtr_lb;

Liege ich da richtig, oder bin ich komplett auf dem Holzweg?

P.S.: Ich habe versucht danach zu googeln, finde unter "verilog bedingte 
zuweisung" nur die Erklärung für den einfachen Fall: "Bedingung  ? 
Anweisung  (wenn   wahr)  :  Anweisung  (wenn falsch)". Wenn ich diese 
Struktur "weiterspinne" komme ich auf meine Lösung, möchte sie aber von 
Verilog-Experten bestätigt wissen.

Danke im voraus


~Freduardo

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
freduardo schrieb:
> set_mtr_lb <= (axi_config_cs == SETSLAVELOOPBACK) ? 0 : (axi_config_cs
> == SETMASTERLOOPBACK) ? 1 : set_mtr_lb;
Oh, übersichtlicher, wartbarer Code ;-)

Ich würe es so versuchen:
process( axi_config_cs, set_mtr_lb)
begin

  if axi_config_cs =  SETSLAVELOOPBACK then
      set_mtr_lb <= '0';
  else
    if axi_config_cs =  SETMASTERLOOPBACK then
      set_mtr_lb <= '1';
    end if;
  end if;

end process;

Duke

: Bearbeitet durch Moderator
Autor: freduardo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Duke Scarring schrieb:
> freduardo schrieb:
>> set_mtr_lb <= (axi_config_cs == SETSLAVELOOPBACK) ? 0 : (axi_config_cs
>> == SETMASTERLOOPBACK) ? 1 : set_mtr_lb;
> Oh, übersichtlicher, wartbarer Code ;-)
>
> Ich würe es so versuchen:
> [vhdl]
> process( axi_config_cs, set_mtr_lb)
> begin
>
>   if axi_config_cs =  SETSLAVELOOPBACK then
>       set_mtr_lb <= '0';
>   else
>     if axi_config_cs =  SETMASTERLOOPBACK then
>       set_mtr_lb <= '1';
>     end if;
>   end if;
>
> end process;
> [/vhld]
>
> Duke

Der Verilog-Code stammt aus einem automatisch erzeugten Beispiel-Projekt 
für nen Ethernet-IP Core von Xilinx. Leider sind diese Projekte so gut, 
wie immer in Verilog geschrieben, da tue ich mir als VHDL-ler z.T. recht 
schwer mit der "komischen" Syntax.

Sorry, dass ich es nicht direkt dazugeschrieben habe: Die Zuweisung 
befindet sich in einem getakteten Prozess. Beim Umsetzen nach VHDL habe 
ich das Ganze als if elsif... beschrieben.

Danke für die schnelle Antwort.

Autor: Duke Scarring (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Ja Xilinx scheint VHDL nicht zu mögen oder kennt sich mit den 
Möglichkeiten nicht wirklich aus.
Ich hänge hier gerade mit diversen AXI-Interfaces ab. Da wären 
VHDL-records ideal, um die Verdrahtung übersichtlich zu machen, aber 
nein: jedes Signal wird einzeln behandelt...

Autor: Vancouver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
freduardo schrieb:
> Liege ich da richtig, oder bin ich komplett auf dem Holzweg?

Sieht richtig aus. Ich würde den zweiten Teilausdruck (nach dem ersten 
else) noch in Klammern setzen, zwecks Übersichtlichkeit.

Btw, seit VHDL-2008 kann man 'when' auch in Prozessen benutzen, d.h. man 
musst das nicht mehr in if/then/else übersetzen.

Siehe 
http://www.synthworks.com/papers/VHDL_2008_end_of_verbosity_2013.pdf
Slide 9.

Welche Lösung übersichtlicher ist, sei dahin gestellt.

Autor: freduardo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke schon mal für die Antworten auf die erste Frage.

Ich nutze den Thread für eine weitere Frage - hoffe es ist so in 
Ordnung.

Heute bin ich über einen Verilog-"Prozess" gestolpert, den ich nicht 
ganz verstehe.
always @ (*) begin
    wait_cnt_int = wait_cnt;
    if (pkt_gen_load_config_reg) begin
        wait_cnt_int = 16'h450;
    end else if (wait_cnt[15]) begin
        wait_cnt_int = wait_cnt_int;
    end else begin
        wait_cnt_int = wait_cnt_int - 1;
    end
end

Wenn ich das in VHDL (2008) schreibe komme ich auf:
    process(all)
    begin
        wait_cnt_int <= wait_cnt;
        if (pkt_gen_load_config_reg = '1') then
            wait_cnt_int <= x"0450";
        elsif (wait_cnt(15) = '1') then
            wait_cnt_int <= wait_cnt_int;
        else
            wait_cnt_int <= wait_cnt_int - 1;
        end if;
    end process;

*wobei das elsif auch durch einen else if Zweig ersetzt werden kann, 
ohne dass der logische Sinn sich ändern würde (richtig?)

Jetzt frage ich mich, welchen Sinn die Default-Zuweisung:
 wait_cnt_int <= wait_cnt; 

hat?

Dem Signal wait_cnt_int wird ja durch if-elsif-else in jedem Durchlauf 
ein Wert zugewiesen. Die Default-Zuweisung wird nie "bis zum Ende des 
Prozesses überleben".

Was übersehe ich?
Oder kann man diese always @(*)-Block nicht einfach so in einen 
VHDL-Prozess übersetzen?

Auch dieser Verilog-Code stammt aus dem Xilinx Beispiel-Projekt für den 
Ethernet-Core.

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
freduardo schrieb:
> Heute bin ich über einen Verilog-"Prozess" gestolpert
Ist der tatsächlich komplett oder wird das wait_cnt_int im Originalcode 
weiter unten nochmal verwendet?

> Jetzt frage ich mich, welchen Sinn die Default-Zuweisung:
> wait_cnt_int <= wait_cnt;
> hat?
Das ist ja deine (vermutlich falsche) Übertragung, im Verilog-Original 
steht da:
wait_cnt_int <= wait_cnt;
Und vermutlich verhält sich wait_cnt_int in diesem Verilog-Fall wie eine 
VHDL Variable und über nimmt den Wert "sofort" in dieser Zeile. 
Fürderhin wird dann auf wait_cnt_int herumgerechnet und das Ergebnis 
später wait_cnt zugewiesen.

: Bearbeitet durch Moderator
Autor: Vancouver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
freduardo schrieb:
> wobei das elsif auch durch einen else if Zweig ersetzt werden kann,
> ohne dass der logische Sinn sich ändern würde (richtig?)

Richtig.

> Jetzt frage ich mich, welchen Sinn die Default-Zuweisung: [...]
> hat?

Keinen, aus den Gründen, die du schon genannt hast. Aber an diesem 
Codeschnipsel ist noch mehr seltsam, z.B. will man

wait_cnt_int = wait_cnt_int - 1;

in keinem kombinatorischen Prozess sehen. Und

wait_cnt_int = wait_cnt_int;

will man überhaupt nicht sehen.
Ein typisches Beispiel für einen schlampig formulierten Codefetzen. Hast 
du mal probiert, ob dieser Code simuliert und synthetisiert?

Autor: freduardo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar hat Recht. Weiter unten im Code kommt:
always @ (posedge axis_clk) begin
    if ( !axis_resetn ) begin
        pkt_size_cnt <= 0;
        txc_cnt <= 0;
        en_packet_gen <= 0;
        cur_pkt_last_word_reg <= 0;
        wait_cnt <= 16'hFFFF;
        wait_cnt_16r <= 1'b1;
    end else begin
        en_packet_gen <= mtrlb_en_packet_gen;
        pkt_size_cnt <= pkt_size_cnt_int ;
        wait_cnt <= wait_cnt_int;
        wait_cnt_16r <= wait_cnt[15] ;
        txc_cnt <= txc_cnt_int;
        cur_pkt_last_word_reg <= cur_pkt_last_word;
    end
end

@Vancouver: Der Code lässt sich simulieren. Es ist das Beispiel-Projekt 
zum Xilinx IP-Core AXI 1G/2.5G Ethernet Subsystem - lässt sich in Vivado 
mit "Open IP Exmaple Design" erzeugen.

Danke Euch für die Hilfe.

Autor: freduardo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmal,

je weiter ich mich durch das Beispiel-Projekt (immernoch das in Vivado 
automatisch erzeugte Example-Project zum AXI-Ethernet IP-Core) 
durchkämpfe, umso mehr Fragen tauchen auf...

(Falls es möglich ist, könnte ein Moderator den Thread evtl. umbenennen 
in sowas wie: "Anfängerfragen zu Verilog".


Jetzt bin ich über ein case-Statement in Verilog gestolpert, das ich mir 
gar nicht erklären kann.

In einem Module werden folgende localparam definiert:
localparam  CMNDSETSPEED1000            = 8'h1 ,
            CMNDSETSPEED100             = 8'h2 ,
            CMNDSETSPEED10              = 8'h3 ,
            CMNDTGLEADDRSWAP            = 8'h8 ,
            CMNDTGLEADDRSWAPMTR         = 8'h8 ,
            CMNDSETMASTERLOOPBACK       = 8'h5 ,
            CMNDTOGGLEEXTPHYLB          = 8'hC ,
            CMNDSETSLAVELOOPBACK        = 8'h9 ,
            CMNDAPPLYSOFTRESET          = 8'h6 ,
            CMNDTGLEPATGENEN            = 8'hB ,
            CMNDTGLEPATCHKEN            = 8'hA ,
            CMNDREPROGRAMREG            = 8'h0 ,
            CMNDRESETPATCHKERROR        = 8'h4 ,
            CMNDWRITE2AXILREG           = 8'hD ,
            CMNDREADAXILREG             = 8'h7 ,
            CMNDTGLETXACTIVITY          = 8'hE ;

CMNDTGLEADDRSWAP und CMNDTGLEADDRSWAPMTR haben jeweils den Wert 8.

im gleichen Module wird die folgende Function definiert:
function [6:0] get_ns_axi_config  ;
    input [7:0] cmnd_data    ;
begin
    case (cmnd_data)
        CMNDSETSPEED1000       : begin get_ns_axi_config = SETTMACSPEED1000   ;  end
        CMNDSETSPEED100        : begin get_ns_axi_config = SETTMACSPEED100    ;  end
        CMNDSETSPEED10         : begin get_ns_axi_config = SETTMACSPEED10     ;  end
        CMNDSETSLAVELOOPBACK   : begin get_ns_axi_config = SETSLAVELOOPBACK   ;  end
        CMNDSETMASTERLOOPBACK  : begin get_ns_axi_config = SETMASTERLOOPBACK  ;  end
        CMNDRESETPATCHKERROR   : begin get_ns_axi_config = RESETPATCHKERROR   ;  end
        CMNDREPROGRAMREG       : begin get_ns_axi_config = STARTREPROGRAMREG  ;  end
        CMNDTOGGLEEXTPHYLB     : begin get_ns_axi_config = SETTOGGLEEXTPHYLB  ;  end
        CMNDWRITE2AXILREG      : begin get_ns_axi_config = STARTAXIWRTRANS    ;  end
        CMNDREADAXILREG        : begin get_ns_axi_config = STARTAXIRDTRANS    ;  end
        CMNDTGLEADDRSWAP       : begin get_ns_axi_config = TOGGLEADDRSWAPSLB  ;  end
        CMNDTGLEADDRSWAPMTR    : begin get_ns_axi_config = TOGGLEADDRSWAPMTR  ;  end
        CMNDTGLEPATGENEN       : begin get_ns_axi_config = TOGGLEPATGENEN     ;  end
        CMNDTGLEPATCHKEN       : begin get_ns_axi_config = TOGGLEPATCHKEN     ;  end
        CMNDTGLETXACTIVITY     : begin get_ns_axi_config = TOGGLETXACTIVITY   ;  end
        CMNDAPPLYSOFTRESET     : begin get_ns_axi_config = ASSERTSOFTRESET    ;  end
        default                : begin get_ns_axi_config = INVALIDCMNDCMD     ;  end
    endcase
end
endfunction

In dem case-Statement innerhalb der Funktion gibt es eine überlappende 
Abfrage.

Soweit ich gelesen habe, dürfen solche überlappenden case-Statements in 
Verilog mit casez verwendet werden.

Die function wird in dem Module aufgerufen und der Code lässt sich 
simulieren.

Daher jetzt die Frage: Was übersehe ich hier schon wieder?

Autor: freduardo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kleiner Nachtrag:

...
        CMNDTGLEADDRSWAP       : begin get_ns_axi_config = TOGGLEADDRSWAPSLB  ;  end
        CMNDTGLEADDRSWAPMTR    : begin get_ns_axi_config = TOGGLEADDRSWAPMTR  ;  end
...

Die localparam TOGGLEADDRSWAPSLB und TOGGLEADDRSWAPMTR haben 
unterschiedliche Werte. Daher ist mir völlig unklar, welcher Wert von 
der Funktion zurückgegeben wird, wenn ein Aufruf mit dem cmnd_data = 8 
geschieht.

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
freduardo schrieb:
> Falls es möglich ist, könnte ein Moderator den Thread evtl. umbenennen
> in sowas wie: "Anfängerfragen zu Verilog".
Den Betreff kann man mit jedem Beitrag ändern...

freduardo schrieb:
> Daher ist mir völlig unklar, welcher Wert von
> der Funktion zurückgegeben wird, wenn ein Aufruf mit dem cmnd_data = 8
> geschieht.
Im Zweifelsfall kannst Du die Funktion separat simulieren.
Ich würde stark vermuten, das bei einem Input von 8 das Resultat 
TOGGLEADDRSWAPSLB ausgegeben wird.

Möglicherweise ist aber auch die Definition von CMNDTGLEADDRSWAP oder 
CMNDTGLEADDRSWAPMTR falsch und es ist nur noch niemandem aufgefallen...

Duke

Autor: Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Duke Scarring schrieb:
> Ja Xilinx scheint VHDL nicht zu mögen oder kennt sich mit den
> Möglichkeiten nicht wirklich aus.
> Ich hänge hier gerade mit diversen AXI-Interfaces ab. Da wären
> VHDL-records ideal, um die Verdrahtung übersichtlich zu machen, aber
> nein: jedes Signal wird einzeln behandelt...

Das Problem ist nicht VHDL, sondern die Tatsache, dass Vivado derzeit 
massive Probleme hat, records für Interfaces in Block Designs zu 
verwenden. Dort ist std_logic_vector schon das höchste der Gefühle. Ich 
fände es auch wesentlich schöner, wenn man sich Interfaces nicht 
zwingend per IP-XACT und Gräbern an Attributen wie X_INTERFACE_INFO und 
X_INTERFACE_PARAMETER zusammenbauen müsste, sondern wahlweise auch 
einfach einen Record verwenden könnte.

Vancouver schrieb:
> Btw, seit VHDL-2008 kann man 'when' auch in Prozessen benutzen, d.h. man
> musst das nicht mehr in if/then/else übersetzen.

Xilinx mag VHDL-2008 nicht, zumindest nicht in Vivado. :-( Man darf es 
nicht in IP-Blöcken verwenden, und die Umsetzung der Features ist 
offenbar halbherziger als in ISE.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.