做网站的毕设开题依据,wordpress 做小程序,trellis wordpress,七台河新闻联播5.3 Verilog 带参数例化
分类 Verilog 教程 关键词#xff1a; defparam#xff0c;参数#xff0c;例化#xff0c;ram
当一个模块被另一个模块引用例化时#xff0c;高层模块可以对低层模块的参数值进行改写。这样就允许在编译时将不同的参数传递给多个相同名字的模块…5.3 Verilog 带参数例化
分类 Verilog 教程 关键词 defparam参数例化ram
当一个模块被另一个模块引用例化时高层模块可以对低层模块的参数值进行改写。这样就允许在编译时将不同的参数传递给多个相同名字的模块而不用单独为只有参数不同的多个模块再新建文件。
参数覆盖有 2 种方式1使用关键字 defparam2带参数值模块例化。
defparam 语句
可以用关键字 defparam 通过模块层次调用的方法来改写低层次模块的参数值。
例如对一个单口地址线和数据线都是 4bit 宽度的 ram 模块的 MASK 参数进行改写
实例
//instantiation defparam u_ram_4x4.MASK 7 ; ram_4x4 u_ram_4x4 ( .CLK (clk), .A (a[4-1:0]), .D (d), .EN (en), .WR (wr), //1 for write and 0 for read .Q (q) );
ram_4x4 的模型如下
实例
module ram_4x4 ( input CLK , input [4-1:0] A , input [4-1:0] D , input EN , input WR , //1 for write and 0 for read output reg [4-1:0] Q ); parameter MASK 3 ; reg [4-1:0] mem [0:(14)-1] ; always (posedge CLK) begin if (EN WR) begin mem[A] D MASK; end else if (EN !WR) begin Q mem[A] MASK; end end endmodule
对此进行一个简单的仿真testbench 编写如下
实例
timescale 1ns/1ns module test ; parameter AW 4 ; parameter DW 4 ; reg clk ; reg [AW:0] a ; reg [DW-1:0] d ; reg en ; reg wr ; wire [DW-1:0] q ; //clock generating always begin #15 clk ~clk ; // 修改 end initial begin clk 0 ; a 10 ; d 2 ; en b0 ; wr b0 ; repeat(10) begin (negedge clk) ; en 1b1; a a 1 ; wr 1b1 ; //write command d d 1 ; end a 10 ; repeat(10) begin (negedge clk) ; a a 1 ; wr 1b0 ; //read command end end // initial begin //instantiation defparam u_ram_4x4.MASK 7 ; ram_4x4 u_ram_4x4 ( .CLK (clk), .A (a[AW-1:0]), .D (d), .EN (en), .WR (wr), //1 for write and 0 for read .Q (q) ); //stop simulation initial begin forever begin #100; if ($time 1000) $finish ; end end endmodule // test
仿真结果如下
图中黄色部分当地址第一次为 c 时写入数据 4 当第二次地址为 c 时读出数据为 4可知此时 ram 行为正确且 MASK 不为 3。 因为 ram 的 Q 端 bit2 没有被屏蔽。
当第一次地址为 1 时写入数据为 9第二次地址为 1 时读出的数据却是 1因为此时 MASK 为 7ram 的 Q 端信号 bit3 被屏蔽。由此可知MASK 参数被正确改写。 带参数模块例化
第二种方法就是例化模块时将新的参数值写入模块例化语句以此来改写原有 module 的参数值。
例如对一个地址和数据位宽都可变的 ram 模块进行带参数的模块例化
实例
ram #(.AW(4), .DW(4)) u_ram ( .CLK (clk), .A (a[AW-1:0]), .D (d), .EN (en), .WR (wr), //1 for write and 0 for read .Q (q) );
ram 模型如下
实例
module ram #( parameter AW 2 , parameter DW 3 ) ( input CLK , input [AW-1:0] A , input [DW-1:0] D , input EN , input WR , //1 for write and 0 for read output reg [DW-1:0] Q ); reg [DW-1:0] mem [0:(1AW)-1] ; always (posedge CLK) begin if (EN WR) begin mem[A] D ; end else if (EN !WR) begin Q mem[A] ; end end endmodule
仿真时只需在上一例的 testbench 中将本次例化的模块 u_ram 覆盖掉 u_ram_4x4, 或重新添加之即可。
仿真结果如下。由图可知ram 模块的参数 AW 与 DW 均被改写为 4 且 ram 行为正确。 区别与建议
(1) 和模块端口实例化一样带参数例化时也可以不指定原有参数名字按顺序进行参数例化例如 u_ram 的例化可以描述为
ram #(4, 4) u_ram (......) ;
(2) 当然利用 defparam 也可以改写模块在端口声明时声明的参数利用带参数例化也可以改写模块实体中声明的参数。例如 u_ram 和 u_ram_4x4 的例化分别可以描述为
实例
defparam u_ram.AW 4 ; defparam u_ram.DW 4 ; ram u_ram(......); ram_4x4 #(.MASK(7)) u_ram_4x4(......);
(3) 那能不能混合使用这两种模块参数改写的方式呢当然能前提是所有参数都是模块在端口声明时声明的参数或参数都是模块实体中声明的参数例如 u_ram 的声明还可以表示为模块实体中参数可自行实验验证
实例
defparam u_ram.AW 4 ; ram #(.DW(4)) u_ram (......); //也只有我这么无聊才会实验这种写法
(4) 那如果一个模块中既有在模块在端口声明时声明的参数又有在模块实体中声明的参数那这两种参数还能同时改写么例如在 ram 模块中加入 MASK 参数模型如下
实例
module ram #( parameter AW 2 , parameter DW 3 ) ( input CLK , input [AW-1:0] A , input [DW-1:0] D , input EN , input WR , //1 for write and 0 for read output reg [DW-1:0] Q ); parameter MASK 3 ; reg [DW-1:0] mem [0:(1AW)-1] ; always (posedge CLK) begin if (EN WR) begin mem[A] D ; end else if (EN !WR) begin Q mem[A] ; end end endmodule
此时再用 defparam 改写参数 MASK 值时编译报 Error
实例
//都采用defparam时会报Error defparam u_ram.AW 4 ; defparam u_ram.DW 4 ; defparam u_ram.MASK 7 ; ram u_ram (......); //模块实体中parameter用defparam改写也会报Error defparam u_ram.MASK 7 ; ram #(.AW(4), .DW(4)) u_ram (......);
重点来了如果你用带参数模块例化的方法去改写参数 MASK 的值编译不会报错MASK 也将被成功改写
ram #(.AW(4), .DW(4), .MASK(7)) u_ram (......);
可能的解释为在编译器看来如果有模块在端口声明时的参数那么实体中的参数将视为 localparam 类型使用 defparam 将不能改写模块实体中声明的参数。
也可能和编译器有关系大家也可以在其他编译器上实验。
5建议对已有模块进行例化并将其相关参数进行改写时不要采用 defparam 的方法。除了上述缺点外defparam 一般也不可综合。
6而且建议模块在编写时如果预知将被例化且有需要改写的参数都将这些参数写入到模块端口声明之前的地方用关键字井号 # 表示。这样的代码格式不仅有很好的可读性而且方便调试。