一、参数映射
参数映射的功能就是实现参数化元件。所谓的”参数化元件“就是指元件的某些参数是可调的,通过调整这些参数从而可实现一类结构类似而功能不同的电路。在应用中,很多电路都可采用参数映射来达到统一设计,如计数器、分频器、不同位宽的加法器以及不同刷新频率的VGA视频接口驱动电路等。
参数传递
参数传递就是在编译时对参数重新赋值而改变其值。传递的参数是子模块中定义的parameter,其传递方法有下面两种。
- 时钟”#“符号
在同一模块中使用”#“符号。参数赋值的顺序必须与原始模块中进行参数定义的顺序相同,并不是一定要给所有的参数都赋予新值,但不允许跳过任何一个参数,即使是保持不变的值也要写在相应的位置。
module #(parameter1, parameter2) inst_name(port_map);
module_name #(.parameter_name(para_value), .parameter_name(para_value)) inst_name(port_map);
例:通过”#“字符实现一个模值可调的加1计数器
module cnt( input clk, input rst, output reg[15:0] cnt_o ); //定义参数化变量 parameter[15:0] Cmax = 1024; always @(posedge clk or negedge rst) begin if(!rst) cnt_o <= 0; else if(cnt_o == Cmax) cnt_o <= 0; else cnt_o <= cnt_o + 1; end endmodule
module param_counter( input clk, input rst, output [15:0] cnt_o ); //参数化调用,利用#符号将计数器的模值10传入被调用模块 cnt #10 inst_cnt( .clk(clk), .rst(rst), .cnt_o(cnt_o) ); endmodule
- 使用defparam关键字
defparam关键字可以在上层模块去直接修改下层模块的参数值,从而实现参数化调用,其语法格式如下:
defparam heirarchy_path.paramer_name = value;
这种方法与例化分开,参数需要写绝对路径来指定。参数传递时各个参数值的排列次序必须与被调用模块中各个参数的次序保持一致,并且参数值和参数个数也必须相同。
如果只希望对被调用模块内的个别参数进行更改,所有不需要更改的参数值也必须按对应参数的顺序在参数值列表中全部列出(原值拷贝)。
使用defparam语句进行重新赋值时必须参照原参数的名字生成成分级参数名。
例:通过”defparam“实现一个模值可调的加1计数器。
module param_counter( input clk, input rst, output [15:0] cnt_o ); //参数化调用,利用#符号将计数器的模值10传入被调用模块 cnt inst_cnt( .clk(clk), .rst(rst), .cnt_o(cnt_o) ); //同过defparam修改参数 defparam inst_cnt.Cmax = 12; endmodule
二、寄存器类型
寄存器变量,都有“寄存性”,即在接手下一次赋值前,将保持原值不变。寄存器型变量没有强度之分,且所有寄存器类变量都必须明确给出类型说明(无缺省状态),寄存器数据类型这里仅介绍两种常用类型。
- reg:常用的寄存器型变量。用于行为描述中对寄存器类的说明,由过程赋值语句赋值;
- Integer: 32位带符号整型变量
1、reg寄存器类型
寄存器数据类型reg是最常见的数据类型。寄存器可以取任意长度。reg型数据的缺省值是未知的,reg型数据可以为正值或负值。但当一个reg型数据是一个表达式中的操作数时,它的值被当无符号值,即正值。如果一个4位的reg型数据被写入-1,在表达式中运算时,其值被认为是+15。例如:
reg [3:0] Comb;
Comb = -2; //Comb的值为14(1110),1110是-2的补码
2、integer寄存器类型
整数寄存器包含整数值。整数寄存器可以作为普通寄存器使用。使用整数型说明形式如下:
integer integer1, integer2,......integerN[msb:lsb];
integer Hist[3:6]; //一组四个寄存器
一个整数型寄存器可存储有符号数,并且算术操作符提供2的补码运算结果。整数不能作为向量访问。例如,对于上面的整数B的说明,B[6]和B[20:10]是非法的。一种截取位值的方法是将整数赋值给一般的reg类型变量,然后从中选取相应的位,如下:
reg [31:0] Breg;
integer Bint;
Breg = Bint;
上例说明了如果通过简单的赋值将整数装换为位向量。类型转型自动完成,不必使用特定的函数。从位向量到整数的转换也可以通过赋值完成。例如:
integer J;
reg [3:0] Bcq;
J = 6; //J的值为32‘b0000...00110
Bcq = J; //Bcq的值为4‘b0110
Bcq = 4‘d0101;
J = Bcq; //J的值为32’b0000...00101
J = -6; // J的值为32‘b1111...11010
Bcq = J ; //Bcq的值为4‘b1010