FPGA & Verilog ismertetı
BME Méréstechnika és Információs Rendszerek Tanszék
FPGA-k • FPGA: Field Programmable Gate Array – programozható logikai áramkör • Jelentısebb gyártók: Xilinx, Altera, Actel, Quicklogic, Lattice • Jellemzık – A funkciót, mőködést a konfiguráció határozza meg – A konfiguráció esetleg módosítható, törölhetı – Komplexitás • 50000 – 8000000 kapu • 100 – 600 I/O láb • 100 – 400 MHz mőködés (terv függı) – Felépítés lehet pl. RAM alapú, MUX alapú
Xilinx FPGA-k • Több család – Spartan: hatékony, optimalizált struktúra – Virtex: speciális funkciók, gyorsabb, komplexebb, gazdagabb funkcionalitás • Felépítés: – CLB: logikai blokk – IOB: I/O blokk – BlokkRAM: belsı memória – Szorzó – Huzalozás
Xilinx FPGA: Alap logikai elem • Logikai elem (Slice): 2 LUT + 2 FF + kiegészítı logika
• LUT: Look-Up Table – 16x1 bites memória – Cím: a logikai függvény bemeneti változói – Tartalom: Karnaugh tábla – Bármilyen négy bemenető, egy kimenető logikai függvény megvalósítható
Xilinx FPGA-k • Részlet egy kész tervbıl: logikai blokkok + huzalozás
Xilinx FPGA-k: a logikai elem részletei
Xilinx FPGA: konfiguráció • A konfigurációt (LUT tartalom, huzalozás, csatlakozások, egyéb paraméterek) SRAM tárolja • Tápfeszültség kikapcsolásakor elveszíti a konfigurációt • Bekapcsolás után konfiguráció szükséges – EEPROM-ból, automatikusan – Fejlesztıi kábel segítségével ún. JTAG porton keresztül
Szabvány HDL nyelvek • Szabványos HDL (hardware description language) nyelvek – Verilog • 1984: Gateway Design Automation Inc. • 1990: Cadence -> Open Verilog International • 1995: IEEE szabványosítás • 2001: Verilog 2001 – VHDL • 1983-85: IBM, Texas Instruments • 1987: IEEE szabvány • 1994: VHDL-1993
Egyéb HDL • HDL fejlesztés a szoftver fejlesztéshez viszonyítva továbbra is idıigényes • Sok fejlesztı rendelkezik C/C++ ismerettel, viszonylag kevés HDL ismerettel • Magasszintő hardver leíró nyelvek – Celoxica Handel-C: C alapú, spec. kiegészítések – SystemC: szabványos, ma már (részben) szintetizálható, C++ alapú – Mentor Catapult-C: C++ kiegészítések nélkül • Gyorsabb szimuláció/verifikáció • HW/SW együttes tervezés
HDL nyelvek célja • Hardver modellezés – Mindkét nyelv jelentıs része csak a hardver funkciók modellezésére ill. szimulációra használható – Szintetizálható részhalmaz szintézer függı • Kapuszintő modulokból építkezı, kapcsolási rajzon alapuló tervezési módszerek leváltása • RTL (Register Transfer Level) szintő leírás – Automatikus hardver szintézis a leírásból – Tervezıi hatékonyság növelése
HDL nyelvek • Alapvetıen moduláris felépítéső tervezést tesz lehetıvé • HDL modul – Be-, kimenetek definiálása – Be-, kimenetek közötti logikai kapcsolatok és idızítések definiálása • NEM szekvenciálisan végrehajtódó szoftver – Alapvetıen idıben párhuzamos, konkurrens mőködést ír le
Verilog Modulok
Modulok • „Építıelem” komplex rendszerek létrehozására • Hierarchikus leírás, feladat partícionálás
Verilog 2001 Module „module” név „module” kulcsszó module something( input clock, input reset,
Modul bemeneti portjai
input [7:0] bus_in, output [7:0] bus_out, );
„endmodule” kulcsszó
always @ (posedge clock) if (reset) bus_out <=0; else bus_out <= bus_in; endmodule
Modul kimeneti portjai
Kívánt funkcionalítás
Modul használat .... wire clock, reset; wire local_bus_in, local_bus_out; something inst_name ( .clock (clock), .reset (reset), .bus_in (local_bus_in), .bus_out (local_bus_out) ); Almodulban deklarált változó
„Itteni” változó
Strukturális leírás • Hierarchia felépítése: modulok összekapcsolása module top_level (input in0, in1, in2, output r); wire xor0; xor_m xor_inst0(.i0(in0), .i1(in1), .o(xor0)); xor_m xor_inst1(.i0(xor0), .i1(in2), .o(r)); endmodule
xor_m in0 in1
i0 i1
o
xor_inst0 in2
xor_m i0 i1
o
xor_inst1
r
Verilog alapok
Szintaktika • Megjegyzések (mint C-ben) – // egy soros – /* */ több soros • Konstansok –
<‘alap><érték> • 5’b00_100: 00100 • 8’h4e: 01001110 • 4’bZ: ZZZZ
decimális érték: 4, 5 bites decimális érték: 78, 8 bites nagy impedanciás, kikapcsolt állapot
Bitmőveletek • ~, &, |, ^, ~^ (negálás, és, or, xor, xnor) • Vektorokon bitenként értelmezett, pl: – 4’b1101 & 4’b0110 = 4’b0100 • Ha a két operandus szélessége nem egyezik meg, a kisebbik az MSB biteken 0-val kiterjesztve – 2’b11 & 4’b1101 = 4’b0001 • (Logikai operátorok: !, &&, ||)
Komparátor operátorok • C-szintakszissal megegyezı • Egyenlıség, nem egyenlıség – ==, != – ===: egyenlıség az „x, z” értékek figyelembevételével – !==: nem egyenlı, „x, z” figyelembevételével • Összehasonlítás – <, >, <=, >=
Aritmetikai operátorok • C-szintakszissal megegyezı • Operátorok: +, -, *, /, % – Nem mindegyik szintetizálható • Szintézer függı, de tipikusan az osztás pl. csak akkor, ha az osztó kettı hatvány – Negatív számok kettes komplemens kódban
Egyéb operátorok • Konkatenálás (összefőzés): {} Pl.: – {4’b0101, 4’b1110} = 8’b01011110 • Shift operátor – <<, >> • Bit kiválasztás – Tartomány kiválasztó kifejezés konstans – data[5:3]
Bit redukciós operátorok • Egy vektor összes bitjén végeznek mőveletet, eredményük egy bites érték • &, ~&, |, ~|, ^, ~^ (és, nem és, vagy, nem vagy, xor, xnor) – &4’b1101 = 1’b0 – |4’b1101 = 1’b1 – Tipikus alkalmazások: • Számláló végérték feltételek, • Paritásvizsgálat • ALU mővelet eredmény jelzés
Verilog misztika
wire - reg assign - always
Carry OUT Comb. OUT
Adattípusok
L U T
4 LUT
I N
Carry + MUX
MUX IN
• Wire assign – Nevének megfelelıen viselkedik (vezeték) – Pl. 8 bites vezeték: wire [7:0] data;
Carry IN
• Reg always – Szintézis utáni eredmény nem mindig regiszter • Vezeték Assign kombinációs • Flip-flop Always @ (*) kombinációs • Latch Always @ ( _wire_) kombinációs – Pl.: reg [7:0] data; Always @ (posedge clk)
regiszter
FF
FF OUT
Assign – Kombinációs logika • assign-nal csak wire típusú változónak lehet értéket adni • Folyamatos értékadás – A bal oldali változó folyamatosan kiértékelıdik • Pl. – assign c = a & b; a b
c
• Egy változó csak egy assign által kaphat értéket • assign értékadások egymással párhuzamosan mőködnek (hardver) • Kombinációs logika leírására alkalmas
Always két esete • Kombinációs logika always @ (a, b) c <= a & b; a b
c
always @ (*) c <= a & b;
• Flip-Flop
always @ (posedge clk) c <= a & b;
clk
a b
D[0] Q[0]
c
Always blokk finomságok • Szintakszis: always @ (….) begin ….. ….. end
• • • •
Érzékenységi lista Blokkon belüli mőveletek
Egy változó csak egy always blokkban kapjon értéket always blokk nem lehet érzékeny a saját kimenetére always blokkon belül ne használjunk assign értékadást Az always blokkok egymással (és az assign típusú értékadásokkal) párhuzamosan mőködnek
Always – Flip Flop • Flip Flop: élérzékeny tároló always @ (posedge clk) c <= a & b;
clk
a b
D[0] Q[0]
c
• Szinkron reset always @ (posedge clk) if (rst) c <= 1'b0; else c <= a & b;
• Aszinkron reset always @ (posedge clk, posedge rst) if (rst) c <= 1'b0; else c <= a & b;
clk
a b
rst
D[0] Q[0] R
c
Always – Flip Flop • Xilinx FPGA-kban – A reset, set lehet szinkron, illetve aszinkron – Szinkron eset prioritás: • reset, set, ce • Aszinkron reset/set példa: always @ (posedge clk, posedge rst, posedge set) if (rst) c <= 1'b0; else if (set) c <= 1'b1; else if (ce) c <= a & b;
Always – latch • Latch: szintvezérelt tároló: amíg a „gate” bemenete ‘1’, addig mintavételezi az adatbemeneteket
always @ (*) If (g) c <= a & b;
a b
lat D[0] C
Q[0]
c g
c
Always – latch hiba • Latch “véletlen” létrehozása – Nem teljes “if” vagy „case” szerkezet – Szintézer általában figyelmeztet always @ (*) case (sel) 2’b00: r <= in0; 2’b01: r <= in1; 2’b10: r <= in2; endcase always @ (*) if (sel==0) r <= in0; else if (sel==1) r <= in1; else if (sel==2) r <= in2;
sel[1:0]
[1:0]
[0]
[0]
in0
0 1
[1]
in1
0
LD
1
D Q G
r
in2
[1] [0]
r
Always – helyesen • Helyes kód always @ (*) case (sel) 2’b00: r <= in0; 2’b01: r <= in1; 2’b10: r <= in2; default: r <= ‘bx; endcase always @ (*) if (sel==0) r <= in0; else if (sel==1) r <= in1; else r <= in2;
Always – értékadás • Blokkoló értékadás: = – Kiértékelıdéséig blokkolja az utána következı értékadásokat -> szekvenciális utasítás végrehajtás • Nem-blokkoló értékadás: <= – A nem-blokkoló értékadások párhuzamosan hajtódnak végre • Blokkoló – nem-blokkoló példa késıbb • Nem-blokkoló értékadás használata javasolt
Blokkoló – nem blokkoló reg t, r; always @ (posedge clk) begin t = a & b; r = t | c; end
reg t, r; always @ (posedge clk) begin t <= a & b; r <= t | c; end
clk c a b
D[0] Q[0]
r
r
clk c
a b
D[0] Q[0]
t
D[0] Q[0]
r
r
Blokkoló – nem blokkoló • Pl. 3 bemenető összeadó reg s0, s1; always @ (posedge clk) begin s0 = in0 + in1; s1 = s0 + in2; end
reg s2, s3; always @ (posedge clk) begin s2 <= in0 + in1; s3 <= s2 + in2; end
reg s4; always @ (posedge clk) begin s4 <= in0 + in1 + in2; end
In0
2
6
In0
2
6
In0
2
6
In1
4
9
In1
4
9
In1
4
9
In2
5
3
In2
5
3
In2
5
3
s0
6
15
s2
s1
11
18
s3
6
15 9
s4
11
18
Praktikák • Tervezési tanácsok: – 1 modul, egy funkcióért felelıs (pl. órajel generátor, összeadó blokk, szőrı blokk, memória tömb etc...) – Minden modulban az always és assign utasítások párhuzamosan értékelıdnek ki. – Always blokkban nem használunk assignt! – Egy always blokk egy jól meghatározott funkciót tölt be. (pl. shift regiszter, multiplexer, órajel osztó etc.) – Egy always blokk egyetlen vagy néhány – funkciójában szorosan kapcsolódó- reg változónak ad értréket. – Minden (reg) változónak csak 1 always blokkban adjunk értéket.
Gyakorlati példák 5 dolog amibıl minden felépíthetı
Edit menü > Language Templates Verilog \ Synthesis Constructs \ Coding Examples
D Flip-Flop reg ff; always @(posedge clk) if (reset) //sync. reset ff <= 1'b0; else ff<= new_value; end
reg c; wire a,b; always @ (posedge clk) c <= a & b; clk
a b
D[0] Q[0]
c
Számláló reg [3:0] count; always @(posedge clk) if (reset) count <= 0; else if (enable) count<= count + 1; reg [7:0] cntr_reg; always @ (posedge clk) if (reset) cntr_reg <= 0; else if (ce) if (load) cntr_reg <= din; else if (dir) cntr_reg <= cntr_reg – 1; else cntr_reg <= cntr_reg + 1;
Multiplexer (4:1)
module mux_41 (input in0, in1, in2, in3, input [1:0] sel, output reg r); always @ (*) case(sel) 2’b00: r <= in0; 2’b01: r <= in1; 2’b10: r <= in2; 2’b11: r <= in3; endcase endmodule
Decoder reg [3:0] output; wire [1:0] select; wire enable; always @( * ) if (enable) case (select) 2'b00 : output <= 4'b0001; 2'b01 : output <= 4'b0010; 2'b10 : output <= 4'b0100; 2'b11 : output <= 4'b1000; default : output <= 4'b0000; endcase else output <=0; wire [3:0] output; wire [1:0] select; wire enable; assign output = enable << (select);
Shift regiszter (párh. – soros. ) reg [2:0] shift; wire out; always @(posedge clock) if (reset) shift <= 0; else if (load) shift <= load_input[2:0]; else if (shift_enable) shift <= { shift[1:0] , 1’b0}; assign out = shift[2];
Ami mindig kell (De sohasem jut eszembe)
Órajel osztása (tízzel) reg [3:0] clk_div; wire tc; always @ (posedge clk) If (rst) clk_div <= 0; else if (tc) clk_div <= 0; else clk_div <= clk_div + 1; assign tc = (clk_div == 9);
Adat késleltetés és éldetektálás reg data_dly1, data_dly2; always @ (posedge clk) begin data_dly1 <= data_in; data_dly2 <= data_dly1; end
wire rising, falling; assign rising = data_in & !data_dly1; (data_in==1) && (data_dly1==0) assign falling = !data_in & data_dly1; (data_in==0) && (data_dly1==1)
Háromállapotú vonalak • Kétirányú kommunikációs vonalak, pl. – Külsı memóriák adatbusza module tri_state (input clk, inout [7:0] data_io); wire [7:0] data_in, data_out; wire bus_drv; assign data_in = data_io; assign data_io = (bus_drv) ? data_out : 8’bz; endmodule
• A kétirányú vonalak meghajtását engedélyezı jel (bus_drv) kritikus
Nyelvi sokszínőség
Feltétel leírása assign wire_name =
(condition) ? input1 : input0;
always @ ( * ) - always @ (posedge clk) if (condition0) statement0; else if (condition1) statement1; else statement2;
always @ ( * ) - always @ (posedge clk) case (two_bit select) 2'b00 : statement0; 2'b01 : statement1; 2'b10 : statement2; 2'b11 : statement3; default: statement_def; endcase
Példa – MUX • 2:1 multiplexer module mux_21 (input in0, in1, sel, output r); assign r = (sel==1’b1) ? in1 : in0; endmodule
Assign
module mux_21 (input in0, in1, sel, output reg r); always @ (*) if (sel==1’b1) r <= in1; else r <= in0; endmodule
If
module mux_21 (input in0, in1, sel, output reg r); always @ (*) case(sel) 1’b0: r <= in0; 1’b1: r <= in1; endmodule
Case
Példa – 1 bites összeadó module add1_full (input a, b, cin, output cout, s); xor3_m xor(.i0(a), .i1(b), .i2(cin), .o(s)); wire a0, a1, a2; and2_m and0(.i0(a), .i1(b), .o(a0)); and2_m and1(.i0(a), .i1(cin), .o(a1)); and2_m and2(.i0(b), .i1(cin), .o(a2)); or3_m or(.i0(a0), .i1(a1), .i2(a2) , .o(cout)) endmodule module add1_full (input a, b, cin, output cout, s); assign s = a ^ b ^ cin; assign cout = (a & b) | (a & cin) | (b & cin); endmodule module add1_full (input a, b, cin, output cout, s); assign {cout, s} = a + b + cin; endmodule
Állapotgépek
P
PS
S
Z
FSM – Finite State Machine • Állapotgép – vezérlési szerkezetek kialakítása • Általános struktúra
• State register: állapotváltozó • Next state funkction: következı állapotot dekódoló logika • Output function: kimeneti jeleket elıállító logika – Moore: állapotváltozó alapján – Mealy: állapotváltozó + bemenetek alapján
FSM példa • Közlekedési lámpa – Állapotok: piros, sárga, zöld, piros-sárga (a villogó sárga nem implementált) – Bemeneti változók: idızítı az egyes állapotokhoz – Kimenet: az állapot P
PS
S
Z
FSM példa – Verilog (1) module lampa( input clk, rst, output reg [2:0] led); parameter PIROS parameter PS parameter ZOLD parameter SARGA
= 2'b00; = 2'b01; = 2'b10; = 2'b11;
reg [15:0] timer_ps, timer_p, timer_s, timer_z; reg [1:0] state_reg; reg [1:0] next_state; always @ (posedge clk) if (rst) state_reg <= PIROS; else state_reg <= next_state;
always @ (*) case(state_reg) PIROS: begin if (timer == 0) next_state <= PS; else next_state <= PIROS; end PS: begin if (timer == 0) next_state <= ZOLD; else next_state <= PS; end SARGA: begin if (timer == 0) next_state <= PIROS; else next_state <= SARGA; end ZOLD: begin if (timer == 0) next_state <= SARGA; else next_state <= ZOLD; end default: next_state <= 3'bxxx; endcase
FSM példa – Verilog (2) always @ (posedge clk) case(state_reg) PIROS: begin if (timer == 0) timer <= 500; //next_state <= PS; else timer <= timer - 1; end PS: begin if (timer == 0) timer <= 4000; //next_state <= ZOLD; else timer <= timer - 1; end SARGA: begin if (timer == 0) timer <= 4500; //next_state <= PIROS; else timer <= timer - 1; end ZOLD: begin if (timer == 0) timer <= 500; //next_state <= SARGA; else timer <= timer - 1; end endcase
• Idızítı – Állapotváltáskor egy állapotfüggı kezdıértéket tölt be – Lefelé számol – ==0: állapotváltás
always @ (*) case (state_reg) PS: led <= 3'b110; PIROS: led <= 3'b100; SARGA: led <= 3'b010; ZOLD: led <= 3'b001; endcase endmodule
Szimuláció
Szimuláció • Testbench: ISE két lehetıséget biztosít – Testbench Waveform • Grafikus felületen megadható bemenetek – Verilog Test Fixture • Verilog kódban megírt stimulus • Szimulátor – ISE szimulátor – Modelsim (MXE)
Verilog Test Fixture • Test Fixture – A Test Fixture egy Verilog modul – A tesztelendı modul almodulként van beillesztve – Minden, a szintézisnél használt nyelvi elem felhasználható – Nem szintetizálható nyelvi elemek • Idıalap – ‘timescale 1ns/1ps • Megadott idık ns-ban értendık • Szimulációs lépésköz: 1 ps
Test Fixture - initial • „initial” blokk – 0. idıpillanatban kezdıdik a végrehajtása – Egyszer fut le – Az „initial” blokkok egymással, és az „always” blokkokkal párhuzamosan mőködnek • Az „initial” blokkon belüli késleltetések összeadódnak, pl. initial begin a <= 0; #10 a <= 1; #25 a <= 2; #5 a <= 0; end
1 0
10
2 35 40
0
Test Fixture - always • Órajel generálás initial clk <= 1; always #5 clk <= ~clk;
• Órajelre mőködı bemenetek (pl. számláló) initial cntr <= 0; always @ (posedge clk) #2 cntr <= cntr + 1;
0
1
tOH =2ns
2
3
4
5
6