久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Verilog的135個(gè)經(jīng)典設(shè)計(jì)實(shí)例

 春華_秋實(shí) 2011-10-16
    王金明:《Verilog HDL程序設(shè)計(jì)教程》【例3.1】4位全加器
module adder4(cout,sum,ina,inb,cin);
output[3:0] sum;
output cout;
input[3:0] ina,inb;
input cin;
assign {cout,sum}=ina+inb+cin;
endmodule
【例3.2】4位計(jì)數(shù)器
module count4(out,reset,clk);
output[3:0] out;
input reset,clk;
reg[3:0] out;
always @(posedge clk)
    begin
    if (reset)  out<=0;           //同步復(fù)位
    else         out<=out+1;     //計(jì)數(shù)
    end
endmodule
【例3.3】4位全加器的仿真程序
`timescale 1ns/1ns
`include "adder4.v"
module adder_tp;                   //測(cè)試模塊的名字
reg[3:0] a,b;      //測(cè)試輸入信號(hào)定義為reg型
reg cin;
wire[3:0] sum;       //測(cè)試輸出信號(hào)定義為wire型
wire cout;
integer i,j;
adder4 adder(sum,cout,a,b,cin);  //調(diào)用測(cè)試對(duì)象
always #5 cin=~cin;       //設(shè)定cin的取值
initial
begin
a=0;b=0;cin=0;
for(i=1;i<16;i=i+1)
#10   a=i;      //設(shè)定a的取值
end
    - 1 - 程序文本
   initial
   begin
   for(j=1;j<16;j=j+1)
   #10   b=j;      //設(shè)定b的取值
   end
   initial       //定義結(jié)果顯示格式
   begin
   $monitor($time,,,"%d + %d + %b={%b,%d}",a,b,cin,cout,sum);
   #160  $finish;
   end
   endmodule
    【例3.4】4位計(jì)數(shù)器的仿真程序
   `timescale 1ns/1ns
   `include "count4.v"
   module coun4_tp;
   reg clk,reset;       //測(cè)試輸入信號(hào)定義為reg型
   wire[3:0] out;             //測(cè)試輸出信號(hào)定義為wire型
   parameter DELY=100;
   count4 mycount(out,reset,clk);       //調(diào)用測(cè)試對(duì)象
   always #(DELY/2) clk = ~clk;      //產(chǎn)生時(shí)鐘波形
   initial
    begin       //激勵(lì)信號(hào)定義
    clk =0; reset=0;
    #DELY    reset=1;
    #DELY    reset=0;
    #(DELY*20) $finish;
    end
   //定義結(jié)果顯示格式
   initial $monitor($time,,,"clk=%d reset=%d out=%d", clk, reset,out);
   endmodule
    【例3.5】“與-或-非”門電路
    module AOI(A,B,C,D,F);     //模塊名為AOI(端口列表A,,B,C,,D,,F(xiàn))
    input A,B,C,D;     //模塊的輸入端口為A,,B,C,,D
    output F;     //模塊的輸出端口為F
- 2 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》wire A,B,C,D,F;                    //定義信號(hào)的數(shù)據(jù)類型
    assign  F= ~((A&B)|(C&D));  //邏輯功能描述
endmodule
【例5.1】用case語句描述的4選1數(shù)據(jù)選擇器
module mux4_1(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)    //敏感信號(hào)列表
   case(sel)
    2'b00:  out=in0;
    2'b01:  out=in1;
    2'b10:  out=in2;
    2'b11:  out=in3;
    default: out=2'bx;
   endcase
endmodule
【例5.2】同步置數(shù),、同步清零的計(jì)數(shù)器
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上升沿觸發(fā)
    begin
    if (!reset)     out = 8'h00;     //同步清0,低電平有效
    else if (load)   out = data;      //同步預(yù)置
         else     out = out + 1;     //計(jì)數(shù)
    end
 endmodule
【例5.3】用always過程語句描述的簡單算術(shù)邏輯單元
`define add 3'd0
`define minus 3'd1
`define band 3'd2
`define bor 3'd3
`define bnot 3'd4
    - 3 - 程序文本
   module alu(out,opcode,a,b);
   output[7:0] out;
   reg[7:0] out;
   input[2:0] opcode;       //操作碼
   input[7:0] a,b;      //操作數(shù)
   always@(opcode or a or b)      //電平敏感的always塊
    begin
    case(opcode)
    `add: out = a+b;          //加操作
    `minus: out = a-b;         //減操作
    `band: out = a&b;         //求與
    `bor: out = a|b;            //求或
    `bnot: out=~a;         //求反
    default: out=8'hx;         //未收到指令時(shí),,輸出任意態(tài)
    endcase
    end
   endmodule
    【例5.4】用initial過程語句對(duì)測(cè)試變量A,、B、C賦值
   `timescale 1ns/1ns
   module test;
   reg A,B,C;
   initial
    begin
    A = 0;  B = 1;  C = 0;
    #50    A = 1;  B = 0;
    #50    A = 0;  C = 1;
    #50    B = 1;
    #50    B = 0;  C = 0;
    #50    $finish ;
    end
   endmodule
    【例5.5】用begin-end串行塊產(chǎn)生信號(hào)波形
   `timescale 10ns/1ns
   module wave1;
   reg wave;
   parameter cycle=10;
   initial
    begin
- 4 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    wave=0;
   #(cycle/2)  wave=1;
   #(cycle/2)  wave=0;
   #(cycle/2)  wave=1;
   #(cycle/2)  wave=0;
   #(cycle/2)  wave=1;
   #(cycle/2)  $finish ;
  end
initial $monitor($time,,,"wave=%b",wave);
endmodule
【例5.6】用fork-join并行塊產(chǎn)生信號(hào)波形
`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】持續(xù)賦值方式定義的2選1多路選擇器
module MUX21_1(out,a,b,sel);
input a,b,sel;
output out;
assign out=(sel==0)?a:b;
    //持續(xù)賦值,,如果sel為0,,則out=a ;否則out=b
endmodule
【例5.8】阻塞賦值方式定義的2選1多路選擇器
module MUX21_2(out,a,b,sel);
input a,b,sel;
    - 5 - 程序文本
    output out;
    reg out;
    always@(a or b or sel)
    begin
    if(sel==0) out=a;         //阻塞賦值
    else        out=b;
    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.11】模為60的BCD碼加法計(jì)數(shù)器
    module count60(qout,cout,data,load,cin,reset,clk);
    output[7:0] qout;
    output cout;
    input[7:0] data;
    input load,cin,clk,reset;
    reg[7:0] qout;
    always @(posedge clk)     //clk上升沿時(shí)刻計(jì)數(shù)- 6 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》begin
    if (reset)     qout<=0;     //同步復(fù)位
    else  if(load)     qout<=data;      //同步置數(shù)
          else  if(cin)
    begin
    if(qout[3:0]==9)     //低位是否為9,,是則
    begin
    qout[3:0]<=0;     //回0,,并判斷高位是否為5
    if (qout[7:4]==5)  qout[7:4]<=0;
    else
    qout[7:4]<=qout[7:4]+1;      //高位不為5,則加1
    end
    else     //低位不為9,,則加1
    qout[3:0]<=qout[3:0]+1;
    end
 end
assign cout=((qout==8'h59)&cin)?1:0;     //產(chǎn)生進(jìn)位輸出信號(hào)
endmodule
【例5.12】BCD碼—七段數(shù)碼管顯示譯碼器
module decode4_7(decodeout,indec);
output[6:0] decodeout;
input[3:0] indec;
reg[6:0] decodeout;
always @(indec)
 begin
    case(indec)             //用case語句進(jìn)行譯碼
    4'd0:decodeout=7'b1111110;
    4'd1:decodeout=7'b0110000;
    4'd2:decodeout=7'b1101101;
    4'd3:decodeout=7'b1111001;
    4'd4:decodeout=7'b0110011;
    4'd5:decodeout=7'b1011011;
    4'd6:decodeout=7'b1011111;
    4'd7:decodeout=7'b1110000;
    4'd8:decodeout=7'b1111111;
    4'd9:decodeout=7'b1111011;
    default: decodeout=7'bx;
    endcase
 end
    - 7 - 程序文本
    endmodule
    【例5.13】用casez描述的數(shù)據(jù)選擇器
    module mux_casez(out,a,b,c,d,select);
    output out;
    input a,b,c,d;
    input[3:0] select;
    reg out;
   always @(select or a or b or c or d)
    begin
    casez(select)
    4'b???1: out = a;
    4'b??1?: out = b;
    4'b?1??: out = c;
    4'b1???: out = d;
    endcase
    end
   endmodule
    【例5.14】隱含鎖存器舉例
    module buried_ff(c,b,a);
    output c;
    input b,a;
    reg c;
    always @(a or b)
    begin
    if((b==1)&&(a==1))  c=a&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;
- 8 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    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
【例5.16】用for語句實(shí)現(xiàn)2個(gè)8位數(shù)相乘
module mult_for(outcome,a,b);
parameter size=8;
input[size:1] a,b;     //兩個(gè)操作數(shù)
output[2*size:1] outcome;     //結(jié)果
reg[2*size:1] outcome;
integer i;
always @(a or b)
    begin
    outcome=0;
    for(i=1; i<=size; i=i+1)      //for語句
    if(b[i])  outcome=outcome +(a << (i-1));
    end
endmodule
【例5.17】用repeat實(shí)現(xiàn)8位二進(jìn)制數(shù)的乘法
module mult_repeat(outcome,a,b);
parameter size=8;
input[size:1] a,b;
output[2*size:1] outcome;
reg[2*size:1] temp_a,outcome;
reg[size:1] temp_b;
always @(a or b)
 begin
    outcome=0;
    temp_a=a;
    temp_b=b;
    repeat(size)          //repeat語句,size為循環(huán)次數(shù)
    begin
    if(temp_b[1])        //如果temp_b的最低位為1,,就執(zhí)行下面的加法
    outcome=outcome+temp_a;
    temp_a=temp_a<<1;        //操作數(shù)a左移一位
    - 9 - 程序文本
    temp_b=temp_b>>1;        //操作數(shù)b右移一位
    end
    end
    endmodule
    【例5.18】同一循環(huán)的不同實(shí)現(xiàn)方式
   module loop1;              //方式1
   integer i;
   initial
    for(i=0;i<4;i=i+1)     //for語句
    begin
    $display(“i=%h”,i);
    end
   endmodule
   module loop2;     //方式2
   integer i;
   initial begin
    i=0;
    while(i<4)       //while語句
    begin
    $display ("i=%h",i);
    i=i+1;
    end
    end
   endmodule
   module loop3;     //方式3
   integer i;
   initial begin
    i=0;
    repeat(4)     //repeat語句
    begin
    $display ("i=%h",i);
    i=i+1;
    end
    end
   endmodule
    【例5.19】使用了`include語句的16位加法器
- 10 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》`include "adder.v"
module adder16(cout,sum,a,b,cin);
output cout;
parameter my_size=16;
output[my_size-1:0] sum;
input[my_size-1:0] a,b;
input cin;
adder my_adder(cout,sum,a,b,cin);        //調(diào)用adder模塊
endmodule
//下面是adder模塊代碼
module adder(cout,sum,a,b,cin);
parameter size=16;
output cout;
output[size-1:0] sum;
input cin;
input[size-1:0] a,b;
    assign {cout,sum}=a+b+cin;
endmodule
【例5.20】條件編譯舉例
module compile(out,A,B);
output out;
input A,B;
`ifdef  add                         //宏名為add
    assign out=A+B;
