FPGA学习笔记(四)————Verilog HDL条件语句与循环语句

文章目录

  • FPGA学习笔记(四)————Verilog HDL条件语句与循环语句
    • 1.if--else语句
    • 2.case语句
    • 3.forever语句
    • 4.repeat语句
    • 5.while语句
    • 6.for语句
    • 7.disable语句

1.if–else语句

  • 其格式与C语言中的if–else语句类似,使用方法有以下3种:

    //形式1:只有if的形式
    if(表达式)  语句1;
    if(表达式)begin表达式1;end
    //形式2:if--else形式
    if(表达式)语句或语句块1;
    else语句或语句块2;
    //形式3:if--else嵌套形式
    if ( 表达式1)    语句1;
    else if ( 表达式2 )  语句2;
    else if ( 表达式3 )  语句3;
    ........
    else if ( 表达式m )  语句m;
    else               语句n;
    //例如:
    if ( a > b )      out = int1;
    else if ( a == b)  out1= int2;
    else           out1 = int3; 
  • 表达式:一般为逻辑表达式或关系表达式,也可能是一位的变量。

  • 系统对表达式的值进行判断,若为0,x,z,按“假”处理;若为1,按“真”处理,执行指定语句。

  • 语句可是单句,也可是多句,多句时用“begin - end”语句括起来。对于if语句的嵌套,若不清楚if和else的匹配,最好用begin-end语句括起来。

  • 条件语句必须在过程块中使用:

    always@(a,b,int1,int2) beginif(a>b)begin      out1=int1;     out2=int2;        endelsebegin       out1=int2;       out2=int1;      endend
    
  • 允许一定形式的表达式简写方式:

    if(expression) 等同于 if(expression == 1)

    if(!expression) 等同于 if(expression!= 1)

  • if语句的嵌套,即在if语句中又包含一个或多个if语句称为if语句的嵌套。应当注意if与else的配对关系,else总是与它上面的最近的if配对。

  • if-else 嵌套形式隐含优先级关系:

     always@(sela or selb or a or b or c)beginif(sela)  q=a;else if(selb) q=b;else q=c;end
    

2.case语句

  • Verilog语言提供的case语句直接处理多分支选择,通常用于描述译码器、数据选择器、状态机及微处理器的指令译码等,它的一般形式如下:

    case(表达式)分支表达式1:语句1;分支表达式2:语句2;···分支表达式n:语句n;default: 语句n+1; //如果前面列出了表达式所有可能取值,default语句可以省略
    endcase
    
  • case括弧内的表达式称为控制表达式,case分支项中的表达式称为分支表达式。分支表达式则用这些控制信号的具体状态值来表示,因此分支表达式又可以称为常量表达式。

  • 当控制表达式的值与分支表达式的值相等时,就执行分支表达式后面的语句;如果所有的分支表达式的值都没有与控制表达式的值相匹配,就执行default后面的语句。

  • 分支表达式后面的语句也可以是由begin-end括起来的语句块。

  • default项可有可无,一个case语句里只准有一个default项。同样,case也只能在块语句中使用。

