Verilog 入门简明教程

依公知及经验整理,原创保护,禁止转载。

专栏 《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.001232.99792e8

  • 参数化数值表示:使用参数化的方式来表示数值,例如N'b1010表示一个N位的二进制数值。

  • 字符串表示方法:需要定义相应大小的存储单元,比如字符串"baidu.com"需要13*8bit的存储单元。

reg [13*8-1:0] str;
assign str = "www.baidu.com";

4. 操作符

常用的操作符列表:

算术操作符:

  • 加法:+
  • 减法:-
  • 乘法:*
  • 除法:/
  • 取模:%
  • 求负:-
  • 自增:++
  • 自减:--

比较操作符:

  • 相等:==
  • 不等:!=
  • 大于:>
  • 小于:<
  • 大于等于:>=
  • 小于等于:<=

逻辑操作符:

  • 与:&&
  • 或:||
  • 非:!
  • 与非:~&
  • 或非:~|
  • 异或:^
  • 同或:~^

位操作符:

  • 与:&
  • 或:|
  • 异或:^
  • 非:~

归约操作符:
归约与 “&”
归约与非 ~ &
归约或 |
归约或非 ~ |
归约异或 ^
归约同或 ~ ^

位操作符用于对向量的单个位进行操作
归约操作符用于对向量的所有位进行逻辑操作

移位操作符:
左移:<<
右移:>>

赋值操作符:

  • 直接赋值:=
  • 等效赋值:<=
  • 加法赋值:+=
  • 减法赋值:-=
  • 乘法赋值:*=
  • 除法赋值:/=
  • 位与赋值:&=
  • 位或赋值:|=
  • 位异或赋值:^=
  • 左移赋值:<<=
  • 有符号右移赋值:>>=
  • 无符号右移赋值:<<<=
  • 实数右移赋值:<<<>=

位选择操作符:

  • 索引选择:[ ]
  • 切片选择:[ : ]
  • 选择运算符:{ }

其他操作符:

  • 条件运算符:? :
  • 逗号运算符:,
  • 强制类型转换:$signed$unsigned

这些操作符可以用于将不同的信号连接在一起,实现各种逻辑和计算功能。

5. 表达式

表达式:由操作符和操作数构成,目的是根据操作符的意义得到一个计算结果。

  1. 逻辑表达式:

    • 与运算: A & B
    • 或运算: A | B
    • 非运算: ~A
    • 异或运算: A ^ B
    • 逻辑与运算: A && B
    • 逻辑或运算: A || B
  2. 算术表达式:

    • 加法: A + B
    • 减法: A - B
    • 乘法: A * B
    • 除法: A / B
    • 模运算: A % B
    • 自增: A++
    • 自减: A--
  3. 位运算表达式:

    • 位与: A & B
    • 位或: A | B
    • 位非: ~A
    • 位异或: A ^ B
    • 左移: A << B
    • 右移: A >> B
    • 位拼接: {A, B}
  4. 条件表达式:

    • 三元运算符: 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. 过程结构

  1. initial: 这是一个初始化过程结构,在模拟开始时执行一次。它用于初始化变量或执行其他初始化操作。例如:

    initial begin
      // 进行相应的初始化操作
    end
    
  2. always: 这是一个通用过程结构,根据敏感信号的类型,在其值发生变化时执行操作。它类似于 always @(敏感信号列表)。例如:

    always @(a or b) begin
      // 进行相应的操作
    end
    

常用的前面这两个就可以了。

  1. always_ff: 这是一个时钟驱动的过程结构,仅在时钟边沿触发时执行。它类似于 always @(posedge clk)。例如:

    always_ff @(posedge clk) begin
      // 进行相应的操作
    end
    
  2. always_comb: 这是一个组合逻辑过程,每当输入信号发生变化时,都会重新计算输出。它类似于 always @( * )。

  3. always_latch: 这是一个锁存器过程,只在锁存器使能信号为高电平时才执行操作。它类似于 always @(latch_en)。

  4. always_ff @(posedge clk or posedge rst): 这是一个带有复位的时钟驱动过程结构,当时钟边沿触发或复位信号为高电平时执行。

  5. 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. 时序控制

  1. 线性时序控制:

    • #N:表示延迟N个时间单位,其中N可以是一个具体的整数值。
    • #N.M:表示延迟N个时间单位和M个时间精度单位,其中N和M都可以是具体的整数值。
  2. 条件时序控制:

    • posedge clk:表示在时钟上升沿触发。
    • negedge clk:表示在时钟下降沿触发。
    • @(posedge clk):表示等待时钟上升沿触发的条件。
    • @(negedge clk):表示等待时钟下降沿触发的条件。
  3. 循环时序控制:

    • for(i=0; i<N; i=i+1):表示循环执行N次,其中i是一个循环变量,N是一个具体的整数值。
    • while(condition):表示在满足指定条件的情况下循环执行,其中condition是一个逻辑表达式。
  4. 重复时序控制:

    • repeat(N):表示重复执行N次,其中N是一个具体的整数值。
    • forever:表示无限循环执行。

这些时序控制语句可以在Verilog代码中灵活地组合与使用,实现不同的时序控制功能。

12. 条件语句

  1. if-else语句:
if (条件) begin
    // 条件为真时执行的代码
end
else begin
    // 条件为假时执行的代码
end

case语句中,每个比较项必须完全匹配(即需要精确匹配)。
casez语句中,比较项的某些位可以为x(无关位),只要其他位匹配。
casex语句中,比较项的某些位可以为x(无关位)或z(高阻态),只要其他位匹配

  1. case语句:
case (选择表达式)
    值1: begin
        // 对应值1时执行的代码
    end
    值2: begin
        // 对应值2时执行的代码
    end
    default: begin
        // 选择表达式不匹配任何值时执行的代码
    end
endcase
  1. casez语句(针对部分匹配的情况):
casez (选择表达式)
    值1: begin
        // 对应值1时执行的代码
    end
    值2: begin
        // 对应值2时执行的代码
    end
    default: begin
        // 选择表达式不匹配任何值时执行的代码
    end
endcase
  1. casex语句(针对通配符匹配的情况):
casex (选择表达式)
    值1: begin
        // 对应值1时执行的代码
    end
    值2: begin
        // 对应值2时执行的代码
    end
    default: begin
        // 选择表达式不匹配任何值时执行的代码
    end
endcase

循环语句

  1. for循环语句:
for (循环变量初始值; 循环条件; 循环变量更新) begin
    // 循环体代码
end
  1. while循环语句:
while (循环条件) begin
    // 循环体代码
end
  1. do-while 循环:
    先执行一段代码块,然后在满足指定条件时重复执行这段代码块。示例代码如下:
begin
	A;
end
  1. repeat循环语句:
repeat (循环次数) begin
    // 循环体代码
end
  1. forever循环语句:
forever //相当于while(1),表示永久循环,通过系统函数$finish退出
	begin
		A;
	end

参考

1 ProNeverFake, Verilog入门教程与实例分享

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/vagrant0407/article/details/135442918
今日推荐