`else
    assign out=A-B;
`endif
endmodule
【例6.1】加法計(jì)數(shù)器中的進(jìn)程
module count(data,clk,reset,load,cout,qout);
output cout;
output[3:0] qout;
reg[3:0] qout;
input[3:0] data;
input clk,reset,load;
    - 11 - 程序文本
    always @(posedge clk)        //進(jìn)程1,,always過程塊
    begin
    if (!reset)     qout= 4'h00;     //同步清0,低電平有效
    else if (load)   qout= data;      //同步預(yù)置
    else         qout=qout + 1;     //加法計(jì)數(shù)
    end
    assign cout=(qout==4'hf)?1:0;     //進(jìn)程2,,用持續(xù)賦值產(chǎn)生進(jìn)位信號(hào)
    endmodule
    【例6.2】任務(wù)舉例
   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;                     //任務(wù)定義,,注意無端口列表
   input[3:0] a,b;                 //a,b,out名稱的作用域范圍為task任務(wù)內(nèi)部
   output[4:0] out;
   integer i;
    begin
    for(i=3;i>=0;i=i-1)
    out[i]=a[i]&b[i];            //按位與
    end
   endtask
   always@(code or a or b)
    begin
    case(code)
    2'b00: my_and(a,b,c);
    /* 用任務(wù)my_and,需注意端口列表的順序應(yīng)與任務(wù)定義中的一致,,這里的a,b,c分別對(duì)應(yīng)任務(wù)定義中的a,b,out */
    2'b01: c=a|b;               //或
    2'b10: c=a-b;              //相減
    2'b11: c=a+b;         //相加
    endcase
    end
   endmodule
- 12 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》【例6.3】測(cè)試程序
`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);                 //調(diào)用被測(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】函數(shù)
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】用函數(shù)和case語句描述的編碼器(不含優(yōu)先順序)
module code_83(din,dout);
input[7:0] din;
output[2:0] dout;
    - 13 - 程序文本
    function[2:0] code;                   //函數(shù)定義
    input[7:0] din;                     //函數(shù)只有輸入,,輸出為函數(shù)名本身
    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) ;           //函數(shù)調(diào)用
    endmodule
    【例6.6】階乘運(yùn)算函數(shù)
   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的上升沿時(shí)執(zhí)行運(yùn)算
    begin
    if(!reset)  result<=0;         //復(fù)位
    else  begin
    result <= 2 * factorial(n); //調(diào)用factorial函數(shù)
    end
    end
   function[31:0] factorial;         //階乘運(yùn)算函數(shù)定義(注意無端口列表)
   input[3:0] opa;              //函數(shù)只能定義輸入端,輸出端口為函數(shù)名本身
   reg[3:0] i;
    begin
    factorial = opa ? 1 : 0;
    for(i= 2; i <= opa; i = i+1)      //該句若要綜合通過,,opa應(yīng)賦具體的數(shù)值
    factorial = i* factorial;         //階乘運(yùn)算
    end
- 14 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》endfunction
endmodule
【例6.7】測(cè)試程序
`define clk_cycle  50
`include "funct.v"
module funct_tp;
reg[3:0] n;
reg reset,clk;
wire[31:0] result;
   initial                       //定義激勵(lì)向量
   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;           //產(chǎn)生時(shí)鐘信號(hào)
funct funct_try(.clk(clk),.n(n),.result(result),.reset(reset));
    //調(diào)用被測(cè)試模塊
endmodule
【例6.8】順序執(zhí)行模塊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】順序執(zhí)行模塊2
module serial2(q,a,clk);
output q,a;
    - 15 - 程序文本
    input clk;
    reg q,a;
    always @(posedge clk)
    begin
    a=~q;
    q=~q;
    end
    endmodule
    【例6.10】并行執(zhí)行模塊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】并行執(zhí)行模塊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.1】調(diào)用門元件實(shí)現(xiàn)的4選1 MUX- 16 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》module mux4_1a(out,in1,in2,in3,in4,cntrl1,cntrl2);
output out;
input in1,in2,in3,in4,cntrl1,cntrl2;
wire notcntrl1,notcntrl2,w,x,y,z;
not  notcntrl1,cntrl2),
    (notcntrl2,cntrl2);
and  (w,in1,notcntrl1,notcntrl2),
    (x,in2,notcntrl1,cntrl2),
    (y,in3,cntrl1,notcntrl2),
    (z,in4,cntrl1,cntrl2);
or  (out,w,x,y,z);
endmodule
【例7.2】用case語句描述的4選1 MUX
module mux4_1b(out,in1,in2,in3,in4,cntrl1,cntrl2);
output out;
input in1,in2,in3,in4,cntrl1,cntrl2;
reg out;
always@(in1 or in2 or in3 or in4 or cntrl1 or cntrl2)
    case({cntrl1,cntrl2})
    2'b00:out=in1;
    2'b01:out=in2;
    2'b10:out=in3;
    2'b11:out=in4;
    default:out=2'bx;
    endcase
endmodule
【例7.3】行為描述方式實(shí)現(xiàn)的4位計(jì)數(shù)器
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
    - 17 - 程序文本
    【例7.4】數(shù)據(jù)流方式描述的4選1 MUX
    module mux4_1c(out,in1,in2,in3,in4,cntrl1,cntrl2);
    output out;
    input in1,in2,in3,in4,cntrl1,cntrl2;
    assign out=(in1 & ~cntrl1 & ~cntrl2)|(in2 & ~cntrl1 & cntrl2)|
    (in3 & cntrl1 & ~cntrl2)|(in4 & cntrl1 & cntrl2);
    endmodule
    【例7.5】用條件運(yùn)算符描述的4選1 MUX
    module mux4_1d(out,in1,in2,in3,in4,cntrl1,cntrl2);
    output out;
    input in1,in2,in3,in4,cntrl1,cntrl2;
    assign out=cntrl1 ? (cntrl2 ? in4:in3):(cntrl2 ? in2:in1);
    endmodule
    【例7.6】門級(jí)結(jié)構(gòu)描述的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】數(shù)據(jù)流描述的2選1MUX
    module MUX2_1c(out,a,b,sel);
    output out;
- 18 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》input a,b,sel;
    assign out = sel ? b : a;
endmodule
【例7.9】調(diào)用門元件實(shí)現(xiàn)的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】數(shù)據(jù)流方式描述的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;
    - 19 - 程序文本
    reg sum,cout;
    always @(a or b)
    begin
    sum= a^b;
    cout=a&b;
    end
    endmodule
    【例7.13】調(diào)用門元件實(shí)現(xiàn)的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】數(shù)據(jù)流描述的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;
- 20 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》reg sum,cout;     //在always塊中被賦值的變量應(yīng)定義為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塊中被賦值的變量應(yīng)定義為reg型wire s1;
xor x1(s1,a,b);            //調(diào)用門元件
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持續(xù)賦值語句
endmodule
【例7.18】結(jié)構(gòu)描述的4位級(jí)連全加器
`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);     //級(jí)連描述
full_add1 f1(a[1],b[1],cin1,sum[1],cin2);
full_add1 f2(a[2],b[2],cin2,sum[2],cin3);
    - 21 - 程序文本
   full_add1 f3(a[3],b[3],cin3,sum[3],cout);
   endmodule
    【例7.19】數(shù)據(jù)流描述的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.1】$time與$realtime的區(qū)別
    `timescale 10ns/1ns
    module time_dif;
    reg ts;
    parameter delay=2.6;
    initial
    begin
    #delay  ts=1;
    #delay  ts=0;
    #delay  ts=1;
    #delay  ts=0;
    end
    initial  $monitor($time,,,"ts=%b",ts);   //使用函數(shù)$time- 22 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》endmodule
【例8.2】$random函數(shù)的使用
`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;         //每次產(chǎn)生一個(gè)隨機(jī)數(shù)
    end
endmodule
【例8.3】1位全加器進(jìn)位輸出UDP元件
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.4】包含x態(tài)輸入的1位全加器進(jìn)位輸出UDP元件
primitive carry_udpx1(cout,cin,a,b);
input cin,a,b;
output cout;
    table
    // cin  a  b  :  cout     //真值表
    0   0   0  :    0;
    - 23 - 程序文本
    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;
    0   0   x  :    0;     //只要有兩個(gè)輸入為0,,則進(jìn)位輸出肯定為0
    0   x   0  :    0;
    x   0   0  :    0;
    1   1   x  :    1;     //只要有兩個(gè)輸入為1,則進(jìn)位輸出肯定為1
    1   x   1  :    1;
    x   1   1  :    1;
    endtable
    endprimitive
    【例8.5】用簡縮符“,?”表述的1位全加器進(jìn)位輸出UDP元件
   primitive carry_udpx2(cout,cin,a,b);
   input cin,a,b;
   output cout;
    table
    // cin  a  b :  cout           //真值表
       0   0  :    0;      //只要有兩個(gè)輸入為0,,則進(jìn)位輸出肯定為0
    0   ?   0  :    0;
    0   0   ?  :    0;
       1   1  :    1;     //只要有兩個(gè)輸入為1,則進(jìn)位輸出肯定為1
    1   ?   1  :    1;
    1   1   ?  :    1;
    endtable
    endprimitive
    【例8.6】3選1多路選擇器UDP元件
    primitive mux31(Y,in0,in1,in2,s2,s1);
    input in0,in1,in2,s2,s1;
    output Y;
    table
    //in0 in1 in2 s2 s1 : Y
    0   ?   ?    0   0  :  0;     //當(dāng)s2s1=00時(shí),,Y=in0
    1   ?   ?    0   0  :  1;
       0   ?    0   1  :  0;     //當(dāng)s2s1=01時(shí),,Y=in1
- 24 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
       1   ?    0   1  :  1;
          0    1   ?  :  0;     //當(dāng)s2s1=1?時(shí),Y=in2
          1    1   ?  :  1;
    0   0   ?    0   ?  :  0;
    1   1   ?    0   ?  :  1;
    0   ?   0    ?   0  :  0;
    1   ?   1    ?   0  :  1;
       0   0    ?   1  :  0;
       1   1    ?   1  :  1;
    endtable
endprimitive
【例8.7】電平敏感的1位數(shù)據(jù)鎖存器UDP元件
primitive latch(Q,clk,reset,D);
input clk,reset,D;
output Q;
reg Q;
initial Q = 1'b1;    //初始化
    table
    // clk reset D : state : Q
       1   ?  : ? : 0 ;  //reset=1,,則不管其他端口為什么值,,輸出都為0
    0   0   0  : ? : 0 ;  //clk=0,鎖存器把D端的輸入值輸出
    0   0   1  : ? : 1 ;
    1   0   ?  : ? : - ;   //clk=1,,鎖存器的輸出保持原值,,用符號(hào)“-”表示
    endtable
endprimitive
【例8.8】上升沿觸發(fā)的D觸發(fā)器UDP元件
primitive DFF(Q,D,clk);
output Q;
input D,clk;
reg Q;
   table
   //clk  D : state : Q
    (01)  0   : ? :   0;     //上升沿到來,輸出Q=D
    (01)  1   : ? :   1;
    (0x)  1   : 1 :   1;
    (0x)  0   : 0 :   0;
    (?0)  ?   : ? :   -;     //沒有上升沿到來,,輸出Q保持原值
       (??)  : ? :   - ;     //時(shí)鐘不變,,輸出也不變
    - 25 - 程序文本
    endtable
   endprimitive
    【例8.9】帶異步置1和異步清零的上升沿觸發(fā)的D觸發(fā)器UDP元件
   primitive DFF_UDP(Q,D,clk,clr,set);
   output Q;
   input D,clk,clr,set;
   reg Q;
    table
    // clk  D   clr  et   state : Q
    (01)  1   0   0   : ? :   0;
    (01)  1   0   x   : ? :   0;
            0   x   : 0 :   0;
    (01)  0   0   0   : ? :   1;
    (01)  0   x   0   : ? :   1;
            x   0   : 1 :   1;
    (x1)  1   0   0   : 0 :   0;
    (x1)  0   0   0   : 1 :   1;
    (0x)  1   0   0   : 0 :   0;
    (0x)  0   0   0   : 1 :   1;
            1   ?   : ? :   1;       //異步復(fù)位
            0   1   : ? :   0;       //異步置1
    n     ?   0   0   : ? :   -;
         *   ?   ?   : ? :   -;
            (?0) ?  : ? :   -;
               (?0): ? :   -;
                  : ? :   x;
    endtable
   endprimitive
    【例8.12】延遲定義塊舉例
    module delay(out,a,b,c);
    output out;
    input a,b,c;
    and a1(n1,a,b);
    or o1(out,c,n1);
    specify
    (a=>out)=2;
    (b=>out)=3;
    (c=>out)=1;
- 26 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    endspecify
endmodule
【例8.13】激勵(lì)波形的描述
'timescale 1ns/1ns
module test1;
reg A,B,C;
initial
    begin                    //激勵(lì)波形描述
    A = 0; B = 1; C = 0;
    #100 C = 1;
    #100 A = 1; B = 0;
    #100 A = 0;
    #100 C = 0;
    #100 $finish;
    end
initial $monitor($time,,,"A=%d B=%d C=%d",A,B,C);    //顯示
endmodule
【例8.15】用always過程塊產(chǎn)生兩個(gè)時(shí)鐘信號(hào)
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
【例8.17】存儲(chǔ)器在仿真程序中的應(yīng)用
module ROM(addr,data,oe);
output[7:0] data;      //數(shù)據(jù)信號(hào)
input[14:0] addr;      //地址信號(hào)
input oe;      //讀使能信號(hào),低電平有效
    - 27 - 程序文本
   reg[7:0] mem[0:255];      //存儲(chǔ)器定義
   parameter DELAY = 100;
   assign #DELAY data=(oe==0) ? mem[addr] : 8'hzz;
   initial $readmemh("rom.hex",mem);    //從文件中讀入數(shù)據(jù)
   endmodule
    【例8.18】8位乘法器的仿真程序
   `timescale 10ns/1ns
   module mult_tp;                     //測(cè)試模塊的名字
   reg[7:0] a,b;      //測(cè)試輸入信號(hào)定義為reg型
   wire [15:0] out;      //測(cè)試輸出信號(hào)定義為wire型
   integer i,j;
   mult8 m1(out,a,b);     //調(diào)用測(cè)試對(duì)象
    //激勵(lì)波形設(shè)定
   initial
    begin
    a=0;b=0;
    for(i=1;i<255;i=i+1)
    #10 a=i;
    end
   initial
    begin
    for(j=1;j<255;j=j+1)
    #10 b=j;
    end
   initial       //定義結(jié)果顯示格式
    begin
    $monitor($time,,,"%d * %d= %d",a,b,out);
    #2560  $finish;
    end
   endmodule
   module mult8(out, a, b);      //8位乘法器源代碼
   parameter size=8;
   input[size:1] a,b;     //兩個(gè)操作數(shù)
   output[2*size:1] out;     //結(jié)果
   assign out=a*b;                 //乘法運(yùn)算符- 28 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》endmodule
【例8.19】8位加法器的仿真程序
`timescale 1ns/1ns
module add8_tp;         //仿真模塊無端口列表
reg[7:0] A,B;      //輸入激勵(lì)信號(hào)定義為reg型
reg cin;
wire[7:0] SUM;        //輸出信號(hào)定義為wire型
wire cout;
parameter DELY = 100;
add8  AD1(SUM,cout,A,B,cin);      //調(diào)用測(cè)試對(duì)象
initial begin     //激勵(lì)波形設(shè)定
    A= 8'd0;    B= 8'd0;    cin=1'b0;
