您现在的位置是:首页 >技术教程 >ASIC-WORLD Verilog(8)if-else语句和case语句网站首页技术教程

ASIC-WORLD Verilog(8)if-else语句和case语句

孤独的单刀 2023-06-11 20:00:03
简介ASIC-WORLD Verilog(8)if-else语句和case语句

 写在前面

        在自己准备写一些简单的verilog教程之前,参考了许多资料----Asic-World网站的这套verilog教程即是其一。这套教程写得极好,奈何没有中文,在下只好斗胆翻译过来(加了自己的理解)分享给大家。

        这是网站原文:Verilog Tutorial

        这是系列导航:Verilog教程系列文章导航

条件语句之if-else

        和C语言等程序语言类似,Verilog语法中的 if - else 语句可以根据条件的真假来选择执行不同分支的语句。如果每个分支需要执行的语句不止一条,则需要将这些语句都包含在 begin-end 语句之中。

if语句

        不带有分支的单独的if语句的一般语法:

if (condition)               //如果条件为真

        statements;        //则执行这条语句

        以下代码:当使能信号enable为真即执行语句latch <= din;

module simple_if();

reg latch;
wire enable,din;

always @ (enable or din)
if (enable) begin
  latch <= din;
end  

endmodule

  

if-else语句

        带有分支的if-else语句的一般语法:

if (condition)                //如果条件为真

        statements;         //则执行这条语句       

else                             //否则,即条件为假

        statements;         //则执行这条语句 

        以下代码:当复位信号reset为真即执行语句dff <= 0;否则执行语句dff <= din;

module if_else();

reg dff;
wire clk,din,reset;

always @ (posedge clk)
if (reset) begin
  dff <= 0;
end else  begin
  dff <= din;
end

endmodule

 

if-else if-else语句

        多级的if-else if-else语句的一般语法:

if (condition1)                //如果条件1为真

        statements;           //则执行这条语句            

else if (condition2)        //如果条件1为假但是条件2为真

        statements;           //则执行这条语句       

        ................

        ................

else                                //如果以上所有例举的条件均为假

        statements;            //则执行这条语句       

        以下代码:当复位信号reset为真即执行语句counter <= 4'b0000;当复位信号reset为假且使能信号为真与up_en信号为真即执行语句counter <= counter  + 1; 当复位信号reset为假且使能信号为真且up_en信号为假与up_down信号为真即执行语句counter <= counter  - 1; 当以上所有条件均不满足,则执行语句 counter <= counter;

module nested_if();

reg [3:0] counter;
reg clk,reset,enable, up_en, down_en;

