Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti Simulace číslicových obvodů (MI-SIM) zimní semestr 2010/2011 Jiří Douša, katedra číslicového návrhu (K18103), České vysoké učení technické v Praze, fakulta informačních technologií Přednáška 13: VERILOG syntéza obvodů Stručný obsah: pravidla pro syntézu kombinačních i sekvenčních programů, implicitní a explicitní automaty, syntéza cyklů, přehled syntetizovatelných částí jazyka Verilog,
Verilog: syntetizovatelné konstrukce Podporované konstrukce jazyka : porty, input, output, inout parametry, moduly a jejich instalace, signály a proměnné ( pouze wire, tri, reg ), procesy always, funkce a procedury sekvenční příkazy: if, else, case, casex, casez, cykly: for, while, forever; tyto musí obsahovat operátory @ ( posedge clk ) nebo @ ( negedge clk ) procedurální bloky: begin., jmenné bloky, paralelní příkazy: assign. Nepodporované konstrukce jazyka : procesy initial, abstraktní události event, operátor zpoždění #, datové typy: real, time, specifikace logických funkcí UDP, procedurální příkazy assign, deassign, příkazy force, release, fork, join 2
Syntéza kombinačních obvodů syntetizovatelné konstrukce: instalace primitivních elementů, příklad: and A1 ( y1, a, b ) ; or O1 ( y3, y1, y2 ) ; paralelní příkazy, příklad: : assign y3 = ( a & b ) ( c & d ) ; hladinově citlivé procesy: příklad: : always @( a, b, c, d ) y3 = ( a & b ) ( c & d ) ; přípustný zápis: citlivost na všechny vstupy obvodu příklad: : always @ (*) begin zásady: popis kombinačních obvodů musí přiřadit hodnotu výstupů pro všechny možné kombinace vstupů, zpětné vazby v propojení primitivních elementů nebo v paralelních příkazech nejsou přípustné, nepřípustné ukázky: nand N1 ( q, qb, sb ); nand N2 ( qb, q, rb ); assign q = sb ~& qb; assign qb = rb ~& q; // propojení pro RS latch // vytvoření RS latch 3
Syntéza kombinačních obvodů Vkládání hladinových klopných obvodů: záměrné: paralelní příkaz assign se zpětnou vazbou: příklad: assign q = (en)? a : q; // if ( en ) a else y; neúplný příkaz if: příklad: always @ ( en, a ) if ( en ) y = a ; // y je latch řízený signálem en neúplný příkaz case: nežádoucí: příklad: always @ ( s1, s2, d1, d2 ) case ( {s1, s2} ) case 2 b01: y = d1; 2 b10: y = d2; // y je latch řízený signálem s1 & (~s2) (~s1) & s2 např. chyba v citlivostním seznamu: nejsou použity všechny vstupy modulu k aktivaci příslušného procesu 4
Syntéza kombinačních obvodů // následuje správný model: module Or4 ( output reg y, input [3:0] a ); integer i; always @ ( a [3:0] ) begin : BL y = 0; for ( i = 0; i < 4; i = i + 1 ) if ( a[ i ] == 1 ) begin y = 1; disable BL; ; module Poznámka: předpokládejme následující modifikaci citlivostního seznamu always @ ( a [ 2 : 0 ] ) ; důsledek: signál a [ 3 ] je vstupem obvodu, ale jeho změna neaktivuje blok BL, v případě, že nastane změna ostatních vstupů, pak tento signál má také vliv na výstup y ( je testován v cyklu); jde tedy o průchod obvodem typu latch, latch je vložen do vstupu a [ 3 ] a řízen signálem a [ 2 ] a [ 1 ] a [ 0 ] 5
Vkládání budičů pomocí podmíněných paralelních příkazů: reg [ 3 : 0 ] a; wire [ 3 : 0 ] y; assign y = ( en == 1 )? a : 4 bz; // budič s výstupem y Příklad: třístavový budič jednosměrné sběrnice data module M1 ( output wire [ 31 : 0 ] data, input en ); reg [ 31 : 0 ] vystup;..; // popis obvodumodule assign data = ( en )? vystup : 32 bz; ; module Příklad: rozhraní obousměrné sběrnice data module M2 ( inout wire [ 31 : 0 ] data, input rd, wr ); reg [ 31 : 0 ] vystup; wire [ 31 : 0 ] vstup ;..; // popis obvodu assign vstup = ( rd )? data : 32 bz; //čtení data assign data = ( wr )? vystup : 32 bz; //zápis na data ; module 6
Syntéza sekvenčních obvodů podmínky pro implementaci proměnných typu reg pomocí FF: 1) v hranově citlivém procesu always existují větve ve kterých do dané proměnné dochází k zápisu, 2) výše uvedená proměnná je použita vně hranově citlivého procesu always, Příklad: paralelní registr module D_reg ( data_in, data_out, clk ); parameter sire = 4; output reg [ sire-1 : 0 ] data_out; input [ sire-1 : 0 ] data_in; input clk; reg [ sire-1 : 0 ] data_out; // následuje hranově citlivý proces always @ ( posedge clk ) begin data_out <= data_in ; ; // zápis do registru typu FF module jiná možnost přiřazení : integer k ; always @ ( posedge clk ) begin for ( k = 0; k < sire ; k = k + 1 ) // k není FF data_out [ k ] <= data_in [ k ] ; // data_out je FF 7
Syntéza sekvenčních obvodů výskyt nekompletního příkazu if nebo case v hranově citlivém procesu nemá za následek vložení latch, ale implementaci FF se vstupem enable, je-li hranově citlivý proces always citlivý na více proměnných pak: vstupy pro set, či reset jsou explicitně testovány v příkazu if, který musí být prvním příkazem procesu, synchronizační signál clk není explicitně testován, poslední větev else příkazu if specifikuje synchronizované akce, případné neúplné if definuje uvolňovací logiku Příklad: sekvenční obvod se synchronními vstupy set, reset module D_reg ( data_in, data_out, set, reset, clk ); parameter sire = 4; output reg [ sire -1 : 0 ] data_out; input [ sire -1 : 0 ] data_in; input clk; reg [ sire -1: 0 ] data_out; integer k ; always @ ( posedge clk ) // hranově citlivý proces begin // synchronní set i reset if ( set ) for ( k = 0; k < sire ; k = k + 1) data_out [ k ] <= 1 b1; //set else if ( reset ) for ( k = 0; k < sire ; k = k + 1) data_out [ k ] <= 1 b0; else data_out <= data_in ; // zápis při náběžné hraně clk module 8
Syntéza sekvenčních obvodů Příklad: paralelní register s asynchronními vstupy set, reset module D_reg ( data_in, data_out, set, reset, clk ); parameter sire = 4; output reg [ sire -1: 0 ] data_out; input [ sire -1: 0 ] data_in; input reg integer k ; clk; [ sire -1: 0 ] data_out; always @ ( posedge clk or posedge set or posedge reset ) // analogie wait until clk = 1 or set = 1 or reset = 1 ; begin if ( set ) // asynchronní set for ( k = 0; k <sire ; k = k + 1) data_out [ k ] <= 1 b1; else module if ( reset ) // asynchronní set for ( k = 0; k < sire ; k = k + 1) data_out [ k ] <= 1 b0; else data_out <= data_in ; // zápis při náběžné // hraně clk 9
Vitřní schéma: Příklad: sériový vysílač PD_in 1 S_reg S_out clk reset DR START sstav CTR shift CONTRL_KL pstav clear start load CONTRL_PO Specifikace řadiče: DR = 0 / ( load =0, clear =0, start =0, shift = 0 ) CTR = 9/ ( load =0, clear =1, start =0, shift = 0 ) idle DR=1/ ( load =1, clear =0, start =0, shift = 0 ) sing waiting START = 0 / ( load =0, clear =0, start =0, shift = 0 ) CTR!= 9 / ( load =0, clear =0, start =0, shift = 1 ) START = 1/ ( load =0, clear =0, start =1, shift = 0 ) 10
Sériový vysílač (pokračování) module transmitter ( S_out, PD_in, DR, START, reset, clk ); parameter idle = 3 b001; // vnitřní stavy řadiče parameter waiting = 3 b010; parameter sing = 3 b100; output S_out; // porty input [ 7 : 0 ] PD_in; input DR, START, reset, clk; reg [ 8 : 0 ] S_reg; // lokální registry datové části reg [ 3 : 0 ] CTR; // čítač bitů reg [ 2 : 0 ] sstav = idle; // současný stav reg [ 2 : 0 ] pstav; // příští stav řadiče reg start, clear, shift, load ; // lokální proměnné always @ ( sstav, DR, START ) // kombinační logika řadiče begin: CONTRL_KL // následují výstupy kombinačního obvodu load = 0; clear = 0; shift = 0; start = 0; pstav = sstav; case ( sstav ) idle: if ( DR ==1 ) begin load = 1; pstav = waiting; waiting: if ( START ==1) begin start = 1; pstav = sing; sing: if ( CTR!= 9 ) shift = 1; else begin clear = 1; pstav = idle; default: pstav = idle; case 11
Sériový vysílač (pokračování) always @ ( posedge clk, negedge reset ) // paměťové obvody řadiče begin: CONTRL_PO if ( reset == 0 ) sstav <= idle; else sstav <= pstav; // přechod do nového stavu // následují paměťové obvody datové cesty a čítače always @ ( posedge clk, negedge reset ) begin: if ( reset == 0 ) begin S_reg <= 9 b111111111 ; // bez přenosu CTR <= 0; else begin if ( load ==1) S_reg <= { PD_in, 1 b1 } ; if ( start ==1) S_reg [ 0 ] <= 0; // start bit if ( clear ==1) CTR <= 0; if ( shift ==1) begin CTR <= CTR + 1; S_reg <= { 1 b1, S_reg [ 8:1 ] } ; assign S_out = S_reg [ 0 ] ; module // paralelní příkaz 12
Syntéza implicitních automatů některé syntetizátory umožňují i syntézu implicitních automatů či cyklů ( ISE to nedovoluje) Implicitní automat: není explicitně definován stavový registr, vnitřní stav: vyplývá implicitně z provádění časově synchronizovaného procesu s více hranově citlivými synchronizačními operátory (každý takový operátor určuje přechod do dalšího stavu), omezení: v přechodové funkci není možné větvení: do každého vnitřního stavu lze přejít pouze z jediného jiného stavu, jednocyklový implicitné automat: v každém taktu se provádí stejná operace, příklady: čítač, paralelní register, posuvný register, po každém hranově citlivém příkazu je třeba testovat reset obvodu. 13
Syntéza implicitních automatů Příklad: periodicky spouštěný čítač po aktivaci externího signálu reset je nulován, čítá existenci vstupní jedničky během trvání čtveřice hodinových cyklů, v pátém cyklu je automaticky resetován, možné řešení: gen: generátor signálu res pro pravidelný reset čitače, standardní synchronní čítač vstupních pulsů. x res čítač mod 5 pocet reset gen clk 14
Modul gen jako implicitní automat Příklad: generátor signálu res // vstup: reset, výstup: res (impuls o šířce 1 hodinový cyklus) // na svém výstupu res generuje 1 v každém pátém cyklu module M1 ( input clk, reset, output reg res ); always @ (posedge clk) begin: BL if (reset) begin res = 1; disable BL; else res = 0; // toto není vnitřní stav @ (posedge clk) if (reset) begin res = 1; disable BL; else res = 0; @ (posedge clk) if (reset) begin res = 1; disable BL; else res = 0; @ (posedge clk) if (reset) begin res = 1; disable BL; else res = 0; @ (posedge clk) res = 1; module 15
Modul gen jako explicitní automat Příklad: generátor gen z minulého příkladu ( explicitní ) module M2 ( input clk, reset, output reg res); // následuje výčet vnitřních stavů parameter S0 = 0; parameter S1 = 1; parameter S2 = 2; parameter S3 = 3; parameter S4 = 4; reg [ 2:0 ] sstav, pstav; // register vnitřních stavů always // klopné obvody explicitního řadiče @(posedge clk ) if (reset == 1 b1) sstav<= 0; else sstav<= pstav; always @( sstav, reset ) // kombinační část řadiče begin case ( sstav ) S0: if (reset == 1 b1) begin res = 1; pstav = S0; else begin res = 0; pstav = S1; S1: if (reset == 1 b1) begin res = 1; pstav = S0; else begin res = 0; pstav = S2; S2: if (reset == 1 b1) begin res = 1; pstav = S0; else begin res = 0; pstav = S3; S3: if (reset == 1 b1) begin res = 1; pstav = S0; else begin res = 0; pstav = S4; S4: begin res = 1; pstav = S0; case module 16
Syntéza výsledného modulu Přílad: periodicky spouštěný čítač (viz minulé slajdy ) propojení čítače modulo 5 s implicitním generátorem periodického signálu reset module MM ( input clk, x, reset, output reg [ 2 : 0 ] pocet ); always // čítač @ (posedge clk) if ( reset==1 b1) pocet <= 0; else if ( x==1 b1) pocet <= pocet +1; module module Celek; // periodicky spouštěný čítač reg clk, reset, x; wire res; wire [ 2 : 0 ] pocet ; MM cit ( clk, x, res, pocet ); // instalace čítače M1 gen ( clk, reset, res ); // instalace generátoru // následuje jednoduchý test initial begin clk = 0; forever #2 clk = ~ clk; initial begin reset = 1; #6 reset = 0; x = 1; #9 x = 0; module // Celek 17
Syntéza cyklů Rozdělení cyklů: statické: počet iterací je konstantní 1) bez závislosti na hodinovém signálu: realizace kombinačním obvodem, 2) s vnitřní závislostí na hodinovém signálu: realizace sekvenčním obvodem, funkce cyklu je distribuována do více hodinových cyklů, dynamické: počet iterací není znám v době překladu 3) s vnitřní závislostí na hodinovím signálu: realizaqce sekvenčním obvodem, dílčí iterace cyklu jsou distribuovány do více hodinových cyklů, 4) bez závislosti na hodinovém signálu syntetiza problematická?? Příklad: zjištění počtu jedniček pomocí cyklu vstup: paralelní - 8 bitů, výstup: paralelní - 4 bity, následuje řešení s použitím uvedených variant 18
Statický cyklus varianta bez časových závislostí: module M1 ( output reg [3:0] pocet, input wire [7:0] data, input wire clk, reset ); reg [ 7:0 ] pom ; // omocná proměnná integer i; always @ ( posedge clk ) if ( reset ) begin pocet = 0 ; pom = 0; else begin pom = data; // inicializace // následuje statický cyklus bez časové závislosti // při simulaci nelze použít neblokující přířazení // ISE: syntéza OK for ( i = 0; i < 8 ; i = i + 1) // cyklus bez závislosti na clk pocet = pocet + pom [ i ] ; module 19
Statický cyklus varianta s vnitřní časovou závislostí: module M2 ( output reg [3:0] pocet, input wire [7:0] data, input wire clk, reset ) ; reg [ 7:0 ] pom; reg [ 3:0 ] i; // pomocné proměnné always @ ( posedge clk ) // hranově citlivý proces begin: BL; // pojmenovaný blok if ( reset ) begin pocet <= 0 ; disable BL; else begin pom = data; // inicializace // následuje cyklus s vnitřní závislostí na clk ( trvá 8 taktů ) for ( i = 0; i < 8 ; i = i + 1) @ ( posedge clk ) // ISE hlásí chybu if ( reset ) begin pocet <= 0; // výstup FF disable BL; else pocet <= pocet + pom [ i ] ; // BL module 20
Dynamický cyklus varianta s vnitřní časovou závislostí: module M3 ( output reg [3:0] pocet, input [7:0] data, input clk, reset ); reg [ 7:0 ] pom; // pomocná proměnná always @ ( posedge clk ) begin if ( reset ) pocet <= 0 ; else begin: BL; pom = data; // následuje cyklus s vnitřní čas. závislostí // ISE chyba while ( pom ) @ ( posedge clk ) if ( reset ) begin pocet <= 0; disable BL; else begin pocet <= pocet + pom [ 0 ] ; pom = pom >> 1; // if, while // BL module 21
Dynamický cyklus varianta bez časových závislostí: module M4 ( output reg [3:0] pocet, input wire [7:0] data, input wire clk, reset ); reg [ 7:0 ] pom ; always @ ( posedge clk ) if ( reset ) begin pocet = 0 ; else begin: BL; pom = data; // inicializace // následuje cyklus bez časové závisti while ( pom ) // ISE hlásí chybu begin pocet = pocet + pom [ 0 ] ; pom = pom >> 1; // BL module 22