Menu Close

Verilog if语句

在Verilog语法中有三种判断与分支语句,分别是if语句,case 语句,和问号?语句。它们有相似的地方,也有不同之处,下面就语法定义、使用场景、注意事项以及异同点进行描述,并以实例应用的方式一一介绍。

在Verilog语法中if 语句有如下几种形式:

1.If(…)格式

if (判断条件)
begin
    ....
    ....
    ....
end

  • 格式描述

if 后面跟由()括起来的判断条件,之后是由begin…end关键字括起来的顺序语句块,如果if后只跟一条执行语句,begin和end关键字可以省略。如:

if(a>b) 
begin
    c[3:0] = 5;
end

可以直接写成:

if(a>b)
    c[3:0] = 5;

  •   if引导的语句块是顺序语句

由if和begin…end 引导的语句是顺序语句,因此if语句只能用在如always,initial,function,task等顺序过程中,不能在连续赋值语句中使用。

if 语句的含义:如果判断条件为真,则执行if之后的语句,否则不执行。

例1:错误位置使用if语句

module selx
(
    input  [1:0] sel,
    input  [3:0] a,b,

    output [3:0] c
);

if(sel) 
begin //错误,if语句不能直接用在并发过程中
    assign c = a;
end

endmodule

例1中红色部分表示在并发过程中使用if语句是错误的。if语句只能用在顺序语句中,可以将上面的程序改写成例2所示就正确。

 

  • 判断条件
    • 判断条件一般为关系表达式、等式表达式或由逻辑符号组成复杂表达式的返回值,一般只有真/假两个值。

例2:

module  selx
(
    input            sel,
    input      [3:0] a, b,
 
    output reg [3:0] c
);
 
always@(*)
if(sel)  
begin   
    c = a;
end
 
endmodule

该程序在sel为1时执行c=a; 否则该语句不被执行,而c将维持原值不变。

注: if(sel)等效为if(sel==1’b1),实际判断条件为等式表达式。

 

2. 双重选择结构if …else…

如果有双重选择,则需要使用if…else…结构。

例3:

module selx
(
    input            sel,
    input      [3:0] a, b,
 
    output reg [3:0] c
);
 
always@(*)
if(sel)    
    c = a;
else
    c = b;
 
endmodule

例3中的行为解释如下:如果sel为1,则a赋值给c,否则b赋值给c。

注意在仿真时sel的值为X时,将会按照false进行处理,这一点在Modelsim仿真时可以得到验证,因此if语句将会阻止 ‘X’的传递。下面加上激励程序,观察仿真结果。

例3的仿真程序如下:

module  top_sim
(
);
 
reg        sel;
reg [3:0]  a,b;
wire [3:0] c;
initial 
begin
    sel = 0;
    a = 1;
    b = 2;
    #10
 
    sel = 1;
    #10
 
    sel = 1'bX;
end
 
selx selx_dut
(
    .sel (sel),
    .a   (a),
    .b   (b),
    .c   (c)
);
 
endmodule

%title插图%num
图1

从图1中可以看出在判断语句中,如果判断语句的结果为’x’或’Z’,也是判断为假的(false)。

当判断表达式为向量时的情况, 参照例4。
例4:

module selx 
( 
    input      [1:0] sel, 
    input      [3:0] a, b, 
    output reg [3:0] c 
); 
always@(*) 
if(sel) 
    c = a; 
else 
    c = b; 

endmodule

 

例4的仿真程序如下:

module
(
 
);
 
reg [1:0] sel;
reg [3:0] a,b;
 
wire [3:0] c;
 
initial 
begin
    sel = 0;
    a = 1;
    b = 2;
    #10
    sel = 2'b01;
    #10
    sel = 2'b10;
    #10
    sel = 2'b11;
    #10
    sel = 2'b0x;
    #10
    sel = 2'b1x;
    #10
    sel = 2'bx0;
    #10
    sel = 2'bx1;
    #10
    sel = 2'bxx;
end
 
