Verilogvs. VHDL Janne Koljonen University of Vaasa
Sälää Huom! Verilogistauseita versioita: 1995, 2001 ja 2005. Kommentit Javasta tutut // ja /* */ ovat kommenttimerkkejä. Case sensitivity Isot ja pienet kirjaimet erotettava. Varatut sanat ovat pienillä kirjaimilla.
module Verilogin suunnitteluyksikkö on module Ainoa tietotyyppi, jonka käyttäjä voi määritellä. Piirihierarkia syntyy luomalla toisista moduleista olioita. entity + architecture modulenlisäksi on myös mm. library-ja config-yksiköt.
wireja reg VHDL:n signaalia vastaa wire. wireon johdin, joka ei muista arvoa vaan luo kiinteän kytkennän. Mikäli halutaan luoda rekisteri käytetään puolestaan tietotyyppiä reg. regon unsigned-tyyppinenmuuttuja (Verilog2001:ssä se voidaan myös julistaa signed-tyyppiseksi). reg näkyy globaalisti! Vektorit määritellään hakasuluilla: Esim. wire[15:0] A; reg[7:2] B; Puolipiste päättää määrittelyt ja signaalikytkennät, mutta ei esimerkiksi end-rivejä.
Portit Modulin portti suunta voi olla input, output tai inout. Portti voi olla skalaari tai vektori. Esim. output[15:0] määrittelee 16-bittisen ulostuloportin. Portti on oletusarvoisesti tyypiltään wire, mutta output-portista voidaan tehdä myös esimerkiksi reg.
assign Signaalien kiinteä, asynkroninen kytkennässä käytetään varattua sanaa assign. Esim. wire a; wire b; wire c; wire d; assignc = a && b; assign#10 d = a && b; // #10 -> viive = 10 timescaleyksikköä
Esimerkki Verilog2001-tyylillä module myfunction(output y, input[3:0] x); wire temp1; wire temp2; assigntemp1 = x[0] && x[1]; assigntemp2 =!x[2] && x[3]; //! ja ~ on not assigny = temp1 temp2; endmodule
Synkroninen logiikka Synkroniseen logiikkaan käytetään always-lohkoa. Herkkyyslista mukaan: always@(clock) Kellon etu- ja takareuna vastaavasti: always@(posedge clock) always@(negedge clock) Tällöin käytetään <= -operaattoria sijoittamiseen. Synkronisen lauseen lähde voi olla esim. wiretai reg, mutta kohde täytyy olla reg.
Esimerkki: D-kiikku module Dff(output Q, input clock, input D); regq; always@(posedge clock) q <= D; assignq = q; endmodule
D-kiikku asynkronisella resetillä // Verilog 1995-tyyllillä module Dff_ar(Q, clock, D, reset); input D, clock, reset; output Q; reg Q; // Määritetään ulostuloportti rekisteriksi always@(posedgeclockornegedgereset) begin if( ~reset) Q <= 1 b0; elseq <= D; end endmodule
Rakennekuvaus Moduleistaluodaan olioita suoraviivaisesti. <modulinnimi> <olion nimi> (<lista kytkennöistä>); // VHDL:ssä <olion nimi>: <komponentin nimi> jne // Listan osat erotetaan pilkuilla Porttien kytkentä voidaan tehdä joko esiintymisjärjestyksessä (implisiittisesti) tai nimetysti. Implisiittinen kytkentä: (<tämän modulin muuttuja>, ) Nimetyn syntaksi on: (.(<olion portti>(<tämän modulin muuttuja>), ) Seuraavassa esimerkissä yhdistetään myfunctionja Dff_ar:
moduletoplevel(outputy, input[3:0] x, input clock, input reset); wire temp; myfunctionu1 (.y(temp),.x(x)); Dff_aru2 (.Q(y),.clock(clock),.D(temp),.reset(reset)); endmodule
Muuttujat Muuttujat voivat olla joko register- tai nettyyppisiä. Neljä arvoa: 0, 1, x ja z. Register-tyyppejäovat: reg, integer, realja time. reg on unsigned, jonka pituus voi vaihdella Esim. reg[3:0] A; Reg voidaan julistaa signed-tyyppiseksikin ainakin 2001- versiossa. integer on 32-bittinen signed.
Muuttujat Net-tyyppejä ovat: wire, tri, wand, wor, triand, tri0, tri1, supply0, supply1, trieg wireja triovat identtisiä, mutta trion tarkoitettu käytettäväksi kolmitilaisten lähteiden kanssa. wandon wiredand: kaikista lähteistä lasketaan and. wor on wired or: kaikista lähteistä lasketaan or. tri0: johdin, jossa alasvetovastus. Jos ei lähdettä, arvona 0.
Muuttujat Net-tyyppejä ovat: wire, tri, wand, wor, triand, tri0, tri1, supply0, supply1, trieg tri1: johdin, jossa ylösvetovastus. Jos ei lähdettä, arvona 1. supply0: referenssimaa. supply1: referenssijännite. trieg: johdin, joka kytketty kapasitanssilla maahan. Jos lähteet z-arvoisia, muistaa edellisen tilansa.
Muuttujat: esimerkki module testnets(output[3:1] y, input[1:-1] x); wand a; worb; supply0 c; assigna = x[0]; assigna = x[1]; assignb = a; assignb = x[-1]; assigny[1] = a; assigny[2] = b; assigny[3] = c; endmodule // assigna = x[0] && x[1]; // assignb = a && x[-1]; // assigny[3] = 1 b0;
Vakiot Vakio voi olla numero, merkkijono tai parameter. Numero on aina integer-tai real-tyyppiäja muotoa: <kaistanleveys> <kantaluku><arvo>, josta kaistanleveys ja kantaluku {b, o, d, h} voidaan jättää pois, oletuksena on d, mutta määrittämättömän kaistanleveyden toteutus riippuu siitä, mihin se on kytketty. 1 b1 on yksibittinen 2-kantainen luku 1. Myös 1 bx ja 1 bz ovat käytössä. 8 h15, 8 b0001_0101 ja 21 ovat yhtä suuria. (21 on tosin ehkä 32-bittinen integer.)
Vakiot Merkkijono kirjoitetaan lainausmerkkeihin: abc. parameter on nimetty vakio. Se on oletukseltaan unsigned. parametera = 1 b1; parameter B = 10; // 32-bittinen unsigned? parameter C = -15; // 32-bittinen signed? parameter signed[15:0] C = -15; // 16-bittinen signed
Aritmetiikkaa modulearithmetics(output[3:0] y, inputsigned[2:0] x, inputplus, input use_x, input clock); parametera = 4; reg signed[3:0] akku; assigny = akku; always@(negedge clock) begin if(use_x) else if(plus) akku <= akku + x; else akku <= akku -x; if(plus) akku <= akku + a; else akku <= akku -a; end endmodule
vector, array Vektorin indeksialue tulee heti tyypin jälkeen. Taulukon (array) indeksialue tulee heti muuttujanimen jälkeen. Voidaan tehdä vektoritaulukko: reg[15:0] muistipiiri [255:0]; ja viitata siihen: reg[7:0] tavu; tavu <= muistipiiri[123][15:8];
Konkatenointi Vektorit ja vakiot voidaan yhdistää konkatenoinnilla. Vektoreiden dimensioiden pitää täsmätä. Esimerkiksi: reg[3:0] a; reg[1:0] b; reg[5:0] c; always@(posedgeclock) c <= {a, b};
Reductionoperators Lasketaan yhdellä operaattorilla usean bitin looginen operaatio. Tuloksena yksi bitti. &, ~&,, ~, ^, ~^ and, nand, or, nor, xor, xnor Esim. ^4 b0101 antaa 0. reg[3:0] a; reg[4:0] b; always@(posedge clock) b <= {^a, a}; Lisää pariteettibitin konkatenoinnilla.
MixedVHDL ja Verilog VHDL-entiteeteistä ja Verilog-moduleista luotuja olioita voidaan käyttää sekaisin rakennekuvauksessa. Yksiköstä voidaan luoda olio ja kytkeä portit täysin tietämättä olion lähdekieltä. Tehdään esimerkiksi D-kiikku VHDL:lläja liitetään se aiempaan toplevel-moduliin, joka säilyy itse asiassa ennallaan, kunhan portit on nimetty samoin. (Nyt kuitenkin suunnitteluyksikön nimeä muutetaan hieman.)
// Aiemmin oli moduledff_ar(q, clock, D, reset); input D, clock, reset; output Q; regq; // Määritetään ulostuloportti rekisteriksi always@(posedge clock ornegedgereset) begin if( ~reset) Q <= 1 b0; elseq <= D; end endmodule -- Nyt VHDL:llä Library ieee; Use ieee.std_logic_1164.all; Entity Dff_ar2 is Port(clock, D, reset: in std_logic; Q: out std_logic); End Dff_ar2; Architecture arch of Dff is Begin Process(clock, reset) Begin If reset= 0 then Q <= 0 ; elsif rising_edge(clock) then Q <= D; End if; End process; End arch;