//case语句实现3-8译码器的部分代码如下:wire[2:0] sel;reg[7:0]  res;always @ (sel or res)begin
//case语句;case (sel)3’b000 : res=8’b00000001;3’b001 : res=8’b00000010;3’b010 : res=8’b00000100;3’b011 : res=8’b00001000;3’b100 : res=8’b00010000;3’b101:  res=8’b00100000;3’b110 : res=8’b01000000;default:  res=8’b10000000;endcaseend
  • case语句的所有表达式值的位宽必须相等,只有这样,控制表达式和分支表达式才能进行对应位的比较。一个经常犯的错误是用’bx,'bz来替代n’bx,n’bz,这样写是不对的,因为信号x,z的默认宽度是机器的字节宽度,通常是32位。

  • 执行完case分项后的语句,则跳出该case语句结构,终止case语句的执行。

  • 在case语句中,表达式与分支表达式1到分支表达式n之间的比较是一种全等比较(===),必须保证两者的对应位全等。如果表达式的值和分支表达式的值同时为不定值或者同时为高阻态,则认为是相等的

    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
    case ( a )2’b1x:out = 1;   // 只有a = 1x,才有out = 12’b1z:out = 0;    // 只有a = 1z,才有out = 0...
    endcase
    
  • case(select[1,2])2'b00: result   = 0;2'b01: result   = flaga;2'b0x,2'b0z: result   = flaga ? 'bx:0;2'b10: result   = flagb;2'bx0,2'bz0: result   = 0;default: result   = flagb ? 'bz:0;endcase
    //当多个分项可以共用一个语句或语句块。其分支表达式之间用“,”隔开。
    
  • case语句还有两种变种,即casez语句和casex语句。

  • casez:

    ​ 忽略比较过程中值为z的位,即如果比较的双方(表达式的值与分支表达式的值)有一方的某一位的值是z,那么对这些位的比较就不予考虑,只需关注其他位的比较结果。

  • casex:

    ​ 在casex语句中,则把这种处理方式进一步扩展到对x的处理,即将z和x均视为无关值。

    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
    //在分支表达式中,z常用?代替。
    casez(a)3'b1?? :  out1 = 1;//如果a=100、101、110、111或1xx,1zz等,都有out1 = 1。3'b0?1 :  out2 = 1; //如果a=001、011、0x1、0z1,都有out2 = 1.......
    endcase
    
    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
    例如:casex(a)2'b1x:out=1;  ..................endcase
    //如果a=10、11、1x、1z,都有out=1。
    
  • if语句条件不完备情况

    如果if语句和case语句的条件描述不完备,会造成不必要的锁存器 。

    一般不可能列出所有分支,因为每一变量至少有4种取值0,1,z,x。为包含所有分支,可在if语句最后加上else;在case语句的最后加上default语句。

  • 回顾一下锁存器和寄存器的区别:

always@(a or b) begin if(a == 1’b1)y = b;end

always@(posedge clk) begin if(a == 1’b1)y <= b;end
//毛刺通过D触发器被滤除


  • 对FPGA来说,它的基本逻辑单元由多输入查找表、 D触发器构成,并不存在锁存器结构,因此如果在FPGA设计中使用锁存器,需要更多的资源来搭建锁存器,反而会更消耗资源。

  • 所以在FPGA设计中,应该避免锁存器。在时序逻辑电路中,可以将锁存器改为带使能端的D触发器;在组合电路中,可以通过更改代码以覆盖所有条件分支等方式避免产生锁存器。

     always @(al or d)beginif(al)q<=d;end//有锁存器
    always @(al or d)beginif(al)   q<=d;else    q<=0end//无锁存器
    
  • 检查一下上边的"always"块,if语句保证了只有当al=1时,q才取d的值。这段程序没有写出 al = 0 时的结果, 那么当al=0时会怎么样呢?

    在"always"块内,如果在给定的条件下变量没有赋值,这个变量将保持原值,也就是说会生成一个锁存器!

  • 避免偶然生成锁存器的错误。如果用到if语句,最好写上else项。如果用case语句,最好写上default项。遵循上面两条原则,就可以避免发生这种错误,使设计者更加明确设计目标,同时也增强了Verilog程序的可读性。

3.forever语句

forever语句的格式如下:forever   语句;或者:    foreverbegin            语句1;语句2;……end
  • forever表示永久循环,无条件地无限次执行其后的语句,相当于while(1),直到遇到系统任务$finish$stop,如果需要从循环中退出,可以使用disable

  • 循环语句多用于生成时钟等周期性波形,它与always语句不同之处在于不能独立写在程序中,而必须写在initial块中。

    initialbeginclk = 0;forever #25 clk = ~clk;     end
    
  • forever应该是过程块中最后一条语句。其后的语句将永远不会执行。

  • forever语句不可综合,通常用于testbench描述。

    ...
    reg clk;
    initialbeginclk = 0;forever //这种行为描述方式可以非常灵活的描述时钟,可以控制时钟的开始时间及周期占空比。仿真效率也高。begin#10 clk = 1;#10 clk = 0;end
    end
    ...
    

4.repeat语句

  • repeat语句是最简单的循环语句,用于循环次数已知的情况。

    repeat语句的表达形式为:

    repeat(循环次数)begin操作1;操作2;………end
    
  • 下例实现连续8次循环左移的操作:

    if (rotate == 1)repeat (8)     begintemp = data[15];data = {data << 1,temp};  // data循环左移8次end
    

