【翻译】在Verilog设计中使用参数化模块库(Quartus II)(Verilog)
本文介绍如何在Quartus II里使用Altera的模块库。
Contents:
范例电路
参数化模块库
使用LPM的扩展电路(Arguemented Circuit)
扩展设计的结果
实际设计中经常包含通用的电路块,比如:加法器、减法器、乘法器、译码器、计数器和移位寄存器。Altera以模块库的
形式提供这些电路块,可在Verilog设计中例化。编译器可以识别模块库里用Verilog代码指定的标准功能,这样就会自动推断这个模块。但是,很多模块库提供太复杂的功能而不能被自动识别。这些模块必须被用户在设计里明确的例化。
Quartus II包含一个参数化的模块库(LPM)。这些模块采用通用结构,并且需要修该指定的参数值来实现指定的应用。
完成本文,读者将学会:
- 参数化的模块库(LPMs)
- 在电路里配置一个LPM
- 在设计电路里例化一个LPM
本文范例的细节由Quartus II 9.1截取,其他版本类似。
1. 范例电路
作为范例,我们使用图1所示的加/减器电路。它可以加、减,并以2的补码表示运算n-bit的数。2个主要的输入是数A=
an-1an-2…a0和B=bn-1bn-2…b0,主要的输出是Z=zn-1zn-2…z0。另一个输入是控制信号AddSub,当AddSub
=0时Z=A+B;当AddSub=1时,Z=A-B.第2个输入控制信号Sel被用来选择运算模式的操作。当Sel=0时,Z=A+-B;
当Sel=1时,B被从当前Z的值加到或减去。如果加法或减法操作的结果溢出,一个输出信号Overflow被激活。
为了较容易处理异步输入信号,在时钟上升沿它们被加载到触发器。因此,输入A和B将被加载到寄存器Areg和Breg,
而Sel和AddSub将被加载到触发器SelR和AddSubR。加/减器电路的结果放在寄存器Zreg。
图 1
需要的电路如图2 描述。在我们的例子里,我们用一个16位的电路,指定n=16.实现的过程如下:
- 创建一个工程addersubtractor。
- 在工程里包含图2相应的文件addersubtractor.v。为了方便,这个文件在DE2附带光盘里提供:DE2_tutorial\
design_files。
- 选择器件Cyclone II EP2C35F672C6,因为DE2上用得这个:)
- 编译设计
- 通过应用一些典型的输入仿真设计
代码:

