原创 那些年,我们拿下了FPGA-第11章循环语句笔记(2)

2012-12-6 07:58 5917 18 18 分类: FPGA/CPLD 文集: 那些年,我们拿下了FPGA

 

11.1.3 有限的while

我们有了定数的循环和永远的循环,貌似还是少了什么,当我们需要在一定条件下实现有限的循环的时候,又怎么办呢?Verilog这个时候告诉你还有while呢,其格式如下:

while(条件表达式)

         begin

         end

while语句是执行块语句直到某个条件不满足,如果一开始条件就不满足,则while中的块语句一条也不执行,这个与C语言中的用法相同,例如:我们用while对数据中1的个数进行计算,程序代码段如下:

                            while(data_while)

                            begin

                                     if(data_while[0])

                                     begin

                                               data_count = data_count+1;

                                               data_while = data_while>>1;

                                     end

                                     else

                                     begin

                                               data_while = data_while>>1;

                                     end

                            end

 

7.jpg

 

 

上图中红色所圈数据分别是输入数据,和while语句统计的结果,明显地,while语句实现了我们想要的功能,同样地,while语句还是只能仿真,并不能形成电路,最终为我们所用,对于写测试文件,还是会很有帮助的。

 

11.2特立独行的for

前面我们介绍了只能仿真的循环语句,在实际实现的过程中,似乎它们都帮不上什么忙,但是Verilog中还有一个特立独行的for,它能够在电路中实现循环,可是它也存在着弊端,下面我们会通过具体的例子看看Verilog中的for语句存在什么样的问题。

 

11.2.1 for的基本形态

Verilog中的for循环与C语言中的for循环有着相同的使用方式,它是while和repeat的结合体,在满足一定条件下做次数确定的循环。其格式如下:

for(表达式1;表达式2;表达式3) 执行语句

相信这样的表达形式对于写过代码的人都非常熟悉,“表达式1”是循环变量赋初值,它只在第一次循环开始之前被执行一次;“表达式2”是循环执行条件,它在每次循环开始之前都会执行;“表达式3”是循环变量增量,而它是在每次循环结束之后被执行。一般来说,循环变量赋初值即表达式1和循环变量增量即表达式3是两条过程赋值语句,循环执行条件即表达式2是一个逻辑表达式,在每次执行循环体之前都需要判断该表达式是否成立。

有了Verilog中for的基本形态,我们就通过具体的例子来看看这个可以综合的for,以及前面我们提到的for的弊端,且看下节。

 

11.2.2可以综合的for

Verilog中for的基本形态和C语言中一样,就连它的使用也与C语言大同小异,不同之处在于Verilog中的for循环要放在always块语句中,下面是一个用for循环来实现输入数据阶乘的一个简单程序:

moduleLoopingFor(

                                                        data,

                                                        clk,

                                                        rst,

                                                        out

                                              

    );

 

input [3:0] data;

inputclk;

inputrst;

 

output wire [15:0] out;

 

reg [15:0] out_temp=16'd1;

reg [3:0] j;

 

always @(data)

begin

         out_temp=16'd1;

         for(j=data;j!=0;j=j-1)

                   begin

                            out_temp = out_temp*j;

                   end

end

 

assign out = out_temp;

 

endmodule

 

 

8.jpg

 

上图是程序的仿真结果,仿真我们是实现了,但是当我们对上述程序进行综合时,会发现有着这样的问题:

 

9.jpg

for(j=data;j!=0;j=j-1)中表达式1,即循环变量赋初值必须是确定的数值,不能用输入信号进行赋值,也就是说,对于可综合的for循环,for中的三个表达式必须是能计算出来且不再变化的表达式,输入信号出现在三个表达式的任何一个表达式中都不能综合。将上面的例子改为可以综合的for循环,例如:

always @(data)

begin

         out_temp=32'd1;

         for(j=4'd1;j<=4'd16;j=j+1)

                   begin

                            out_temp = (j<=data)?(out_temp*j):out_temp;

                   end

end

所以并不是所有的for都能综合,有的for语句是只能仿真,不能综合,只有当for的三个表达式满足一定条件时才能两面皆能,既仿真又综合,比如下面这个例子,我们对输入数据中1的个数进行计数,程序代码段如下:

always @(posedgeclk)

begin

         if(!rst)

         begin

                   count_1=4'd0;

         end

         else

         begin

                   count_1=4'd0;

                   for(j=0;j<=3;j=j+1)

                            begin

                                     if(data[j])

                                               count_1 = count_1+1;

                                     else;                                     

                            end

         end

end

仿真结果如下:

 

10.jpg

计数输出比输入数据晚一个时钟周期,如图中红线所圈,通过仿真,我们知道该代码段实现了我们想要的功能,同时也能完成综合。

不管怎样,在Verilog编程中,还是建议少使用for循环语句,尤其是过大的for循环,因为循环几次就意味着几个相同电路单元的出现,这样容易造成组合过大,而for循环要在一个时钟周期内执行完毕,过大的for循环可能会导致一些时序问题,不仅仅如此,还会造成资源的浪费,是一种比较懒的编程语句,它仅仅节省了代码长度,但是对于硬件上的实现,却要花费意想不到的代价,得不偿失。

漂亮姑娘不一定适合做老婆,所以好看的程序也不一定适合硬件实现,for循环也正是如此,所以,我还是觉得尽量用别的方式来实现,比如计数,总归是能找到替代品的,正所谓天涯何处无芳草,循环别把for来找。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
18
关闭 站长推荐上一条 /3 下一条