5.while语句

  • while语句通过控制某个变量的取值来控制循环次数。一般表达形式:

    while(条件)begin操作1;操作2;………end
    

    在使用while语句时,一般在循环体内更新条件的取值,以保证在适当的时候退出循环。

  • 下例实现连续4次循环的操作

    i = 0;
    while(i < 4)begina = a + 1;//更新条件取值,使循环4次退出循环i = i + 1; end
    
  • 可见在while结构中只要表达式为真(不为0),则重复执行一条语句(或语句块)

    //其功能为:统计tempreg中 1 的个数
    . . .
    reg [7: 0] tempreg;
    reg [3: 0] count;
    . . .count = 0;while (tempreg) beginif (tempreg[0]) count = count + 1;tempreg = tempreg >> 1; // Shift rightend
    end
    . . .
    /*
    Tempreg:10110101001000010000
    */
    

6.for语句

  • for语句可以实现所有的循环结构。其表达形式如下:

    for(循环变量赋初值;条件表达式;更新循环变量)begin操作1:操作2;………end
    
  • 它的执行过程如下:

    (1)先对循环变量赋初值。

    (2)计算条件表达式,若其值为真(非0),则执行for语句中指定的内嵌语句,然后执行下面的第(3)步。若为假(0),则结束循环,转到第5步。

    (3) 若条件表达式为真,在执行指定的语句后,执行更新循环变量。

    (4) 转回上面的第(2)步骤继续执行。

    (5) 执行for语句下面的语句。

for(i = 0; i <4; i =i+1)begin a = a+1;end
  • 例:用for语句来实现8位数据中低4位左移到高4位;

        integer i;reg [7:0] datain;always @ (posedge clk)beginfor(i=4;i<=7;i=i+1)begindatain[i]  <=  datain [i-4];endend   
    
  • 例:编写 在一个时钟周期内用for语句计算出13路脉冲信号为高电平的个数。

       input clk,rst;input [12:0]  datain;    output [3:0]  numout;    reg [3:0] i;reg [3:0] num;always @ (posedge clk) beginif ( !rst )  //重置信号num <= 0;  else beginfor ( i = 0; i < 13; i = i + 1)   //用for循环进行计算if ( datain [i ] )  num  <= num +1;                   endend
    

7.disable语句

  • 在有些特殊的情况下,需要使用disable强制退出循环。
  • 使用disable语句强制退出循环,首先要给循环部分起个名字,方法是在begin后添加“: 名字”。即disable语句可以中止有名字的begin…end块和fork…join块。
  • 语句块可以具有自己的名字,这称为命名块。

命名块的特点是:

命名块中可以声明局部变量;

命名块是设计层次的一部分,命名块中声明的变量可以通过层次名引用进行访问

命名块可以被禁用,例如停止其执行。

 //命名块module top;initialbegin : block1integer i;……….endinitialfork : block2reg i;……….……….join
  • Verilog通过关键字disable提供了一种中止命名块执行的方法。

    disable可以用来从循环中退出、处理错误条件以及根据控制信号来控制某些代码段是否被执行。

    对块语句的禁用导致本块语句终止执行,紧接在块后面的那条语句被执行。

  • 例:(在C语言中break和continue的区别)

    begin  :continuea = 0; b =0;for(i=0;i<4;i = i+1)begina = a+1;if(i==2) disable continue;b = b+1;endend……………….;//a做3次加1操作后强制退出循环;而b只做2次加1操作。
    
         a=0; b=0;for( i=0; i<4; i=i+1)begin: continuea = a+1;if( i ==2) disable continue;b= b+1;end……………………….;
    //中止一次循环,继续下一次循环; a做4次加1操作, b只做3次加1操作.
    

