概述
第一章 Verilog语言和Vivado初步使用
在这一章我将总结Verilog语言的基本语法,并对Vivado软件使用进行说明。
1.1Verilog基本结构
简单的组合逻辑实例
下面以一个简单的组合逻辑来说明Verilog的基本结构
module AND(a, b, out);
output[3:0] out; // 4位输出
input [3:0] a, b; // 4位输入a, b
assign out = a & b; // out <- a & b
endmodule
从模块的声明开始,最开始的关键词为module
,模块名为AND
,模块结束的关键词为endmodule
。除了以上写法还有一种颇为常见的写法如下:
module AND (
output[3:0] out,
input [3:0] a, b,
);
assign out = a & b;
endmodule
简单的时序逻辑实例
下面介绍一个简单的时序逻辑,时序逻辑比组合逻辑复杂且要考虑的的东西更多。
module fenpin (
input clk_in,
output clk_out
);
reg c_out = 0;
assign clk_out = c_out;V
always @ (posedge clk_in) begin
c_out = ~c_out;
end
endmodule
上述时序逻辑的时序图如下:
Verilog HDL不同于我们常见的C语言,clk_out = c_out
是建立了一种电路上的连接,将c_out
的值输出到clk_out
中,不仅仅是在assign clk_out = c_out
这个赋值语句发生时才进行,而是之后无论c_out
变为何值clk_out
都要为之改变。为了更好的描述这层关系,用如下电路图来表示上面这段代码。
可以看到c_out
和clk_out
的确建立了永久性的连接,而不是在语句结束后就释放这种连接,这点是要和C语言或者其他语言区别开的,不能忘记HDL是用来描述电路的。
Verilog HDL结构要求
在编写Verilog代码的时候需要注意以下几点
- 模块的时序逻辑部分在
always
块的内部,在always
块的内部只能对寄存器变量进行赋值。 - 模块中对端口或其他
wire
型变量的赋值,必须在always
块的外部使用assign
语句,通常是将寄存器的值送出。
块中对端口或其他wire
型变量的赋值,必须在always
块的外部使用assign
语句,通常是将寄存器的值送出。
1.2 数据类型及变量、常量
Verilog HDL
中有两种常见的数据类型线网类型和变量类型。对于线网类型我们主要介绍wire
型,对于变量类型则主要介绍reg
型。
1.2.1 逻辑值与常量
逻辑值
逻辑值 | 含义 |
---|---|
0 0 0 | 逻辑0 |
1 1 1 | 逻辑1 |
x x x | 逻辑值未知 |
z z z | 高阻态 |
常量表示方法
表达方式 | 说明 | 举例 |
---|---|---|
<位宽>'<进制><数字> | 完整的表达方式 | 4'b0101 or 4'h5 |
<进制><数字> | 缺省位宽,位宽由机器决定,最小是32位 | h05 |
<数字> | 缺省进制则默认为10进制,位宽默认为32位 | 5 |
????说明:
4'h5
和4'b0101
实质上是等价的只是采用了不同进制的表示方法8'h2x
表示为八位二进制数时8'b0010xxxx
1.2.2 线网型wire
1.1节的例子中clk_in
和clk_out
变量是wire
类型,如果没有接触过Verilog HDL对这个类型会感到很不适应,可以先这样想wire
类型就是电路中的一条线,可以随着端口的改变而改变电线中的逻辑值,之后进行项目设计的时候会对这些变量有更深刻的理解。
给出wire
型变量的两种定义方法:
wire[7:0] a, b, c; // 定义了三个位宽为8位的wire型变量
wire d //定义了一个1位的wire
1.2.3 寄存器型reg
当定义一个reg
类型就相当于使用了一个D触发器,只有在时钟有效边沿到来时,保存的值才能改变。
给出reg
型变量的两种定义方法:
reg[7:0] a, b, c; // 定义了三个位宽为8位的reg型变量
reg d //定义了一个1位的reg
1.2.4 符号常量
如果使用关键字parameter
来定义一个标识符来代表一个常量,这个常量就被成为符号常量。
例如:parameter width = 3;
将程序中的所有width
用3替换。
调用模块的时候也可以改变parameter
常量的值
module add(sum, a, b);
parameter time_dl = 5, time_cnt = 10;
...
endmodule
module top;
wire[2:0] a1, b1;
wire[3:0] a2, b2, sum1;
wire[4:0] sum2;
add # (4, 3) AD1(sum1, a1, b1); //使time_dl=4,time_cnt=8
add # (12) AD2(sum2, a2, b2); //time_dl=12,time_cnt=10
endmodule
1.2.5 存储器型变量
存储器其实就是一个寄存器数组,我们写MIPS CPU的时候接触过寄存器堆,其实就是这个。可以使用如下方法定义
reg [msb:lsb] mem[upper1:lower1]
例如:
reg[3:0] mem1[63:0]; // 定义了64个4位寄存器组
reg mem2[5:1]; // 定义了5个1位的寄存器组
mem2[4] = 1; // 对其中1位的寄存器赋值
mem2[1:5] = 0; // 对存储器大范围赋值,速度很快
最后
以上就是自然戒指为你收集整理的第一章 Verilog语言和Vivado初步使用的全部内容,希望文章能够帮你解决第一章 Verilog语言和Vivado初步使用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复