Verilog-程序设计语句-三种建模方式

程序设计语句

数据流建模

        显式连续赋值语句:

                ;

                assign # = Assignment expression;

        隐式连续赋值语句:

                # = assignment expression;

                ps. wire(strong0, weak1)[3:0]#(2, 1, 3) w = (a^b)&(m^n);        //对于变量w:赋“0”值时的驱动强度较强,为strong:赋“1”值时的驱动强度较弱,为weak。比如,当0和1共同驱动变量w时,由于0定义的驱动强度较强,所以w为0。

        注意事项:

  • 赋值目标只能是线网类型(wire)。
  • 在连续赋值中,只要赋值语句右边表达式任何一个变量有变化,表达式立即被计算, 计算的结果立即赋给左边信号(若没有定义延时量)。

  • 连续赋值语句不能出现在过程块中。

  • 多个连续赋值语句之间是并行关系,因此与位置顺序无关。

  • 连续赋值语句中的延时具有硬件电路中惯性延时的特性,任何小于其延时量的信号变化脉冲都将被滤除掉,不会出现在输出端口。

行为级建模

Verilog-程序设计语句-三种建模方式_第1张图片

        可综合描述语句:

                过程语句 always

                语句块 串行语句块begin-end 

                赋值语句 过程赋值语句=、<=

                条件语句 if-else case, casez, casex

                循环语句 for

                编译向导语句 'define 'include 'ifdef, 'else, 'endif

        不可综合描述语句:

                过程语句 initial

                语句块 并行语句块fork-join  

                赋值语句 过程连续赋值语句assign

                循环语句 forever repeat while

                编译向导语句 'define 'include 'ifdef, 'else, 'endif

        initial过程语句

                initial过程语句通常用于仿真模块中对激励向量的描述,或用于给寄存器变量赋初值。

                initial过程块在进行仿真时从模拟0时刻开始执行,它在仿真过程中只执行一次,在执

行完一次后该initial过程块就被挂起,不再执行。

initial
    begin
        语句I;
        语句2; 
        语句n;
    end
module initial_tb1:
    reg A, B, C;
        initial
        begin
                A = 0;B= 1;C = O;
            #100 A= 1; B = 0;
            #100 A = 0;C= I;
            #100 B = 1;
            #100 B = 0; C = 0;
        end
endmodule

        always过程语句

always@(<敏感事件列表>)
    语句块;

@(a) //当信号a的值发生改变时
@(a or b) //当信号a或信号b的值发生改变时
@(posedge clock) //当clock的上升沿到来时
@(negedge clock) //当clock的下降沿到来时
@(posedge elk or negedge reset) //当clk的上升沿到来或reset信号的下降沿(低电平有效)到来时

                注意事项:

  • 在信号的形式定义方面,无论是对时序逻辑电路还是对组合逻辑电路进行描述,Verilog HDL要求在过程语句(initial和always)中,被赋值信号必须定义为“reg”类型。

  • 敏感事件列表:

    • 采用过程语句对组合电路进行描述时,需要把全部的输入信号列入敏感事件列表。

    • 采用过程语句对时序电路进行描述时,需要把时间信号和部分输入信号列入敏感事件列表

        四选一数据选择器

/*四选一数据选择器*/
module mux4_l(out, in0, in1, in2, in3, sel):
    output out;
    input in0, ini, in2, in3;
    inpul[1 :0] sel;
    reg out; 〃被赋值信号定义为“reg”类型
    always @(in0 or ini or in2 or in3 or sel) 〃敏感事件列表
        case(sel)
            2'b00: out = inO;
            2'b01: out = ini;
            2'b10: out = in2;
            Z'b11: out = in3;
            default: out = 2'bx;
        endcase
endmodule

        同步置数、同步清零计数器:

module counter 1 (out, data, load, rst, elk);
    output[7:0] out;
    input[7:0] data;
    input load, elk, rst;
    reg[7:0] out;
    always @(posedge elk)    //clk上升沿触发
    begin
        if(!rst) out = 8'h00;    //同步清零,低电平有效
        else if(load) out = data;    //同步置数
        else out = out+ 1;
    end
endmodule

        异步清零计数器:

