Verilog——入门进程学习(四)
简单的Verilog HDL模块
Verilog的编程模块结构
module 模块名(端口1, 端口2, 端口3)
//内容:
//I/O说明:
input 端口名;
output 端口名;
//内部信号:
reg [width-1:0] r变量1,r变量2;
wire [width-1:0] w变量1,w变量2;
//功能定义:
a. assign 连线
assign a = b&c;
b. 实例化其他元件
and and_inst(q, a, b);
c. always模块
always @(posedge clk or posedge clr)
begin
if(clr)
q <= 0;
else
if(en)
q <= d;
end
endmodule
在verilog设计中,模块名就是文件名,这是由于软件编译的问题而限制的。所以设置模块名的时候也决定了文件名。因此,模块名的设定要体现出模块的功能,这样设定对于大的工程项目设计很有用处,便于查找分析。
module/endmodule
首先我们要知道Verilog中的module/endmodule是做什么用的。如果你学过C语言,那么你就应该知道模块的概念。而模块是 Verilog 中基本单元的定义形式,是与外界交互的接口。
在Verilog中,我们要使用module开头,endmodule结尾。例子如下:
module counter10(
//端口定义
input rstn, //复位端,低有效
input clk, //输入时钟
output [3:0] cnt, //计数输出
output cout); //溢出位
reg [3:0] cnt_temp ; //计数器寄存器
always@(posedge clk or negedge rstn) begin
if(! rstn)
begin //复位时,计时归0
cnt_temp <= 4'b0 ;
end
else if (cnt_temp==4'd9) begin //计时10个cycle时,计时归0
cnt_temp <=4'b000;
end
else begin //计时加1
cnt_temp <= cnt_temp + 1'b1 ;
end
end
assign cout = (cnt_temp==4'd9) ; //输出周期位
assign cnt = cnt_temp ; //输出实时计时器
endmodule
- 我们能够清楚地看到,在上面这个4 位宽 10 进制计数器中,module和endmodule的使用用法。这个是Verilog的基础。
- 一个 .v文件中主要由 一个或多个 module … endmodule块组成
- 每个module块内包括:模块名,输入端口,输出端口,以及多个时序电路,组合电路等组成
input(输入)/output(输出)
我们能够在上面的模块结构中清晰地看到input与output的用法,主要是用来定义端口的类型是输出还是输入。其余则没有什么意义了。这里要将我们所使用的端口给定义成这两类。
数据类型wire/reg
这里如果不懂的话,可以点击下面的链接,就不详细解释了。
数据类型解释
但是这里需要注意的是:reg类型的变量不能使用assign进行连续赋值,这是因为reg类型的变量可以存储数据,并且不需要连续驱动。我们只能在initial以及always块内对reg类型变量进行赋值。
always/ initial
两者的关系 一个程序块可以有多个initial和always过程块。每个initial和always说明语句在仿真的一开始同时立即开始执行
- initial语句只执行一次,而always语句则不断重复的活动着,直到仿真结束。
- 一段程序中使用的initial和always语句的次数不受限制,他们都是同时开始运行的。
- always语句则没有次数限制,是否运行取决于其后面的限制条件,满足则运行一次,直到程序结束。
if与begin/end的关系
我想如果学习过编程的同学,对if这个语句都不陌生,判断语句,如果满足则运行一次。运行的是begin和end里面的语句,这里的begin和end就相当于C语言中的{ }一样。
assign
关键字assign开头则代表的是赋值语句,后面是信号名,可以是单个信号,也可以是不同信号网的连接。
assign <net_expression> = [drive_strength] [delay] <expression of different signals or constant value>
使用 assign 语句时, 需要遵循一些规则:
- LHS(左值) 应该始终是wire类型的标量或向量网络, 或者标量或矢量网络的串联, 而绝对不能是reg类型的标量或矢量寄存器。
- RHS 可以包含标量或向量寄存器以及函数调用。
- 只要 RHS 上的任何操作数的值发生变化, LHS 就会使用新值进行更新。
- assign 语句也称为连续赋值, 并且始终处于活动状态
如果有什么不对之处,欢迎指正,谢谢