(原創) 如何使用參數式模組? (SOC) (Verilog) (C/C++) (template)
Abstract
Verilog一向不在語法上耍花槍,參數式模組的寫法,算是Verilog最奇特的寫法,在C與C++也沒有。
Introduction
使用環境:Quartus II 7.2 SP3 + ModelSim-Altera 6.1g + DE2(Cyclone II EP2C35F672C6)
counter是最基本的循序電路應用,為了更加彈性,我們想讓使用者可以自己指定counter的大小,從什麼數字開始數,數到哪個數字停止,而不是寫死在程式裡。
parameter_counter.v / Verilog
2 (C) OOMusou 2008 http://oomusou.cnblogs.com
3
4 Filename : parameter_counter.v
5 Compiler : Quartus II 7.2 SP3 + ModelSim 6.1g
6 Description : demo how to use parameter
7 Release : 07/09/2008 1.0
8 */
9 module parameter_counter (
10 clk,
11 rst_n,
12 cnt,
13 );
14
15 parameter size = 16;
16 parameter start = 0;
17 parameter stop = 100;
18
19 input clk;
20 input rst_n;
21 output reg [size-1 : 0] cnt;
22
23 always@(posedge clk or negedge rst_n) begin
24 if (!rst_n)
25 cnt <= start;
26 else if (cnt == stop)
27 cnt <= start;
28 else
29 cnt <= cnt + 1;
30 end
31
32 endmodule
15行
parameter start = 0;
parameter stop = 100;
parameter宣告,即為Verilog的參數式寫法,之後接的是預設值,如此一來,counter的大小,從什麼數字開始數,數到哪個數字停止都不在是寫死在程式裡。
parameter_counter_tb.v / Verilog
2 (C) OOMusou 2008 http://oomusou.cnblogs.com
3
4 Filename : parameter_counter_tb.v
5 Compiler : Quartus II 7.2 SP3 + ModelSim 6.1g
6 Description : demo how to use parameter in testbench
7 Release : 07/09/2008 1.0
8 */
9 `timescale 1ns/10ps
10 `include "parameter_counter.v"
11
12 module parameter_counter_tb;
13
14 reg clk;
15 reg rst_n;
16 wire [7:0] cnt;
17
18 // parameter_counter u0 (.clk(clk), .rst_n(rst_n), .cnt(cnt));
19
20 parameter_counter # (.size(8),.start(3),.stop(9))
21 u0 (.clk(clk), .rst_n(rst_n), .cnt(cnt));
22
23 /*
24 parameter_counter u0 (
25 .clk(clk),
26 .rst_n(rst_n),
27 .cnt(cnt)
28 );
29
30 defparam u0.size = 8;
31 defparam u0.start = 3;
32 defparam u0.stop = 9;
33 */
34 parameter clkper = 100;
35 initial clk = 1'b0;
36 always #(clkper / 2) clk = ~clk;
37
38 initial begin
39 rst_n = 1'b0;
40 #1;
41 rst_n = 1'b1;
42 end
43
44 endmodule
要讓testbench調用module時,能動態的調整參數,有幾種寫法:
18行
若想使用預設的參數,則寫法並沒有兩樣。
20行
u0 (.clk(clk), .rst_n(rst_n), .cnt(cnt));
若要傳入參數,這是第一種寫法,加上#,再用()傳入參數。
24行
.clk(clk),
.rst_n(rst_n),
.cnt(cnt)
);
defparam u0.size = 8;
defparam u0.start = 3;
defparam u0.stop = 9;
這是第二種傳入參數的寫法,靠defparam將參數傳進去。
或許你會問,什麼時會用到這種寫法呢?
1.想讓自己的module更具彈性時。
2.使用megafunction時。
10行
若搭配的是自己寫的module,就一定要加上include,若使用megafunction,就可省略include。
所以這參數式模組的寫法在實務上都看的到,是C/C++所沒有的語法,所以特別提出來。
執行結果
C++的Nontype Template Parameter在Verilog重出江湖
看到以下的寫法時,你是否想起了C++的Nontype Template Parameter?
u0 (.clk(clk), .rst_n(rst_n), .cnt(cnt));
我趕緊用C++也寫了一次同樣功能的counter
template_nontype_template_parameter_verilog.cpp / C++
2 (C) OOMusou 2008 http://oomusou.cnblogs.com
3
4 Filename : template_nontype_template_parameter_verilog.cpp
5 Compiler : Visual C++ 8.0
6 Description : Demo how to use nontype template paramter
7 Release : 07/09/2008 1.0
8 */
9
10 #include <iostream>
11
12 using namespace std;
13
14 template<int start = 0, int stop = 100>
15 class parameter_counter {
16 private:
17 int cnt;
18
19 public:
20 parameter_counter() : cnt(0) {}
21 void count();
22 };
23
24 template<int start, int stop>
25 void parameter_counter<start, stop>::count() {
26 while(1) {
27 if (cnt == stop)
28 cnt = start;
29 else
30 cnt++;
31
32 cout << cnt << endl;
33 }
34 }
35
36 int main() {
37 parameter_counter<3, 9> u0;
38 //parameter_counter<> u0;
39 u0.count();
40 }
執行結果
4
5
6
7
8
9
3
4
5
6
7
由與軟體不需要clk與非同步的reset機制,這兩個都加以省略,原來的size也因為改用int代替,最後的nontype template paramter只剩下start與stop。
class parameter_counter {
private:
int cnt;
public:
parameter_counter() : cnt(0) {}
void count();
};
37行
//parameter_counter<> u0;
為C++傳入參數的方式,若C++要使用預設參數,仍需要<>表示。重點來了,讓我們再看一次Verilog語法:
u0 (.clk(clk), .rst_n(rst_n), .cnt(cnt));
C++和Verilog的語法幾乎一樣!!也就是說,Verilog也支援泛型,但僅限於Nontype Template Parameter,Verilog雖然不像C++那樣的強大,但最少觀念是一樣的。