[Home](index.html) | [Verilog osnove](verilog-start.htm) | [Stavki in izrazi](verilog-izrazi.htm) # Osnove jezika Verilog ## Verilog in VHDL Verilog je veliko bolj kompakten jezik za opis digitalnih vezij kot je VHDL. Za primerjavo vzemimo opis 8-bitnega seštevalnika z izhodnim registrom v obeh jezikih. **Verilog** ```verilog module adder ( input [7:0] a, input [7:0] b, input clk, output reg [7:0] sum, output reg carry ); always @(posedge clk) {carry, sum} <= a + b; endmodule ``` Osnovna enota jezika Verilog je modul. Ime vezja je zapisano za rezervirano besedo **module**, v oklepaju so deklaracije vhodnih in izhodnih signalov, nato pa stavki z opisom zgradbe ali delovanja vezja in na koncu **endmodule**. Izhodni register z vsoto opišemo s stavkom: **always**, kjer definiramo fronto ure ob kateri se izvede prireditev. Jezik Verilog predpostavlja, da je vsota 8-bitnih signalov 9-biten vektor, ki ga v eni sami vrstici priredimo 8-bitni izhodni vsoti s prenosom (carry). **VHDL** ```vhdl library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity adder is Port ( a, b : in std_logic_vector (7 downto 0); clk : in std_logic; sum : out std_logic_vector (7 downto 0); carry : out std_logic); end adder; architecture Behavioral of adder is signal s: unsigned(8 downto 0); begin p: process(clk) begin if rising_edge(clk) then s <= resize(unsigned(a), 9) + resize(unsigned(b), 9); end if; end process; sum <= std_logic_vector(s(7 downto 0)); carry <= s(8); end Behavioral; ``` Opis seštevalnika je v jeziku VHDL precej daljši. V opis so vključene knjižnice, sestavljen je iz opisa vmesnika **entity** in arhitekture, kar omogoča izdelavo različnih arhitektur za enako vezje. Za izračuin vsote s prenosom potrebujemo podatkovni tip *unsigned* in deklaracijo 9-bitnega notranjega signala. Izhodni register dobimo tako, da vsoto priredimo v procesu ob naraščajoči fronti ure *rising_edge(clk)*. V prireditvenem stavku za izračun vsote explicitno pretvorimo vhoda v *unsigned* in ju razširimo na 9 bitov. Na koncu določimo kateri biti so povezani z vektorjem izhodne vsote in kateri s prenosom ter naredimo pretvorbo nazaj v *std_logic_vector*. Strojno-opisni jezik **VHDL** je veliko bolj deskriptiven, razvijalec mora natančno določiti pretvarjanje podatkov in delovanje operacij, kar ima za posledico daljšo kodo, predvsem za enostavne operacije. Koda jezika **Verilog** je krajša, ker predpostavlja zelo dobro razumevanje delovanja prevajalnikov in imlicitnih pretvorb podatkov. Vsak pristop ima svoje prednosti, tako da sta na področju razvoja digitalnih vezij danes zastopana oba jezika. ## Strukturni opis vezja Osnovna enota opisa vezja je modul. Modul lahko vsebuje druge enote, ki jih ni potrebno posebej deklarirati (v jeziku VHDL moramo deklarirati vse vključene komponente). Primer takšnega opisa je štiribitni seštevalnik, ki je sestavljen iz štirih polnih seštevalnikov *full_adder*. ```verilog module full_adder( input a, input b, input cin, output s, output cout ); assign s = a ^ b ^ cin; assign cout = (a & b) | (cin & (a ^ b)); endmodule module adder( input [3:0] a, input [3:0] b, output [3:0] sum, output carry ); wire c0, c1, c2; full_adder u0 (a[0], b[0], 1'b0, sum[0], c0 ); full_adder u1 (a[1], b[1], c0, sum[1], c1 ); full_adder u2 (a[2], b[2], c1, sum[2], c2 ); full_adder u3 (a[3], b[3], c2, sum[1], carry); endmodule ``` Logika polnega seštevalnika je opisana s sočasnima stavkoma **assign** in logičnimi operatorji: xor `^`, and `&` in or `|`. S stavkom **assign** označujemo neprekinjeno prirejanje vrednosti. V opisu 4-bitnega seštevalnika *adder* imamo deklarirane 4-bitne vektorske vrednosti `[3:0]`, kjer v oglatem oklepaju zapišemo območje indeksov. Deklarirali smo tudi povezovalne signale `c0, c1, c2` za povezavo prenosov med polnimi seštevalniki. Polni seštevalnik vključimo v strukturni opis vezja tako, da navedemo ime modula *full_adder*, enolično oznako, npr. *u1* in povezave signalov v oklepaju. V našem primeru smo uporabili krajše (pozicijske) zapise povezav, kjer je povezava določena z zaporednim mestom signala v oklepaju. Verilog pozna tudi daljši (imenski) zapis, pri katerem eksplicitno določimo kateri priključek vključenega modula je povezan z določenim signalom vezja. Primer takšnega zapisa za prvi polni seštevalnik: ```verilog full_adder u0 ( .a(a[0]), .b(b[0]), .s(sum[0]), .cin(1'b0), .cout(c0) ); ``` Eksplicitno povezovanje zahteva več pisanja, vendar je manj podvrženo napakam in ne zahteva določitve vseh povezav, ki so lahko zapisane v poljubnem vrstnem redu.