Verilog: Diferență între versiuni

De la WikiLabs
Jump to navigationJump to search
Linia 70: Linia 70:
* blocuri '''initial'''
* blocuri '''initial'''
* blocuri '''forever'''
* blocuri '''forever'''


'''''Observație:''''' Nu orice bloc '''assign''' sau '''always''' este sintetizabil. Există construcții valide sintactic dar care nu au corespondent în circuit. Aceste blocuri pot fi simulate dar nu pot fi utilizate pentru programarea unei plăci [[FPGA]].
'''''Observație:''''' Nu orice bloc '''assign''' sau '''always''' este sintetizabil. Există construcții valide sintactic dar care nu au corespondent în circuit. Aceste blocuri pot fi simulate dar nu pot fi utilizate pentru programarea unei plăci [[FPGA]].

Versiunea de la data 30 ianuarie 2012 10:06

Module

Limabjul Verilog este structurat pe module. Fiecare modul reprezintă un circuit care implementează o anume funcție. Spre exemplu un modul poate reprezenta un sumator, adică un circuit care are două intrări ce specifică cei doi operanzi și o ieșire ce reprezintă rezultatul adunării. Conținutul modulului reprezintă descrierea (structurală sau comportamentală) a porților care calculeaza suma celor două intrări. Prin urmare, definiția unui modul Verilog are două părți:

  • interfață - lista tuturor porturilor de intrare și ieșire ale circuitului, specificate prin nume și dimensiune;
  • implementare - descrierea efectivă a circuitului care se folosește de valorile de intrare pentru a calcula valorile de ieșire;

Interfața modulelor Verilog

Interfața modulului Adder este prezentată mai jos. Observație: Ca și în sistemul numeral zecimal, unde suma a două numere de n cifre are nevoie de n + 1 cifre (9 + 9 = 18), și în sistemul binar, suma a două numere de n biți va fi pe n + 1 biți.

Reprezentarea interfetei modulului "Adder" (black box)
module Adder(
    output [4:0] out,
    input  [3:0] in0,
    input  [3:0] in1
);

//implementare

endmodule

Cuvintele cheie module și endmodule sunt folosite pentru a începe și a încheia definirea unui modul. Imediat după cuvântul cheie module urmează numele modulului.

Convenție: Numele unui modul va începe cu literă mare.

După definirea numelui modulului, urmează lista de porturi, plasată între paranteze rotunde și separate prin virgulă. Cuvintele cheie acceptate sunt output (reprezentând un port de ieșire), input (reprezentând un port de intrare) și inout (reprezentând un port bidirecțional).

Sfat: Când aveți de ales în privința interfeței unui modul, se evită utilizarea semnalelor de tip inout. Acestea introduc elemente de tip Tri-state Buffer care sunt ineficiente. O alternativă mai eficientă este definirea a două porturi, unul de intrare și unul de ieșire, cu nume similare (ex: data_in și data_out).

Convenție: Întâi se definesc ieșirile, apoi intrările unui modul.

Convenție: Porturile unui modul se scriu unul sub altul, pe câte o linie, aliniate cu un tab la dreapta față de cuvântul cheie module.

După tipul portului, urmează dimensiunea acestuia, specificată în indecșii biților, unde cel mai puțin semnificativ bit are indexul 0. Spre exemplu, un semnal de 4 biți va avea următoarea specificație [3:0] (bitul cel mai semnificativ are indexul 3, cel mai puțin semnificativ 0, în total 4 biți). Observație: Semnalelor de un bit le lipsește specificația de dimensiune:

input oneBitSignal,

După lista de porturi aflată între paranteze, definirea interfeței se termină cu caracterul ;.

Implementarea modulelor Verilog

Implementarea modulelor Verilog se face prin blocuri. Aceste blocuri pot avea sau nu corespondent într-un ciruit fizic. Dacă toate blocurile unui modul au corespondent într-un circuit fizic, atunci modulul este sintetizabil și poate fi transformat într-un circuit fizic. Blocurile care pot genera construcții sintetizabile sunt de patru tipuri:

  • blocuri assign
  • blocuri always
  • blocuri generate
  • blocuri de instanțiere

În plus, în Verilog se pot defini fire (wire) și registre (reg).

Blocurile care sunt întotdeauna nesintetizabile și sunt folosite exclusiv pentru simulare:

  • blocuri initial
  • blocuri forever

Observație: Nu orice bloc assign sau always este sintetizabil. Există construcții valide sintactic dar care nu au corespondent în circuit. Aceste blocuri pot fi simulate dar nu pot fi utilizate pentru programarea unei plăci FPGA.

Observație: Ordinea blocurilor într-un modul nu contează.

Fire (wire) și registre (reg)

Observație: Un element de tip reg nu se translatează neapărat într-un registru fizic. Tranlatarea lui depinde de modul în care se utilizează.

Regulă: Un element de tip reg își schimbă valoarea doar în blocuri de tip always sau initial.

Regulă: Niciun element nu își poate schimba valoarea în mai mult de un bloc. Adică pentru un fir (wire), nu pot exista două blocuri assign în care acesta ia valori, iar pentru elemente reg, nu există decât un bloc always sau initial în care acesta își schimbă valoarea.


Blocuri assign

Assign este un cuvănt cheie care generează circuite combinaționale. Cum sumatorul este un circuit combinațional, îl putem implementa cu un bloc assign:

module Adder(
    output [4:0] out,
    input [3:0] in0,
    input [3:0] in1
);

assign out = in0 + in1;

endmodule

Observație: În general, un bloc assign va genera un circuit sintetizabil. Există și excepții, atunci când operația dorită este prea complexă pentru a fi implementată printr-un circuit combinațional, în mod eficient. Spre exemplu:

assign out = in0 / in1;

nu este un cod sintetizabil pentru majoritatea tool-urilor de sinteză, dar funcționează perfect într-o simulare.

Blocuri always