依公知及经验整理,原创保护,禁止转载。
专栏 《Verilog语言入门教程》
<<<< 返回总目录 <<<<
全文 6000
字
1. 基本语法
- 换行: 格式自由,可以在一行内编写,也可跨多行编写, 建议换行。
- 每个语句必须以 ;为结束符
- 单行注释用
//xxx
,跨行注释用/* xxx */
- 标识符(
identifier
)第一个字符必须是字母或者下划线,可以是任意一组字母、数字、$
符号和 _(下划线)符号的组合。 - 关键字全部为小写。
"module" 和 "Module" 是不同的关键词
2. 数据类型
bit
:单个位的值,只能取0或1。integer
:整数类型,无符号。int
:整数类型,有符号。reg
:寄存器类型,用于存储多个位的值。wire
:线类型,用于连接模块中的不同部分。
wire [8-1:0] addr;
reg [8-1:0] addr_temp;
real
:浮点数类型。parameter
:参数类型,用于定义模块中的常量值。time
:时间类型,表示时间单位。event
:事件类型,用于同步设计中的事件。string
:字符串类型,用于存储文本。boolean
:布尔类型,取值为真或假。logic
:逻辑类型,可以表示多个位的值。
3. 数值表示
-
整数(Integer):使用十进制表示,例如
256
、-42
。 -
二进制数(Binary):使用
'b
或者'B
前缀,后面跟上由0和1组成的二进制数,例如'b1010
。 -
八进制数(Octal):使用
'o
或者'O
前缀,后面跟上由0到7组成的八进制数,例如'o17
。 -
十进制数(Decimal):使用
'd
或者'D
后缀,表示十进制整数,例如-123d
。 -
十六进制数(Hexadecimal):使用
'h
或者'H
前缀,后面跟上由0到9以及字母A到F组成的十六进制数,例如'hFF
。 -
无符号数(Unsigned):使用
'u
或者'U
后缀,表示无符号整数,例如8u
。 -
负数(Negative):使用
-
符号表示负数,例如-42
。 -
实数(Real):使用十进制或者指数形式表示,例如
3.14
、-0.00123
、2.99792e8
。 -
参数化数值表示:使用参数化的方式来表示数值,例如
N'b1010
表示一个N
位的二进制数值。 -
字符串表示方法:需要定义相应大小的存储单元,比如字符串"baidu.com"需要13*8bit的存储单元。
reg [13*8-1:0] str;
assign str = "www.baidu.com";
4. 操作符
常用的操作符列表:
算术操作符:
- 加法:
+
- 减法:
-
- 乘法:
*
- 除法:
/
- 取模:
%
- 求负:
-
- 自增:
++
- 自减:
--
比较操作符:
- 相等:
==
- 不等:
!=
- 大于:
>
- 小于:
<
- 大于等于:
>=
- 小于等于:
<=
逻辑操作符:
- 与:
&&
- 或:
||
- 非:
!
- 与非:
~&
- 或非:
~|
- 异或:
^
- 同或:
~^
位操作符:
- 与:
&
- 或:
|
- 异或:
^
- 非:
~
归约操作符:
归约与 “&”
归约与非 ~ &
归约或 |
归约或非 ~ |
归约异或 ^
归约同或 ~ ^
位操作符用于对向量的单个位进行操作
归约操作符用于对向量的所有位进行逻辑操作
移位操作符:
左移:<<
右移:>>
赋值操作符:
- 直接赋值:
=
- 等效赋值:
<=
- 加法赋值:
+=
- 减法赋值:
-=
- 乘法赋值:
*=
- 除法赋值:
/=
- 位与赋值:
&=
- 位或赋值:
|=
- 位异或赋值:
^=
- 左移赋值:
<<=
- 有符号右移赋值:
>>=
- 无符号右移赋值:
<<<=
- 实数右移赋值:
<<<>=
位选择操作符:
- 索引选择:
[ ]
- 切片选择:
[ : ]
- 选择运算符:
{ }
其他操作符:
- 条件运算符:
? :
- 逗号运算符:
,
- 强制类型转换:
$signed
、$unsigned
等
这些操作符可以用于将不同的信号连接在一起,实现各种逻辑和计算功能。
5. 表达式
表达式:由操作符和操作数构成,目的是根据操作符的意义得到一个计算结果。
-
逻辑表达式:
- 与运算:
A & B
- 或运算:
A | B
- 非运算:
~A
- 异或运算:
A ^ B
- 逻辑与运算:
A && B
- 逻辑或运算:
A || B
- 与运算:
-
算术表达式:
- 加法:
A + B
- 减法:
A - B
- 乘法:
A * B
- 除法:
A / B
- 模运算:
A % B
- 自增:
A++
- 自减:
A--
- 加法:
-
位运算表达式:
- 位与:
A & B
- 位或:
A | B
- 位非:
~A
- 位异或:
A ^ B
- 左移:
A << B
- 右移:
A >> B
- 位拼接:
{A, B}
- 位与:
-
条件表达式:
- 三元运算符:
condition ? A : B
- if-else语句:
if (condition) A else B
- 三元运算符:
6. 编译指令
-
`include:用于将其他文件中的代码包含到当前文件中。通常用于包含头文件。
-
`define:用于定义宏。可以将一段代码或常用参数定义为宏,方便在代码中多处引用。
-
`undef:用于取消先前定义的宏。
-
`ifdef:用于条件编译。如果给定的宏已定义,则编译指定语句块。
-
`ifndef:用于条件编译。如果给定的宏未定义,则编译指定语句块。
-
`else:用于条件编译。与
ifdef或
ifndef一起使用,表示在宏已定义或未定义时执行的语句块。 -
`endif:用于条件编译。用于结束
ifdef、
ifndef和`else之后的语句块。 -
`timescale:用于设置仿真时间单位和精度。例如:
timescale 1ns/1ps
表示时间单位为纳秒(ns),时间精度为皮秒(ps)。时间精度要小于等于时间单位 -
`pragma:用于设置编译器的指令。可以用于设定编译选项、警告设置等。
-
`celldefine:用于指定在开始模块定义后、模块实例化之前可以使用的单元和宏定义。
-
`endcelldefine:用于结束`celldefine块。
`celldefine
module (input clk,input rst,output A,output B );
endmodule
`endcelldefine
-
`default_nettype:用于指定默认的信号类型。可以将默认的信号类型设置为none、wire或tri。
-
`unconnected_drive:用于指定未连接的端口的驱动类型。可以将默认驱动类型设置为pull0、pull1、strong0、strong1、weak0、weak1或highz。
-
`nounconnected_drive:用于取消先前定义的未连接端口的驱动类型。
7. 过程结构
-
initial: 这是一个初始化过程结构,在模拟开始时执行一次。它用于初始化变量或执行其他初始化操作。例如:
initial begin// 进行相应的初始化操作 end
-
always: 这是一个通用过程结构,根据敏感信号的类型,在其值发生变化时执行操作。它类似于 always @(敏感信号列表)。例如:
always @(a or b) begin// 进行相应的操作 end
常用的前面这两个就可以了。
-
always_ff: 这是一个时钟驱动的过程结构,仅在时钟边沿触发时执行。它类似于 always @(posedge clk)。例如:
always_ff @(posedge clk) begin// 进行相应的操作 end
-
always_comb: 这是一个组合逻辑过程,每当输入信号发生变化时,都会重新计算输出。它类似于 always @( * )。
-
always_latch: 这是一个锁存器过程,只在锁存器使能信号为高电平时才执行操作。它类似于 always @(latch_en)。
-
always_ff @(posedge clk or posedge rst): 这是一个带有复位的时钟驱动过程结构,当时钟边沿触发或复位信号为高电平时执行。
-
always_ff @(posedge clk or posedge rst or posedge en): 这是一个带有复位和使能的时钟驱动过程结构,当时钟边沿触发、复位信号为高电平或使能信号为高电平时执行。
8. 过程赋值
- 阻塞赋值
=
:在执行完当前的赋值操作之后,会继续执行下一条语句. - 非阻塞赋值
<=
:语句并行执行,即其他语句的执行和当前语句的执行同时进行,当前时间步结束后才进行更新 - 连续赋值 (
assign
): 通常用于连接模块之间的信号赋值。 - 延时赋值(
<= #delay
): 赋值操作,并延迟指定的时间步后再更新被赋值的变量。赋值对象只能是wire型变量而不能是reg型变量. - -force(强制赋值), 赋值对象可以是reg型或wire型变量
force作用在寄存器上时,寄存器当前值被覆盖,release时该寄存器值将继续保留强制赋值时的值;
force作用在线网上时,线网当前值被覆盖,但release时该线网值马上变为原有的驱动值
9. 语句块
module
块:定义模块的输入、输出端口以及内部信号always
块:描述组合逻辑或时序逻辑的行为initial
块:描述初始化行为,在模拟仿真开始时执行一次assign
块:连续赋值模块内的连线,用于组合逻辑reg
块:定义寄存器类型的变量,在时序逻辑中使用wire
块:定义线网类型的变量,在组合逻辑中使用if/else
块:用于条件分支case
/casex
/casez
块:用于多路选择for/while
块:用于循环fork/join
块:用于并行执行
10. 延时语句
(连续赋值)延时语句“assign #time”用于控制任意操作数发生变化到语句左端赋予新值之间的延时时间
11. 时序控制
-
线性时序控制:
#N
:表示延迟N个时间单位,其中N可以是一个具体的整数值。#N.M
:表示延迟N个时间单位和M个时间精度单位,其中N和M都可以是具体的整数值。
-
条件时序控制:
posedge clk
:表示在时钟上升沿触发。negedge clk
:表示在时钟下降沿触发。@(posedge clk)
:表示等待时钟上升沿触发的条件。@(negedge clk)
:表示等待时钟下降沿触发的条件。
-
循环时序控制:
for(i=0; i<N; i=i+1)
:表示循环执行N次,其中i是一个循环变量,N是一个具体的整数值。while(condition)
:表示在满足指定条件的情况下循环执行,其中condition是一个逻辑表达式。
-
重复时序控制:
repeat(N)
:表示重复执行N次,其中N是一个具体的整数值。forever
:表示无限循环执行。
这些时序控制语句可以在Verilog代码中灵活地组合与使用,实现不同的时序控制功能。
12. 条件语句
if-else
语句:
if (条件) begin// 条件为真时执行的代码
end
else begin// 条件为假时执行的代码
end
case语句中,每个比较项必须完全匹配(即需要精确匹配)。
casez语句中,比较项的某些位可以为x(无关位),只要其他位匹配。
casex语句中,比较项的某些位可以为x(无关位)或z(高阻态),只要其他位匹配
case
语句:
case (选择表达式)值1: begin// 对应值1时执行的代码end值2: begin// 对应值2时执行的代码enddefault: begin// 选择表达式不匹配任何值时执行的代码end
endcase
casez
语句(针对部分匹配的情况):
casez (选择表达式)值1: begin// 对应值1时执行的代码end值2: begin// 对应值2时执行的代码enddefault: begin// 选择表达式不匹配任何值时执行的代码end
endcase
casex
语句(针对通配符匹配的情况):
casex (选择表达式)值1: begin// 对应值1时执行的代码end值2: begin// 对应值2时执行的代码enddefault: begin// 选择表达式不匹配任何值时执行的代码end
endcase
循环语句
for
循环语句:
for (循环变量初始值; 循环条件; 循环变量更新) begin// 循环体代码
end
while
循环语句:
while (循环条件) begin// 循环体代码
end
- do-while 循环:
先执行一段代码块,然后在满足指定条件时重复执行这段代码块。示例代码如下:
beginA;
end
repeat
循环语句:
repeat (循环次数) begin// 循环体代码
end
- forever循环语句:
forever //相当于while(1),表示永久循环,通过系统函数$finish退出beginA;end
参考
1 | ProNeverFake, Verilog入门教程与实例分享 |