Verilog 笔记

本文最后更新于 2024年12月30日 下午

特性

三种建模方式

  1. 行为级描述——使用过程化结构描述
  2. 数据流描述——使用连续赋值语句建模
  3. 结构化方式——使用门和模块例化语句描述

两类数据类型

mindmap
	))数据类型((
		(wire)
		(reg)
			[integer]
			[real]
			[time]
			[paramater]
  1. 线网(wire)——物理元件之间的连线

  2. 寄存器(reg)——数据存储元件

    • integer

      声明时不用指明位宽,位宽和编译器有关,一般为32 bit。reg 型变量为无符号数,而 integer 型变量为有符号数。

    • real

      实数用关键字 real 来声明,可用十进制或科学计数法来表示。实数声明不能带有范围,默认值为 0。如果将一个实数赋值给一个整数,则只有实数的整数部分会赋值给整数。

    • time

      Verilog 使用特殊的时间寄存器 time 型变量,对仿真时间进行保存。其宽度一般为 64 bit,通过调用系统函数 $time 获取当前仿真时间。

    • paramater

      常用于定义常数

    • 数组

    • 存储器

    • 字符串

Verilog 支持可变的向量域选择

Verillog 还支持指定 bit 位后固定位宽的向量域选择访问。

  • [bit+: width] : 从起始 bit 位开始递增,位宽为 width。
  • [bit-: width] : 从起始 bit 位开始递减,位宽为 width。

连续赋值

连续赋值语句是 Verilog 数据流建模的基本语句,用于对 wire 型变量进行赋值。:

格式如下

1
assign     LHS_target = RHS_expression  ;

LHS(left hand side) 指赋值操作的左侧,RHS(right hand side)指赋值操作的右侧。

assign 为关键词,任何已经声明 wire 变量的连续赋值语句都是以 assign 开头,例如:

1
2
wire      Cout, A, B ;
assign Cout = A & B ; //实现计算A与B的功能

需要说明的是:

  • LHS_target 必须是一个标量或者线型向量,而不能是寄存器类型。
  • RHS_expression 的类型没有要求,可以是标量或线型或存器向量,也可以是函数调用。
  • 只要 RHS_expression 表达式的操作数有事件发生(值的变化)时,RHS_expression 就会立刻重新计算,同时赋值给 LHS_target。

Verilog 还提供了另一种对 wire 型赋值的简单方法,即在 wire 型变量声明的时候同时对其赋值。wire 型变量只能被赋值一次,因此该种连续赋值方式也只能有一次。例如下面赋值方式和上面的赋值例子的赋值方式,效果都是一致的。

1
2
wire      A, B ;
wire Cout = A & B ;

时延

连续赋值时延一般可分为普通赋值时延、隐式时延、声明时延。

mindmap
	))时延((
		[普通时延]
		[隐式时延]
		[声明时延]

下面 3 个例子实现的功能是等效的,分别对应 3 种不同连续赋值时延的写法。

(1)普通时延,A&B计算结果延时10个时间单位赋值给Z wire Z, A, B ; assign #10 Z = A & B ;

(2)隐式时延,声明一个wire型变量时对其进行包含一定时延的连续赋值。 wire A, B; wire #10 Z = A & B;

(3)声明时延,声明一个wire型变量是指定一个时延。因此对该变量所有的连续赋值都会被推迟到指定的时间。除非门级建模中,一般不推荐使用此类方法建模。 wire A, B; wire #10 Z ; assign Z =A & B

惯性时延

在上述例子中,A 或 B 任意一个变量发生变化,那么在 Z 得到新的值之前,会有 10 个时间单位的时延。如果在这 10 个时间单位内,即在 Z 获取新的值之前,A 或 B 任意一个值又发生了变化,那么计算 Z 的新值时会取 A 或 B 当前的新值。所以称之为惯性时延,即信号脉冲宽度小于时延时,对输出没有影响。

过程结构

(1)initial 语句

initial 语句从 0 时刻开始执行,只执行一次,多个 initial 块之间是相互独立的。

如果 initial 块内包含多个语句,需要使用关键字 begin 和 end 组成一个块语句。

如果 initial 块内只要一条语句,关键字 begin 和 end 可使用也可不使用。

initial 理论上来讲是不可综合的,多用于初始化、信号检测等。

(2)always 语句

与 initial 语句相反,always 语句是重复执行的。always 语句块从 0 时刻开始执行其中的行为语句;当执行完最后一条语句后,便再次执行语句块中的第一条语句,如此循环反复。

由于循环执行的特点,always 语句多用于仿真时钟的产生,信号行为的检测等。

过程赋值

过程性赋值是在 initial 或 always 语句块里的赋值,赋值对象是寄存器、整数、实数等类型。

这些变量在被赋值后,其值将保持不变,直到重新被赋予新值。

连续性赋值总是处于激活状态,任何操作数的改变都会影响表达式的结果;过程赋值只有在语句执行的时候,才会起作用。这是连续性赋值与过程性赋值的区别。

Verilog 过程赋值包括 2 种语句:阻塞赋值与非阻塞赋值。


Verilog 笔记
http://blog.kdata.top/2024/07/01/计算机技术/编程语言/Verilog/
作者
Louis Liang
发布于
2024年7月1日
许可协议