1 //Top-level module
2 module addersubtractor(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 adderk nbit_adder(AddSubR,G,H,M,carryout);
18 defparam nbit_adder.k=n;
19 assign over_flow=carryout^G[n-1]^H[n-1]^M[n-1];
20 assign Z=Zreg;
21
22 //Define flip-flops and registers
23 always @(posedge Reset or posedge Clock)
24 if(Reset==1)
25 begin
26 Areg<=0;
27 Breg<=0;
28 Zreg<=0;
29 SelR<=0;
30 AddSubR<=0;
31 Overflow<=0;
32 end
33 else
34 begin
35 Areg<=A;
36 Breg<=B;
37 Zreg<=M;
38 SelR<=Sel;
39 AddSubR<=AddSub;
40 Overflow<=over_flow;
41 end
42 endmodule
43
44 //k-bit 2-to-1 multiplexer
45 module mux2to1(V,W,Sel,F);
46 parameter k=8;
47 input [k-1:0]V,W;
48 input Sel;
49 output [k-1:0]F;
50 reg [k-1:0]F;
51
52 always @(V or W or Sel)
53 if(Sel==0)
54 F=V;
55 else
56 F=W;
57 endmodule
58
59 //k-bit adder
60 module adderk(carryin,X,Y,S,carryout);
61 parameter k=8;
62 input carryin;
63 input [k-1:0]X,Y;
64 output [k-1:0]S;
65 output carryout;
66 reg [k-1:0]S;
67 reg carryout;
68
69 always @(X or Y or carryin)
70 {carryout,S}=X+Y+carryin;
71 endmodule
2. 参数化模块库
LPM采用通用结构,通过指定参数值来应用。选择Help > Megafunctions/LPM打开可用的LPM列表。其中一个是加/减器
模块,lpm_add_sub megafunction。选择这个模块,查看其描述。这个模块有一些输入和输出,其中部分可省略。几个
参数可用来定义指定的操作。比如,操作数的位由参数LPM_WIDTH指定。参数LPM_REPRESENTATION指定操作数作为
有符号数还是无符号数,等等。在模块描述中给出如何例化一个LPM的模板。使用这些模板稍微不便,因此Quartus II提供
一个更容易的例化向导。
我们将使用lpm_add_sub模块来简化图1和图2的加/减器。修改电路如图3.lpm_add_sub模块例化为megaddsub,代
替加法电路里提供加法输入H的异或门。既然运算溢出是LPM的一个输出,就没必要单独用一个异或门生成。
要完成这个加减器电路,创建一个新的目录tutorial_lpm,并创建一个新工程addersubtractor2。
图 3
新的设计将包括目标LPM子电路,并在顶层设计模块例化。LPM子电路的Verilog 模块生成步骤如下:
- 选择Tools > MegaWizard Plug-in Manager,弹出配置窗口。
- 在图4,选择Create a new custom megafunction variation 然后单击Next。
图 4
图 5
3. 在图5的窗口提供可用的LPM列表。展开arithmetic子列表并选择LPM_ADD_SUB。选择输出文件类型为Verilog HDL。指定输出文件名megaddsub.v和路径。单击Next。
图 6
4. 在图6中指定输入数据的位宽为16位,通过一个端口指定操作模式,执行加或减运算。在窗口的左上角可以看到这个
LPM的符号。注意,当add_sub=1时,result=A+B;反之,result=A-B.这个图1的设计不同。在图3中已经提到。
单击Next.
图 7
5. 在图7的窗口,选择输入值都可改变,单击Next。
图 8
6. 在图8窗口选择Create an overflow output,单击Next。
图 9
7. 在图9窗口,选择No,单击next。
8. 图10给出向导创建的文件的总结。单击Finish。
图 10
3 使用LPM的扩展电路
在修改的设计中将使用megaddsub.v。
代码megaddsub.v

// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module megaddsub (
add_sub,
dataa,
datab,
overflow,
result);
input add_sub;
input [15:0] dataa;
input [15:0] datab;
output overflow;
output [15:0] result;
wire sub_wire0;
wire [15:0] sub_wire1;
wire overflow = sub_wire0;
wire [15:0] result = sub_wire1[15:0];
lpm_add_sub lpm_add_sub_component (
.dataa (dataa),
.add_sub (add_sub),
.datab (datab),
.overflow (sub_wire0),
.result (sub_wire1)
// synopsys translate_off
,
.aclr (),
.cin (),
.clken (),
.clock (),
.cout ()
// synopsys translate_on
);
defparam
lpm_add_sub_component.lpm_direction = "UNUSED",
lpm_add_sub_component.lpm_hint = "ONE_INPUT_IS_CONSTANT=NO,CIN_USED=NO",
lpm_add_sub_component.lpm_representation = "UNSIGNED",
lpm_add_sub_component.lpm_type = "LPM_ADD_SUB",
lpm_add_sub_component.lpm_width = 16;
endmodule
修改后的加减器代码如下。将这个代码加入文件tutorial_lpm\addersubtractor2。为了方便,DE2附带光盘也提供了这个
文件。这个代码和前面的不同之处在于:
- 定义over_flow信号的赋值语句和异或门不再需要。
- 加法电路的实例adderk被megaddsub取代。注意在图6输入dataa和datab各自被变量G和Breg驱动。信号AddSub
取反以适合这个控制信号在LPM里的用法。
- 删除adderk模块。
代码 addersubtractor2

1 //Top-level module
2 module addersubtractor2(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,M,Z;
11 wire over_flow;
12
13 //Define combinational logic circuit
14 mux2to1 multiplexer(Areg,Z,SelR,G);
15 defparam multiplexer.k=n;
16 megaddsub nbit_adder(~AddSubR,G,Breg,M,over_flow);
17 assign Z=Zreg;
18
19 //Define flip-flop and register
20 always @(posedge Reset or posedge Clock)
21 if(Reset==1)
22 begin
23 Areg<=0;
24 Breg<=0;
25 Zreg<=0;
26 SelR<=0;
27 AddSubR<=0;
28 Overflow<=0;
29 end
30 else
31 begin
32 Areg<=A;
33 Breg<=B;
34 Zreg<=M;
35 SelR<=Sel;
36 AddSubR<=AddSub;
37 Overflow<=over_flow;
38 end
39 endmodule
40
41 //k-bit 2-to-1 multiplexer
42 module mux2to1(V,W,Selm,F);
43 parameter k=8;
44 input [k-1:0]V,W;
45 input Selm;
46 output [k-1:0]F;
47 reg [k-1:0]F;
48
49 always @(V or W or Selm)
50 if(Selm==0)
51 F=V;
52 else
53 F=W;
54 endmodule
55
添加megaddsub.v到工程。选择Porject > Add/Remove Files in Project(图13)。文件addersubtractor2.v已经存在,添加megaddsub.v,单击Ok。
图 13
图 14
4 结果
编译设计,查看总结,图15.注意修改后的电路使用52个le。因为本例比较简单,使用LPM的优势并不明显。在更复杂的设
计中使用LPM,优势比较明显。当有合适的LPM时,建议使用。
图 15
Seealso
Using Library Modules in Verilog Designs
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 百万级群聊的设计实践
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期