selx selx_dut
(
    .sel (sel),
    .a   (a),
    .b   (b),
    .c   (c)
);
 
endmodule

仿真结果如下:

%title插图%num

图2

由图2可见,如果表达式的结果为向量,首先将sel按位或运算,即等效为if(|sel),如果sel中含有’X’或’Z’, 先按位或处理 ‘x’或’z’,再判断。

或者也可以这样理解,即向量中各个位的组合有全0值即为假,否则为真。

如”0x”组合为00,01两种,有“00” 组合,因此为假。

同样“x0″的两种组合为”00″,”10″也包含”00″ 组合,因此也为假。

而”1x”的组合为”10″,”11″,因此结果判断为真。请自行分析”x1″,”xx”的情况。

 

3.多重分支结构If…else if…else if …else…

如果分支多于两个则可以选择多重分支结构。多重分支结构用于判断条件比较多的情况,如果不能罗列所有条件,else将执行所有没有列出的条件。

例5:

module selx 
(
    input      [1:0] sel, 
    input      [3:0] a, b, m, n,
    output reg [3:0] c 
);
always@(*)
if(sel==0) 
    c = a;
else if(sel==1)
    c = b; 
else if(sel==2)
    c = m;
else
    c = n;
 
endmodule

例5的仿真程序如下:

module tb
(
 
);
 
reg [1:0] sel;
reg [3:0] a,b;
 
wire [3:0] c;
 
initial 
begin
    sel = 0;
    a = 1;
    b = 2;
    m = 3;
    n = 4;
    #10
    sel = 2'b01;
    #10
    sel = 2'b10;
    #10
    sel = 2'b11;
    #10
    sel = 2'b0x;
    #10
    sel = 2'b1x;
    #10
    sel = 2'bx0;
    #10
    sel = 2'bx1;
    #10
    sel = 2'bxx;
end
 
selx selx_dut
(
    .sel (sel),
    .a   (a),
    .b   (b),
    .m   (m),
    .n   (n),
    .c   (c)
);
 
endmodule

 

例5中,如果sel!=0,1,2三个值,其它的条件都会执行c=n; 如if(sel==2’bxx)等。

  • 程序中else是可选的,此时如果不满足if…else if…条件时,不执行任何代码,变量的值也保持不变。

如果将例5改成例6,则在if(sel==2’bxx)成立时,变量c的值将保持不变。

例6:

module selx
( 
    input      [1:0] sel,
    input      [3:0] a, b, m, n,
    output reg [3:0] c
);
 
always@(*)
if(sel==0)      c = a;
else if(sel==1) c = b;
else if(sel==2) c = m;
 
endmodule
  • if语句是有优先顺序的,也就说在if…else if …的结构中if…的优先级(level of precedence ) 高于else if…,而else if…的优先级又高于之后的else if….或else…。因此if语句更适合描述含有优先级的电路。

例7:利用有优先级功能的if语句描述74LS148 8/3优先编码器

 module M74ls148
(

    input        nst,
    input  [7:0] nin,

    output [2:0] y,
    output       yex,
    output       ys
);


always@(*) 
begin
    if(nst)
    begin
        y = 3'b111;
        yex = 1'b1;
        ys = 1'b1;
    end
    else
    begin
        if( !nin[7] )     y = 3'b000;
        else if (!nin[6]) y = 3'b001;
        else if (!nin[5]) y = 3'b010;
        else if (!nin[4]) y = 3'b011;
        else if (!nin[3]) y = 3'b100;
        else if (!nin[2]) y = 3'b101;
        else if (!nin[1]) y = 3'b110;
        else if (!nin[0]) y = 3'b111;
        else              y = 3'b111;


       if(~nin)
       begin
           yex = 1'b0;
           ys = 1'b1;
       end
       else
       begin
           yex = 1'b1;
           ys = 1'b0;
       end
    end
end


endmodule

 

Posted in FPGA, FPGA, Verilog, Verilog

发表评论

相关链接