在C語言中,常常用到for循環語句,但在硬件描述語言中for語句的使用較C語言等軟件描述語言有較大的區別。html
在Verilog中除了在Testbench(仿真測試激勵)中使用for循環語句外,在Testbench中for語句在生成激勵信號等方面使用較廣泛,但在RTL級編碼中卻不多使用for循環語句。主要緣由就是for循環會被綜合器展開爲全部變量狀況的執行語句,每一個變量獨立佔用寄存器資源,每條執行語句並不能有效地複用硬件邏輯資源,形成巨大的資源浪費。簡單的說就是:for語句循環幾回,就是將相同的電路複製幾回,所以循環次數越多,佔用面積越大,綜合就越慢。算法
在RTL硬件描述中,遇到相似的算法,推薦的方法是先搞清楚設計的時序要求,作一個reg型計數器。在每一個時鐘沿累加,並在每一個時鐘沿判斷計數器狀況,作相應的處理,能複用的處理模塊儘可能複用,即便全部的操做不能複用,也採用case語句展開處理。測試
對於下面的for循環語句: 優化
1 for(i=0;i<16;i++) 2 DoSomething();
能夠採用以下代碼實現:
reg [3:0] counter; always @(posedge clk) if(syn_rst) counter<=4'b0;
else counter<=counter+1; always @(posedge clk) begin case(counter) 4'b0000:
4'b0001:
...... default: endcase end
另外,有幾個語法的細節須要注意一下。for(i=0;i<16;i=i+1)中的i既能夠是reg型的變量也能夠是integer類型的變量,可是當i是reg型的變量時,須要注意由於判斷語句i<16的緣故,i應定義爲reg[4:0] i而不是reg[3:0] i 。因爲verilog中沒有自增運算符,文中提到的for語句不能寫成for(i=0;i<16; i++)的形式。
下面簡單的列舉幾個用for實現的程序代碼:
示例一:
仿真結果以下:編碼
1 //Leftshift for 4 bits
2 module For_Leftshift( 3 input wire [3:0]inp, 4 input wire L_EN, 5 output reg [7:0]result 6 ); 7
8 integer i; 9 always@(inp or L_EN) 10 begin 11 result[7:4] = 0; 12 result[3:0] = inp; 13 if(L_EN == 1) 14 begin 15 for(i=4;i<=7;i=i+1) 16 begin 17 result[i] = result[i-4]; 18 end 19 result[3:0] = 0; 20 end 21 end 22
23 endmodule
綜合結果(RTL視圖,實際是一個4位選擇器)spa
示例三:for不只能夠用在組合邏輯中,並且還能夠用在時序邏輯中,用於在1個週期類完成整個for循環。
1 module For_Counter( 2 input wire clk, 3 input wire rst_n, 4 input wire [12:0] data, 5 output wire [3:0] numout 6 ); 7 integer i; 8 reg[3:0] num; 9
10 always @(posedge clk) 11 begin 12 if(!rst_n) 13 num = 0; 14 else
15 begin 16 for(i=0;i<13;i=i+1) 17 if(data[i]) num = num + 1; 18 end 19 end 20
21 assign numout = num; 22
23 endmodule
綜合結果(RTL視圖,加法器+觸發器)設計