Kodutöö #2 - simuleerimine

Matriklinumber: 999999-le vastava funktsioonide süsteemi tõeväärtus-tabel oleks järgmine:

0000 1-00
0001 01-0
0010 11-1
0011 0-01
0100 1110
0101 1010
0110 -111
0111 01-0
1000 0011
1001 -10-
1010 -0-1
1011 1001
1100 11-0
1101 0-10
1110 -000
1111 1011

Seda tabelit kirjeldav SystemVerilog kood oleks järgmine (vt. ka faili):

module fs_table (input x1, x2, x3, x4, output y1, y2, y3, y4);
  logic [1:4] out_word;
  always_comb
    case ({x1,x2,x3,x4}) 
      4'b0000 : out_word = 4'b1z00;
      4'b0001 : out_word = 4'b01z0;
      4'b0010 : out_word = 4'b11z1;
      4'b0011 : out_word = 4'b0z01;
      4'b0100 : out_word = 4'b1110;
      4'b0101 : out_word = 4'b1010;
      4'b0110 : out_word = 4'bz111;
      4'b0111 : out_word = 4'b01z0;
      4'b1000 : out_word = 4'b0011;
      4'b1001 : out_word = 4'bz10z;
      4'b1010 : out_word = 4'bz0z1;
      4'b1011 : out_word = 4'b1001;
      4'b1100 : out_word = 4'b11z0;
      4'b1101 : out_word = 4'b0z10;
      4'b1110 : out_word = 4'bz000;
      default : out_word = 4'b1011;
    endcase
  assign {y1,y2,y3,y4} = out_word;
endmodule

Andmetüüp logic on 4-valentne ja väärtus z tähistab määramatust (signaal out_word).

Lihtsa testpingi SystemVerilog kood oleks järgmine (vt. ka faili):

`timescale 1 ns / 1 ns
module test_single;
  logic [1:4] xi = 0;
  logic y1, y2, y3, y4;
  // Sequence 0000 ... 1111
  initial begin
    repeat (16) #10 xi++;
    $stop;
  end
  fs_table u1 (xi[1], xi[2], xi[3], xi[4], y1, y2, y3, y4);
endmodule

Kõige lihtsam ModelSim'i kasutamise juhend oleks alljärgnev (keerukam juhend on siin):
- käsk "cad" abil valida Mentor Graphics (nt. 2);
- käsk "vsim" paneb simulaatori tööle;
- simulaatori töötades "File->New->Library..." abil luua teek "work" (kui pole varem loodud);
- "Compile->Compile..." abil kompileerida nii funktsioonide süsteem kui ka testpink;
- "Simulate->Start Simulation..." alt valida "work" seest "test" (veenduda, et "Enable optimization" oleks lubatud); lisaks tuleb "Optimization Options..." seest valida "Apply full visibility to all modules (full debug mode)", sest muidu optimeeritakse osad signaalid välja;
- aktiveerige alam-aken "Objects" ja "Add->To Wave->Signal in Design" lisab kõik signaalid lainekuju aknasse;
- simulaatori käsureal "run -all" teostab simuleerimise;
- aktiveerige alam-aken "Wave" ja menüüst "Wave->Zoom->Zoom Full" täidab akna ühtlaselt tulemustega.

Võrrelge tulemusi lähteülesandega.

tabel


Korrake seda sama (kompileerimine & simuleerimine) espresso tulemusest saadud funktsioonide süsteemiga (vt. ka faili):

module fs_espresso (input x1, x2, x3, x4, output y1, y2, y3, y4);
  assign y1 = ((!x1) & x2 & (!x3) & x4) |
              (x2 & (!x3) & (!x4)) |
              ((!x1) & (!x4)) | (x1 & x3);
  assign y2 = !( ((!x1) & x2 & (!x3) & x4) |
                 (x1 & (!x2) & (!x4)) | (x1 & x3) );
  assign y3 = (x2 & (!x3) & (!x4)) | (x2 & x4) |
              ((!x1) & x3 & (!x4)) | (x1 & (!x2) & (!x4));
  assign y4 = (x1 & x3 & x4) | ((!x2) & x3) |
              ((!x1) & x3 & (!x4)) | (x1 & (!x2) & (!x4));
endmodule  

Pange testpingis komponent fs_table asemele fs_espr ja simuleerige uuesti. Võrrelge tulemusi lähteülesandega (simulatsiooniga).

espr


Korrake seda sama ka loogika-tehete tasemel oleva (optimeeritud) skeemiga (vt. ka faili):

module fs_opti (input x1, x2, x3, x4, output y1, y2, y3, y4);
  logic x2i, t1i, t2i, t3x, t3i, t4i, t5i, t6;
  logic t7, t8x, t8, t68i, t9i, t19, t197i;
  assign x2i = !(x2 & x2);
  assign t1i = t4i | x1 | x3;
  assign t2i = !(x1 & x3 & x4);
  assign t3x = !(x3 | x4);
  assign t3i = !(x2  & t3x);
  assign t4i = !(x2 & x4);
  assign t5i = !(x2i & x3);
  assign t6  = t7  & x3;
  assign t7  = !(x1 | x4);
  assign t8x = !(x2 | x4);
  assign t8  = x1 & t8x;
  assign t68i = !(t6 | t8);
  assign t9i  = !(x1 & x3);
  assign t19  = !(t1i & t9i);
  assign t197i = !(t19 | t7);
  assign y1 = !(t197i & t3i);
  assign y2 = !(t19 | t8);
  assign y3 = !(t3i & t4i & t68i);
  assign y4 = !(t2i & t5i & t68i);
endmodule 

Pange testpingis komponendiks fs_opti ja simuleerige uuesti. Võrrelge tulemusi lähteülesandega (simulatsiooniga).

opti




Oluliselt mugavam oleks, kui saaks omavahel võrrelda mitut eri etappi sama simulatsiooni käigus. Heaks näiteks on alljärgnev testpink, mis lubav korraga simuleerida kolme disaini (algne tabel, espresso tulemus ja optimeeritud skeem). Lisaks sisaldab testpink ka kontrollivat funktsiooni - kolme komponendi v&ljundid tüürivat vastavat kontroll-signaali, mis erinevuse korral saab vigase väärtuse (x) ja punase värvuse (signaalid y1x, y2x, y3x ja y4x). Sama kood on ka failist leitav:

`timescale 1 ns / 1 ns
module test_bench;
  logic [1:4] xi = 0;
  wire y1a, y1b, y1c, y1x;
  wire y2a, y2b, y2c, y2x;
  wire y3a, y3b, y3c, y3x;
  wire y4a, y4b, y4c, y4x;
  // Sequence 0000 ... 1111
  initial begin
    repeat (16) #10 xi++;
    $stop;
  end
  // Truth table
  fs_table u1 (xi[1], xi[2], xi[3], xi[4], y1a, y2a, y3a, y4a);
  assign y1x=y1a, y2x=y2a, y3x=y3a, y4x=y4a;
  // Espresso result
  fs_espresso u2 (xi[1], xi[2], xi[3], xi[4], y1b, y2b, y3b, y4b);
  assign y1x=y1b, y2x=y2b, y3x=y3b, y4x=y4b;
  // Optimized circuit
  fs_opti u3 (xi[1], xi[2], xi[3], xi[4], y1c, y2c, y3c, y4c);
  assign y1x=y1c, y2x=y2c, y3x=y3c, y4x=y4c;
