【原创】在FPGA中使用for循环一定浪费资源吗?
1赞
发表于 11/9/2015 1:06:38 AM
阅读(3317)
渐渐地,发现自己已经习惯于发现细节,喜欢打破常规,真的非常喜欢这种feel。
相信很多人在书上或者博文上都有提出“在FPGA中使用for语句是很占用资源的”的观点,特权同学也不例外。那么,这种观点正确吗?我的答案是:对一半,错一半。在某些情况下,使用for循环也许真的挺占用资源的。但我并不想去探讨这种情况。而是谈谈在另外一些情况下使用for语句的好处。
第一个好处:有时使用for循环不但不会浪费多余的资源,而且可以减少代码量,从而提高编码效率;第二个好处是:方便模块的移植。下面举个移位寄存器的简单例子来说明就一目了然了。假设设计一个深度为16、位宽为8的移位寄存器。
1、基于非for语句的移位寄存器电路设计如下:
module shift_register #( parameter DATA_WIDTH = 8 ) ( input clk, input [DATA_WIDTH-1:0] din, output [DATA_WIDTH-1:0] dout ); //--------------------------------------------- reg [DATA_WIDTH-1:0] mem [0:15]; always @(posedge clk) begin mem[0 ] <= din; mem[1 ] <= mem[0 ]; mem[2 ] <= mem[1 ]; mem[3 ] <= mem[2 ]; mem[4 ] <= mem[3 ]; mem[5 ] <= mem[4 ]; mem[6 ] <= mem[5 ]; mem[7 ] <= mem[6 ]; mem[8 ] <= mem[7 ]; mem[9 ] <= mem[8 ]; mem[10] <= mem[9 ]; mem[11] <= mem[10]; mem[12] <= mem[11]; mem[13] <= mem[12]; mem[14] <= mem[13]; mem[15] <= mem[14]; end assign dout = mem[15]; endmodule
综合后资源消耗为:
2、基于for语句的移位寄存器电路设计如下:
module shift_register_for #( parameter DATA_WIDTH = 8, parameter SHIFT_LEVEL = 16 ) ( input clk, input [DATA_WIDTH-1:0] din, output [DATA_WIDTH-1:0] dout ); //------------------------------------------------------- reg [DATA_WIDTH-1:0] mem [0:SHIFT_LEVEL-1]; always @(posedge clk) begin : shift_reg integer i; for(i = 0; i < SHIFT_LEVEL-1; i = i + 1) mem[i+1] <= mem[i]; mem[0] <= din; end assign dout = mem[SHIFT_LEVEL-1]; endmodule
综合后资源消耗为:
通过对比,两者消耗资源一样,但使用for语句可大大减少代码量。在这里,我问大家一个问题,如果我想要一个深度为40、位宽为8的移位寄存器,怎么办?对基于for语句的移位寄存器很容易实现,只要将SHIFT_LEVEL=16改为SHIFT_LEVEL=40就可以了;而对于没有使用for语句的移位寄存器并没有快捷的修改方法,只能乖乖地按部就班了,如下所示:
module shift_register #( parameter DATA_WIDTH = 8 ) ( input clk, input [DATA_WIDTH-1:0] din, output [DATA_WIDTH-1:0] dout ); //-------------------------- reg [DATA_WIDTH-1:0] mem [0:15]; always @(posedge clk) begin mem[0 ] <= din; mem[1 ] <= mem[0 ]; mem[2 ] <= mem[1 ]; mem[3 ] <= mem[2 ]; mem[4 ] <= mem[3 ]; mem[5 ] <= mem[4 ]; mem[6 ] <= mem[5 ]; mem[7 ] <= mem[6 ]; mem[8 ] <= mem[7 ]; mem[9 ] <= mem[8 ]; mem[10] <= mem[9 ]; mem[11] <= mem[10]; mem[12] <= mem[11]; mem[13] <= mem[12]; mem[14] <= mem[13]; mem[15] <= mem[14]; mem[16] <= mem[15]; mem[17] <= mem[16]; mem[18] <= mem[17]; mem[19] <= mem[18]; mem[20] <= mem[19]; mem[21] <= mem[20]; mem[22] <= mem[21]; mem[23] <= mem[22]; mem[24] <= mem[23]; mem[25] <= mem[24]; mem[26] <= mem[25]; mem[27] <= mem[26]; mem[28] <= mem[27]; mem[29] <= mem[28]; mem[30] <= mem[39]; mem[31] <= mem[30]; mem[32] <= mem[31]; mem[33] <= mem[32]; mem[34] <= mem[33]; mem[35] <= mem[34]; mem[36] <= mem[35]; mem[37] <= mem[36]; mem[38] <= mem[37]; mem[39] <= mem[38]; end assign dout = mem[39]; endmodule
由此,使用for语句的移位寄存器很方便移植。
总结:在一些情况下,适当使用for语句不但可以节省设计的时间,还有利于设计的移植。