1.过程赋值语句
a.阻塞式赋值(=)
特点:一旦执行完当前赋值语句,赋值变量即刻获得来自等号右边的表达式的计算值。如果在一个语句块中有多条阻塞式赋值语句,当执行到某条赋值语句时,其他语句被禁止执行,其语句特点与C等语言赋值语句类似。
b.非阻塞式赋值(<=)
特点:必须在语句块结束执行时才完成整体的赋值操作。可理解为在同一个语句块中,所有非阻塞式赋值语句并行运行。
注意:在同一过程中对同一变量赋值,阻塞式赋值和非阻塞式赋值不可混用。
2.Verilog例化语句及其用法
例化有调用复制的意思,例化的对象叫做实例或实体,通俗的说就是元件。
模块例化可以理解成模块调用。对于一个FPGA工程,通常是由一个顶层模块与多个功能子模块组成,为了实现顶层模块与子模块的连接,需要进行模块间的例化(或说是调用)。在一个FPGA项目工程中,其输入、输出端口命名通常在设计前期就已确定下来,但会存在一些中间变量,一个工程可能会让不同的工程师在不同的时间段内共同完成,不同的人对于这些变量的命名会有所不同,故例化很有必要。
举例:静态数码管显示
根据功能将 FPGA 顶层例化了以下两个功能子模块:计时模(time_count)和数码管静态显示模块(seg_led_static),如下图所示:
1.计时模块
module time_count(
input clk , // 时钟信号
input rst_n , // 复位信号
output reg flag // 一个时钟周期的脉冲信号
);
//parameter define
parameter MAX_NUM = 25000_000; // 计数器最大计数值
......(省略功能代码)
endmodule
2.数码静态管显示模块
module seg_led_static (
input clk , // 时钟信号
input rst_n , // 复位信号(低有效)
input add_flag, // 数码管变化的通知信号
output reg [5:0] sel , // 数码管位选
output reg [7:0] seg_led // 数码管段选
);
......(省略功能代码)
endmodule
3.顶层模块(着重看下面“例化计时模块”、“例化数码管静态显示模块”)
module seg_led_static_top (
input sys_clk , // 系统时钟
input sys_rst_n, // 系统复位信号(低有效)
output [5:0] sel , // 数码管位选
output [7:0] seg_led // 数码管段选
);
//parameter define
parameter TIME_SHOW = 25'd25000_000; // 数码管变化的时间间隔0.5s
//wire define
wire add_flag; // 数码管变化的通知信号
//例化计时模块
time_count #( //参数例化使用’#‘
.MAX_NUM (TIME_SHOW)
) u_time_count(
.clk (sys_clk ),
.rst_n (sys_rst_n),
.flag (add_flag )
);
//例化数码管静态显示模块
seg_led_static u_seg_led_static (
.clk (sys_clk ),
.rst_n (sys_rst_n),
.add_flag (add_flag ),
.sel (sel ),
.seg_led (seg_led )
);
endmodule
上面给出了顶层模块的完整代码,子模块只有模块的端口和参数定义的代码。这是因为顶层模块对子模块做例化时,只需要知道子模块的端口信号名,而不用关心子模块内部具体是如何实现的。
如果子模块内部使用parameter 定义了一些参数,Verilog 也支持对参数的例化(也叫参数的传递),即顶层模块可以通过例化参数来修改子模块内定义的参数。
下图为模块例化。
Verilog例化语句一般格式如下:
<模块元件名> <例化元件名>( .例化元件端口(例化元件外接端口名),...);
再举一个简单的例化语句:
h_adder U2(.A(net1),.SO(sum),.B(cin),.CO(net3));
//端口名关联法
h_adder:待调用的元件名
U2:用户在特定情况下调用元件h_adder而取的名字,即例化名
.A(net1):A就是例化元件端口名,也即原始h_adder模块文件中已定义的端口名
net1:U2的A端将要连接的连线名或其他元件的端口名,也称外部端口名。
还有一种连接表述方法称为位置关联法:
hadder_U1(ain,bin,net1,net2)
//位置关联法
连接信号与端口表位置要严格对应