DIY编程器网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1204|回复: 0
打印 上一主题 下一主题

[待整理] Verilog HDL基础之:其他常用语句

[复制链接]
跳转到指定楼层
楼主
发表于 2014-10-12 16:33:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
        循环语句

        在Verilog HDL中存在着4种类型的循环语句,用来控制执行语句的执行次数。
        (1)forever:连续的执行语句。
        (2)repeat:连续执行一条语句 n 次。
        (3)while:执行一条语句直到某个条件不满足。如果一开始条件即不满足(为假),则语句一次也不能被执行。
        (4)for通过以下3个步骤来决定语句的循环执行。
        ① 先给控制循环次数的变量赋初值。
        ② 判定控制循环的表达式的值,如为假则跳出循环语句,如为真则执行指定的语句后,转到步骤③。
        ③ 执行一条赋值语句来修正控制循环变量次数的变量的值,然后返回步骤②。
        下面将详细地对各种循环语句进行介绍。
         
        1.forever语句

        forever语句的格式如下:
         
        forever 语句;
         
        或者:
         
        forever begin
              多条语句
        end
         
        forever循环语句常用于产生周期性的波形,用来作为仿真测试信号。它与always语句不同之处在于它不能独立写在程序中,而必须写在initial块中。
         
        2.repeat语句

        repeat语句的格式如下:
         
        repeat(表达式) 语句;
         
        或者:
         
        repeat(表达式) begin
              多条语句
        end
         
        在repeat语句中,其表达式通常为常量表达式。下面的例子中使用repeat循环语句及加法和移位操作来实现一个乘法器。
         
        parameter size=8,longsize=16;                 //参数声明
        reg [size:1] opa, opb;                            //寄存器声明
        reg [longsize:1] result;
        begin: mult                                          //为begin_end模块定名模块名
             reg [longsize:1] shift_opa, shift_opb;    //寄存器声明
             shift_opa = opa;                                //将opa、opb的值赋为shift_opa、shift_opb
             shift_opb = opb;
             result = 0;
             repeat(size) begin                            //循环次数
                  if(shift_opb[1])
                  result = result + shift_opa;             //加法操作
                  shift_opa = shift_opa <<1;               //左移1位
                  shift_opb = shift_opb >>1;               //右移1位
             end
        end
         
        3.while语句

        while语句的格式如下:
         
        while(表达式)  语句
         
        或者:
         
        while(表达式) begin
             多条语句
        end
         
        下面举一个while语句的例子,该例子用while循环语句对rega这个8位二进制数中值为1的位进行计数。
         
        begin: count1s
             reg[7:0] tempreg;
             count=0;
             tempreg = rega;
             while(tempreg) begin                //当tempreg中有不为0的位时,循环执行
                  if(tempreg[0])  count = count + 1;    //低位为1时,计数
                  tempreg = tempreg>>1;                     //否则右移1位,此时高位用0填补
             end
        end
         
        4.for语句

        for语句的一般形式为:
         
        for(表达式1;表达式2;表达式3)  语句
         
        它的执行过程如下。
        ① 先求解表达式1。
        ② 求解表达式2,若其值为真(非0),则执行for语句中指定的内嵌语句,然后执行步骤③;若为假(0),则结束循环,转到步骤⑤。
        ③ 若表达式为真,在执行指定的语句后,求解表达式3。
        ④ 转到步骤②继续执行。
        ⑤ 执行for语句下面的语句。
        for语句最简单的应用形式是很易理解的,其形式如下:
         
        for(循环变量赋初值;循环结束条件;循环变量增值)
             执行语句
         
        for循环语句实际上相当于采用while循环语句建立以下的循环结构:
         
        begin
             循环变量赋初值;
             while(循环结束条件) begin
                  执行语句
                  循环变量增值;
             end
        end
         
        这样对于需要8条语句才能完成的一个循环控制,for循环语句只需两条即可。
        下面分别举两个使用for循环语句的例子。例1用for语句来初始化memory。例2则用for循环语句来实现前面用repeat语句实现的乘法器。
         
        例1:for语句1。
        begin: init_mem
             reg[7:0] tempi;
             for(tempi=0;tempi<memsize;tempi=tempi+1)  //使用for循环语句初始化存储器
                  memory[tempi]=0;
             end
         
        例2:for语句2。
        parameter  size = 8, longsize = 16;
        reg[size:1] opa, opb;
        reg[longsize:1] result;
        begin: mult
             integer bindex;
             result=0;
             for( bindex=1; bindex<=size; bindex=bindex+1 )//使用for循环语句实现前面的乘法器
                  if(opb[bindex])
                       result = result + (opa<<(bindex-1)); //加法并移位
        end
         
        在for语句中,循环变量增值表达式可以不必是一般的常规加法或减法表达式。下面是对rega这个8位二进制数中值为1的位进行计数的另一种方法,如下所示:
         
        begin: count1s
             reg[7:0] tempreg;
             count=0;
             for( tempreg=rega; tempreg; tempreg=tempreg>>1 )//循环变量增值表达式使用右移操作
                       if(tempreg[0])
                           count=count+1;
        end
         
        结构说明语句

        Verilog语言中的任何过程模块都从属于以下4种结构的说明语句。
        (1)initial说明语句。
        (2)always说明语句。
        (3)task说明语句。
        (4)function说明语句。
         
        initial和always说明语句在仿真的一开始即开始执行。initial语句只执行一次,always语句则是不断地重复执行,直到仿真过程结束。在一个模块中,使用initial和always语句的次数是不受限制的。task和function语句可以在程序模块中的一处或多处调用,其具体使用方法在第4章中详细介绍。这里只对initial和always语句加以介绍。
         
        1.initial语句

        initial语句的格式如下:
         
        initial begin
             语句1;
             语句2;
             ......
             语句n;
        end
         
        举例说明。
        例3:initial语句1。
         
        initial begin
              areg=0;                               //初始化寄存器areg
              for(index=0; index<size; index=index+1)
                    memory[index]=0;             //初始化一个memory
        end
         
        在这个例子中用initial语句在仿真开始时对各变量进行初始化。
         
        例4:initial语句2。
        initial begin
             inputs = 'b000000;                  //初始时刻为0
             #10 inputs = 'b011001;             //赋值时刻为10
             #10 inputs = 'b011011;             //赋值时刻为20
             #10 inputs = 'b011000;             //赋值时刻为30
             #10 inputs = 'b001000;             //赋值时刻为40
        end
         
        从这个例子中,我们可以看到initial语句的另一个用途,即用initial语句来生成激励波形作为电路的测试仿真信号。一个模块中可以有多个initial块,它们都是并行运行的。initial块常用于测试文件和虚拟模块的编写,用来产生仿真测试信号和设置信号记录等仿真环境。
         
        2.always语句

        always语句在仿真过程中是不断重复执行的,其声明格式如下:
         
        always <时序控制>  <语句>
         
        always语句由于其不断重复执行的特性,只有和一定的时序控制结合在一起才有用。如果一个always语句没有时序控制,则这个always语句将会发成一个仿真死锁,例如:
         
        always  areg = ~areg;
         
        这个always语句将会生成一个0延迟的无限循环跳变过程,这时会发生仿真死锁。如果加上时序控制,则这个always语句将变为一条非常有用的描述语句,例如:
         
        always #half_period  areg = ~areg;
         
        这个例子生成了一个周期为period(2×half_period) 的无限延续的信号波形,常用这种方法来描述时钟信号,作为激励信号来测试所设计的电路。
         
        reg[7:0] counter;
        reg tick;
        always @(posedge areg) begin
             tick = ~tick;                  //tick反相
             counter = counter + 1;        //计数器递增
        end
         
        这个例子中,每当areg信号的上升沿出现时,把tick信号反相,并且把counter增加1。这种时间控制是always语句最常用的。
        always 的时间控制可以是沿触发也可以是电平触发的,可以单个信号也可以多个信号,中间需要用关键字 or 连接,如:
         
        always @(posedge clock or posedge reset) begin   //由两个沿触发的always块
            …
        end
         
        always @( a or b or c ) begin                        //由多个电平触发的always块
            …
        end
         
        沿触发的always块常常描述时序逻辑,如果符合,可综合风格要求,用综合工具自动转换为表示时序逻辑的寄存器组和门级逻辑。电平触发的always块常常用来描述组合逻辑和带锁存器的组合逻辑,如果符合,可综合风格要求,转换为表示组合逻辑的门级逻辑或带锁存器的组合逻辑。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|文字版|手机版|DIY编程器网 ( 桂ICP备14005565号-1 )

GMT+8, 2025-8-3 05:01 , 耗时 0.081946 秒, 18 个查询请求 , Gzip 开启.

各位嘉宾言论仅代表个人观点,非属DIY编程器网立场。

桂公网安备 45031202000115号

DIY编程器群(超员):41210778 DIY编程器

DIY编程器群1(满员):3044634 DIY编程器1

diy编程器群2:551025008 diy编程器群2

QQ:28000622;Email:libyoufer@sina.com

本站由桂林市临桂区技兴电子商务经营部独家赞助。旨在技术交流,请自觉遵守国家法律法规,一旦发现将做封号删号处理。

快速回复 返回顶部 返回列表