昨天在altera的一篇官方文档上看到一段程序,代码如下:
1: //Top-level module
2: module TEST_NO(A,B,Clock,Reset,Sel,AddSub,Z,Overflow);
3: parameter n=16;
4: input [n-1:0]A,B;
5: input Clock,Reset,Sel,AddSub;
6: output [n-1:0]Z;
7: output Overflow;
8: reg SelR,AddSubR,Overflow;
9: reg [n-1:0]Areg,Breg,Zreg;
10: wire [n-1:0]G,H,M,Z;
11: wire carryout,over_flow;
12:
13: //Define combinational logic circuit
14: assign H=Breg^{n{AddSubR}};
15: mux2to1 multiplexer(Areg,Z,SelR,G);
16: defparam multiplexer.k=n;
17:
18: adderk nbit_adder(AddSubR,G,H,M,carryout);
19: defparam nbit_adder.k=n;
20: assign over_flow=carryout^G[n-1]^H[n-1]^M[n-1];
21: assign Z=Zreg;
22:
23:
24: //Define flip-flops and registers
25: always @(posedge Reset or posedge Clock)
26: if(Reset==1)
27: begin
28: Areg<=0;
29: Breg<=0;
30: Zreg<=0;
31: SelR<=0;
32: AddSubR<=0;
33: Overflow<=0;
34: end
35: else
36: begin
37: Areg<=A;
38: Breg<=B;
39: Zreg<=M;
40: SelR<=Sel;
41: AddSubR<=AddSub;
42: Overflow<=over_flow;
43: end
44: endmodule
45:
46: //k-bit 2-to-1 multiplexer
47: module mux2to1(V,W,Sel,F);
48: parameter k=8;
49: input [k-1:0]V,W;
50: input Sel;
51: output [k-1:0]F;
52: reg [k-1:0]F;
53:
54: always @(V or W or Sel)
55: if(Sel==0)
56: F=V;
57: else
58: F=W;
59: endmodule
60:
61: //k-bit adder
62: module adderk(carryin,X,Y,S,carryout);
63: parameter k=3;
64: input carryin;
65: input [k-1:0]X,Y;
66: output [k-1:0]S;
67: output carryout;
68: reg [k-1:0]S;
69: reg carryout;
70:
71: always @(X or Y or carryin)
72: {carryout,S}=X+Y+carryin;
73:
74: endmodule
从第46行往下,是两个module ,一个叫mux2to1,一个叫adderk;15行和18行分别例化了它们:
mux2to1 multiplexer(Areg,Z,SelR,G);
adderk nbit_adder(AddSubR,G,H,M,carryout);
这种例化,和我平时用的不太一样,平时的话:
mux2to1 multiplexer
(
.Areg(Areg),
.Z(Z),
.SelR(SelR),
.G(G)
);
他这种例化方法叫做顺序例化,虽然简洁但是,顺序必须是和原模块的引脚顺序一样。当然本文的重点并不是顺序例化。
我们在顺序例化的下面紧接着有一句:defparam multiplexer.k=n; 这句话是干什么用的呢?
首先,multiplexer就是模块mux2to1的例化名,n就是一个parameter等于16,那k是什么?multiplexer.k是个什么意思?
我们定位到mux2to1原模块,发现k就是mux2to1模块内部的一个parameter且等于8。且k是与引脚的位宽相关联的——input [k-1:0]V,W;
也就是说模块引脚的weikuan是8,可是我们观察RTL视图发现:
引脚的位宽不是8而是16。导致这个结果的原因就是:defparam multiplexer.k=n;这句话的意思就是从新定义这个模块的k的值为n,即16。我感觉这个方法挺不错的,增加了例化的灵活性。
总结:
我们可以将自己的模块定义添加某些parameter,并且可将parameter关联上某些值,比如上述程序中的引脚的位宽。然后通过defparam multiplexer.参数名,这种语法来例化出不同的模块,是不是很赞呢。