宋桓公

【技术分享】谈谈verilog例化

0
阅读(5851)

昨天在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视图发现:

image

引脚的位宽不是8而是16。导致这个结果的原因就是:defparam multiplexer.k=n;这句话的意思就是从新定义这个模块的k的值为n,即16。我感觉这个方法挺不错的,增加了例化的灵活性。

总结:

我们可以将自己的模块定义添加某些parameter,并且可将parameter关联上某些值,比如上述程序中的引脚的位宽。然后通过defparam multiplexer.参数名,这种语法来例化出不同的模块,是不是很赞呢。

Baidu
map