module counter2(rst, elk, out);
    output[7:0] out;
    input elk, rst;
    reg[7:0] out;
    always @(posedge clk or negedge rst) // clk 上升沿和 rst 低电平清零有效
        begin
            if(!rst) //异步清零
                out = 0;
            else out = out+1;
        end
endmodule

        语句块 

                串行语句块:其中的语句按串行方式顺序执行,可以用于可综合电路程序和仿真测试程序

                        块名即该块的名字,当块内有变量时必须有块名,否则在编译时将出现语法错误。块内声明语句是可选的,可以是参数说明语句‘integer型变量声明语句、reg型变量声明语句、time型变量声明语句和事件(event)说明语句。

begin:块名
    块内声明语句;
    语句1; 
    语句2;
    ...
    语句n;
end

                 并行语句块:语句按并行方式执行,只能用于仿真测试程序,不能用于可综合电路程序。

fork:块名
    块内声明语句: 
    语句1;
    语句2; 
    ...
    语句n;
join

                 两者比较:

语句块

串行语句块(begin-cnd)

并行语句块(fork-join)

执行顺序

按照语句顺序执行

所有语句均在同一时刻执行

语句前面延迟

时间的意义

相对于前一条语句执行结束的相对时间

相对于并行语句块启动的时间

起始时间

首句开始执行的时间

转入并行语句块的时间

结束时间

最后一条语句执行结束的时间

执行时间最长的那条语句执行 结束的时间

行为描述的 意义

电路中的数据在时钟及控制信号的作用下, 沿数据通道中各级寄存器之间传送的过程

电路上电后,各电路模块同时开始工作的过程

        过程赋值语句: 

                阻塞赋值语句:变量=表达式;

                                当一个语句块中有多条阻塞赋值语句时,如果前面的赋值语句没有完成,则后面的语句就不能被执行,仿佛被阻塞了一样,因此称为阻塞赋值方式。

                        特点:

                                在串行语句块中,各条阻塞赋值语句将按照排列顺序依次执行;在并行语句块中的各条阻塞赋值语句则同时执行,没有先后之分。

                                执行阻塞赋值语句的顺序是,先计算等号右端表达式的值,然后立刻将计算的值赋给左边的变量,与仿真时间无关。

                非阻塞赋值语句 :变量 <=表达式;

                        特点:

                               在串行语句块中,各条非阻塞赋值语句的执行没有先后之分,排在前面的语句不会影响到后面语句的执行,各条语句并行执行。

                                执行非阻塞赋值语句的顺序是,先计算右端表达式的值,然后等待延迟时间的结束,再将计算的值赋给左边的变量。

        过程连续赋值语句

                赋值语句和重新赋值语句:assign deassign:使用assign给寄存器型变量赋值之后,该值将一直保 持在这个寄存器上,直至遇到deassign。

                        assign <寄存器型变量>=<赋值表达式>;

                        deassign<寄存器型变量>;

                强制语句和释放语句:force release:主要用于Verilog HDL仿真测试程序中,便于对某种信号进行临时性的赋值和测试。

                        force <寄存器或连线型变量>=<赋值表达式>;

                        release<寄存器或连线型变量>;

        条件分支语句

                if语句:

if(条件表达式)语句块;    //form 1


if(条件表达式)    //form 2
    语句块1;
else
    语句块2;

if(条件表达式1)    //form 3
    语句块1;
else if(条件表达式2)
    语句块2;
    ...
else if(条件表达式i)
    语句块i;
else
    语句块n;

        case语句: 

case(控制表达式) 
    值1:语句块1 
    值2:语句块2 
    ...
    值n:语句块n
    default:语句块 n+l
endcase

                case语句的真值表:

case 0 1 x z
0 1 0 0 0
1 0 1 0 0
x 0 0 1 0
z 0 0 0 1

                 BCD数码管译码:

module BCD_decoder(out, in);
    output[6:0]out;
    input[3:0]in;
    reg[6:0]out;
    always@(in)
        begin
            case(in)
                4'b0000:out = 7'b1111110;
                4'b0001:out = 7'b0110000;
                4'b0010:out = 7'b1101101;
                4'b0011:out = 7'b1111001;
                4'b0100:out = 7'b0110011;
                4'b0101:out = 7'b1011011;
                4'b0110:out = 7'b1011111;
                4'b0111:out = 7'b1110000;
                4'bl000:out = 7'blllllll;
                4'bl001:out = 7'bllll011;
                default:out = 7'bx;
            endcase
        end