#DELY    A= 8'd100;  B= 8'd200;  cin=1'b1;
#DELY    A= 8'd200;  B= 8'd88;
#DELY    A= 8'd210;  B= 8'd18;   cin=1'b0;
#DELY    A= 8'd12;   B= 8'd12;
#DELY    A= 8'd100;  B= 8'd154;
#DELY    A= 8'd255;  B= 8'd255;  cin=1'b1;
#DELY    $finish;
end
//輸出格式定義
initial $monitor($time,,,"%d + %d + %b = {%b, %d}",A,B,cin,cout,SUM);endmodule
module add8(SUM,cout,A,B,cin);     //待測(cè)試的8位加法器模塊
output[7:0] SUM;
output cout;
input[7:0] A,B;
input cin;
assign {cout,SUM}=A+B+cin;
endmodule
【例8.20】2選1多路選擇器的仿真
`timescale 1ns/1ns
module mux_tp;
reg a,b,sel;
wire out;
    - 29 - 程序文本
   MUX2_1 m1(out,a,b,sel);         //調(diào)用待測(cè)試模塊
   initial
   begin
    a=1'b0; b=1'b0; sel=1'b0;
   #5   sel=1'b1;
   #5   a=1'b1;  el=1'b0;
   #5   sel=1'b1;
   #5   a=1'b0; b=1'b1;  el=1'b0;
   #5   sel=1'b1;
   #5   a=1'b1; b=1'b1; sel=1'b0;
   #5   sel=1'b1;
   end
   initial $monitor($time,,,"a=%b b=%b sel=%b out=%b",a,b,sel,out);
   endmodule
   module MUX2_1(out,a,b,sel);         //待測(cè)試的2選1MUX模塊
   input a,b,sel;
   output out;
   not #(0.4,0.3) (sel_,sel);     //#(0.4,0.3)為門延時(shí)
   and #(0.7,0.6) (a1,a,sel_);
   and #(0.7,0.6) (a2,b,sel);
   or #(0.7,0.6) (out,a1,a2);
   endmodule
    【例8.21】8位計(jì)數(shù)器的仿真
   `timescale 10ns/1ns
   module count8_tp;
   reg clk,reset;       //輸入激勵(lì)信號(hào)定義為reg型
   wire[7:0] qout;            //輸出信號(hào)定義為wire型
   parameter DELY=100;
   counter  C1(qout,reset,clk);       //調(diào)用測(cè)試對(duì)象
   always #(DELY/2) clk = ~clk;      //產(chǎn)生時(shí)鐘波形
   initial
   begin      //激勵(lì)波形定義
    clk =0; reset=0;
- 30 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》#DELY   reset=1;
#DELY   reset=0;
#(DELY*300)  $finish;
end
    //結(jié)果顯示
initial $monitor($time,,,"clk=%d reset=%d qout=%d",clk,reset,qout);endmodule
module counter(qout,reset,clk);      //待測(cè)試的8位計(jì)數(shù)器模塊
output[7:0] qout;
input clk,reset;
reg[7:0] qout;
always @(posedge clk)
   begin    if (reset)  qout<=0;
    else     qout<=qout+1;
   end
endmodule
【例9.1】基本門電路的幾種描述方法
(1)門級(jí)結(jié)構(gòu)描述
module gate1(F,A,B,C,D);
input A,B,C,D;
output F;
nand(F1,A,B);     //調(diào)用門元件
and(F2,B,C,D);
or(F,F1,F2);
endmodule
(2)數(shù)據(jù)流描述
module gate2(F,A,B,C,D);
input A,B,C,D;
output F;
assign F=(A&B)|(B&C&D);      //assign持續(xù)賦值
endmodule
(3)行為描述
module gate3(F,A,B,C,D);
input A,B,C,D;
output F;
    - 31 - 程序文本
    reg F;
    always @(A or B or C or D)     //過程賦值
    begin
    F=(A&B)|(B&C&D);
    end
    endmodule
    【例9.2】用bufif1關(guān)鍵字描述的三態(tài)門
   module tri_1(in,en,out);
   input in,en;
   output out;
   tri out;
   bufif1 b1(out,in,en);     //注意三態(tài)門端口的排列順序
   endmodule
    【例9.3】用assign語句描述的三態(tài)門
   module tri_2(out,in,en);
   output out;
   input in,en;
   assign out = en ? in : 'bz;
    //若en=1,,則out=in,;若en=0,則out為高阻態(tài)
    endmodule
    【例9.4】三態(tài)雙向驅(qū)動(dòng)器
   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】三態(tài)雙向驅(qū)動(dòng)器
   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
- 32 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    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優(yōu)先編碼器
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;
    - 33 - 程序文本
    else if(b)      outtemp=4'b0001;
    else if(a)      outtemp=4'b0000;
    else         outtemp=4'b1000;
    end
    endmodule
    【例9.8】用函數(shù)定義的8-3優(yōu)先編碼器
   module code_83(din, dout);
   input[7:0] din;
   output[2:0] dout;
   function[2:0] code;      //函數(shù)定義
   input[7:0] din;           //函數(shù)只有輸入端口,,輸出為函數(shù)名本身
   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);   //函數(shù)調(diào)用
   endmodule
    【例9.9】七段數(shù)碼管譯碼器
    module decode47(a,b,c,d,e,f,g,D3,D2,D1,D0);
    output a,b,c,d,e,f,g;
    input D3,D2,D1,D0;     //輸入的4位BCD碼
    reg a,b,c,d,e,f,g;
    always @(D3 or D2 or D1 or D0)
    begin
    case({D3,D2,D1,D0})          //用case語句進(jìn)行譯碼
    4'd0: {a,b,c,d,e,f,g}=7'b1111110;
    4'd1: {a,b,c,d,e,f,g}=7'b0110000;
    4'd2: {a,b,c,d,e,f,g}=7'b1101101;
    4'd3: {a,b,c,d,e,f,g}=7'b1111001;
    4'd4: {a,b,c,d,e,f,g}=7'b0110011;
    4'd5: {a,b,c,d,e,f,g}=7'b1011011;
- 34 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    4'd6: {a,b,c,d,e,f,g}=7'b1011111;
    4'd7: {a,b,c,d,e,f,g}=7'b1110000;
    4'd8: {a,b,c,d,e,f,g}=7'b1111111;
    4'd9: {a,b,c,d,e,f,g}=7'b1111011;
    default: {a,b,c,d,e,f,g}=7'bx;
    endcase
  end
endmodule
【例9.10】奇偶校驗(yàn)位產(chǎn)生器
module parity(even_bit,odd_bit,input_bus);
output even_bit,odd_bit;
input[7:0] input_bus;
assign odd_bit = ^ input_bus;     //產(chǎn)生奇校驗(yàn)位
assign even_bit = ~odd_bit;      //產(chǎn)生偶校驗(yàn)位
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
    - 35 - 程序文本
    case(sel)
    2'b00: out=in0;
    2'b01: out=in1;
    2'b10: out=in2;
    default: out=in3;
    endcase
    end
   endmodule
    【例9.13】用組合電路實(shí)現(xiàn)的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觸發(fā)器- 36 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》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觸發(fā)器
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觸發(fā)器
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
    - 37 - 程序文本
    q <= 0; qn <= 1;     //同步清0,,高電平有效
    end
    else if (set) begin
    q <=1; qn <=0;      //同步置1,,高電平有效
    end
    else       begin
    q <= d;  n <= ~d;
    end
    end
    endmodule
    【例9.17】帶異步清0、異步置1的JK觸發(fā)器
    module JK_FF(CLK,J,K,Q,RS,SET);
    input CLK,J,K,SET,RS;
    output Q;
    reg Q;
    always @(posedge CLK or negedge RS or negedge SET)
    begin
    if(!RS)  Q <= 1'b0;
    else if(!SET) Q <= 1'b1;
    else case({J,K})
    2'b00 :   <= Q;
    2'b01 :   <= 1'b0;
    2'b10 : Q <= 1'b1;
    2'b11 : Q <= ~Q;
    default: Q<= 1'bx;
    endcase
    end
    endmodule
    【例9.18】電平敏感的1位數(shù)據(jù)鎖存器
   module latch_1(q,d,clk);
   output q;
   input d,clk;
   assign q = clk ? d : q;     //時(shí)鐘信號(hào)為高電平時(shí),,將輸入端數(shù)據(jù)鎖存
   endmodule
    【例9.19】帶置位和復(fù)位端的1位數(shù)據(jù)鎖存器
   module latch_2(q,d,clk,set,reset);
   output q;
- 38 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》input d,clk,set,reset;
assign q = reset ? 0 : (set ? 1 : (clk ? d : q));
endmodule
【例9.20】8位數(shù)據(jù)鎖存器
module latch_8(qout,data,clk);
output[7:0] qout;
input[7:0] data;
input clk;
reg[7:0] qout;
always @(clk or data)
    begin
    if (clk) qout<=data;
    end
endmodule
【例9.21】8位數(shù)據(jù)寄存器
module reg8(out_data,in_data,clk,clr);
output[7:0] out_data;
input[7:0] in_data;
input clk,clr;
reg[7:0] out_data;
always @(posedge clk or posedge clr)
    begin
    if(clr)  out_data <=0;
    else     out_data <=in_data;
    end
endmodule
【例9.22】8位移位寄存器
module shifter(din,clk,clr,dout);
input din,clk,clr;
output[7:0] dout;
reg[7:0] dout;
always @(posedge clk)
    begin
    if (clr)  dout<= 8'b0;     //同步清0,,高電平有效
    else
    begin
    dout <= dout << 1;     //輸出信號(hào)左移一位
    - 39 - 程序文本
    dout[0] <= din;      //輸入信號(hào)補(bǔ)充到輸出信號(hào)的最低位
    end
    end
   endmodule
    【例9.23】可變模加法/減法計(jì)數(shù)器
   module updown_count(d,clk,clear,load,up_down,qd);
   input[7:0] d;
   input clk,clear,load;
   input up_down;
   output[7:0] qd;
   reg[7:0] cnt;
   assign qd = cnt;
   always @(posedge clk)
    begin
    if (!clear)       cnt = 8'h00;     //同步清0,低電平有效
    else  if (load)     cnt = d;     //同步預(yù)置
    else  if (up_down)  cnt = cnt + 1;     //加法計(jì)數(shù)
    else       cnt = cnt - 1;     //減法計(jì)數(shù)
    end
    endmodule
    【例9.24】4位Johnson計(jì)數(shù)器(異步復(fù)位)
   module johnson(clk,clr,out);
   input clk,clr;
   output[3:0] out;
   reg[3:0] out;
   always @(posedge clk or posedge clr)
    begin
    if (clr)    out<= 4'h0;
    else
    begin   out<= out<< 1;
    out[0]<= ~out[3];
    end
    end
   endmodule
    【例9.25】256×8 RAM模塊
   module ram256x8(data,address,we,inclock,outclock,q);
   input[7:0] data;
- 40 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》input[7:0] address;
input we,inclock,outclock;
output[7:0] q;
lpm_ram_dq myram(.q(q),.data(data),.address(address),
    .we(we),.inclock(inclock),.outclock(outclock));
defparam myram.lpm_width=8;     //定義數(shù)據(jù)寬度
defparam myram.lpm_widthad=8;     //定義地址寬度
endmodule
【例9.26】256×16 RAM塊
module map_lpm_ram(dataout,datain,addr,we,inclk,outclk);
input[15:0] datain;      //端口定義
input[7:0] addr;
input we,inclk,outclk;
output[15:0] dataout;
    //lpm_ram_dq元件例化
lpm_ram_dq ram(.data(datain),.address(addr),.we(we),.inclock(inclk),
    .outclock(outclk),.q(dataout));
defparam ram.lpm_width=16;     //參數(shù)賦值
defparam ram.lpm_widthad=8;
defparam ram.lpm_indata="REGISTERED";
defparam ram.lpm_outdata="REGISTERED";
defparam ram.lpm_file="map_lpm_ram.mif";     //RAM塊中的內(nèi)容取自該文件endmodule
【例9.27】4位串并轉(zhuǎn)換器
module serial_pal(clk,reset,en,in,out);
input clk,reset,en,in;
output[3:0] out;
reg[3:0] out;
always @(posedge clk)
    begin
    if(reset)      out<=4'h0;
    else if(en)     out<={out,in};         //使用連接運(yùn)算符
    end
