[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.