Abstract
在C/C++或任何程式語言,integer是最常用的型別之一,但在Verilog大部分用的都是wire和reg,很少用到integer,該如何正確地使用integer呢?
Introduction
首先,integer和reg與wire最大的差別是,integer本身是個32位元的有號數,含正負。
實務上,若在RTL中,integer建議只出現於for loop中,用來複製電路,讓程式精簡一些,在其他地方使用這種類型的的變數,容易出現與設計者意料之外的情況[1]。
如一個4 bit serial in / serial out的shift register
Verilog / Shift_Register_SISO.v
在C/C++或任何程式語言,integer是最常用的型別之一,但在Verilog大部分用的都是wire和reg,很少用到integer,該如何正確地使用integer呢?
Introduction
首先,integer和reg與wire最大的差別是,integer本身是個32位元的有號數,含正負。
實務上,若在RTL中,integer建議只出現於for loop中,用來複製電路,讓程式精簡一些,在其他地方使用這種類型的的變數,容易出現與設計者意料之外的情況[1]。
如一個4 bit serial in / serial out的shift register
Verilog / Shift_Register_SISO.v
1 /* 2 (C) OOMusou 2008 http://oomusou.cnblogs.com
3
4 Filename : Shift_Register_SISO.v 5 Compiler : Quartus II 7.2 SP1 6 Description : Shift register / serial in serial out 7 Release : 05/27/2008 1.0 8 */
9
10 module Shift_Register_SISO (
11 iCLK,
12 iRESET_n,
13 iSI,
14 oSO
15 );
16
17 input iCLK;
18 input iRESET_n;
19 input iSI;
20 output reg oSO;
21
22 reg [3:0] reg4;
23
24 always@(posedge iCLK) begin
25 if (!iRESET_n)
26 reg4 <= 4'h0;
27 else begin
28 reg4[0] <= iSI;
29 reg4[1] <= reg4[0];
30 reg4[2] <= reg4[1];
31 reg4[3] <= reg4[2];
32 oSO <= reg4[3];
33 end
34 end
35
36 endmodule
3
4 Filename : Shift_Register_SISO.v 5 Compiler : Quartus II 7.2 SP1 6 Description : Shift register / serial in serial out 7 Release : 05/27/2008 1.0 8 */
9
10 module Shift_Register_SISO (
11 iCLK,
12 iRESET_n,
13 iSI,
14 oSO
15 );
16
17 input iCLK;
18 input iRESET_n;
19 input iSI;
20 output reg oSO;
21
22 reg [3:0] reg4;
23
24 always@(posedge iCLK) begin
25 if (!iRESET_n)
26 reg4 <= 4'h0;
27 else begin
28 reg4[0] <= iSI;
29 reg4[1] <= reg4[0];
30 reg4[2] <= reg4[1];
31 reg4[3] <= reg4[2];
32 oSO <= reg4[3];
33 end
34 end
35
36 endmodule
若使用integer配合for loop後,可將程式精簡成
Verilog / Shift_Register_SISO.v
1 /* 2 (C) OOMusou 2008 http://oomusou.cnblogs.com
3
4 Filename : Shift_Register_SISO2.v 5 Compiler : Quartus II 7.2 SP1 6 Description : Shift register / serial in serial out 7 Release : 05/27/2008 1.0 8 */
9
10 module Shift_Register_SISO2 (
11 iCLK,
12 iRESET_n,
13 iSI,
14 oSO
15 );
16
17 input iCLK;
18 input iRESET_n;
19 input iSI;
20 output reg oSO;
21
22 reg [3:0] reg4;
23
24 always@(posedge iCLK) begin
25 integer i;
26
27 if (!iRESET_n)
28 reg4 <= 4'h0;
29 else begin
30
31 reg4[0] <= iSI;
32
33 for(i = 0; i < 3; i = i + 1)
34 reg4[i+1] <= reg4[i];
35
36 oSO <= reg4[3];
37 end
38 end
39
40 endmodule
3
4 Filename : Shift_Register_SISO2.v 5 Compiler : Quartus II 7.2 SP1 6 Description : Shift register / serial in serial out 7 Release : 05/27/2008 1.0 8 */
9
10 module Shift_Register_SISO2 (
11 iCLK,
12 iRESET_n,
13 iSI,
14 oSO
15 );
16
17 input iCLK;
18 input iRESET_n;
19 input iSI;
20 output reg oSO;
21
22 reg [3:0] reg4;
23
24 always@(posedge iCLK) begin
25 integer i;
26
27 if (!iRESET_n)
28 reg4 <= 4'h0;
29 else begin
30
31 reg4[0] <= iSI;
32
33 for(i = 0; i < 3; i = i + 1)
34 reg4[i+1] <= reg4[i];
35
36 oSO <= reg4[3];
37 end
38 end
39
40 endmodule
原來的29 ~ 31行
reg4[1] <= reg4[0];
reg4[2] <= reg4[1];
reg4[3] <= reg4[2];
reg4[2] <= reg4[1];
reg4[3] <= reg4[2];
最後精簡成
for(i = 0; i < 3; i = i + 1)
reg4[i+1] <= reg4[i];
reg4[i+1] <= reg4[i];
這兩個程式將來合成出來的硬體電路完全一樣,只是程式比較精簡些,適合用來複製電路。
另外一個初學者常疏忽的地方,原本想設計一個8位元的計數器,因為使用了integer卻得到一個32位元計數器,除了引起設計錯誤,也耗用了更多的資源。[1]
1 integer counter;
2
3 always@(posedge clk) begin
4 if (counter < 200)
5 counter <= counter + 1;
6 else
7 counter <= 0;
8 end
2
3 always@(posedge clk) begin
4 if (counter < 200)
5 counter <= counter + 1;
6 else
7 counter <= 0;
8 end
應該改成
1 reg[7:0] counter;
2
3 always@(posedge clk) begin
4 if (counter < 200)
5 counter <= counter + 1;
6 else
7 counter <= 0;
8 end
2
3 always@(posedge clk) begin
4 if (counter < 200)
5 counter <= counter + 1;
6 else
7 counter <= 0;
8 end
Conclusion
在RTL中,建議integer只配合for loop使用來複製電路,其他都應該使用wire或reg。
沒有留言:
張貼留言