endmodule
【例9.28】用函數(shù)實(shí)現(xiàn)簡單的處理器
module mpc(instr,out);
input[17:0] instr;                 //instr為輸入的指令
    - 41 - 程序文本
   output[8:0] out;      //輸出結(jié)果
   reg[8:0] out;
   reg func;
   reg[7:0] op1,op2;     //從指令中提取的兩個(gè)操作數(shù)
   function[16:0] code_add;      //函數(shù)的定義
   input[17:0] instr;
   reg add_func;
   reg[7:0] code,opr1,opr2;
    begin
    code=instr[17:16];     //輸入指令instr的高2位是操作碼
    opr1=instr[7:0];      //輸入指令instr的低8位是操作數(shù)opr1
    case(code)
    2'b00:
    begin
    add_func=1;
    opr2=instr[15:8];     //從instr中取第二個(gè)操作數(shù)
    end
    2'b01:
    begin
    add_func=0;
    opr2=instr[15:8];     //從instr中取第二個(gè)操作數(shù)
    end
    2'b10:
    begin
    add_func=1;
    opr2=8'd1;     //第二個(gè)操作數(shù)取為1,,實(shí)現(xiàn)+1操作
    end
    default:
    begin
    add_func=0;
    opr2=8'd1;       //實(shí)現(xiàn)-1操作
    end
    endcase
    code_add={add_func,opr2,opr1};
    end
    endfunction
   always @(instr)
    begin
- 42 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    {func,op2,op1}=code_add(instr);     //調(diào)用函數(shù)
    if(func==1)  out=op1+op2;     //實(shí)現(xiàn)兩數(shù)相加,、操作數(shù)1加1操作
    else         out=op1-op2;     //實(shí)現(xiàn)兩數(shù)相減、操作數(shù)1減1操作
    end
endmodule
【例9.29】微處理器的測(cè)試代碼
`timescale 10ns/1ns
`include "mpc.v"
module mpc_tp;
reg[17:0] instr;
wire[8:0] out;
parameter DELY=10;
mpc m1(instr,out);                   //調(diào)用待測(cè)試模塊
initial begin
    instr=18'd0;
#DELY instr=18'b00_01001101_00101111;
#DELY instr=18'b00_11001101_11101111;
#DELY instr=18'b01_01001101_11101111;
#DELY instr=18'b01_01001101_00101111;
#DELY instr=18'b10_01001101_00101111;
#DELY instr=18'b11_01001101_00101111;
#DELY instr=18'b00_01001101_00101111;
#DELY $finish;
end
initial $monitor($time,,,"instr=%b out=%b",instr,out);
endmodule
【例9.30】乘累加器(MAC)代碼
module MAC(out,opa,opb,clk,clr);
output[15:0] out;
input[7:0] opa,opb;
input clk,clr;
wire[15:0] sum;
reg[15:0] out;
function[15:0] mult;        //函數(shù)定義,,mult函數(shù)完成乘法操作
input[7:0] opa,opb;         //函數(shù)只能定義輸入端,,輸出端口為函數(shù)名本身reg[15:0] result;
    - 43 - 程序文本
   integer i;
   begin
    result = opa[0]? opb : 0;
    for(i= 1; i <= 7; i = i+1)
    begin
    if(opa[i]==1)  result=result+(opb<<(i-1));
    end
    mult=result;
   end
   endfunction
   assign sum=mult(opa,opb)+out;
   always @(posedge clk or posedge clr)
    begin
    if(clr)  out<=0;
    else     out<=sum;
    end
   endmodule
    【例9.31】乘累加器的測(cè)試代碼
   'timescale 1ns/1ns
   'include "mac.v"
   module mac_tp;
   reg[7:0] opa,opb;      //測(cè)試輸入信號(hào)用reg型變量
   reg clr,clk;
   wire[15:0] out;       //測(cè)試輸出信號(hào)用wire型變量
   parameter DELY = 100;
   //測(cè)試對(duì)象調(diào)用
   MAC m1(out,opa,opb,clk,clr);
   always #(DELY) clk = ~clk;     //產(chǎn)生時(shí)鐘波形
   initial begin      //激勵(lì)波形定義
    clr=1;clk=0;opa=8'd0; opb=8'd0;
   #DELY clr=0;opa=8'd1; opb=8'd10;
   #DELY opa=8'd2; opb=8'd10;
   #DELY opa=8'd3; opb=8'd10;
- 44 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》#DELY opa=8'd4; opb=8'd10;
#DELY opa=8'd5; opb=8'd10;
#DELY opa=8'd6; opb=8'd10;
#DELY opa=8'd7; opb=8'd10;
#DELY opa=8'd8; opb=8'd10;
#DELY opa=8'd9; opb=8'd10;
#DELY opa=8'd10; opb=8'd10;
#DELY $finish;
end
    //結(jié)果顯示
initial $monitor($time,,,"clr=%b opa=%d opb=%d out=%d",clr,opa,opb,out);endmodule
【例10.1】非流水線方式8位全加器
module adder8(cout,sum,ina,inb,cin,clk);
output[7:0] sum;
output cout;
input[7:0] ina,inb;
input cin,clk;
reg[7:0] tempa,tempb,sum;
reg cout;
reg tempc;
always @(posedge clk)
    begin
    tempa=ina;  tempb=inb;  tempc=cin;       //輸入數(shù)據(jù)鎖存
    end
always @(posedge clk)
    begin
    {cout,sum}=tempa+tempb+tempc;
    end
endmodule
【例10.2】4級(jí)流水方式的8位全加器
module pipeline(cout,sum,ina,inb,cin,clk);
output[7:0] sum;
output cout;
input[7:0] ina,inb;
input cin,clk;
reg[7:0] tempa,tempb,sum;
reg tempci,firstco,secondco,thirdco,cout;
    - 45 - 程序文本
   reg[1:0] firsts,thirda,thirdb;
   reg[3:0] seconda,secondb,seconds;
   reg[5:0] firsta,firstb,thirds;
   always @(posedge clk)
    begin
    tempa=ina;  tempb=inb;  tempci=cin;      //輸入數(shù)據(jù)緩存
    end
    always @(posedge clk)
    begin
    {firstco,firsts}=tempa[1:0]+tempb[1:0]+tempci;
    //第一級(jí)加(低2位)
    firsta=tempa[7:2];     //未參加計(jì)算的數(shù)據(jù)緩存
    firstb=tempb[7:2];
    end
    always @(posedge clk)
    begin
    {secondco,seconds}={firsta[1:0]+firstb[1:0]+firstco,firsts};
    //第二級(jí)加(第2、3位相加)
    seconda=firsta[5:2];     //數(shù)據(jù)緩存
    secondb=firstb[5:2];
    end
    always @(posedge clk)
    begin
    {thirdco,thirds}={seconda[1:0]+secondb[1:0]+secondco,seconds};
    //第三級(jí)加(第4,、5位相加)
    thirda=seconda[3:2];     //數(shù)據(jù)緩存
    thirdb=secondb[3:2];
    end
    always @(posedge clk)
    begin
    {cout,sum}={thirda[1:0]+thirdb[1:0]+thirdco,thirds};
    //第四級(jí)加(高兩位相加)
    end
    endmodule
    【例10.3】兩個(gè)加法器和一個(gè)選擇器的實(shí)現(xiàn)方式
   module resource1(sum,a,b,c,d,sel);
   parameter size=4;
   output[size:0] sum;
- 46 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》input sel;
input[size-1:0] a,b,c,d;
reg[size:0] sum;
always @(a or b or c or d or sel)
    begin
    if(sel)  um=a+b;
    else    sum=c+d;
    end
endmodule
【例10.4】兩個(gè)選擇器和一個(gè)加法器的實(shí)現(xiàn)方式
module resource2(sum,a,b,c,d,sel);
parameter size=4;
output[size-1:0] sum;
input sel;
input[size-1:0] a,b,c,d;
reg[size-1:0] atemp,btemp;
reg[size:0] sum;
always @(a or b or c or d or sel)
    begin
    if(sel)  egin  atemp=a;  btemp=b;  end
    else    begin  atemp=c;  btemp=d;  end
    sum=atemp+btemp;
    end
endmodule
【例10.5】狀態(tài)機(jī)設(shè)計(jì)的例子
module FSM(clk,clr,out,start,step2,step3);
input clk,clr,start,step2,step3;
output[2:0] out;
reg[2:0] out;
reg[1:0] state,next_state;
parameter    state0=2'b00,state1=2'b01,
    state2=2'b11,state3=2'b10;
    /*狀態(tài)編碼,,采用格雷(Gray)編碼方式*/
always @(posedge clk or posedge clr)      /*該進(jìn)程定義起始狀態(tài)*/
begin
    if (clr) state <= state0;
    else state <= next_state;
    - 47 - 程序文本
   end
   always @(state or start or step2 or step3)      /*該進(jìn)程實(shí)現(xiàn)狀態(tài)的轉(zhuǎn)換*/
   begin
   case (state)
    state0: begin
    if (start)  next_state <=state1;
    else      next_state <=state0;
    end
    state1: begin
    next_state <= state2;
    end
    state2: begin
    if (step2)  next_state <=state3;
    else      next_state <=state0;
    end
    state3: begin
    if (step3)  next_state <=state0;
    else      next_state <=state3;
    end
    default:     next_state <=state0;    /*default語句*/
    endcase
   end
   always @(state)       /*該進(jìn)程定義組合邏輯(FSM的輸出)*/
   begin
   case(state)
    state0: out=3'b001;
    state1: out=3'b010;
    state2: out=3'b100;
    state3: out=3'b111;
    default:out=3'b001;      /*default語句,避免鎖存器的產(chǎn)生*/
   endcase
   end
   endmodule
    【例10.6】自動(dòng)轉(zhuǎn)換量程頻率計(jì)控制器
   /*信號(hào)定義:
   clk:     輸入時(shí)鐘,;
- 48 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》clear:     為整個(gè)頻率計(jì)的異步復(fù)位信號(hào),;
reset:     用來在量程轉(zhuǎn)換開始時(shí)復(fù)位計(jì)數(shù)器;
std_f_sel: 用來選擇標(biāo)準(zhǔn)時(shí)基,;
cntover:    代表超量程,;
cntlow:     代表欠量程。
狀態(tài)A,,B,,C,,D,E,,F(xiàn)采用一位熱碼編碼  */
module control(std_f_sel,reset,clk,clear,cntover,cntlow);
output[1:0] std_f_sel;
output reset;
input clk,clear,cntover,cntlow;
reg[1:0] std_f_sel;
reg reset;
reg[5:0] present,next;     //用于保存當(dāng)前狀態(tài)和次態(tài)的中間變量parameter start_fl00k=6'b000001,     //狀態(tài)A編碼,,采用1位熱碼
    fl00k_cnt=6'b000010,     //狀態(tài)B
    start_fl0k=6'b000100,     //狀態(tài)C
    fl0k_cnt=6'b001000,      //狀態(tài)D
    start_flk=6'b010000,     //狀態(tài)E
    flk_cnt=6'b100000;     //狀態(tài)F
always @(posedge clk or posedge clear)
    begin
    if(clear)   present<=start_fl0k;     //start_fl0k為起始狀態(tài)
    else      present<=next;
    end
always @(present or cntover or cntlow)
    begin
    case(present)      //用case語句描述狀態(tài)轉(zhuǎn)換
    start_fl00k:    next<=fl00k_cnt;
    fl00k_cnt:
    begin
    if(cntlow)  next<=start_fl0k;
    else      next<=fl00k_cnt;
    end
    start_fl0k:     next<=fl0k_cnt;
    fl0k_cnt:
    begin
    if(cntlow)       next<=start_flk;
    else  if(cntover)   next<=start_fl00k;
    - 49 - 程序文本
    else       next<=fl0k_cnt;
    end
    start_flk:     next<=flk_cnt;
    flk_cnt:
    begin
    if(cntover)     next<=start_fl0k;
    else       next<=flk_cnt;
    end
    default:next<=start_fl0k;        //缺省狀態(tài)為起始狀態(tài)
    endcase
    end
   always @(present)     //該進(jìn)程產(chǎn)生各狀態(tài)下的輸出
    begin
    case(present)
    start_fl00k:    begin   reset=1;  std_f_sel=2'b00;  end
    fl00k_cnt:     begin   reset=0;  std_f_sel=2'b00;  end
    start_fl0k:     begin   reset=1;  std_f_sel=2'b01;  end
    fl0k_cnt:     begin   reset=0;  std_f_sel=2'b01;  end
    start_flk:     begin   reset=1;  std_f_sel=2'b11;  end
    flk_cnt:     begin   reset=0;  std_f_sel=2'b11;  end
    default:     begin   reset=1;  std_f_sel=2'b01;  end
    endcase
    end
   endmodule
    【例10.7】8位全加器
   module add8(sum,cout,b,a,cin);
   output[7:0] sum;
   output cout;
   input[7:0] a,b;
   input cin;
    assign {cout,sum}=a+b+cin;
   endmodule
    【例10.8】8位寄存器
    module reg8(qout,in,clk,clear);
    output[7:0] qout;
    input[7:0] in;
    input clk,clear;
- 50 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》reg[7:0] qout;
always @(posedge clk or posedge clear)
    begin
    if(clear)   qout=0;     //異步清0
    else       qout=in;
    end
