Verilog中使用'include实现参数化设计

来源:转载

前段时间在FPGA上用Verilog写了一个多端口以太网的数据分发模块,因为每个网口需要独立的MAC地址和IP地址,为了便于后期修改,在设计中使用parameter来定义这些地址和数据总线的位宽等常量。 
当时的做法是,顶层模块和子模块中都定义parameter型常数,在顶层模块引用子模块时,通过参数传递改变在被引用子模块中已定义的参数,实现在顶层模块统一管理参数的功能,代码如下

 1 module top(); // 顶层模块

2 parameter eth1_ip_addr = {8'd192, 8'd168, 8'd100, 8'd1}; // 以太网1 IP地址 192.168.100.1

3 parameter eth2_ip_addr = {8'd192, 8'd168, 8'd100, 8'd2}; // 以太网2 IP地址 192.168.100.2

4

5 // 子模块1例化

6 sub1

7 #( .ip_addr(eth1_ip_addr) // 参数传递

8 )

9 sub1_inst( ); //端口映射

10

11 // 子模块2例化

12 sub2

13 #( .ip_addr(eth2_ip_addr) // 参数传递

14 )

15 sub2_inst( ); //端口映射

子模块1和2分别实现以太网1和2的收发功能,ip_addr为各自的本地IP地址,通过参数传递将eth1_ip_addr和eth2_ip_addr的值分别传递给两个子模块的ip_addr常数。 
不过上述方法的缺点在于: 
1. 当子模块的参数较多,并且要多次实例化时,代码会显得较为臃肿 
2. 假如工程的层次有4层,某个参数只在第4层的模块使用到,为了实现将参数从顶层传递到第4层,第2层和第3层模块的参数列表中必须包含该参数。 
解决上述问题有两种方法: 
1. 使用defparam命令在顶层模块对子模块中的参数重定义,但是该方法同样存在一个问题:改变已经实例化后的模块中的参数,必须用英文小数点(.)表示层次逻辑关系,如下所示

 1 module top;

2 reg clk;

3 reg [0:4] in1;

4 reg [0:9] in2;

5 wire [0:4] o1;

6 wire [0:9] o2;

7 // 子模块实例化

8 vdff m1 (o1, in1, clk);

9 vdff m2 (o2, in2, clk);

10 endmodule

11 // 子模块定义

12 module vdff (out, in, clk);

13 parameter size = 1, delay = 1;

14 input [0:size-1] in;

15 input clk;

16 output [0:size-1] out;

17 reg [0:size-1] out;

18

19 always @(posedge clk)

20 # delay out = in;

21 endmodule

22 // 参数重定义模块

23 module annotate;

24 defparam

25 top.m1.size = 5, // size参数的层次化表示

26 top.m1.delay = 10,

27 top.m2.size = 10,

28 top.m2.delay = 20;

29 endmodule

具体使用方法见http://www.cnblogs.com/hechengfei/p/4116667.html 
2. 使用`inculude预处理命令 
最近在STM官网上找M95xxx系列的EEPROM资料时,看到该芯片的Verilog Testbench模块,如下图所示

 

M95XXX_Macro_Mux.v:定义M95xxx系列芯片的AC参数 
M95XXX_Parameters.v:定义Memory大小、有效地址位数和Page大小等参数 
M95xxx_Testbench.v:链接 M95xxx_Driver.v和M95xxx_Memory.v 
M95xxx_Driver.v:模拟M95xxx_Memory.v文件基于SPI接口的读写行为 
M95xxx_Memory.v:M95xxx EEPROM的行为级描述模型 
在上述文件中,M95XXX_Macro_Mux.v和M95XXX_Parameters.v定义了全局参数,被其他文件通过’include命令包含到文件内。具体使用方法如下 
M95XXX_Parameters.v 参数定义文件

1 `define MEM_ADDR_BITS 11 //memory address bits

2 `define PAGE_ADDR_BITS 6 //page address bits

M95xxx_Driver.v   驱动文件

`include "M95XXX_Parameters.v"

reg[`MEM_ADDR_BITS-1:0] memory_address;

reg[`PAGE_ADDR_BITS-1:0] page_address;

可以看到要调用参数文件中参数时,需要: 
1. 使用'include命令包含参数文件 
2. 使用反引号+参数名的方式来调用该参数


 

STM MP95xxx系列EEPROM Verilog Testbench模型的链接地址: 
https://gitee.com/hombeen/codes/y9rb0g7ej385sipqozvla95

分享给朋友:
您可能感兴趣的文章:
随机阅读: