Zum Hauptinhalt springen

System Verilog - Reference

  1// Literatur:
  2//    Vorlesungsunterlagen AMV von Rainer Findenig (FH-Hagenberg)
  3//    Doulos       - http://www.doulos.com/knowhow/sysverilog/
  4//    ASIC World   - http://www.asic-world.com/systemverilog/tutorial.html
  5//    ElectroSofts - http://electrosofts.com/systemverilog/
  6
  7// HDVL - Hardware Description and Verification Language
  8// Erweiterung zu Verilog
  9
 10
 11// Definition von Packages
 12// -> globale bzw. Projektspezifische Definitionen und Parameter
 13        package global;
 14            parameter DATA_WIDTH   = 8;
 15            parameter ADDR_WIDTH   = 8;
 16            parameter END_ADDRESS  = (2**ADDR_WIDTH) - 1;
 17            
 18            parameter DEAKTIVATED  = 0;
 19            parameter AKTIVATED    = 1;
 20            
 21            parameter CLOCK_PERIOD = 10ns;
 22        endpackage
 23
 24
 25// den Namensraum verfuegbar machen
 26        import global::*;
 27// Datei includieren
 28        `include "ram-bh.sv"
 29
 30
 31// verschiedene Module (Architekturen)
 32        module RAM # (
 33                // Paramter Liste
 34                parameter int gDataWidth = 32;
 35                parameter int gAddrWidth = 8
 36            )
 37            (
 38                // Port Liste
 39                input  logic                    clk_i;
 40                input  logic                    rst_i;
 41                input  logic [gDataWidth-1 : 0] dat_i;
 42                input  logic [gAddrWidth-1 : 0] adr_i;
 43                input  logic                    we_i;
 44                output logic [gDataWidth-1 : 0] dat_o
 45            );
 46            logic [gDataWidth-1 : 0] storage [2**gAddrWidth-1 : 0];
 47            
 48            // Prozess wird zu Begin einmal aufgerufen
 49            initial begin
 50                storage[0] = '0;
 51                storage[1] = '0;
 52                ...
 53            end
 54            
 55            // Prozess existiert immer und wird bei den Events aufgerufen
 56            always @(posedge clk_i or rst_i)
 57            begin
 58                ...
 59            end
 60        endmodule
 61
 62        module top ();
 63            logic clk = 0;
 64            logic rst = AKTIVATED;
 65            ...
 66            
 67            initial begin
 68                #0ns rst = AKTIVATED;
 69                #1ns rst = DEAKTIVATED;
 70            end
 71            
 72            always #CLOCK_PERIOD clk = ~clk;
 73            
 74            // Ram Instantiieren
 75            RAM # (.gDataWidth (DATA_WIDTH),
 76                   .gAddrWidth (ADDR_WIDTH)
 77                  )
 78                duv(.clk_i (clk),
 79                    .rst_i (rst),
 80                    .dat_i (datM),
 81                    .adr_i (adr),
 82                    .we_i  (we),
 83                    .dat_o (datS)
 84                   );
 85        endmodule
 86
 87        // eigenes Modul-Konstrukt fuer die Testbench
 88        program ram_tb ();
 89            // nur initial begin Bloecke
 90            initial begin : stimuli
 91                // koennen aber endlos Schleifen haben
 92            end : stimuli
 93        endprogram
 94
 95
 96// Basisdatentypen
 97        // 4-state-logic (0, 1, X, Z)
 98        reg clk = 0;                    // user-defined size
 99        logic                           // identical to reg in every way
100                                        // logic [7:0] a_byte;
101        integer                         // 32 bits, signed
102        
103        // 2-state-logic (0, 1) -> Simulationszeit verringert sich
104        bit  	                        // user-defined size
105        byte                            // 8 bits, signed
106        shortint                        // 16 bits, signed
107        int                             // 32 bits, signed
108        longint                         // 64 bits, signed
109        
110        time                            // 64-bit, unsigned
111        shortreal                       // like float in C
112        real                            // like double in C
113        realtime                        //identical to real
114
115
116// Typdefinitionen und Enumerationen
117        typedef bit [7 : 0] data_v;
118        data_v data;
119        
120        enum { circle, ellipse, freeform } c;
121        enum bit [3:0] {bronze=0, silver, gold} newMedal;
122        
123        typedef enum {Idel = 0, StartBit, Data, Parity, StopBit} aState;
124        aState s = Idle;
125        case(s)
126            Idle:
127            ...
128        endcase
129
130
131// Arraydefinitionen
132        // packed arrays, festgelegte Darstellung als Bitstrom
133        bit [7 : 0] data;
134        
135        // unpacked arrays, Werkzeug kann Abbildung frei waehlen
136        bit data [7 : 0];
137        
138        bit [7 : 0] data_list [4]   // [0:3]
139                                    // z.B. data_list[0]  xxxxxxxx 76543210
140                                    //      data_list[1]  xxxxxxxx 76543210
141                                    //      data_list[2]  xxxxxxxx 76543210
142                                    //      data_list[3]  xxxxxxxx 76543210
143        
144        // dynamische Arrays (nur unpacked, aufsteigend Indiziert)
145        bit a1[], a2[];                 // zwei leere Arrays
146        a1 = new[10];                   // Array anlegen
147        a2 = a1;                        // Array kopieren
148        a2 = new[a2.size*2](a2);        // a2 Groesse verdoppeln
149        a1 = new[5];                    // neues Array anlegen
150                                        // (-> Garbage Collector)
151        a1.delete;                      // Array loeschen
152        
153        // packed <-> unpacked (Bit-stream cast)
154        typedef bit [0 : 7] data_v;
155        data_v packed;
156        bit unpacked [8];
157        packed = data_v'(unpacked);     // unpacked -> packed
158        
159        // packed <-> unpacked (Streaming operators)
160        int a[2], b1, b2;
161        bit [64:1] x = { >> {a}};       // pack a left-to-right
162        bit [63:0] x = { << {a}};       // pack a bit reverse
163        bit [0:63] x = { >> {b1, b2}};  // pack b1, b2
164        
165            { << { 8'b0011_0101 }}      // bit reverse -> 1010_1100
166            { << 4 { 6'b11_0101 }}      // 0101_11
167            { >> 4 { 6'b11_0101 }}      // 1101_01
168            
169        // linke Seite kuerzer als rechte: Fehler
170        // rechte Seite kuerzer als linke: linksbuendig, mit 0 gefuellt
171        
172        // Streams nicht direkt als Wert verwendbar -> Cast notwendig
173        typedef bit [0 : 7] data_v;
174        data_v data;
175        bit ret[8];
176        assert (data == data_v'({ >> {ret}}))
177        
178        // Array durchlaufen
179        int a[] = new[100];
180        foreach (a[i])
181            a[i] = i;
182        
183        a = '0;                         // Array mit 0 fuellen
184        a = '1;
185        a = 'z;
186        a = 'x;
187
188
189// Strukturen und Unions (aehnlich zu C)
190        struct {
191            int x, y;
192        } p;
193        p.x = 1;
194        p = { 1,2 };
195        
196        typedef struct packed {
197            int x, y;
198        } Point;
199        Point p;
200
201
202// Zuweisungen
203        // non-blocking Assignment: Zuweisung im naechsten "Delta-Cycle"
204        always @(posedge clk) begin
205            A <= A + 1;
206            B <= A;                     // B bekommt alten Zustand von A
207        end
208        
209        // blocking Assignment: Zuweisung sofort
210        always @(posedge clk) begin
211            A = A + 1;
212            B = A;                      // B bekommt neuen Zustand von A
213        end
214
215
216// Operatoren
217        //Type                  Symbol              Operation
218        //  Arithmetik              *                   Multiplizieren
219        //                          /                   Dividieren
220        //                          +                   Addieren
221        //                          -                   Subtrahieren
222        //                          %                   Modulo
223        //                          +                   unaer Plus
224        //                          -                   unaer minus
225        //  Logik                   !                   logische Negation
226        //                          &&                  logisches Und
227        //                          ||                  logisches Oder
228        //  Vergleich               >                   groeser
229        //                          <                   kleiner
230        //                          >=                  groeser gleich
231        //                          <=                  kleiner gleich
232        //  Gleichheit              ==                  gleich
233        //                          !=                  ungleich
234        //  Bit                     ~                   bitweise Negation
235        //                          ~&                  nand
236        //                          |                   or
237        //                          ~|                  nor
238        //                          ^                   xor
239        //                          ^~                  xnor
240        //                          ~^                  xnor
241        //  Shift                   >>                  right shift
242        //                          <<                  left shift
243        //  Verkettung              { }                 Concatenation
244        //  Bedingung               ?                   Conditional
245
246
247// Schleifen und Bedingungen
248        // IF
249        if (Cond1)
250            doSomething1();
251        else if (Cond2)
252            doSomething2();
253        else
254            doSomething3();
255        
256        if (Cond)
257        begin
258            doSomething1();         // werden mehrere Zeilen benoetigt,
259            doSomething2();         // so braucht man einen begin-end-Block
260        end
261        
262        // DO-WHILE
263        do
264            ...
265        while(Cond);
266        
267        // WHILE
268        while (Cond) begin
269            ...
270        end
271        
272        // FOR
273        for (int i=15, logic j=0; i>0; i--,j=~j)
274            ...
275        
276        // CASE
277        case(address)
278            0 : $display ("Adresse = 0");
279            1 :
280            begin
281                $display ("Adresse = 1");
282                $display ("weitere Zeile");
283            end
284            default : $display  ("default Zweig");
285        endcase
286      
287        // REPEAT
288        repeat (16) begin
289            ...
290        end
291
292
293// Ueberschriften
294        begin : label
295        end : label
296        
297        module myModule ...
298            ...
299        endmodule : myModule
300        
301        loop : for (...)
302
303
304// Ausgaben
305        // Syntax aehnlich zu "printf"
306        $display("@%t: data = %0d", $time, data);
307        $write();
308        $time                       // aktuelle Simulationszeit
309        $finish                     // Simulation beenden
310        
311        string sv = "SystemVerilog";
312        string s;
313        s = {sv, " ", "ist echt einfach."}; 
314        $display ("%s\n", s);       // Bildschirmausgabe:
315                                    // "SystemVerilog ist echt einfach."
316
317
318
319// Assertions
320        assert (A == B);            // wenn A!=B wird ein Fehler ausgegeben
321        assert (A == B) $display ("OK. A gleich B");
322        assert (A == B) $display ("OK. A gleich B");
323            else $error("Fehler: A ungleich B");
324        assert (A == B) else $error("Fehler: A ungleich B");
325
326
327// Timing-Kontrolle
328        wait (cond);                // level-sensitive
329                                    // -> warte, bis cond wahr ist
330        @(posedge clk);             // warte auf steigende Flanke von clk
331        repeat (2) @(negedge clk);  // warte 2x auf negative Flanke von clk
332        @(sig);                     // warte, bis sich sig aendert
333        @(posedge clk, rst)  ==  @(posedge clk or rst)
334        #1ns rst = 0;               // 1e ns warten, danach rst auf 0 setzen
335        ##1 rst = 0;                // 1en Clock Zyklus warten
336        wait(0);                    // endlos Warten
337
338
339// Function vs. Task
340        // fuer Berechnungen (passieren in Nullzeit)
341        function int calcCrc(input int data0 = '0, data1);
342            ...
343            calcCrc = 0;
344            ...
345            return crc;             // return ueberschreibt calcCrc Wert
346        endfunction
347        res = calcCrc(.data0(d0), .data1(d1));
348        res = calcCrc(d0, d1);      // Reihenfolge wird beachtet
349        
350        // koennen Zeit verbrauchen
351        task waitForClk(input int data_i, output int data_o);
352            ...
353            @(posedge clk);
354        endtask
355
356
357// Clocking Block - beschreibt wie die Eingaenge und Ausgaenge
358//                  gesampled und synchronisiert werden
359        clocking clock1 @(posedge clk1);
360            default input #2ns      // default input skew
361                    output #3ns;    // default output skew
362            input a1, a2;
363            input  #1 a3;           // eigens spezifizierte input skew
364            output    b1;
365            output #1 b2;           // eigens spezifizierte output skew
366        endclocking
367
368
369
370
371// Interfaces - fuer gemeinsame Schnittstellen
372        interface wishboneBusIf(input logic clk, rst);
373            logic ack, stb, cyc, we;
374            logic [DATA_WIDTH-1 : 0]   datM, datS;
375            logic [ADDR_WIDTH-1 : 0]   adr;
376            logic [DATA_WIDTH/8-1 : 0] sel;
377    
378            clocking cb @(posedge clk, rst);
379                input ack, datS;
380                output stb, cyc, we, datM, adr, sel;
381            endclocking
382    
383            modport master(clocking cb);
384            modport slave(
385                input stb,
386                input cyc,
387                input we,
388                input datM,
389                input adr,
390                input sel,
391                output ack,
392                output datS
393            );
394        endinterface
395        
396        program wishbone_tb (
397            wishboneBus_if wishboneBus
398        );
399            wishboneBus.clk;
400            wishboneBus.master.cb.ack;
401        endprogram
402        
403        RAM duv (
404            .clk_i      (wishboneBus.clk),
405            .rst_i      (wishboneBus.rst),
406            .adr_i      (wishboneBus.slave.adr),
407            .dat_i      (wishboneBus.slave.datM),
408            ...
409            .ack_o      (wishboneBus.slave.ack)
410        );
411
412
413// OOP - Klassen
414        class wishboneBFM_c;
415            // Interfaces muessen in Klassen immer virtuell sein,
416            // damit die Aenderungen nach aussen sichtbar werden
417            virtual wishboneBus_if wishboneBus;
418            logic [ADDR_WIDTH-1 : 0] actAddr;
419            local logic mem1;       // private Members
420            protected logic mem2;   // protected Members
421        
422            // CTor, nur einer erlaubt
423            function new(virtual wishboneBus_if wishboneBus);
424                this.wishboneBus = wishboneBus;
425            endfunction
426    
427            task busWrite(input logic [ADDR_WIDTH-1 : 0] addr,
428                          input logic [DATA_WIDTH-1 : 0] data);
429                wishboneBus.cpM.stb <= 0;
430                wishboneBus.cpM.cyc <= 0;
431                
432                @(posedge wishboneBus.clk)
433                wishboneBus.cpM.adr  <= addr;
434                wishboneBus.cpM.datM <= data;
435                wishboneBus.cpM.we   <= 1;
436                wishboneBus.cpM.sel  <= '0;
437                wishboneBus.cpM.stb  <= 1;
438                wishboneBus.cpM.cyc  <= 1;
439                do
440                    @(posedge wishboneBus.clk);
441                while(!wishboneBus.cpM.ack);
442                wishboneBus.cpM.stb <= 0;
443                wishboneBus.cpM.cyc <= 0;
444            endtask : busWrite
445            
446            function bit [15 : 0] calcCrc;
447                ...
448                return crc;
449            endfunction
450        endclass
451        
452        wishboneBFM_c bfm = new(...);
453        bfm.busWrite(...);
454        int crc = bfm.calcCrc();
455        
456        
457        // Parametrisierte Klasse
458        class #(parameter int N = 1) Register;
459            bit [N-1:0] data;
460            ...
461        endclass
462        
463        Register #(4) R4;           // data ist bit [3:0]
464        Register #(.N(8)) R8        // data ist bit [7:0]
465        Register R;                 // data ist bit [0:0]
466        
467        
468        // Ableiten
469        class ShiftRegister extends Register;
470            task shiftleft;  data = data << 1; endtask
471            task shiftright; data = data >> 1; endtask
472        endclass
473        
474        
475        // virtuelle Klassen
476        virtual class Register;
477            ...
478        endclass
479
480
481// Automatic Storage
482        // wird eine Funktion bzw. ein Task mehrmals aufgerufen,
483        // so muss die Wiedereintrittsfaehigkeit gegeben sein
484        
485        // in Verilog wurden Parameter statisch allokiert
486        // -> mittels automatic Starge auf Stack legen
487        program automatic Test(...);
488            task automatic doIt();
489                ...
490            endtask
491            ...
492        endprogram
493        
494        // Methoden in Klassen sind immer automatic
495
496
497// gleichzeiteige Prozesse
498        type_of_block @(sensitivity_list)
499        fork
500            statement1;             // zwei parallele Statements
501            statement2;
502            ...
503        join
504        
505        fork
506            begin
507                statement1;         // 1 Prozess mit zwei Statements
508                statement2;
509                ...
510            end
511        join
512        
513        // join      ... der Eltern-Prozess blockiert solange
514        //               bis alle fork-Prozesse fertig sind
515        // join_any  ... der Eltern-Prozess blockiert solange
516        //               bis ein fork-Prozess fertig ist
517        // join_none ... der Eltern-Prozess setzt seine
518        //               Abarbeitung ohne Warten fort
519
520
521// Events
522        program tb (...);
523            event e;
524            
525            initial begin : doIt
526                #1ns -> e;
527                #2ns -> e;
528            end : doIt
529            
530            initial begin : waitForEvent
531                do
532                begin
533                    wait( executeModellEvent.triggered );
534                    
535                    $display ("@%0t -> executeModellEvent (cmd: %0d)",
536                              $time, opcodeCnt+1);
537                    #1ns;
538                end
539                while(1);
540            end : waitForEvent
541        endprogram
542        
543        // ->                       ... triggert ein Event
544        // ->>                      ... triggert ein Event non-blocking
545        @(event);                   // wartet auf ein Event
546        wait(event.triggered);      // -,,-
547        wait_order(a, b, c);        // wartet auf Events nach bestimmten
548                                    // Reihenfolge: zuerst a, dann b, dann c