endmodule
【例10.9】累加器頂層連接文本描述
module acc(accout,cout,accin,cin,clk,clear);
output[7:0] accout;
output cout;
input[7:0] accin;
input cin,clk,clear;
wire[7:0] sum;
add8 accadd8(sum,cout,accout,accin,cin);     //調(diào)用add8子模塊
reg8 accreg8(accout,sum,clk,clear);     //調(diào)用reg8子模塊
endmodule
【例10.10】用`include描述的累加器
`include “add8.v”;
`include “reg8.v”;
module accn(accout,cout,accin,cin,clk,clear);
output[7:0] accout;
output cout;
input[7:0] accin;
input cin,clk,clear;
wire[7:0] sum;
add8 accadd8(sum,cout,accout,accin,cin);     //調(diào)用add8子模塊
reg8 accreg8(accout,sum,clk,clear);     //調(diào)用reg8子模塊
endmodule
【例10.11】阻塞賦值方式描述的移位寄存器1
module block1(Q0,Q1,Q2,Q3,din,clk);
output Q0,Q1,Q2,Q3;
input clk,din;
    - 51 - 程序文本
    reg Q0,Q1,Q2,Q3;
    always @(posedge clk)
    begin
    Q3=Q2;         //注意賦值語句的順序
    Q2=Q1;
    Q1=Q0;
    Q0=din;
    end
    endmodule
    【例10.12】阻塞賦值方式描述的移位寄存器2
    module block2(Q0,Q1,Q2,Q3,din,clk);
    output Q0,Q1,Q2,Q3;
    input clk,din;
    reg Q0,Q1,Q2,Q3;
    always @(posedge clk)
    begin
    Q3=Q2;
    Q1=Q0;           //該句與下句的順序與例10.11顛倒
    Q2=Q1;
    Q0=din;
    end
    endmodule
    【例10.13】阻塞賦值方式描述的移位寄存器3
    module block3(Q0,Q1,Q2,Q3,din,clk);
    output Q0,Q1,Q2,Q3;
    input clk,din;
    reg Q0,Q1,Q2,Q3;
    always @(posedge clk)
    begin
    Q0=din;       //4條賦值語句的順序與例10.11完全顛倒
    Q1=Q0;
    Q2=Q1;
    Q3=Q2;
    end
    endmodule
    【例10.14】非阻塞賦值方式描述的移位寄存器
    module block4(Q0,Q1,Q2,Q3,din,clk);
- 52 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》output Q0,Q1,Q2,Q3;
input clk,din;
reg Q0,Q1,Q2,Q3;
always @(posedge clk)
    begin
    Q3<=Q2;
    Q1<=Q0;
    Q2<=Q1;
    Q0<=din;
    end
endmodule
【例10.15】長幀同步時(shí)鐘的產(chǎn)生
module longframe1(clk,strb);
parameter delay=8;
input clk;
output strb;
reg strb;
reg[7:0] counter;
    begin
    if(counter==255)    counter=0;
    else      counter=counter+1;
    end
    begin
    if(counter<=(delay-1))  strb=1;
    else       strb=0;
    end
endmodule
【例10.16】引入了D觸發(fā)器的長幀同步時(shí)鐘的產(chǎn)生
module longframe2(clk,strb);
parameter delay=8;
input clk;
output strb;
reg[7:0] counter;
reg temp;
reg strb;
    - 53 - 程序文本
    begin
    if(counter==255)    counter=0;
    else       counter=counter+1;
    end
    always@(posedge clk)
    begin
    strb=temp;          //引入一個(gè)觸發(fā)器
    end
    begin
    if(counter<=(delay-1))  temp=1;
    else       temp=0;
    end
    endmodule
    【例11.1】數(shù)字跑表
    /*信號(hào)定義:
    CLK:     CLK為時(shí)鐘信號(hào);
    CLR:     為異步復(fù)位信號(hào),;
    PAUSE:     為暫停信號(hào),;
    MSH,MSL:  百分秒的高位和低位,;
    SH,,SL:     秒信號(hào)的高位和低位;
    MH,,ML:     分鐘信號(hào)的高位和低位,。 */
    module paobiao(CLK,CLR,PAUSE,MSH,MSL,SH,SL,MH,ML);
    input CLK,CLR;
    input PAUSE;
    output[3:0] MSH,MSL,SH,SL,MH,ML;
    reg[3:0] MSH,MSL,SH,SL,MH,ML;
    reg cn1,cn2;     //cn1為百分秒向秒的進(jìn)位,cn2為秒向分的進(jìn)位
    //百分秒計(jì)數(shù)進(jìn)程,,每計(jì)滿100,,cn1產(chǎn)生一個(gè)進(jìn)位
    always @(posedge CLK or posedge CLR)
    begin
    if(CLR)  begin     //異步復(fù)位
    {MSH,MSL}<=8'h00;
    cn1<=0;
    end
    else      if(!PAUSE)      //PAUSE為0時(shí)正常計(jì)數(shù),為1時(shí)暫停計(jì)數(shù)
    begin
    if(MSL==9)  begin
- 54 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    MSL<=0;
    if(MSH==9)
    begin  MSH<=0;  cn1<=1;  end
    else  MSH<=MSH+1;
    end
    else     begin
    MSL<=MSL+1;  cn1<=0;
    end
    end
end
//秒計(jì)數(shù)進(jìn)程,,每計(jì)滿60,,cn2產(chǎn)生一個(gè)進(jìn)位
always @(posedge cn1 or posedge CLR)
begin
    if(CLR)  egin     //異步復(fù)位
    {SH,SL}<=8'h00;
    cn2<=0;
    end
    else    if(SL==9)     //低位是否為9
    begin
    SL<=0;
    if(SH==5)   begin  SH<=0;  cn2<=1;  end
    else       SH<=SH+1;
    end
    else
    begin  SL<=SL+1;  cn2<=0;  end
end
//分鐘計(jì)數(shù)進(jìn)程,每計(jì)滿60,,系統(tǒng)自動(dòng)清零
always @(posedge cn2 or posedge CLR)
begin
    if(CLR)
    begin  {MH,ML}<=8'h00;  end     //異步復(fù)位
    else  if(ML==9) begin
    ML<=0;
    if(MH==5)   MH<=0;
    else       MH<=MH+1;
    end
    else    ML<=ML+1;
end
    - 55 - 程序文本
    endmodule
    【例11.2】4位數(shù)字頻率計(jì)控制模塊
    module fre_ctrl(clk,rst,count_en,count_clr,load);
    output count_en,count_clr,load;
    input clk,rst;
    reg count_en,load;
    always @(posedge clk)
    begin
    if(rst)  egin  count_en=0;  load=1;  end
    else    begin
    count_en=~count_en;
    load=~count_en;      //load信號(hào)的產(chǎn)生
    end
    end
    assign  count_clr=~clk&load;      //count_clr信號(hào)的產(chǎn)生
    endmodule
    【例11.3】4位數(shù)字頻率計(jì)計(jì)數(shù)子模塊
    module count10(out,cout,en,clr,clk);
    output[3:0] out;
    output cout;
    input en,clr,clk;
    reg[3:0] out;
    always @(posedge clk or posedge clr)
    begin
    if (clr)  out = 0;     //異步清0
    else   if(en)
    begin
    if(out==9)  out=0;
    else       out = out+1;
    end
    end
    assign  cout =((out==9)&en)?1:0;     //產(chǎn)生進(jìn)位信號(hào)
    endmodule
    【例11.4】頻率計(jì)鎖存器模塊
    module latch_16(qo,din,load);
    output[15:0] qo;
- 56 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》input[15:0] din;
input load;
reg[15:0] qo;
always @(posedge load)
    begin  qo=din;  end
endmodule
【例11.5】交通燈控制器
/* 信號(hào)定義與說明:
CLK:   為同步時(shí)鐘,;
EN:     使能信號(hào),為1的話,,則控制器開始工作,;
LAMPA: 控制A方向四盞燈的亮滅;其中,,LAMPA0~LAMPA3,,分別控制A方向的
    左拐燈、綠燈,、黃燈和紅燈,;
LAMPB: 控制B方向四盞燈的亮滅;其中,,LAMPB0 ~ LAMPB3,,分別控制B方向的
    左拐燈、綠燈,、黃燈和紅燈,;
ACOUNT: 用于A方向燈的時(shí)間顯示,8位,可驅(qū)動(dòng)兩個(gè)數(shù)碼管,;
BCOUNT: 用于B方向燈的時(shí)間顯示,,8位,可驅(qū)動(dòng)兩個(gè)數(shù)碼管,。 */
module traffic(CLK,EN,LAMPA,LAMPB,ACOUNT,BCOUNT);
output[7:0] ACOUNT,BCOUNT;
output[3:0] LAMPA,LAMPB;
input CLK,EN;
reg[7:0] numa,numb;
reg tempa,tempb;
reg[2:0] counta,countb;
reg[7:0] ared,ayellow,agreen,aleft,bred,byellow,bgreen,bleft;
reg[3:0] LAMPA,LAMPB;
always @(EN)
if(!EN)
 begin                       //設(shè)置各種燈的計(jì)數(shù)器的預(yù)置數(shù)
    ared    <=8'd55;     //55秒
    ayellow <=8'd5;      //5秒
    agreen <=8'd40;     //40秒
    aleft   <=8'd15;     //15秒
    bred    <=8'd65;     //65秒
    byellow <=8'd5;      //5秒
    bleft   <=8'd15;     //15秒
    bgreen <=8'd30;     //30秒
 end
    - 57 - 程序文本
    assign  ACOUNT=numa;
    assign  BCOUNT=numb;
    always @(posedge CLK)        //該進(jìn)程控制A方向的四種燈
    begin
    if(EN)
    begin
    if(!tempa)
    begin
    tempa<=1;
    case(counta)         //控制亮燈的順序
    0:  begin numa<=agreen;     LAMPA<=2; counta<=1; end
    1:  begin numa<=ayellow;    LAMPA<=4; counta<=2; end
    2:  begin numa<=aleft;     LAMPA<=1; counta<=3; end
    3:  begin numa<=ayellow;    LAMPA<=4; counta<=4; end
    4:  begin numa<=ared;     LAMPA<=8; counta<=0; end
    default:     LAMPA<=8;
    endcase
    end
    else  begin               //倒計(jì)時(shí)
    if(numa>1)
    if(numa[3:0]==0) begin
    numa[3:0]<=4'b1001;
    numa[7:4]<=numa[7:4]-1;
    end
    else      numa[3:0]<=numa[3:0]-1;
    if (numa==2)  tempa<=0;
    end
    end
    else    begin
    LAMPA<=4'b1000;
    counta<=0;   tempa<=0;
    end
    end
    always @(posedge CLK)            //該進(jìn)程控制B方向的四種燈
    begin
    if (EN)
    begin
    if(!tempb)
- 58 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    begin
    tempb<=1;
    case (countb)            //控制亮燈的順序
    0:  begin numb<=bred;     LAMPB<=8; countb<=1; end
    1:  begin numb<=bgreen;     LAMPB<=2; countb<=2; end
    2:  begin numb<=byellow;    LAMPB<=4; countb<=3; end
    3:  begin numb<=bleft;     LAMPB<=1; countb<=4; end
    4:  begin numb<=byellow;    LAMPB<=4; countb<=0; end
    default:     LAMPB<=8;
    endcase
    end
   else
    begin                     //倒計(jì)時(shí)
    if(numb>1)
    if(!numb[3:0])    begin
    numb[3:0]<=9;
    numb[7:4]<=numb[7:4]-1;
    end
    else       numb[3:0]<=numb[3:0]-1;
    if(numb==2)  tempb<=0;
   end
  end
    else    begin
    LAMPB<=4'b1000;
    tempb<=0;   countb<=0;
    end
 end
endmodule
【例11.6】“梁?!睒非葑嚯娐?/DIV>
//信號(hào)定義與說明:
//clk_4Hz: 用于控制音長(節(jié)拍)的時(shí)鐘頻率;
//clk_6MHz: 用于產(chǎn)生各種音階頻率的基準(zhǔn)頻率,;
//speaker: 用于激勵(lì)揚(yáng)聲器的輸出信號(hào),,本例中為方波信號(hào);
//high, med, low:分別用于顯示高音,、中音和低音音符,,各驅(qū)動(dòng)一個(gè)數(shù)碼管來顯示。module song(clk_6MHz,clk_4Hz,speaker,high,med,low);
input clk_6MHz, clk_4Hz;
output speaker;
output[3:0] high,med,low;
    - 59 - 程序文本
    reg[3:0] high,med,low;
    reg[13:0] divider,origin;
    reg[7:0] counter;
    reg speaker;
    wire carry;
    assign carry=(divider==16383);
    always @(posedge clk_6MHz)
    begin   if(carry)  divider=origin;
    else    divider=divider+1;
    end
    always @(posedge carry)
    begin
    speaker=~speaker;      //2分頻產(chǎn)生方波信號(hào)
    end
    always @(posedge clk_4Hz)
    begin
    case({high,med,low})         //分頻比預(yù)置
    'b000000000011: origin=7281;
    'b000000000101: origin=8730;
    'b000000000110: origin=9565;
    'b000000000111: origin=10310;
    'b000000010000: origin=10647;
    'b000000100000: origin=11272;
    'b000000110000: origin=11831;
    'b000001010000: origin=12556;
    'b000001100000: origin=12974;
    'b000100000000: origin=13516;
    'b000000000000: origin=16383;
    endcase
    end
    always @(posedge clk_4Hz)
    begin
    if(counter==63)  counter=0;      //計(jì)時(shí),,以實(shí)現(xiàn)循環(huán)演奏
    else      counter=counter+1;
    case(counter)     //記譜
- 60 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》0: {high,med,low}='b000000000011;     //低音“3”
1: {high,med,low}='b000000000011;     //持續(xù)4個(gè)時(shí)鐘節(jié)拍2: {high,med,low}='b000000000011;
3: {high,med,low}='b000000000011;
4: {high,med,low}='b000000000101;     //低音“5”
5: {high,med,low}='b000000000101;     //發(fā)3個(gè)時(shí)鐘節(jié)拍
6: {high,med,low}='b000000000101;
7: {high,med,low}='b000000000110;     //低音“6”
8: {high,med,low}='b000000010000;     //中音“1”
9: {high,med,low}='b000000010000;     //發(fā)3個(gè)時(shí)鐘節(jié)拍
10: {high,med,low}='b000000010000;
11: {high,med,low}='b000000100000;     //中音“2”
12: {high,med,low}='b000000000110;     //低音“6”
13: {high,med,low}='b000000010000;
14: {high,med,low}='b000000000101;
15: {high,med,low}='b000000000101;
16: {high,med,low}='b000001010000;     //中音“5”
17: {high,med,low}='b000001010000;     //發(fā)3個(gè)時(shí)鐘節(jié)拍
18: {high,med,low}='b000001010000;
19: {high,med,low}='b000100000000;     //高音“1”
20: {high,med,low}='b000001100000;
21: {high,med,low}='b000001010000;
22: {high,med,low}='b000000110000;
23: {high,med,low}='b000001010000;
24: {high,med,low}='b000000100000;     //中音“2”
25: {high,med,low}='b000000100000;     //持續(xù)11個(gè)時(shí)鐘節(jié)拍26: {high,med,low}='b000000100000;
27: {high,med,low}='b000000100000;
28: {high,med,low}='b000000100000;
29: {high,med,low}='b000000100000;
30: {high,med,low}='b000000100000;
31: {high,med,low}='b000000100000;
32: {high,med,low}='b000000100000;
33: {high,med,low}='b000000100000;
34: {high,med,low}='b000000100000;
35: {high,med,low}='b000000110000;     //中音“3”
36: {high,med,low}='b000000000111;     //低音“7”
37: {high,med,low}='b000000000111;
    - 61 - 程序文本
    38: {high,med,low}='b000000000110;     //低音“6”
    39: {high,med,low}='b000000000110;
    40: {high,med,low}='b000000000101;     //低音“5”
    41: {high,med,low}='b000000000101;
    42: {high,med,low}='b000000000101;
    43: {high,med,low}='b000000000110;     //低音“6”
    44: {high,med,low}='b000000010000;     //中音“1”
    45: {high,med,low}='b000000010000;
    46: {high,med,low}='b000000100000;     //中音“2”
    47: {high,med,low}='b000000100000;
    48: {high,med,low}='b000000000011;     //低音“3”
    49: {high,med,low}='b000000000011;
    50: {high,med,low}='b000000010000;     //中音“1”
    51: {high,med,low}='b000000010000;
    52: {high,med,low}='b000000000110;
    53: {high,med,low}='b000000000101;     //低音“5”
    54: {high,med,low}='b000000000110;
    55: {high,med,low}='b000000010000;     //中音“1”
    56: {high,med,low}='b000000000101;     //低音“5”
    57: {high,med,low}='b000000000101;     //持續(xù)8個(gè)時(shí)鐘節(jié)拍
    58: {high,med,low}='b000000000101;
    59: {high,med,low}='b000000000101;
    60: {high,med,low}='b000000000101;
    61: {high,med,low}='b000000000101;
    62: {high,med,low}='b000000000101;
    63: {high,med,low}='b000000000101;
    endcase
    end
    endmodule
    【例11.7】自動(dòng)售飲料機(jī)
    /*信號(hào)定義:
    clk:     時(shí)鐘輸入,;
    reset:      為系統(tǒng)復(fù)位信號(hào);
    half_dollar:   代表投入5角硬幣,;
    one_dollar:     代表投入1元硬幣,;
    half_out:     表示找零信號(hào);
    dispense:     表示機(jī)器售出一瓶飲料,;
    collect:     該信號(hào)用于提示投幣者取走飲料。 */
- 62 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》module sell(one_dollar,half_dollar,
    collect,half_out,dispense,reset,clk);
parameter idle=0,one=2,half=1,two=3,three=4;
    //idle,one,half,two,three為中間狀態(tài)變量,,代表投入幣值的幾種情況input one_dollar,half_dollar,reset,clk;
output collect,half_out,dispense;
reg collect,half_out,dispense;
reg[2:0] D;
always @(posedge clk)
 begin
    if(reset)
    begin
    dispense=0;     collect=0;
    half_out=0;     D=idle;
    end
    case(D)
    idle:
    if(half_dollar)  D=half;
    else  if(one_dollar)
    D=one;
    half:
    if(half_dollar)  D=one;
    else if(one_dollar)
    D=two;
    one:
    if(half_dollar) D=two;
    else if(one_dollar)
    D=three;
    two:
    if(half_dollar) D=three;
    else if(one_dollar)
    begin
    dispense=1;        //售出飲料
    collect=1;  D=idle;
    end
    three:
    if(half_dollar)
    begin
    dispense=1;         //售出飲料
    - 63 - 程序文本
    collect=1;  D=idle;
    end
    else if(one_dollar)
    begin
    dispense=1;         //售出飲料
    collect=1;
    half_out=1; D=idle;
    end
    endcase
    end
    endmodule
    【例11.8】多功能數(shù)字鐘
    /* 信號(hào)定義:
    clk:     標(biāo)準(zhǔn)時(shí)鐘信號(hào),,本例中,其頻率為4Hz,;
    clk_1k:     產(chǎn)生鬧鈴音,、報(bào)時(shí)音的時(shí)鐘信號(hào),本例中其頻率為1024Hz,;
    mode:     功能控制信號(hào),;  0:計(jì)時(shí)功能;
    為1:鬧鐘功能,;
    為2:手動(dòng)校時(shí)功能,;
    turn:     接按鍵,在手動(dòng)校時(shí)功能時(shí),,選擇是調(diào)整小時(shí),,還是分鐘;
    若長時(shí)間按住該鍵,,還可使秒信號(hào)清零,,用于精確調(diào)時(shí);
    change:     接按鍵,手動(dòng)調(diào)整時(shí),,每按一次,,計(jì)數(shù)器加1;
    如果長按,,則連續(xù)快速加1,,用于快速調(diào)時(shí)和定時(shí);
    hour,min,sec:此三信號(hào)分別輸出并顯示時(shí),、分,、秒信號(hào),
    皆采用BCD碼計(jì)數(shù),,分別驅(qū)動(dòng)6個(gè)數(shù)碼管顯示時(shí)間,;
    alert:     輸出到揚(yáng)聲器的信號(hào),用于產(chǎn)生鬧鈴音和報(bào)時(shí)音,;
    鬧鈴音為持續(xù)20秒的急促的“嘀嘀嘀”音,,若按住“change”鍵,
    則可屏蔽該音,;整點(diǎn)報(bào)時(shí)音為“嘀嘀嘀嘀—嘟”四短一長音,;
    LD_alert:  接發(fā)光二極管,指示是否設(shè)置了鬧鐘功能,;
    LD_hour:   接發(fā)光二極管,,指示當(dāng)前調(diào)整的是小時(shí)信號(hào);
    LD_min:     接發(fā)光二極管,,指示當(dāng)前調(diào)整的是分鐘信號(hào),。
    */
    module clock(clk,clk_1k,mode,change,turn,alert,hour,min,sec,
    LD_alert,LD_hour,LD_min);
    input clk,clk_1k,mode,change,turn;
    output alert,LD_alert,LD_hour,LD_min;
    output[7:0] hour,min,sec;
    reg[7:0] hour,min,sec,hour1,min1,sec1,ahour,amin;
    reg[1:0] m,fm,num1,num2,num3,num4;
    reg[1:0] loop1,loop2,loop3,loop4,sound;
- 64 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》reg LD_hour,LD_min;
reg clk_1Hz,clk_2Hz,minclk,hclk;
reg alert1,alert2,ear;
reg count1,count2,counta,countb;
wire ct1,ct2,cta,ctb,m_clk,h_clk;
always @(posedge clk)
 begin
    clk_2Hz<=~clk_2Hz;
    if(sound==3)  begin sound<=0; ear<=1;  end
    //ear信號(hào)用于產(chǎn)生或屏蔽聲音
    else  begin sound<=sound+1; ear<=0;  end
end
always @(posedge clk_2Hz)    //由4Hz的輸入時(shí)鐘產(chǎn)生1Hz的時(shí)基信號(hào)
    clk_1Hz<=~clk_1Hz;
always @(posedge mode)       //mode信號(hào)控制系統(tǒng)在三種功能間轉(zhuǎn)換
 begin  if(m==2)  m<=0;  else  m<=m+1;  end
always @(posedge turn)
    fm<=~fm;
always        //該進(jìn)程產(chǎn)生count1,count2,counta,countb四個(gè)信號(hào)begin
 case(m)
 2: begin   if(fm)
    begin   count1<=change; {LD_min,LD_hour}<=2;  end
    else
    begin  counta<=change;  {LD_min,LD_hour}<=1;  end
    {count2,countb}<=0;
    end
 1: begin   if(fm)
    begin   count2<=change;  {LD_min,LD_hour}<=2;  end
    else
    begin  countb<=change; {LD_min,LD_hour}<=1;  end
    {count1,counta}<=2'b00;
    end
    default: {count1,count2,counta,countb,LD_min,LD_hour}<=0;
    endcase
end
    - 65 - 程序文本
    always @(negedge clk)
    //如果長時(shí)間按下“change”鍵,則生成“num1”信號(hào)用于連續(xù)快速加1
    if(count2)  begin
    if(loop1==3) num1<=1;
    else
    begin loop1<=loop1+1; num1<=0; end
    end
    else  begin  loop1<=0;  num1<=0;  end
    always @(negedge clk)              //產(chǎn)生num2信號(hào)
    if(countb)  begin
    if(loop2==3)  num2<=1;
    else
    begin  loop2<=loop2+1;  num2<=0;  end
    end
    else  begin  loop2<=0;  num2<=0;  end
    always @(negedge clk)
    if(count1)  begin
    if(loop3==3)  num3<=1;
    else
    begin  loop3<=loop3+1;  num3<=0;  end
    end
    else  begin  loop3<=0;  num3<=0;  end
    always @(negedge clk)
    if(counta)  begin
    if(loop4==3) num4<=1;
    else
    begin  loop4<=loop4+1;  num4<=0;  end
    end
    else  begin  loop4<=0;  num4<=0;  end
    assign ct1=(num3&clk)|(!num3&m_clk);     //ct1用于計(jì)時(shí),、校時(shí)中的分鐘計(jì)數(shù)
    assign ct2=(num1&clk)|(!num1&count2);   //ct2用于定時(shí)狀態(tài)下調(diào)整分鐘信號(hào)
    assign cta=(num4&clk)|(!num4&h_clk);     //cta用于計(jì)時(shí),、校時(shí)中的小時(shí)計(jì)數(shù)
    assign ctb=(num2&clk)|(!num2&countb);   //ctb用于定時(shí)狀態(tài)下調(diào)整小時(shí)信號(hào)
    always @(posedge clk_1Hz)         //秒計(jì)時(shí)和秒調(diào)整進(jìn)程
    if(!(sec1^8'h59)|turn&(!m))
    begin
    sec1<=0; if(!(turn&(!m)))  minclk<=1;
- 66 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    end
    //按住“turn”按鍵一段時(shí)間,秒信號(hào)可清零,,該功能用于手動(dòng)精確調(diào)時(shí)
    else  begin
    if(sec1[3:0]==4'b1001)
    begin  sec1[3:0]<=4'b0000;  sec1[7:4]<=sec1[7:4]+1;  end
    else  sec1[3:0]<=sec1[3:0]+1;   minclk<=0;
    end
assign  m_clk=minclk||count1;
always @(posedge ct1)                //分計(jì)時(shí)和分調(diào)整進(jìn)程
 begin
    if(min1==8'h59)  begin  min1<=0;  hclk<=1;  end
    else    begin
    if(min1[3:0]==9)
    begin  min1[3:0]<=0;  min1[7:4]<=min1[7:4]+1;  end
    else  min1[3:0]<=min1[3:0]+1;  hclk<=0;
    end
 end
assign  h_clk=hclk||counta;
always @(posedge cta)             //小時(shí)計(jì)時(shí)和小時(shí)調(diào)整進(jìn)程
    if(hour1==8'h23) hour1<=0;
    else    if(hour1[3:0]==9)
    begin  hour1[7:4]<=hour1[7:4]+1;  hour1[3:0]<=0;  end
    else  hour1[3:0]<=hour1[3:0]+1;
always @(posedge ct2)              //鬧鐘定時(shí)功能中的分鐘調(diào)節(jié)進(jìn)程
    if(amin==8'h59)  amin<=0;
    else     if(amin[3:0]==9)
    begin  amin[3:0]<=0;  amin[7:4]<=amin[7:4]+1;  end
    else  amin[3:0]<=amin[3:0]+1;
always @(posedge ctb)              //鬧鐘定時(shí)功能中的小時(shí)調(diào)節(jié)進(jìn)程
    if(ahour==8'h23)  ahour<=0;
    else    if(ahour[3:0]==9)
    begin  ahour[3:0]<=0;  ahour[7:4]<=ahour[7:4]+1;  end
    else  ahour[3:0]<=ahour[3:0]+1;
always            //鬧鈴功能
    if((min1==amin)&&(hour1==ahour)&&(amin|ahour)&&(!change))
    - 67 - 程序文本
    //若按住“change”鍵不放,,可屏蔽鬧鈴音
    if(sec1<8'h20)  alert1<=1;     //控制鬧鈴的時(shí)間長短
    else  alert1<=0;
    else  alert1<=0;
    always                      //時(shí)、分,、秒的顯示控制
    case(m)
    3'b00: begin  hour<=hour1;  min<=min1;  sec<=sec1;  end
    //計(jì)時(shí)狀態(tài)下的時(shí),、分、秒顯示
    3'b01: begin  hour<=ahour;  min<=amin;  sec<=8'hzz;  end
    //定時(shí)狀態(tài)下的時(shí),、分,、秒顯示
    3'b10: begin  hour<=hour1;  min<=min1;  sec<=8'hzz;  end
    //校時(shí)狀態(tài)下的時(shí)、分,、秒顯示
    endcase
    assign  LD_alert=(ahour|amin)?1:0;       //指示是否進(jìn)行了鬧鈴定時(shí)
    assign  alert=((alert1)?clk_1k&clk:0)|alert2;    //產(chǎn)生鬧鈴音或整點(diǎn)報(bào)時(shí)音
    always                     //產(chǎn)生整點(diǎn)報(bào)時(shí)信號(hào)alert2
    begin
    if((min1==8'h59)&&(sec1>8'h54)||(!(min1|sec1)))
    if(sec1>8'h54)  alert2<=ear&clk_1k; //產(chǎn)生短音
    else  alert2<=!ear&clk_1k;     //產(chǎn)生長音
    else  alert2<=0;
    end
    endmodule
    【例11.9】電話計(jì)費(fèi)器程序
    /*信號(hào)定義:
    clk:     時(shí)鐘信號(hào),,本例中其頻率值為1Hz,;
    decide:     電話局反饋回來的信號(hào),代表話務(wù)種類,,“01”表示市話,,“10”表示
    長話,“11”表示特話,;
    dispmoney: 用來顯示卡內(nèi)余額,,其單位為角,這里假定能顯示的最大數(shù)額為50元
    (500角),;
    disptime:  顯示本次通話的時(shí)長,;
    write,read: 當(dāng)write信號(hào)下降沿到來時(shí)寫卡,當(dāng)話卡插入,,read信號(hào)變高時(shí)讀卡,;
    warn:     余額過少時(shí)的告警信號(hào)。本例中,,當(dāng)打市話時(shí),,余額少于3角,打長
    話時(shí),,余額少于6角,,即會(huì)產(chǎn)生告警信號(hào);
    cut:     當(dāng)告警時(shí)間過長時(shí)自動(dòng)切斷通話信號(hào),。  */
- 68 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》module account(state,clk,card,decide,disptime,dispmoney,
    write,read,warn,cut);
output write,read,warn,cut;
input state,clk,card;
input[2:1] decide;
output[10:0] dispmoney;
output[8:0] disptime;
reg[10:0] money;
reg[8:0] dtime;
reg warn,cut,write,t1m;       //t1m為分時(shí)鐘
reg set,reset_ena;
integer num1,temp;
assign  dispmoney=card?money:0;
assign  disptime=dtime;
assign  read=card?1:0;
    //產(chǎn)生分時(shí)鐘
always @(posedge clk)
 begin
  if (num1==59)  begin  num1<=0;  t1m<=1;  end
  else  begin
    if(state)   num1<=num1+1;
    else    num1<=0;  t1m<=0;
    end
 end
always @(negedge clk)         //該進(jìn)程完成電話計(jì)費(fèi)功能
begin
 if(!set)
  begin  money<=11'h500;  set<=1;  end
 if(card&state)
    if(t1m)
    case({state,decide})
  3'b101:  if(money<3)
    begin  warn<=1;  write<=0;  reset_ena<=1;  end
    else
    begin     //市話計(jì)費(fèi)
    if(money[3:0]<4'b0011)
    begin
    money[3:0]<=money[3:0]+7;
    - 69 - 程序文本
    if(money[7:4]!=0)
    money[7:4]<=money[7:4]-1;
    else
    begin  money[7:4]<=9;  money[10:8]<=money[10:8]-1;  end
    end
    else  money[3:0]<=money[3:0]-3;  write<=1;
    //市話通話計(jì)時(shí)
    if(dtime[3:0]==9)
    begin
    dtime[3:0]<=0;
    if(dtime[7:4]==9)
    begin  dtime[7:4]<=0;  dtime[8]<=dtime[8]+1;  end
    else  dtime[7:4]<=dtime[7:4]+1;
    end
    else
    begin
    dtime[3:0]<=dtime[3:0]+1;  warn<=0;  reset_ena<=0;
    end
    end
    3'b110:  if(money<6)
    begin  warn<=1;  write<=0;  reset_ena<=1;  end
    else begin
    //通話計(jì)時(shí)
    if(dtime[3:0]==9)
    begin
    dtime[3:0]<=0;  if(dtime[7:4]==9)
    begin  dtime[7:4]<=0;  dtime[8]<=dtime[8]+1;  end
    else dtime[7:4]<=dtime[7:4]+1;
    end
    else dtime[3:0]<=dtime[3:0]+1;
    //長話計(jì)費(fèi)
    if(money[3:0]<4'b0110)
    begin
    money[3:0]<=money[3:0]+4;
    if(!money[7:4])
    begin  money[7:4]<=9;  money[10:8]<=money[10:8]-1;  end
    else  money[7:4]<=money[7:4]-1;
    end
    else  money[3:0]<=money[3:0]-6;
    write<=1;  reset_ena<=0;   warn<=0;
- 70 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    end
    endcase
    else write<=0;
    else  begin  dtime<=0;  warn<=0;  write<=0;  reset_ena<=0;  end
    //取卡后對(duì)一些信號(hào)進(jìn)行復(fù)位
    end
always @(posedge clk)           //該進(jìn)程在告警時(shí)間過長的情況下切斷本次通話begin
    if(warn)  temp<=temp+1;
    else temp<=0;
    if(temp==15)
    begin  cut<=1;  temp<=0;  end
    if(!card||!reset_ena)
    begin
    cut<=0;            //復(fù)位cut信號(hào)
    temp<=0;
    end
  end
endmodule
【例12.1】8位級(jí)連加法器
module add_jl(sum,cout,a,b,cin);
output[7:0] sum;
output cout;
input[7:0] a,b;
input cin;
full_add1 f0(a[0],b[0],cin,sum[0],cin1);         //級(jí)連描述
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],cin4);
full_add1 f4(a[4],b[4],cin4,sum[4],cin5);
full_add1 f5(a[5],b[5],cin5,sum[5],cin6);
full_add1 f6(a[6],b[6],cin6,sum[6],cin7);
full_add1 f7(a[7],b[7],cin7,sum[7],cout);
endmodule
module full_add1(a,b,cin,sum,cout);     //1位全加器
input a,b,cin;
    - 71 - 程序文本
   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
    【例12.2】8位并行加法器
   module add_bx(cout,sum,a,b,cin);
   output[7:0] sum;
   output cout;
   input[7:0] a,b;
   input cin;
    assign {cout,sum}=a+b+cin;
   endmodule
    【例12.3】8位超前進(jìn)位加法器
   module add_ahead(sum,cout,a,b,cin);
   output[7:0] sum;
   output cout;
   input[7:0] a,b;
   input cin;
   wire[7:0] G,P;
   wire[7:0] C,sum;
   assign G[0]=a[0]&b[0];             //產(chǎn)生第0位本位值和進(jìn)位值
   assign P[0]=a[0]|b[0];
   assign C[0]=cin;
   assign sum[0]=G[0]^P[0]^C[0];
   assign G[1]=a[1]&b[1];     //產(chǎn)生第1位本位值和進(jìn)位值
   assign P[1]=a[1]|b[1];
   assign C[1]=G[0]|(P[0]&cin);
   assign sum[1]=G[1]^P[1]^C[1];
   assign G[2]=a[2]&b[2];     //產(chǎn)生第2位本位值和進(jìn)位值
   assign P[2]=a[2]|b[2];
- 72 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》assign C[2]=G[1]|(P[1]&C[1]);
assign sum[2]=G[2]^P[2]^C[2];
assign G[3]=a[3]&b[3];     //產(chǎn)生第3位本位值和進(jìn)位值
assign P[3]=a[3]|b[3];
assign C[3]=G[2]|(P[2]&C[2]);
assign sum[3]=G[3]^P[3]^C[3];
assign G[4]=a[4]&b[4];     //產(chǎn)生第4位本位值和進(jìn)位值
assign P[4]=a[4]|b[4];
assign C[4]=G[3]|(P[3]&C[3]);
assign sum[4]=G[2]^P[2]^C[2];
assign G[5]=a[5]&b[5];       //產(chǎn)生第5位本位值和進(jìn)位值
assign P[5]=a[5]|b[5];
assign C[5]=G[4]|(P[4]&C[4]);
assign sum[5]=G[5]^P[5]^C[5];
assign G[6]=a[6]&b[6];     //產(chǎn)生第6位本位值和進(jìn)位值
assign P[6]=a[6]|b[6];
assign C[6]=G[5]|(P[5]&C[5]);
assign sum[6]=G[6]^P[6]^C[6];
assign G[7]=a[7]&b[7];       //產(chǎn)生第7位本位值和進(jìn)位值
assign P[7]=a[7]|b[7];
assign C[7]=G[6]|(P[6]&C[6]);
assign sum[7]=G[7]^P[7]^C[7];
assign cout=G[7]|(P[7]&C[7]);      //產(chǎn)生最高位進(jìn)位輸出
endmodule
【例12.4】8位并行乘法器
module mult(outcome,a,b);
parameter size=8;
input[size:1] a,b;     //兩個(gè)操作數(shù)
output[2*size:1] outcome;     //結(jié)果
assign outcome=a*b;                //乘法運(yùn)算符
endmodule
【例12.5】4×4查找表乘法器
    - 73 - 程序文本
   module mult4x4(out,a,b,clk);
   output[7:0] out;
   input[3:0] a,b;
   input clk;
   reg[7:0] out;
   reg[1:0] firsta,firstb;
   reg[1:0] seconda,secondb;
   wire[3:0] outa,outb,outc,outd;
   always @(posedge clk)
   begin
    firsta = a[3:2];  seconda = a[1:0];
    firstb = b[3:2];  secondb = b[1:0];
   end
   lookup  m1(outa,firsta,firstb,clk),
    m2(outb,firsta,secondb,clk),
    m3(outc,seconda,firstb,clk),
    m4(outd,seconda,secondb,clk);    //模塊調(diào)用
   always @(posedge clk)
    begin
    out = (outa << 4) + (outb << 2) + (outc << 2) + outd;
    end
   endmodule
   module lookup(out,a,b,clk);              //用查找表方式實(shí)現(xiàn)2×2乘法
   output[3:0] out;
   input[1:0] a,b;
   input clk;
   reg[3:0] out;
   reg[3:0] address;
   always @(posedge clk)
    begin
    address = {a,b};
    case(address)
    4'h0 : out = 4 'b0000;
    4'h1 : out = 4'b0000;
    4'h2 : out = 4'b0000;
    4'h3 : out = 4'b0000;
    4'h4 : out = 4'b0000;
- 74 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    4'h5 : out = 4'b0001;
    4'h6 : out = 4'b0010;
    4'h7 : out = 4'b0011;
    4'h8 : out = 4'b0000;
    4'h9 : out = 4'b0010;
    4'ha : out = 4'b0100;
    4'hb : out = 4'b0110;
    4'hc : out = 4'b0000;
    4'hd : out = 4'b0011;
    4'he : out = 4'b0110;
    4'hf : out = 4'b1001;
    default : out='bx;
  endcase
 end
endmodule
【例12.6】8位加法樹乘法器
module add_tree(out,a,b,clk);
output[15:0] out;
input[7:0] a,b;
input clk;
wire[15:0] out;
wire[14:0] out1,c1;
wire[12:0] out2;
wire[10:0] out3,c2;
wire[8:0] out4;
reg[14:0] temp0;
reg[13:0] temp1;
reg[12:0] temp2;
reg[11:0] temp3;
reg[10:0] temp4;
reg[9:0] temp5;
reg[8:0] temp6;
reg[7:0] temp7;
function[7:0] mult8x1;     //該函數(shù)實(shí)現(xiàn)8×1乘法
input[7:0] operand;
input sel;
   begin
   mult8x1= (sel) ? (operand) : 8'b00000000;
    - 75 - 程序文本
    end
   endfunction
   always @(posedge clk)     //調(diào)用函數(shù)實(shí)現(xiàn)操作數(shù)b 各位與操作數(shù)a的相乘
    begin
    temp7<=mult8x1(a,b[0]);
    temp6<=((mult8x1(a,b[1]))<<1);
    temp5<=((mult8x1(a,b[2]))<<2);
    temp4<=((mult8x1(a,b[3]))<<3);
    temp3<=((mult8x1(a,b[4]))<<4);
    temp2<=((mult8x1(a,b[5]))<<5);
    temp1<=((mult8x1(a,b[6]))<<6);
    temp0<=((mult8x1(a,b[7]))<<7);
    end
   assign  out1 = temp0 + temp1;     //加法器樹運(yùn)算
   assign  out2 = temp2 + temp3;
   assign  out3 = temp4 + temp5;
   assign  out4 = temp6 + temp7;
   assign  c1 = out1 + out2;
   assign  c2 = out3 + out4;
   assign  out = c1 + c2;
   endmodule
    【例12.7】11階FIR數(shù)字濾波器
   module fir(clk,x,y);
   input[7:0] x;
   input clk;
   output[15:0] y;
   reg[15:0] y;
   reg[7:0] tap0,tap1,tap2,tap3,tap4,tap5,tap6,tap7,tap8,tap9,tap10;
   reg[7:0] t0,t1,t2,t3,t4,t5;
   reg[15:0] sum;
   always@(posedge clk)
    begin
    t0<=tap5;
    t1<=tap4+tap6;
    t2<=tap3+tap7;
- 76 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    t3<=tap2+tap8;
    t4<=tap1+tap9;
    t5<=tap0+tap10;           //利用對(duì)稱性
    sum<=(t1<<4)+{t1[7],t1[7:1]}+{t1[7],t1[7],t1[7:2]}+
    {t1[7],t1[7],t1[7],
    t1[7:3]}-(t2<<3)-(t2<<2)+t2-{t2[7],t2[7],t2[7:2]}
    +(t3<<2)+t3+{t3[7],t3[7],t3[7:2]}+{t3[7],t3[7],t3[7],t3[7],t3[7:4]}
    +{t3[7],t3[7],t3[7],t3[7],t3[7],t3[7:5]}
    -t4-{t4[7],t4[7:1]}-{t4[7],t4[7],t4[7],t4[7:3]}
    +{t5[7],t5[7:1]}-{t5[7],t5[7],t5[7],t5[7],t5[7],t5[7:5]}
    +(t0<<7)-((t0<<2)<<2)-(t0<<2)+{t0[7],t0[7:1]}
    +{t0[7],t0[7],t0[7:2]}+{t0[7],t0[7],t0[7],t0[7],t0[7:4]};
    //16+0.5+0.25+0.125=16.875
    //8+4-1+0.25=11.25
    //4+1+0.25+0.0625+0.03125=5.34375
    //1+0.5+0.125=1.625
    //0.5-0.03125=0.46875
    //128-4*4-4+0.5+0.25+0.0625=108.8125
    /* 0.0036,,-0.0127,0.0417,,-0.0878,,0.1318,0.8500,,0.1318,-0.0878,,
    0.0417,,-0.0127,0.0036,,0.4608,,-1.6256,5.3376,,-11.2384,,16.8704,
    108.800,,16.8704,,-11.238,,5.3376,-1.6256,,0.4608 */
    tap10<=tap9;
    tap9<=tap8;
    tap8<=tap7;
    tap7<=tap6;
    tap6<=tap5;
    tap5<=tap4;
    tap4<=tap3;
    tap3<=tap2;
    tap2<=tap1;
    tap1<=tap0;
    tap0<=x;
   y<={sum[15],sum[15],sum[15],sum[15],sum[15],sum[15],sum[15],sum[15:7]};
   end
   endmodule
    【例12.8】16位高速數(shù)字相關(guān)器
    - 77 - 程序文本
   module correlator(out,a,b,clk);
   output[4:0] out;
   input[15:0] a,b;
   input clk;
   wire[2:0] sum1,sum2,sum3,sum4;
   wire[3:0] temp1,temp2;
   detect  u1(sum1,a[3:0],b[3:0],clk),     //模塊調(diào)用
    u2(sum2,a[7:4],b[7:4],clk),
    u3(sum3,a[11:8],b[11:8],clk),
    u4(sum4,a[15:12],b[15:12],clk);
   add3     u5(temp1,sum1,sum2,clk),
    u6(temp2,sum3,sum4,clk);
   add4     u7(out,temp1,temp2,clk);
   endmodule
   module detect(sum,a,b,clk);     //該模塊實(shí)現(xiàn)4位相關(guān)器
   output[2:0] sum;
   input clk;
   input[3:0] a,b;
   wire[3:0] ab;
   reg[2:0] sum;
   assign ab = a ^ b;
   always @(posedge clk)
    begin
    case(ab)
    'd0: sum = 4;
    'd1,'d2,'d4,'d8:   sum = 3;
    'd3,'d5,'d6,'d9,'d10,'d12: sum = 2;
    'd7,'d11,'d13,'d14: sum = 1;
    'd15: sum = 0;
    endcase
    end
   endmodule
   module add3(add,a,b,clk);     //3位加法器
   output[3:0] add;
   input[2:0] a,b;
   input clk;
- 78 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》reg[3:0] add;
always @(posedge clk)
   begin  add = a + b;  end
endmodule
module add4(add,a,b,clk);     //4位加法器
output[4:0] add;
input[3:0] a,b;
input clk;
reg[4:0] add;
always @(posedge clk)
   begin  add = a + b;  end
endmodule
【例12.9】(7,,4)線性分組碼編碼器
module linear(c,u,clk);
output[6:0] c;     //c為編碼輸出碼字
input[3:0] u;
input clk;
reg[6:0] c;
always @(posedge clk)
 begin
    c[6] = u[3];
    c[5] = u[2];
    c[4] = u[1];
    c[3] = u[0];
    c[2] = u[1] ^ u[2] ^ u[3];
    c[1] = u[0] ^ u[1] ^ u[2];
    c[0] = u[0] ^ u[2] ^ u[3] ;
 end
endmodule
【例12.10】(7,4)線性分組碼譯碼器
module decoder1(c,y,clk);
output[6:0] c;
input[6:0] y;
input clk;
reg[2:0] s;
reg[6:0] e,c;
always @(posedge clk)
    - 79 - 程序文本
    begin
    s[0] = y[0] ^ y[3] ^ y[5] ^ y[6];
    s[1] = y[1] ^ y[3] ^ y[4] ^ y[5];
    s[2] = y[2] ^ y[4] ^ y[5] ^ y[6];     //s[0]~ s[2]為伴隨子
    e[0] = s[0] & (~s[1]) & (~s[2]);
    e[1] = (~s[0]) & s[1] & (~s[2]);
    e[2] = (~s[0]) & (~s[1]) & s[2];
    e[3] = s[0] & s[1] & (~s[2]);
    e[4] = (~s[0]) & s[1] & s[2];
    e[5] = s[0] & s[1] & s[2];
    e[6] = s[0] & (~s[1]) & s[2];     //e[0]~ e[6]為錯(cuò)誤圖樣
    c = e ^ y;     //c為輸出碼字
    end
   endmodule
    【例12.11】(7,,4)循環(huán)碼編碼器
   module cycle(c,u,clk);
   output[6:0] c;
   input[3:0] u;
   input clk;
   reg[2:0] i;
   reg d0,d1,d2,temp;
   reg[6:0] c;
   always @(posedge clk)
    begin
    d0=0; 1=0;   d2=0;     //初始化
    for (i=0;i<4;i=i+1)     //該for循環(huán)計(jì)算碼組的前4個(gè)碼元
    begin
    temp = d2 ^ c[i];
    d2 = d1;    d1 = d0 ^ temp;
    d0 = temp;  c[i] = u[i];
    end
    for (i=4;i<7;i=i+1)     //該for循環(huán)計(jì)算碼組的后3個(gè)碼元
    begin
    temp = d2;
    d2 = d1;     d1 = d0 ^ temp;
    d0 = temp; c[i] = temp;
    end
    end
- 80 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》endmodule
【例12.12】(7,,4)循環(huán)碼糾錯(cuò)譯碼器
module decoder2(c,y,clk);
output[6:0] c;     //c為輸出碼字,c[6]為高次項(xiàng)
input[6:0] y;     //y為接收碼字,,y[6]為高次項(xiàng)
input clk;
reg[6:0] c,c_buf,buffer;
reg temp;
reg s0,s1,s2;     //伴隨式電路寄存器
reg e;     //錯(cuò)誤檢測(cè)輸出信號(hào)
integer i;
always @(posedge clk)
 begin
    s0=0;   s1=0;   s2=0;     //初始化
    temp=0;
    buffer=y;     //接收碼字移入緩存
   for (i=6;i>=0;i=i-1)      //接收碼字進(jìn)入除法電路
    begin
    e=s0&(~s1)&temp;
    temp=s2;
    s2=s1;
    s1=s0^temp;
    s0=y[i]^temp^e;
    end
    for (i=6;i>=0;i=i-1)     //輸出糾錯(cuò)譯碼后的碼字
    begin
    e=s0&(~s1)&temp;
    temp=s2;
    s2=s1;
    s1=s0^temp;
    s0=temp^e;
    c_buf[i]=buffer[i]^e;
    if (e==1)     //若出錯(cuò),,對(duì)緩存進(jìn)行清零
    begin
    s0=0;   s1=0;   s2=0;
    - 81 - 程序文本
    end
    end
    end
   always @(posedge clk)
    begin
    c=c_buf;
    end
   endmodule
    【例12.13】CRC編碼
   module crc(crc_reg,crc,d,calc,init,d_valid,clk,reset);
   output[15:0] crc_reg;
   output[7:0] crc;
   input[7:0] d;
   input calc;
   input init;
   input d_valid;
   input clk;
   input reset;
   reg[15:0] crc_reg;
   reg[7:0] crc;
   wire[15:0] next_crc;
   always @(posedge clk or posedge reset)
    begin
    if (reset)
    begin
    crc_reg <= 16'h0000;
    crc <= 8'h00;
    end
    else if (init)
    begin
    crc_reg <= 16'h0000;
    crc <= 8'h00;
    end
    else if (calc & d_valid)
    begin
- 82 -
    王金明:《Verilog HDL程序設(shè)計(jì)教程》
    crc_reg <= next_crc;
    crc <= ~{next_crc[8], next_crc[9], next_crc[10], next_crc[11],
    next_crc[12], next_crc[13], next_crc[14], next_crc[15]};
    end
    else if (~calc & d_valid)
    begin
    crc_reg <= {crc_reg[7:0], 8'h00};
    crc <= ~{crc_reg[0], crc_reg[1], crc_reg[2], crc_reg[3],
    crc_reg[4], crc_reg[5], crc_reg[6], crc_reg[7]};
    end
   end
   assign next_crc[0] = crc_reg[12] ^ d[7] ^ crc_reg[8] ^ d[3];
   assign next_crc[1] = crc_reg[13] ^ d[6] ^ d[2] ^ crc_reg[9];
   assign next_crc[2] = d[5] ^ crc_reg[14] ^ d[1] ^ crc_reg[10];
   assign next_crc[3] = d[4] ^ crc_reg[15] ^ d[0] ^ crc_reg[11];
   assign next_crc[4] = crc_reg[12] ^ d[3];
   assign next_crc[5]=crc_reg[12]^crc_reg[13]^d[7]^crc_reg[8]^d[2]^d[3];
   assign next_crc[6] = crc_reg[13] ^ d[6] ^ crc_reg[14] ^ d[1] ^ d[2] ^crc_reg[9];
   assign next_crc[7] = d[5] ^ crc_reg[14] ^ crc_reg[15] ^ d[0] ^ d[1] ^crc_reg[10];
   assign next_crc[8] = d[4] ^ crc_reg[15] ^ d[0] ^ crc_reg[0] ^ crc_reg[11];
   assign next_crc[9] = crc_reg[12] ^ crc_reg[1] ^ d[3];
   assign next_crc[10] = crc_reg[13] ^ d[2] ^ crc_reg[2];
   assign next_crc[11] = crc_reg[3] ^ crc_reg[14] ^ d[1];
   assign next_crc[12] = crc_reg[12] ^ crc_reg[4] ^ d[7] ^ crc_reg[15]
    ^ d[0] ^ crc_reg[8] ^ d[3];
   assign next_crc[13] = crc_reg[13] ^ d[6] ^ crc_reg[5] ^ d[2] ^ crc_reg[9];
   assign next_crc[14] = d[5] ^ crc_reg[14] ^ crc_reg[6] ^ d[1] ^ crc_reg[10];
   assign next_crc[15] = d[4] ^ crc_reg[15] ^ d[0] ^ crc_reg[7] ^ crc_reg[11];
   endmodule

    - 83 -
 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多