Verilog例子整理(轉載)
【例5.6 】用fork-join 並行塊產生訊號波形
`timescale 10ns/1ns
module wave2;
reg wave;
parameter cycle=5;
initial
fork
wave=0;
#(cycle) wave=1;
#(2*cycle) wave=0;
#(3*cycle) wave=1;
#(4*cycle) wave=0;
#(5*cycle) wave=1;
#(6*cycle) $finish;
join
initial $monitor($time,,,"wave=%b",wave);
endmodule
【例5.7 】持續賦值方式定義的2 選1 多路選擇器
module MUX21_1(out,a,b,sel);
input a,b,sel;
output out;
assign out=(sel==0)?a:b;
//持續賦值,如果sel為0,則out=a ;否則out=b
endmodule
【例5.8 】阻塞賦值方式定義的2 選1 多路選擇器
module MUX21_2(out,a,b,sel);
input a,b,sel;
output out;
reg out;
begin
if(sel==0) out=a; //阻塞賦值
else out=b;
end
endmodule
【例5.2 】同步置數、同步清零的計數器
module count(out,data,load,reset,clk);
output[7:0] out;
input[7:0] data;
input load,clk,reset;
reg[7:0] out;
always @(posedge clk) //clk 上升沿觸發
begin
if (!reset) out = 8'h00; //同步清0,低電平有效
else if (load) out = data; //同步預置
else out = out + 1; //計數
end
endmodule
【例5.9 】非阻塞賦值
module non_block(c,b,a,clk);
output c,b;
input clk,a;
reg c,b;
always @(posedge clk)
begin
b<=a;
c<=b;
end
endmodule
【例5.10 】阻塞賦值
module block(c,b,a,clk);
output c,b;
input clk,a;
reg c,b;
always @(posedge clk)
begin
b=a;
c=b;
end
endmodule
【例5.15 】用for 語句描述的七人投票表決器
module voter7(pass,vote);
output pass;
input[6:0] vote;
reg[2:0] sum;
integer i;
reg pass;
always @(vote)
begin
sum=0;
for(i=0;i<=6;i=i+1) //for語句
if(vote[i]) sum=sum+1;
if(sum[2]) pass=1; //若超過4人贊成,則pass=1
else pass=0;
end
endmodule
【例6.2 】任務舉例
module alutask(code,a,b,c);
input[1:0] code;
input[3:0] a,b;
output[4:0] c;
reg[4:0] c;
task my_and; //任務定義,注意無埠列表
input[3:0] a,b; //a,b,out 名稱的作用域範圍為task任務內部
output[4:0] out;
integer i;
begin
for(i=3;i>=0;i=i-1)
out[i]=a[i]&b[i]; //按位與
end
endtask
[email protected](code or a or b)
begin
case(code)
2'b00: my_and(a,b,c);
/*呼叫任務my_and,需注意埠列表的順序應與任務定義中的一致,這裡的a,b,c
分別對應任務定義中的a,b,out */
2'b01: c=a|b; //或
2'b10: c=a-b; //相減
2'b11: c=a+b; //相加
endcase
end
endmodule
【例6.3 】測試程式
`include "alutask.v"
module alu_tp;
reg[3:0] a,b;
reg[1:0] code;
wire[4:0] c;
parameter DELY = 100;
alutask ADD(code,a,b,c); //呼叫被測試模組
initial begin
code=4'd0; a= 4'b0000; b= 4'b1111;
#DELY code=4'd0; a= 4'b0111; b= 4'b1101;
#DELY code=4'd1; a= 4'b0001; b= 4'b0011;
#DELY code=4'd2; a= 4'b1001; b= 4'b0011;
#DELY code=4'd3; a= 4'b0011; b= 4'b0001;
#DELY code=4'd3; a= 4'b0111; b= 4'b1001;
#DELY $finish;
end
initial $monitor($time,,,"code=%b a=%b b=%b c=%b", code,a,b,c);
endmodule
【例6.4 】函式
function[7:0] get0;
input[7:0] x;
reg[7:0] count;
integer i;
begin
count=0;
for (i=0;i<=7;i=i+1)
if (x[i]=1'b0) count=count+1;
get0=count;
end
endfunction
【例6.5 】用函式和case 語句描述的編碼器(不含優先順序)
module code_83(din,dout);
input[7:0] din;
output[2:0] dout;
function[2:0] code; //函式定義
input[7:0] din; //函式只有輸入,輸出為函式名本身
casex (din)
8'b1xxx_xxxx : code = 3'h7;
8'b01xx_xxxx : code = 3'h6;
8'b001x_xxxx : code = 3'h5;
8'b0001_xxxx : code = 3'h4;
8'b0000_1xxx : code = 3'h3;
8'b0000_01xx : code = 3'h2;
8'b0000_001x : code = 3'h1;
8'b0000_000x : code = 3'h0;
default: code = 3'hx;
endcase
endfunction
assign dout = code(din) ; //函式呼叫
endmodule
【例6.6 】階乘運算函式
module funct(clk,n,result,reset);
output[31:0] result;
input[3:0] n;
input reset,clk;
reg[31:0] result;
always @(posedge clk) //在clk的上升沿時執行運算
begin
if(!reset) result<=0; //復位
else begin
result <= 2 * factorial(n); // 呼叫factorial函式
end
end
function[31:0] factorial; //階乘運算函式定義(注意無埠列表)
input[3:0] opa; //函式只能定義輸入端,輸出埠為函式名本身
reg[3:0] i;
begin
factorial = opa ? 1 : 0;
for(i= 2; i <= opa; i = i+1) //該句若要綜合通過,opa應賦具體的數值
factorial = i* factorial; //階乘運算
end
endfunction
endmodule
【例6.7 】測試程式
`define clk_cycle 50
`include "funct.v"
module funct_tp;
reg[3:0] n;
reg reset,clk;
wire[31:0] result;
initial //定義激勵向量
begin
n=0; reset=1; clk=0;
for(n=0;n<=15;n=n+1)
#100 n=n;
end
initial $monitor($time,,,"n=%d result=%d",n,result);
//定義輸出顯示格式
always # `clk_cycle clk=~clk; //產生時鐘訊號
funct funct_try(.clk(clk),.n(n),.result(result),.reset(reset));
//呼叫被測試模組
endmodule
【例6.8 】順序執行模組1
module serial1(q,a,clk);
output q,a;
input clk;
reg q,a;
always @(posedge clk)
begin
q=~q;
a=~q;
end
endmodule
【例6.9 】順序執行模組2
module serial2(q,a,clk);
output q,a;
input clk;
reg q,a;
always @(posedge clk)
begin
a=~q;
q=~q;
end
endmodule
【例6.10 】並行執行模組1
module paral1(q,a,clk);
output q,a;
input clk;
reg q,a;
always @(posedge clk)
begin
q=~q;
end
always @(posedge clk)
begin
a=~q;
end
endmodule
【例6.11 】並行執行模組2
module paral2(q,a,clk);
output q,a;
input clk;
reg q,a;
always @(posedge clk)
begin
a=~q;
end
always @(posedge clk)
begin
q=~q;
end
endmodule
【例7.3 】行為描述方式實現的4 位計數器
module count4(clk,clr,out);
input clk,clr;
output[3:0] out;
reg[3:0] out;
always @(posedge clk or posedge clr)
begin
if (clr) out<=0;
else out<=out+1;
end
endmodule
【例7.6 】門級結構描述的2 選1MUX
module mux2_1a(out,a,b,sel);
output out;
input a,b,sel;
not (sel_,sel);
and (a1,a,sel_),
(a2,b,sel);
or (out,a1,a2);
endmodule
【例7.7 】行為描述的2 選1MUX
module mux2_1b(out,a,b,sel);
output out;
input a,b,sel;
reg out;
always @(a or b or sel)
begin
if(sel) out = b;
else out = a;
end
endmodule
【例7.8 】資料流描述的2 選1MUX
module MUX2_1c(out,a,b,sel);
output out;
input a,b,sel;
assign out = sel ? b : a;
endmodule
【例7.9 】呼叫門元件實現的1 位半加器
module half_add1(a,b,sum,cout);
input a,b;
output sum,cout;
and (cout,a,b);
xor (sum,a,b);
endmodule
【例7.10 】資料流方式描述的1 位半加器
module half_add2(a,b,sum,cout);
input a,b;
output sum,cout;
assign sum=a^b;
assign cout=a&b;
endmodule
【例7.11 】採用行為描述的1 位半加器
module half_add3(a,b,sum,cout);
input a,b;
output sum,cout;
reg sum,cout;
always @(a or b)
begin
case ({a,b}) //真值表描述
2'b00: begin sum=0; cout=0; end
2'b01: begin sum=1; cout=0; end
2'b10: begin sum=1; cout=0; end
2'b11: begin sum=0; cout=1; end
endcase
end
endmodule
【例7.12 】採用行為描述的1 位半加器
module half_add4(a,b,sum,cout);
input a,b;
output sum,cout;
reg sum,cout;
always @(a or b)
begin
sum= a^b;
cout=a&b;
end
endmodule
【例7.13 】呼叫門元件實現的1 位全加器
module full_add1(a,b,cin,sum,cout);
input a,b,cin;
output sum,cout;
wire s1,m1,m2,m3;
and (m1,a,b),
(m2,b,cin),
(m3,a,cin);
xor (s1,a,b),
(sum,s1,cin);
or (cout,m1,m2,m3);
endmodule
【例7.14 】資料流描述的1 位全加器
module full_add2(a,b,cin,sum,cout);
input a,b,cin;
output sum,cout;
assign sum = a ^ b ^ cin;
assign cout = (a & b)|(b & cin)|(cin & a);
endmodule
【例7.15 】1 位全加器
module full_add3(a,b,cin,sum,cout);
input a,b,cin;
output sum,cout;
assign {cout,sum}=a+b+cin;
endmodule
【例7.16 】行為描述的1 位全加器
module full_add4(a,b,cin,sum,cout);
input a,b,cin;
output sum,cout;
reg sum,cout; //在always塊中被賦值的變數應定義為reg型
reg m1,m2,m3;
always @(a or b or cin)
begin
sum = (a ^ b) ^ cin;
m1 = a & b;
m2 = b & cin;
m3 = a & cin;
cout = (m1|m2)|m3;
end
endmodule
【例7.17 】混合描述的1 位全加器
module full_add5(a,b,cin,sum,cout);
input a,b,cin;
output sum,cout;
reg cout,m1,m2,m3; //在always塊中被賦值的變數應定義為reg型
wire s1;
xor x1(s1,a,b); //呼叫門元件
always @(a or b or cin) //always 塊語句
begin
m1 = a & b;
m2 = b & cin;
m3 = a & cin;
cout = (m1| m2) | m3;
end
assign sum = s1 ^ cin; //assign 持續賦值語句
endmodule
【例7.18 】結構描述的4 位級連全加器
`include "full_add1.v"
module add4_1(sum,cout,a,b,cin);
output[3:0] sum;
output cout;
input[3:0] a,b;
input cin;
full_add1 f0(a[0],b[0],cin,sum[0],cin1); //級連描述
full_add1 f1(a[1],b[1],cin1,sum[1],cin2);
full_add1 f2(a[2],b[2],cin2,sum[2],cin3);
full_add1 f3(a[3],b[3],cin3,sum[3],cout);
endmodule
【例7.19 】資料流描述的4 位全加器
module add4_2(cout,sum,a,b,cin);
output[3:0] sum;
output cout;
input[3:0] a,b;
input cin;
assign {cout,sum}=a+b+cin;
endmodule
【例7.20 】行為描述的4 位全加器
module add4_3(cout,sum,a,b,cin);
output[3:0] sum;
output cout;
input[3:0] a,b;
input cin;
reg[3:0] sum;
reg cout;
always @(a or b or cin)
begin
{cout,sum}=a+b+cin;
end
endmodule
【例8.2】$random 函式的使用
`timescale 10ns/1ns
module random_tp;
integer data;
integer i;
parameter delay=10;
initial $monitor($time,,,"data=%b",data);
initial begin
for(i=0; i<=100; i=i+1)
#delay data=$random; //每次產生一個隨機數
end
endmodule
primitive carry_udp(cout,cin,a,b);
input cin,a,b;
output cout;
table
//cin a b : cout //真值表
0 0 0 : 0;
0 1 0 : 0;
0 0 1 : 0;
0 1 1 : 1;
1 0 0 : 0;
1 0 1 : 1;
1 1 0 : 1;
1 1 1 : 1;
endtable
endprimitive
【例8.15 】用always 過程塊產生兩個時鐘訊號
module test2;
reg clk1,clk2;
parameter CYCLE = 100;
always
begin
{clk1,clk2} = 2'b10;
#(CYCLE/4) {clk1,clk2} = 2'b01;
#(CYCLE/4) {clk1,clk2} = 2'b11;
#(CYCLE/4) {clk1,clk2} = 2'b00;
#(CYCLE/4) {clk1,clk2} = 2'b10;
end
initial $monitor($time,,,"clk1=%b clk2=%b",clk1,clk2);
endmodule
【例9.1 】基本閘電路的幾種描述方法
(1)門級結構描述
module gate1(F,A,B,C,D);
input A,B,C,D;
output F;
nand(F1,A,B); //呼叫門元件
and(F2,B,C,D);
or(F,F1,F2);
endmodule
(2)資料流描述
module gate2(F,A,B,C,D);
input A,B,C,D;
output F;
assign F=(A&B)|(B&C&D); //assign 持續賦值
endmodule
(3)行為描述
module gate3(F,A,B,C,D);
input A,B,C,D;
output F;
reg F;
always @(A or B or C or D) //過程賦值
begin
F=(A&B)|(B&C&D);
end
endmodule
【例9.2 】用bufif1 關鍵字描述的三態門
module tri_1(in,en,out);
input in,en;
output out;
tri out;
bufif1 b1(out,in,en); //注意三態門埠的排列順序
endmodule
【例9.3 】用assign 語句描述的三態門
module tri_2(out,in,en);
output out;
input in,en;
assign out = en ? in : 'bz;
//若en=1,則out=in;若en=0,則out為高阻態
endmodule
【例9.4 】三態雙向驅動器
module bidir(tri_inout,out,in,en,b);
inout tri_inout;
output out;
input in,en,b;
assign tri_inout = en ? in : 'bz;
assign out = tri_inout ^ b;
endmodule
【例9.5 】三態雙向驅動器
module bidir2(bidir,en,clk);
inout[7:0] bidir;
input en,clk;
reg[7:0] temp;
assign bidir= en ? temp : 8'bz;
always @(posedge clk)
begin
if(en) temp=bidir;
else temp=temp+1;
end
endmodule
【例9.6 】3-8 譯碼器
module decoder_38(out,in);
output[7:0] out;
input[2:0] in;
reg[7:0] out;
always @(in)
begin
case(in)
3'd0: out=8'b11111110;
3'd1: out=8'b11111101;
3'd2: out=8'b11111011;
3'd3: out=8'b11110111;
3'd4: out=8'b11101111;
3'd5: out=8'b11011111;
3'd6: out=8'b10111111;
3'd7: out=8'b01111111;
endcase
end
endmodule
【例9.7 】8-3 優先編碼器
module encoder8_3(none_on,outcode,a,b,c,d,e,f,g,h);
output none_on;
output[2:0] outcode;
input a,b,c,d,e,f,g,h;
reg[3:0] outtemp;
assign {none_on,outcode}=outtemp;
always @(a or b or c or d or e or f or g or h)
begin
if(h) outtemp=4'b0111;
else if(g) outtemp=4'b0110;
else if(f) outtemp=4'b0101;
else if(e) outtemp=4'b0100;
else if(d) outtemp=4'b0011;
else if(c) outtemp=4'b0010;
else if(b) outtemp=4'b0001;
else if(a) outtemp=4'b0000;
else outtemp=4'b1000;
end
endmodule
【例9.8 】用函式定義的8-3 優先編碼器
module code_83(din, dout);
input[7:0] din;
output[2:0] dout;
function[2:0] code; //函式定義
input[7:0] din; //函式只有輸入埠,輸出為函式名本身
if (din[7]) code = 3'd7;
else if (din[6]) code = 3'd6;
else if (din[5]) code = 3'd5;
else if (din[4]) code = 3'd4;
else if (din[3]) code = 3'd3;
else if (din[2]) code = 3'd2;
else if (din[1]) code = 3'd1;
else code = 3'd0;
endfunction
assign dout = code(din); //函式呼叫
endmodule
【例9.10 】奇偶校驗位產生器
module parity(even_bit,odd_bit,input_bus);
output even_bit,odd_bit;
input[7:0] input_bus;
assign odd_bit = ^ input_bus; //產生奇校驗位
assign even_bit = ~odd_bit; //產生偶校驗位
endmodule
【例9.11 】用if-else 語句描述的4 選1 MUX
module mux_if(out,in0,in1,in2,in3,sel);
output out;
input in0,in1,in2,in3;
input[1:0] sel;
reg out;
always @(in0 or in1 or in2 or in3 or sel)
begin
if(sel==2'b00) out=in0;
else if(sel==2'b01) out=in1;
else if(sel==2'b10) out=in2;
else out=in3;
end
endmodule
【例9.12 】用case 語句描述的4 選1 MUX
module mux_case(out,in0,in1,in2,in3,sel);
output out;
input in0,in1,in2,in3;
input[1:0] sel;
reg out;
always @(in0 or in1 or in2 or in3 or sel)
begin
case(sel)
2'b00: out=in0;
2'b01: out=in1;
2'b10: out=in2;
default: out=in3;
endcase
end
endmodule
【例9.13 】用組合電路實現的ROM
module rom(addr,data);
input[3:0] addr;
output[7:0] data;
function[7:0] romout;
input[3:0] addr;
case(addr)
0 : romout = 0;
1 : romout = 1;
2 : romout = 4;
3 : romout = 9;
4 : romout = 16;
5 : romout = 25;
6 : romout = 36;
7 : romout = 49;
8 : romout = 64;
9 : romout = 81;
10 : romout = 100;
11 : romout = 121;
12 : romout = 144;
13 : romout = 169;
14 : romout = 196;
15 : romout = 225;
default : romout = 8'hxx;
endcase
endfunction
assign data = romout(addr);
endmodule
【例9.14 】基本D 觸發器
module DFF(Q,D,CLK);
output Q;
input D,CLK;
reg Q;
always @(posedge CLK)
begin
Q <= D;
end
endmodule
【例9.15 】帶非同步清0、非同步置1 的D 觸發器
module DFF1(q,qn,d,clk,set,reset);
input d,clk,set,reset;
output q,qn;
reg q,qn;
always @(posedge clk or negedge set or negedge reset)
begin
if (!reset) begin
q <= 0; //非同步清0,低電平有效
qn <= 1;
end
else if (!set) begin
q <= 1; //非同步置1,低電平有效
qn <= 0;
end
else begin
q <= d;
qn <= ~d;
end
end
endmodule
【例9.16 】帶同步清0、同步置1 的D 觸發器
module DFF2(q,qn,d,clk,set,reset);
input d,clk,set,reset;
output q,qn;
reg q,qn;
always @(posedge clk)
begin
if (reset) begin
q <= 0;qn <= 1; //同步清0,高電平有效