FPGA学习笔记(四)——Verilog HDL条件语句与循环语句相关推荐

  1. Java快速入门学习笔记6 | Java语言中的for循环语句

    有人相爱,有人夜里开车看海,有人却连LeetCode第一题都解不出来!虽然之前系统地学习过java课程,但是到现在一年多没有碰过Java的代码,遇到LeetCode不知是喜是悲,思来想去,然后清空自己 ...

  2. Java快速入门学习笔记5 | Java语言中的while循环语句

    有人相爱,有人夜里开车看海,有人却连LeetCode第一题都解不出来!虽然之前系统地学习过java课程,但是到现在一年多没有碰过Java的代码,遇到LeetCode不知是喜是悲,思来想去,然后清空自己 ...

  3. Python学习笔记之常用操作符,条件分支和循环用法示例

    本文实例讲述了Python常用操作符,条件分支和循环用法.分享给大家供大家参考,具体如下: #Pyhon常用操作符 ''' 想要学习Python?Python学习交流群:973783996满足你的需求 ...

  4. Python基础学习笔记(三)条件选择与循环

    文章目录 本节知识大纲: 一.条件选择语句 1. if语句 2. if-else语句 3. if-elif语句 二.循环 1. 循环语句三要素 2. while语句 3. while--else--语 ...

  5. python常用操作符_Python3.4学习笔记之常用操作符,条件分支和循环用法示例

    本文实例讲述了Python3.4常用操作符,条件分支和循环用法.分享给大家供大家参考,具体如下: #Pyhon常用操作符 c = d = 10 d /= 8 #3.x真正的除法 print(d) #1 ...

  6. 【FPGA学习笔记】Verilog语言中的或(|和||)

    最近在学习过程中遇到if语句判断位宽不同的数相或的情况,就很迷惑,在询问同学后得到以下结论. 一.|和||的区别 |是按位或:将 a 的每个位与 b 相同的位进行相或 ||是逻辑或:a 或上 b,如果 ...

  7. 【FPGA学习笔记】Verilog语言的模块化设计

    在进行模块化设计中,对于复杂的数字系统,我们一般采用自顶向下的设计方式.可以把系统划分成几个功能模块,每个功能模块再划分成下一层的子模块:每个模块的设计对应一个module,一个module设计成一个 ...

  8. FPGA 学习笔记:Verilog 实现LED流水灯控制

    前言 在初步了解 Xilinx Vivado 的使用后,开启了FPGA Hello World 程序:LED 流水灯控制 在嵌入式MCU中,流水灯需要延时来实现,FPGA的延时,使用外部晶振来实现 目 ...

  9. FPGA学习笔记---Verilog HDL 可综合语句和不可综合语句汇总

    作为HDL语言,有两种基本的用途:系统仿真和设计实现.所有的HDL描述都可用于仿真,但并非所有的HDL描述都可综合. 一般综合工具支持的Verilog HDL结构 Verilog HDL结构 可综合性 ...

  10. (23)Verilog HDL条件语句:if-else语句

    (23)Verilog HDL条件语句:if-else语句 1.1 目录 1)目录 2)FPGA简介 3)Verilog HDL简介 4)Verilog HDL条件语句:if-else语句 5)结语 ...

最新文章

  1. 三分钟基础:什么是拥塞控制?
  2. 什么是婚礼一条龙服务及一站式服务
  3. linux系统上tomcat启动正常,但浏览器无法访问
  4. MacBook file storage 256g is ok
  5. hadoop SecondaryNameNode和NameNode
  6. Python 链接汇总
  7. python字符串创建_在Python上创建完整的字符串
  8. ZendFrameWork——文件夹标准
  9. sqlalchemy mysql教程_SQLAlchemy 教程 —— 基础入门篇
  10. Android/Linux性能分析工具推荐
  11. Apache Hudi入门应用
  12. matlab 求矩阵各行的平均值
  13. Mycat 使用navicat连接 报: no datanode found please check tables defined is schema:test
  14. tomca的用户设置
  15. vue+elementui身份证验证
  16. LabVIEW控制Arduino实现RGB调色灯(基础篇—6)
  17. Ubuntu下PX4飞控开发环境搭建
  18. 基于Proteus的8×8LED点阵实验
  19. 关于瞎报Access violation writing location异常的瞎解决方法
  20. 美国FDA注册,罐头食品FDA注册

热门文章

  1. [转]MFC程序调出console窗口
  2. Notification 与状态栏信息介绍
  3. 手把手教你使用码云(图文并茂,项目讲解)
  4. 基于Linux C++ windows qt开发的在线答题系统
  5. 读心术出现?AI模型将脑成像解读为自然语言!
  6. 【经验】交付代码注意事项
  7. lwIP RAW_API
  8. svn clean up 时 .svn\pristine\cc\cca2e58e9e310a113a37e3bd87eae3a42434e899.svn-base 找不到文件解决方法
  9. 大促流量激增,通过什么手段提升系统的高并发、高可用性?
  10. 怎样隐藏app应用标题