endmodule 

Võrrelge tulemusi eelnevate simulatsioonidega. Signaalide y1a, y1b ja y1c, y2a, y2b ja y2c, y3a, y3b ja y3c ning y4a, y4b ja y4c õige järjekord on tagatud nende deklrareermise järjekorraga SystemVerilog failis. Selle tulemusena on hästi näha, kuidas väärtused eri mudelitel kokku langevad. Üksikud punased piigid tekivad omistamise viitest, sest signaalid läheva sisendist väljunditesse läbi erineva arvu omistamiste.

all together


Kui simulatsioonide tulemused ei klapi, tuleks viga üles otsida. Toodud näites on "ära unustatud" üks inversioon ja viga on näha nendes väljundites, mis seda signaali kasutasid. Vt ka faili (signaal t68i):

module fs_opti (input x1, x2, x3, x4, output y1, y2, y3, y4);
  logic x2i, t1i, t2i, t3x, t3i, t4i, t5i, t6;
  logic t7, t8x, t8, t68i, t9i, t19, t197i;
  assign x2i = !(x2 & x2);
  assign t1i = t4i | x1 | x3;
  assign t2i = !(x1 & x3 & x4);
  assign t3x = !(x3 | x4);
  assign t3i = !(x2  & t3x);
  assign t4i = !(x2 & x4);
  assign t5i = !(x2i & x3);
  assign t6  = t7  & x3;
  assign t7  = !(x1 | x4);
  assign t8x = !(x2 | x4);
  assign t8  = x1 & t8x;
  //assign t68i = !(t6 | t8);
  assign t68i = (t6 | t8);
  assign t9i  = !(x1 & x3);
  assign t19  = !(t1i & t9i);
  assign t197i = !(t19 | t7);
  assign y1 = !(t197i & t3i);
  assign y2 = !(t19 | t8);
  assign y3 = !(t3i & t4i & t68i);
  assign y4 = !(t2i & t5i & t68i);
endmodule 

all together

Varasem silumisnäidis annab ehk ettekujutuse, kuidas seda põhjalikuma analüüsi abil teha. See on küll tehtud vanema näidislahenduse jaoks ja VHDL-s, kui vea otsimise põhimõte jääb siiski samaks...