always @ (posedge clk)
if (reset == 1'b0) begin
   counter <= 4'b0000; 
end else if (enable == 1'b1 && up_en == 1'b1) begin
   counter <= counter + 1'b1;
end else if (enable == 1'b1 && down_en == 1'b1) begin
   counter <= counter - 1'b1;
end else begin
   counter <= counter; 
end

endmodule

并行的if-else语句

        在上面的例子中条件2(enable == 1'b1 && up_en == 1'b1)比条件3(enable == 1'b1 && down_en == 1'b1)的优先级要高,也就是说当up_en == 1'b1与down_en == 1'b1同时有效时(其他条件相同),此时执行的是条件2对应的执行语句。

        这种优先级的if-else语句消耗的资源要比没有优先级的资源多(判断优先级需要消耗资源),有时我们并不需要对条件做优先级的判断,比如2个输入在逻辑上一定是互斥的情况,这时就可以使用并行的if-else语句来节省资源。

module parallel_if();

reg [3:0] counter;
wire clk,reset,enable, up_en, down_en;

always @ (posedge clk)
if (reset == 1'b0) begin
   counter <= 4'b0000; 
end else begin
  if (enable == 1'b1 && up_en == 1'b1) begin
    counter <= counter + 1'b1;
  end
  if (enable == 1'b1 && down_en == 1'b1) begin
    counter <= counter - 1'b1;
  end 
end  

endmodule

条件语句之case

        同样的,和C语言等程序语言类似,Verilog语法除了 if - else 语句外,也有case语句。case语句会列出多个条件(后边跟执行语句),从上到下根据条件的真假判断来执行对应分支的语句。如果每个分支需要执行的语句不止一条,则需要将这些语句都包含在 begin-end 语句之中。

        这是case语句的一般语法:

case ()        //条件

    < case1 > : < statement >    //条件在这里满足执行对应语句
    < case2 > : < statement >    //条件在这里满足执行对应语句
    .....                        //--
    default : < statement >        //所有情况都不满足则执行这条语句

endcase

        这是一个例子:

module mux (a,b,c,d,sel,y); 
input a, b, c, d; 
input [1:0] sel; 
output y; 

reg y;

always @ (a or b or c or d or sel) 
case (sel)           //sel的值即为条件
  0 : y = a;         //当sel = 0时执行y = a;
  1 : y = b;         //当sel = 1时执行y = b;
  2 : y = c;         //当sel = 2时执行y = c;
  3 : y = d;         //当sel = 3时执行y = d;
  default : $display("Error in SEL"); //当sel不为上面列出的任何一个值时执行这条语句
endcase 
    
endmodule

        default关键字的作用是保证那些没有被例举出来的情况也有对应的执行语句。如果不使用 default 关键字,就需要将所有情况都一一列出,非常麻烦,就像这样:

module mux_without_default (a,b,c,d,sel,y);
input a, b, c, d; 
input [1:0] sel; 
output y; 

reg y;

always @ (a or b or c or d or sel) 
case (sel) 
  0 : y = a; 
  1 : y = b; 
  2 : y = c; 
  3 : y = d; 
  2'bxx,2'bx0,2'bx1,2'b0x,2'b1x,
  2'bzz,2'bz0,2'bz1,2'b0z,2'b1z : $display("Error in SEL");
endcase 

endmodule

casex与casez语句

        由于在verilog语法中,合法的值有4种:0,1,x,z。所有除了case语句外,还有casex与casez语句,他们的用法是这样的:

  • casez : 将 z 看做不在乎(don't care),其他用法同case
  • casex : 将 x 和 z 看做不在乎(don't care),其他用法同case

        下面的代码将case、casex与casez语句的用法做了一个比较:

module case_compare;

reg sel;

initial begin
  #1 $display ("
     Driving 0");
  sel = 0;
  #1 $display ("
     Driving 1");
  sel = 1;
  #1 $display ("
     Driving x");
  sel = 1'bx;
  #1 $display ("
     Driving z");
  sel = 1'bz;
  #1 $finish;
end

always @ (sel)
case (sel)
  1'b0 : $display("Normal : Logic 0 on sel");
  1'b1 : $display("Normal : Logic 1 on sel");
  1'bx : $display("Normal : Logic x on sel");
  1'bz : $display("Normal : Logic z on sel");
endcase

always @ (sel)
casex (sel)
  1'b0 : $display("CASEX  : Logic 0 on sel");
  1'b1 : $display("CASEX  : Logic 1 on sel");
  1'bx : $display("CASEX  : Logic x on sel");
  1'bz : $display("CASEX  : Logic z on sel");
endcase

always @ (sel)
casez (sel)
  1'b0 : $display("CASEZ  : Logic 0 on sel");
  1'b1 : $display("CASEZ  : Logic 1 on sel");
  1'bx : $display("CASEZ  : Logic x on sel");
  1'bz : $display("CASEZ  : Logic z on sel");
endcase

endmodule

        其仿真结果是这样的:

  Driving 0
Normal : Logic 0 on sel
CASEX  : Logic 0 on sel
CASEZ  : Logic 0 on sel

  Driving 1
Normal : Logic 1 on sel
CASEX  : Logic 1 on sel
CASEZ  : Logic 1 on sel

  Driving x
Normal : Logic x on sel
CASEX  : Logic 0 on sel
CASEZ  : Logic x on sel

  Driving z
Normal : Logic z on sel
CASEX  : Logic 0 on sel
CASEZ  : Logic 0 on sel

        因为x在casex中视为不在乎,所以直接选择第一条语句有效,即打印  Logic 0 on sel ;同样的,因为z在casez和casex中均视为不在乎,所以都选择第一条语句有效,即打印  Logic 0 on sel。


  • 📣您有任何问题,都可以在评论区和我交流📃!
  • 📣本文由 孤独的单刀 原创,首发于CSDN平台🐵,博客主页:wuzhikai.blog.csdn.net
  • 📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。