endmodule

                 casez:比较双方有一位为z,即认为这一位永远为真

casez 0 1 x z
0 1 0 0 1
1 0 1 0 1
x 0 0 1 1
z 1 1 1 1

                casex:比较双方有一位为x或z,即认为这一位永远为真

casex 0 1 x z
0 1 0 1 1
1 0 1 1 1
x 1 1 1 1
z 1 1 1 1

        循环语句

                forever 语句

forever 语句或语句块;
module forever_tb;
    reg clock;
    initial
        begin
            clock = 0;
            forever #50clock = ~clock;
        end
endmodule

                repeat 语句

repeat(循环次数表达式) 
    语句或语句块(循环体)
module repeat_tb;    //使用repeat语句产生固定周期数的时钟信号。
    reg clock;
    inilial
    begin
        clock = 0;
        repeat(8) clock = -clock;    //循环体所预先制定的循环次数为8次,相应产生4个时钟周期信号
    end
endmodule

                 while 语句

while(条件表达式)语句或语句块;
module while_tb;
    reg clock;
    initial
        begin
            clock = 0;
            while(l)
            #50 clock = ~clock;
        end
endmodule

                 for语句

for(循环变量赋初值:循环结束条件:循环变量增值)语句块;
module for_clk;
    reg cik;
    integer i;
    initial
        begin
            elk = 0;
            for(i = 0; i >= 0: i = i+1)
            #50 elk = ~clk;
        end
endmodule

                        8位移位寄存器

//采用赋值语句实现
module shift_registl(Q, D, rst, elk);
    output [7:0] Q;
    input D, rst, elk:
    reg [7:0] Q;
    always @(posedge elk)
        if(!rst) Q <= 8'b000000;
        else Q <= {Q[6:0], D};
endmodule

//采用for语句实现
module shift_regist2(Q, D, rst, elk);
    output [7:0] Q;
    input D, rst, elk;
    reg [7:0] Q;
    integer i;
    always @(posedge elk)
        if(!rst)Q<= 8'b000000;
        else
        begin
            for (i = 7; i > 0; i = i-1) Q[i] <= Q[i-1];
            Q[0] <= D;
        end
endmodule

结构化建模

模块级建模

        模块调用方式:

                模块名〈参数值列表〉实例名(端口名列表);

        模块端口对应方式:

                端口位置对应方式

                        模块名〈参数值列表〉实例名(<信号名1>. <信号名2>, …,<信号名n>);

                端口名对应方式

                        模块名〈参数值列表〉实例名(.端口名1<信号名1>, .端口名2<信号名2>, …,.端口名n<信号名 n>):

                        dff U4(.q(), ,d(out[2]), .clk(clock), .clr(clear));        //端口列表中第一项内的信号名是缺省的(空括号),表明端口 “q”悬空。

        模块参数值

                使用带有参数的模块实例语句修改参数值

                        模块名〈参数值列表〉调用名(端口名列表);

para l #(4, 3) U1(C1,D1); //利用位置对应方式将4传给a、3传给b,这和模块paral中定义参数的先后顺序有关;
paral #(.b(6), ,a(5)) U2(C2,D2); //利用名称对应方式将6传给b、5传给a,此时和模块paral中定义参数的顺序无关。

                使用参数重定义语句defparam修改参数值      

defparam 
    参数名1 =参数值1,
    参数名2 =参数值2,
    ...
    参数名n =参数值n;
module halfadder(a, b, s, c); 〃半加器模块 halfadder
    input a, b:
    output c, s;
    parameter xor_delay = 2, and_delay = 3:
        assign #xor_delay s = aAb;
        assign #and_delay c = a&b;
endmodule
module fulladder(p, q, ci, co, sum); 〃全加器模块 fulladder
    input p, q, ci;
    output co, sum;
    parameter or_delay = 1;
        wire wl, w2, w3;
            halfadder Ul(p, q, wl, w2);
            halfadder U2(ci, w 1, sum, w3);
            or #or_delay U3(co, w2, w3);
endmodule

