Forum: FPGA, VHDL & Co. Verilog bedingte Zuweisung


von freduardo (Gast)


Lesenswert?

Hallo zusammen,

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

in VHDL beschreiben?


Meine Vermutung ist:
1
 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

von Duke Scarring (Gast)


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:
1
process( axi_config_cs, set_mtr_lb)
2
begin
3
4
  if axi_config_cs =  SETSLAVELOOPBACK then
5
      set_mtr_lb <= '0';
6
  else
7
    if axi_config_cs =  SETMASTERLOOPBACK then
8
      set_mtr_lb <= '1';
9
    end if;
10
  end if;
11
12
end process;

Duke

: Bearbeitet durch Moderator
von freduardo (Gast)


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.

von Duke Scarring (Gast)


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...

von Vancouver (Gast)


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.

von freduardo (Gast)


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.
1
always @ (*) begin
2
    wait_cnt_int = wait_cnt;
3
    if (pkt_gen_load_config_reg) begin
4
        wait_cnt_int = 16'h450;
5
    end else if (wait_cnt[15]) begin
6
        wait_cnt_int = wait_cnt_int;
7
    end else begin
8
        wait_cnt_int = wait_cnt_int - 1;
9
    end
10
end

Wenn ich das in VHDL (2008) schreibe komme ich auf:
1
    process(all)
2
    begin
3
        wait_cnt_int <= wait_cnt;
4
        if (pkt_gen_load_config_reg = '1') then
5
            wait_cnt_int <= x"0450";
6
        elsif (wait_cnt(15) = '1') then
7
            wait_cnt_int <= wait_cnt_int;
8
        else
9
            wait_cnt_int <= wait_cnt_int - 1;
10
        end if;
11
    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:
1
 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.

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


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
von Vancouver (Gast)


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?

von freduardo (Gast)


Lesenswert?

Lothar hat Recht. Weiter unten im Code kommt:
1
always @ (posedge axis_clk) begin
2
    if ( !axis_resetn ) begin
3
        pkt_size_cnt <= 0;
4
        txc_cnt <= 0;
5
        en_packet_gen <= 0;
6
        cur_pkt_last_word_reg <= 0;
7
        wait_cnt <= 16'hFFFF;
8
        wait_cnt_16r <= 1'b1;
9
    end else begin
10
        en_packet_gen <= mtrlb_en_packet_gen;
11
        pkt_size_cnt <= pkt_size_cnt_int ;
12
        wait_cnt <= wait_cnt_int;
13
        wait_cnt_16r <= wait_cnt[15] ;
14
        txc_cnt <= txc_cnt_int;
15
        cur_pkt_last_word_reg <= cur_pkt_last_word;
16
    end
17
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.

von freduardo (Gast)


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:
1
localparam  CMNDSETSPEED1000            = 8'h1 ,
2
            CMNDSETSPEED100             = 8'h2 ,
3
            CMNDSETSPEED10              = 8'h3 ,
4
            CMNDTGLEADDRSWAP            = 8'h8 ,
5
            CMNDTGLEADDRSWAPMTR         = 8'h8 ,
6
            CMNDSETMASTERLOOPBACK       = 8'h5 ,
7
            CMNDTOGGLEEXTPHYLB          = 8'hC ,
8
            CMNDSETSLAVELOOPBACK        = 8'h9 ,
9
            CMNDAPPLYSOFTRESET          = 8'h6 ,
10
            CMNDTGLEPATGENEN            = 8'hB ,
11
            CMNDTGLEPATCHKEN            = 8'hA ,
12
            CMNDREPROGRAMREG            = 8'h0 ,
13
            CMNDRESETPATCHKERROR        = 8'h4 ,
14
            CMNDWRITE2AXILREG           = 8'hD ,
15
            CMNDREADAXILREG             = 8'h7 ,
16
            CMNDTGLETXACTIVITY          = 8'hE ;

CMNDTGLEADDRSWAP und CMNDTGLEADDRSWAPMTR haben jeweils den Wert 8.

im gleichen Module wird die folgende Function definiert:
1
function [6:0] get_ns_axi_config  ;
2
    input [7:0] cmnd_data    ;
3
begin
4
    case (cmnd_data)
5
        CMNDSETSPEED1000       : begin get_ns_axi_config = SETTMACSPEED1000   ;  end
6
        CMNDSETSPEED100        : begin get_ns_axi_config = SETTMACSPEED100    ;  end
7
        CMNDSETSPEED10         : begin get_ns_axi_config = SETTMACSPEED10     ;  end
8
        CMNDSETSLAVELOOPBACK   : begin get_ns_axi_config = SETSLAVELOOPBACK   ;  end
9
        CMNDSETMASTERLOOPBACK  : begin get_ns_axi_config = SETMASTERLOOPBACK  ;  end
10
        CMNDRESETPATCHKERROR   : begin get_ns_axi_config = RESETPATCHKERROR   ;  end
11
        CMNDREPROGRAMREG       : begin get_ns_axi_config = STARTREPROGRAMREG  ;  end
12
        CMNDTOGGLEEXTPHYLB     : begin get_ns_axi_config = SETTOGGLEEXTPHYLB  ;  end
13
        CMNDWRITE2AXILREG      : begin get_ns_axi_config = STARTAXIWRTRANS    ;  end
14
        CMNDREADAXILREG        : begin get_ns_axi_config = STARTAXIRDTRANS    ;  end
15
        CMNDTGLEADDRSWAP       : begin get_ns_axi_config = TOGGLEADDRSWAPSLB  ;  end
16
        CMNDTGLEADDRSWAPMTR    : begin get_ns_axi_config = TOGGLEADDRSWAPMTR  ;  end
17
        CMNDTGLEPATGENEN       : begin get_ns_axi_config = TOGGLEPATGENEN     ;  end
18
        CMNDTGLEPATCHKEN       : begin get_ns_axi_config = TOGGLEPATCHKEN     ;  end
19
        CMNDTGLETXACTIVITY     : begin get_ns_axi_config = TOGGLETXACTIVITY   ;  end
20
        CMNDAPPLYSOFTRESET     : begin get_ns_axi_config = ASSERTSOFTRESET    ;  end
21
        default                : begin get_ns_axi_config = INVALIDCMNDCMD     ;  end
22
    endcase
23
end
24
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?

von freduardo (Gast)


Lesenswert?

kleiner Nachtrag:

1
...
2
        CMNDTGLEADDRSWAP       : begin get_ns_axi_config = TOGGLEADDRSWAPSLB  ;  end
3
        CMNDTGLEADDRSWAPMTR    : begin get_ns_axi_config = TOGGLEADDRSWAPMTR  ;  end
4
...

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.

von Duke Scarring (Gast)


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

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


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.

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.