在顶层模块引用子模块时,顶层模块和子模块中都定义parameter型常数

前段时间在FPGA上用Verilog写了贰个多端口以太网的数量分发模块,因为各个网口要求单独的MAC地址和IP地址,为了便利中期修改,在设计中行使parameter来定义那些地点和数量总线的位宽等常量。 
立马的做法是,顶层模块和子模块中都定义parameter型常数,在顶层模块引用子模块时,通过参数传递改变在被引用子模块中已定义的参数,实以后顶层模块统一保管参数的成效,代码如下

前段时间在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 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分级完结以太网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

  1. 当子模块的参数较多,并且要频仍实例化时,代码会显得比较臃肿 
    2.
    即使工程的层次有4层,有些参数只在第4层的模块使用到,为了完毕将参数从顶层传递到第4层,第2层和第3层模块的参数列表中务必含有该参数。 
    解决上述难点有两种形式: 
    1. 使用defparam命令在顶层模块对子模块中的参数重定义,可是该方法一致存在3个题材:改变一度实例化后的模块中的参数,必须用英文小数点(.)表示层次逻辑关系,如下所示

    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模块,如下图所示

现实应用方法见http://www.cnblogs.com/hechengfei/p/4116667.html 
2. 使用`inculude预处理命令 
前不久在STM官网上找M95xxx多重的EEPROM资料时,看到该芯片的Verilog
Testbench模块,如下图所示

图片 1

图片 2

 

 

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 参数定义文件

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
1 `define MEM_ADDR_BITS       11              //memory address bits
2 `define PAGE_ADDR_BITS      6               //page address bits

M95xxx_Driver.v   驱动文件

M95xxx_Driver.v   驱动文件

`include "M95XXX_Parameters.v"
reg[`MEM_ADDR_BITS-1:0] memory_address;
reg[`PAGE_ADDR_BITS-1:0] page_address;
`include "M95XXX_Parameters.v"
reg[`MEM_ADDR_BITS-1:0] memory_address;
reg[`PAGE_ADDR_BITS-1:0] page_address;

可以见到要调用参数文件中参数时,需求: 
1. 使用'include一声令下包括参数文件 
2. 使用反引号+参数名的方法来调用该参数

可以见到要调用参数文件中参数时,需要: 
1. 使用'include指令包罗参数文件 
2. 使用反引号+参数名的措施来调用该参数



 

 

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

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

相关文章