module topi(topla, top lb, topis, topic); 〃修改半加器模块参数的模块 topi
    input top la, top lb;
    output topis, topic;
        defparam    U1 .xor_delay = 4,
                    U1 .and_delay = 5;
    //名为U1的半加器实例中对参数xor_delay和参数and_delay值的修改
    halfadder Ul(topla, top lb, topis, topic);
endmodule
module top2(top2p, top2q, lop2ci, top2co, top2sum); 〃修改全加器模块参数的模块 top2
    input top2p, top2q, top2ci;
    output top2co, top2sum;
    defparam    U2.U1.xor_delay = 6,
                U2.U2.and_deIay = 7;
    //名为U2的全加器实例中引用的名为U3的半加器实例中对参数xor_delay和
    //参数and.delay值的修改
        U2.or_delay = 5;
    //名为U2的全加器实例中对参数or_delay值的修改
    fulladder U2(lop2p, top2q, top2ci, top2co, lop2sum);
endmodule

门级建模

Verilog HDL中内置有26个基本元件,其中14个是门级元件,12个为开关级元件

类型

元 件

基本门

多输入门

and, nand, or, nor, xor, xnor

多输出门

buf, not

三态门

允许定义驱动强度

bufif0, bufif1, notif0, notif1

MOS开关

无驱动强度

nmos, pmos, emos

rnmos, rpmos, rcmos

双向开关

无驱动强度

tran, tranif0, tranif1

rtran, rtranifO0, rtranif1

上拉、下拉电阻

允许定义驱动强度

pullup, pulldown

Verilog-程序设计语句-三种建模方式_第2张图片

         门级模块调用

                多输入门元件

                        元件名<实例名>(<输出端口>,<输入端口 1>,<输入端口 2>, <输入端口 n>);

and Al (outl, ini, in2);
or O2 (a, b, c, d);
xor X1 (x_out, pl, p2);

                多输出门元件

                        元件名<实例名>(<输出端口 1>,<输出端口 2>,…,〈输出端口 n>,〈输入端口>);

not NOT_1 (outl, out2, in);
buf BUF_1 (bufoutl, bufout2, bufout3, bufin);

                三态门元件

                        元件名<实例名>(<数据输出端口>,<数据输入端口>,<控制输入端口>);

bufifl BF1 (data_bus, mem_data, enable);
bufifO BFO (a, b, c);
notifl NT1 (out, in, Ctrl);
notifD NTO (addr, a_bus, select);

        2线-4线译码器

module decoder2_4(in0, ini, en, outO, outl, out2, out3);
    output outO, outl, out2, out3;
    input inO, ini, en;
        wire wirel, wire2;
        not Ul(wirel» inO),
            U2(wire2, ini);
        nand U3(outO, en, wirel, wire2),
                U4(outl, en, wire 1, ini),
                U5(out2, en, inO, wire2),
                U6(out3, en, inO, ini);
endmodule

开关级建模

        Verilog HDL提供了十几种开关级基本元件,它们是实际的MOS管的抽象表示。这些

开关级基本元件分为两大类:一类是MOS开关,一类是双向开关。每一大类又可分为电阻

型(前缀用r表示)和非电阻型。

        

        MOS开关:nmos、pmos、cmos

                nmos和pmos开关的实例化语言格式如下:

                        nmos/pmos 实例名(out, data, control);

                coms开关的实例化语言格式如下:

                        cmos 实例名(out, data, ncontrol, pcontrol)

        双向开关:无条件双向开关(tran)和有条件双向开关(tranif0、tranif1)

                tran 实例名(inoutl > inout2);

                tranifO/tranifl 实例名(inoutl, inout2, control);

Verilog-程序设计语句-三种建模方式_第3张图片

         nmos

module aNMOS(din, ctr, out);
    input din, ctr;
    output out;
        nmos Ul(oul, din, ctr);
endmodule

        2输入与非门的cmos电路

module nnand2(a, b, y);
    input a, b;
    output y;
    supplyO Gnd;
    supply1 Vdd: //supplyO 和 supply!为内部参 
                    //量,分别表示低电平和高电平
    wire iml;
        pmos gl(y, Vdd, a);
        pmos g2(y, Vdd, b);
        nmos g3(y, iml, a);
        nmos g4(iml, Gnd, b);
endmodule

你可能感兴趣的:(fpga,学习)