verilog Handledning
Komma igång med verilog
Sök…
Anmärkningar
Verilog är ett hårdvarubeskrivningsspråk (HDL) som används för att designa, simulera och verifiera digitala kretsar på beteende- eller registeröverföringsnivå. Det är anmärkningsvärt av skäl som skiljer det från "traditionella" programmeringsspråk:
- Det finns två typer av uppdrag, blockering och icke-blockering, var och en med sitt eget bruk och semantik.
- Variabler måste deklareras som antingen enbits breda eller med en uttrycklig bredd.
- Designer är hierarkiska med förmågan att instansera moduler som har önskat beteende.
- I simulering (inte typiskt i syntes),
wire
kan variabler vara i ett av fyra tillstånd: 0, 1, flytande (z
), och odefinierad (x
).
versioner
Version | Utgivningsdatum |
---|---|
Verilog IEEE-1364-1995 | 1995-01-01 |
Verilog IEEE-1364-2001 | 2001/09/28 |
Verilog IEEE-1364.1-2002 | 2002-12-18 |
Verilog IEEE-1364-2005 | 2006-04-07 |
SystemVerilog IEEE-1800-2009 | 2009-12-11 |
SystemVerilog IEEE-1800-2012 | 2013/02/21 |
Installation eller installation
Detaljerade instruktioner för att få Verilog konfigurerat eller installerat beror på det verktyg du använder eftersom det finns många Verilog-verktyg.
Introduktion
Verilog är ett hårdvarubeskrivningsspråk (HDL) som används för att modellera elektroniska system. Det beskriver oftast ett elektroniskt system på registeröverföringsnivån (RTL) för abstraktion. Det används också för verifiering av analoga kretsar och kretsar med blandad signal. Dess struktur och huvudprinciper (som beskrivs nedan) är utformade för att beskriva och framgångsrikt implementera ett elektroniskt system.
- Stelhet
En elektronisk krets är en fysisk enhet med en fast struktur och Verilog är anpassad för det. Moduler (modul), portar (input / output / inout), anslutningar (kablar), block (@allways), register (reg) är alla fixerade vid sammanställningstiden. Antalet enheter och samtrafik förändras inte dynamiskt. Det finns alltid en "modul" på toppnivå som representerar chipstrukturen (för syntes) och en på systemnivå för verifiering. - parallel~~POS=TRUNC
De inneboende samtidiga operationerna i det fysiska chipet imiteras på språket genom att alltid (mest kommunicera), initiala och gaffel / kopplingsblock.
module top();
reg r1,r2,r3,r4; // 1-bit registers
initial
begin
r1 <= 0 ;
end
initial
begin
fork
r2 <= 0 ;
r3 <= 0 ;
join
end
always @(r4)
r4 <= 0 ;
endmodule
Alla ovanstående uttalanden exekveras parallellt inom samma tidsenhet.
Tid och synkronisering
Verilog stöder olika konstruktioner för att beskriva kretsarnas temporära natur. Tidpunkter och förseningar i kretsar kan implementeras i Verilog, till exempel genom #delay-konstruktioner. På liknande sätt rymmer Verilog också för synkrona och asynkrona kretsar och komponenter som floppar, spärrar och kombinatorisk logik med olika konstruktioner, till exempel "alltid" -block. En uppsättning block kan också synkroniseras via en gemensam klocksignal eller ett block kan utlösas baserat på specifik uppsättning ingångar.#10 ; // delay for 10 time units always @(posedge clk ) // synchronous always @(sig1 or sig2 ) // combinatorial logic @(posedge event1) // wait for post edge transition of event1 wait (signal == 1) // wait for signal to be 1
Osäkerhet
Verilog stöder en del av osäkerheten i elektroniska kretsar. "X" används för att representera kretsens okända tillstånd. "Z" används för att representera kretsens icke drivna tillstånd.reg1 = 1'bx; reg2 = 1'bz;
Abstraktion
Verilog stöder design på olika nivåer av abstraktion. Den högsta abstraktionsnivån för en design är Resister transfer Level (RTL), nästa är gate-nivån och den lägsta cellnivån (User Define Primitives), RTL-abstraktion är den mest använda. Verilog stöder också beteendemässig abstraktionsnivå utan hänsyn till det strukturella genomförandet av designen, främst används för verifiering.
// Example of a D flip flop at RTL abstraction
module dff (
clk , // Clock Input
reset , // Reset input
d , // Data Input
q // Q output
);
//-----------Input Ports---------------
input d, clk, reset ;
//-----------Output Ports---------------
output q;
reg q;
always @ ( posedge clk)
if (~reset) begin
q <= 1'b0;
end else begin
q <= d;
end
endmodule
// And gate model based at Gate level abstraction
module and(input x,input y,output o);
wire w;
// Two instantiations of the module NAND
nand U1(w,x, y);
nand U2(o, w, w);
endmodule
// Gate modeled at Cell-level Abstraction
primitive udp_and(
a, // declare three ports
b,
c
);
output a; // Outputs
input b,c; // Inputs
// UDP function code here
// A = B & C;
table
// B C : A
1 1 : 1;
0 1 : 0;
1 0 : 0;
0 0 : 0;
endtable
endprimitive
Det finns tre huvudsakliga användningsfall för Verilog. De bestämmer strukturen för koden och dess tolkning och bestämmer också de verktygssatser som används. Alla tre applikationer är nödvändiga för en framgångsrik implementering av valfri Verilog-design.
- Fysisk design / back-end
Här används Verilog för att i första hand se designen som en matris av sammankopplade grindar som implementerar logisk design. RTL / logik / Design går igenom olika steg från syntes -> placering -> klockträdkonstruktion -> routing -> DRC -> LVS -> till bandout. De exakta stegen och sekvenserna varierar utifrån den exakta karaktären av implementeringen. - Simulering
I detta användningsfall är det primära syftet att generera testvektorer för att validera designen enligt specifikationen. Koden som är skriven i detta användningsfall behöver inte vara syntetiserbar och den förblir inom verifieringsområdet. Koden här liknar närmare generiska programvarustrukturer som för / medan / gör slingor etc. - Design
Design involverar att implementera specifikationen för en krets generellt på RTL-nivå för abstraktion. Verilog-koden ges sedan för verifiering och den fullständigt verifierade koden ges för fysisk implementering. Koden är skriven med endast de syntetiserbara konstruktionerna av Verilog. Viss RTL-kodningsstil kan orsaka simulering mot felsyntes i syntesen och man måste vara försiktig för att undvika dessa.
Det finns två huvudsakliga implementeringsflöden. De kommer också att påverka hur Verilog-koden skrivs och implementeras. Vissa stilar av kodning och vissa strukturer är mer lämpade i ett flöde över det andra.
- ASIC Flow (applikationsspecifik integrerad krets)
- FPGA Flow (fältprogrammerbar gate-array) - inkludera FPGA och CPLD
Hej världen
Detta exempel använder icarus verilog-kompilatorn.
Steg 1: Skapa en fil som heter hello.v
module myModule();
initial
begin
$display("Hello World!"); // This will display a message
$finish ; // This causes the simulation to end. Without, it would go on..and on.
end
endmodule
Steg 2. Vi sammanställer .v-filen med icarus:
>iverilog -o hello.vvp hello.v
-O-omkopplaren tilldelar ett namn till utgångsobjektfilen. Utan denna switch skulle utgångsfilen kallas a.out. Hello.v anger källfilen som ska sammanställas. Det bör praktiskt taget inte finnas någon utgång när du sammanställer den här källkoden, såvida det inte finns några fel.
Steg 3. Du är redo att simulera detta Hello World verilog-program. För att göra det, åberopa som sådan:
>vvp hello.vvp
Hello World!
>
Installation av Icarus Verilog Compiler för Mac OSX Sierra
- Installera Xcode från App Store.
- Installera Xcode-utvecklarverktygen
> xcode-select --install
Detta kommer att ge grundläggande kommandoradsverktyg som gcc
och make
- Installera Mac-portar
https://www.macports.org/install.php
OSX Sierra-installationspaketet kommer att tillhandahålla en öppen källmetod för att installera och uppgradera ytterligare programvarupaket på Mac-plattformen. Tänk yum
eller apt-get
för Mac.
- Installera icarus med Mac-portar
> sudo port install iverilog
- Verifiera installationen från kommandoraden
$ iverilog
iverilog: no source files.
Usage: iverilog [-ESvV] [-B base] [-c cmdfile|-f cmdfile]
[-g1995|-g2001|-g2005] [-g<feature>]
[-D macro[=defn]] [-I includedir] [-M depfile] [-m module]
[-N file] [-o filename] [-p flag=value]
[-s topmodule] [-t target] [-T min|typ|max]
[-W class] [-y dir] [-Y suf] source_file(s)
See the man page for details.
$
Du är nu redo att kompilera och simulera din första Verilog-fil på Mac.
Installera GTKWave för grafisk visning av simuleringsdata på Mac OSx Sierra
GTKWave är ett fullständigt grafiskt visningspaket som stöder flera grafiska datalagringsstandarder, men det händer också att stödja VCD, som är det format som vvp
kommer att mata ut. Så för att hämta GTKWave har du ett par alternativ
- Gå till http://gtkwave.sourceforge.net/gtkwave.zip och ladda ner den. Denna version är vanligtvis den senaste.
- Om du har installerat MacPorts ( https://www.macports.org/ ) kör du helt enkelt
sudo port install gtkwave
. Detta kommer förmodligen att vilja installera på beroenden till. Observera att den här metoden vanligtvis får en äldre version. Om du inte har MacPorts installerat finns det ett installationsinstallationsexempel för att göra det på den här sidan. ja! Du behöver alla xcode-utvecklarverktyg, eftersom dessa metoder "bygger" dig en GTKWave från källan.
När installationen är klar kan du bli ombedd att välja en pythonversion. Jag hade redan installerat 2.7.10 så jag "valde" aldrig en ny.
Vid denna punkt kan du starta gtkwave från kommandoraden med gtkwave
. När det startar kan du bli ombedd att installera eller uppdatera XQuarts. Göra det. I mitt fall är XQuarts 2.7.11 installerad.
Obs: Jag behövde faktiskt starta om för att få XQuarts korrekt, sedan skrev jag gtkwave
igen och applikationen kommer upp.
I nästa exempel kommer jag att skapa två oberoende filer, en testbänk och en modul för att testa, och vi kommer att använda gtkwave för att se designen.
Använda Icarus Verilog och GTKWaves för att simulera och visa en design grafiskt
Detta exempel använder Icarus och GTKWave. Installationsinstruktioner för dessa verktyg på OSx finns någon annanstans på denna sida.
Låt oss börja med moduldesignen. Denna modul är en BCD till 7-segmentvisning. Jag har kodat designen på ett stöt sätt helt enkelt för att ge oss något som lätt går sönder och vi kan spendera någon gång på att fixa grafiskt. Så vi har en klocka, återställning, en 4 dataingång som representerar ett BCD-värde och en 7-bitarsutgång som representerar den sju segmentvisningen. Skapa en fil som heter bcd_to_7seg.v och placera källan nedan i den.
module bcd_to_7seg (
input clk,
input reset,
input [3:0] bcd,
output [6:0] seven_seg_display
);
parameter TP = 1;
reg seg_a;
reg seg_b;
reg seg_c;
reg seg_d;
reg seg_e;
reg seg_f;
reg seg_g;
always @ (posedge clk or posedge reset)
begin
if (reset)
begin
seg_a <= #TP 1'b0;
seg_b <= #TP 1'b0;
seg_c <= #TP 1'b0;
seg_d <= #TP 1'b0;
seg_e <= #TP 1'b0;
seg_f <= #TP 1'b0;
seg_g <= #TP 1'b0;
end
else
begin
seg_a <= #TP ~(bcd == 4'h1 || bcd == 4'h4);
seg_b <= #TP bcd < 4'h5 || bcd > 6;
seg_c <= #TP bcd != 2;
seg_d <= #TP bcd == 0 || bcd[3:1] == 3'b001 || bcd == 5 || bcd == 6 || bcd == 8;
seg_e <= #TP bcd == 0 || bcd == 2 || bcd == 6 || bcd == 8;
seg_f <= #TP bcd == 0 || bcd == 4 || bcd == 5 || bcd == 6 || bcd > 7;
seg_g <= #TP (bcd > 1 && bcd < 7) || (bcd > 7);
end
end
assign seven_seg_display = {seg_g,seg_f,seg_e,seg_d,seg_c,seg_b,seg_a};
endmodule
Därefter behöver vi ett test för att kontrollera om den här modulen fungerar korrekt. Sakförklaringen i testbänken är enligt min mening faktiskt lättare att läsa och tydligare vad den gör. Men jag ville inte sätta samma fallbeskrivning i designen OCH i testet. Det är dålig praxis. Snarare används två oberoende mönster för att validera varandra.
När du använder koden nedan kommer du att märka två rader $dumpfile("testbench.vcd");
och $dumpvars(0,testbench);
. Dessa rader skapar VCD-utdatafilen som kommer att användas för att utföra grafisk analys av designen. Om du lämnar dem ute får du inte en VCD-fil som genereras. Skapa en fil som heter testbench.v och placera källan nedan i den.
`timescale 1ns/100ps
module testbench;
reg clk;
reg reset;
reg [31:0] ii;
reg [31:0] error_count;
reg [3:0] bcd;
wire [6:0] seven_seg_display;
parameter TP = 1;
parameter CLK_HALF_PERIOD = 5;
// assign clk = #CLK_HALF_PERIOD ~clk; // Create a clock with a period of ten ns
initial
begin
clk = 0;
#5;
forever clk = #( CLK_HALF_PERIOD ) ~clk;
end
initial
begin
$dumpfile("testbench.vcd");
$dumpvars(0,testbench);
// clk = #CLK_HALF_PERIOD ~clk;
$display("%0t, Reseting system", $time);
error_count = 0;
bcd = 4'h0;
reset = #TP 1'b1;
repeat (30) @ (posedge clk);
reset = #TP 1'b0;
repeat (30) @ (posedge clk);
$display("%0t, Begin BCD test", $time); // This displays a message
for (ii = 0; ii < 10; ii = ii + 1)
begin
repeat (1) @ (posedge clk);
bcd = ii[3:0];
repeat (1) @ (posedge clk);
if (seven_seg_display !== seven_seg_prediction(bcd))
begin
$display("%0t, ERROR: For BCD %d, module output 0b%07b does not match prediction logic value of 0b%07b.",$time,bcd, seven_seg_display,seven_seg_prediction(bcd));
error_count = error_count + 1;
end
end
$display("%0t, Test Complete with %d errors", $time, error_count);
$display("%0t, Test %s", $time, ~|error_count ? "pass." : "fail.");
$finish ; // This causes the simulation to end.
end
parameter SEG_A = 7'b0000001;
parameter SEG_B = 7'b0000010;
parameter SEG_C = 7'b0000100;
parameter SEG_D = 7'b0001000;
parameter SEG_E = 7'b0010000;
parameter SEG_F = 7'b0100000;
parameter SEG_G = 7'b1000000;
function [6:0] seven_seg_prediction;
input [3:0] bcd_in;
// +--- A ---+
// | |
// F B
// | |
// +--- G ---+
// | |
// E C
// | |
// +--- D ---+
begin
case (bcd_in)
4'h0: seven_seg_prediction = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F;
4'h1: seven_seg_prediction = SEG_B | SEG_C;
4'h2: seven_seg_prediction = SEG_A | SEG_B | SEG_G | SEG_E | SEG_D;
4'h3: seven_seg_prediction = SEG_A | SEG_B | SEG_G | SEG_C | SEG_D;
4'h4: seven_seg_prediction = SEG_F | SEG_G | SEG_B | SEG_C;
4'h5: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_C | SEG_D;
4'h6: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_E | SEG_C | SEG_D;
4'h7: seven_seg_prediction = SEG_A | SEG_B | SEG_C;
4'h8: seven_seg_prediction = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G;
4'h9: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_B | SEG_C;
default: seven_seg_prediction = 7'h0;
endcase
end
endfunction
bcd_to_7seg u0_bcd_to_7seg (
.clk (clk),
.reset (reset),
.bcd (bcd),
.seven_seg_display (seven_seg_display)
);
endmodule
Nu när vi har två filer, en testbench.v och bcd_to_7seg.v, måste vi sammanställa, utarbeta med Icarus. Att göra detta:
$ iverilog -o testbench.vvp testbench.v bcd_to_7seg.v
Nästa måste vi simulera
$ vvp testbench.vvp
LXT2 info: dumpfile testbench.vcd opened for output.
0, Reseting system
6000, Begin BCD test
8000, Test Complete with 0 errors
8000, Test pass.
Om du vill bekräfta att filen verkligen testas, gå in i filen bcd_2_7seg.v och flytta lite av logiken och upprepa de två första stegen.
Som exempel ändrar jag raden seg_c <= #TP bcd != 2;
att seg_c <= #TP bcd != 4;
. Omkompilera och simulera gör följande:
$ iverilog -o testbench.vvp testbench.v bcd_to_7seg.v
$ vvp testbench.vvp
LXT2 info: dumpfile testbench.vcd opened for output.
0, Reseting system
6000, Begin BCD test
6600, ERROR: For BCD 2, module output 0b1011111 does not match prediction logic value of 0b1011011.
7000, ERROR: For BCD 4, module output 0b1100010 does not match prediction logic value of 0b1100110.
8000, Test Complete with 2 errors
8000, Test fail.
$
Så nu kan vi se simuleringen med GTKWave. Från kommandoraden, utfärda a
gtkwave testbench.vcd &
När GTKWave-fönstret visas ser du i rutan uppe till vänster, testbenken för modulnamnet. Klicka på det. Detta avslöjar undermoduler, uppgifter och funktioner som är associerade med den filen. Ledningar och register visas också i den nedre vänstra rutan.
Dra nu, clk, bcd, error_count och seven_seg_display till signalrutan bredvid vågformfönstret. Signalerna kommer nu att plottas. Error_count visar vilken specifik BCD-ingång som genererade fel Seven_seg_display-utgång.
Du är nu redo att felsöka ett Verilog-fel grafiskt.