SystemVerilog语法
Tags
SystemVerilog Syntax
Combinational Logic
Hardware Description Language
AI summary
本文介绍了SystemVerilog的语法,包括二进制运算符、always语句、组合逻辑与时序逻辑的区别、模块化设计、以及高级用法如typedef、struct、enum和interface等。强调了电路语句与赋值语句的不同,提供了实例和代码示例,帮助理解如何在硬件描述中实现复杂逻辑和电路设计。
0. 二进制与运算符
1. 常用 always 语句,实现时钟同步原语
2. 一些高级用法 比如 unique_case, enum
Lecture1
立即数:位宽+’+进制 如16’habcd
组合/位绑定用法 {a, 1’b1} {a, {16{b}}}
在硬件描述语言中,变量名及其赋值关系被verilog 解读为电路门(与、或、非门)之间的连接,这种关系在复杂电路中可以相当复杂。
Lecture2
逻辑右移 | >> | ㅤ |
逻辑左移 | << | ㅤ |
算术右移 | >>> | ㅤ |
ㅤ | ㅤ | ㅤ |
缩位运算符 | & | &x[31:0] → b[0:0] |
ㅤ | | | |x[31:0] → b[0:0] |
运算符不能作为向量,因此 (a+b)[3:0] 这种写法是非法的!
赋值语句可以左右两边都可以用位绑定 .
以上都不是电路语句?
谭大爷这句话如何理解,难道这些逻辑运算不会对应到实际电路吗?
只有使用电路语句,语句才会实际地对应到一个电路。
Lecture3
电路语句,谭大爷:写电路图之前一定要先把电路图画出来。
assign 语句:assign + 赋值语句
这是最简单的电路语句。
Lecture4 元件例化
类似于面向对象的《类》
实际上用了 assign 语句就已经能够表达一个 pipelined CPU 绝大部分内容了,但是绝大情况下不会这么做。
好处:
- 代码易于维护
- 代码复用
- 黑盒化,便于开发
一个模块应当包含什么?
- 模块声明(不包含电路语句)
- 电路代码
比如 assign c = a + b
- 模块例化
传入端口的三种方式:
Lecture5 always_comb 语句 (combination 语句)
- 内部每一句都是赋值语句,不能有电路语句。
- always_comb 本身是电路语句。
- 它描述电路信号行为 (和一般的电路代码不同,内部执行的逻辑是串行的,赋值有覆盖性。
- 内部可以放置 if, case 等控制语句。
编译器分析每个语句,转换成真值表等,最终还是会成为 assign 语句,但区别在于程序员可以更简单的实现串行逻辑。
Lecture6 always_comb 中 unique_case 以及 priority_case
unique_case 是并行比较(每个选项都是unique的
而 priority 则类似 C 语言中 switch 语法。
有一个值得注意的点,unique_case 如果有 default 分支,则会引入锁存器逻辑,而锁存器是十分影响效率的。因此在实际操作中不仅尽量选择 unique_case,而且要避免写 default 分支,避免影响电路效率。
- system verilog 中的条件语句
- 学会 if-else ,然后忘掉它。
为了避免这样写(麻烦),可以考虑这样的写法,编译器对这样的语法有独特的优化(compiler friendly):
Lecture7 always_comb 中 if 和 for 控制语法
在 always_comb 中,for 会被默认展开(并行操作)
循环变量的上下界都应该是常数。
不应该在循环外面用循环变量,仿真可能能过,但上板会出问题。
Lecture8 电路语句(4)`always_ff`
`always_ff` 可以描述很复杂的逻辑,但那样写不直观。
值得注意的是:`always_ff` 用 <= 表示非阻塞赋值。
assign 语句中使用 = 表示阻塞赋值。
阻塞赋值和非阻塞赋值的区别是什么?如何理解?
状态方程
触发器内部描述比较复杂的逻辑,在写 always_ff 时可以先写状态方程。但是状态方程是什么?
组合逻辑 & 时序逻辑
时序逻辑应当尽量简单,组合逻辑用来做脏活累活,实际的电路延迟也大部分由组合逻辑造成。谭大爷建议:对于不涉及触发器里的电路,全部写到组合逻辑中。
这两张图就描述了组合逻辑(左)与时序逻辑(右)的区别。
时序逻辑的区别在于,结果不会立即存到相应电路中,而是有一个 d 触发器。
时序逻辑描述并列触发器,always_comb 描述电路行为。因此阻塞赋值放在 always_comb,而非阻塞赋值放在 always_ff。
Lecture 9 高级用法(1) typedef
Lecture 10 高级用法(2)struct enum union
struct 举例
enum 举例
union 举例
避免 union 作为输出时的多驱动现象。
Lecture 11 高级用法 (3)parameter
As Template: 增加模块的 flexibility
比如适用同一算法
int
和long long
的加法器,需要写两个。为了使模块代码具有更高的复用性,引入参数
parameter
。全局变量
parameter
可以作为全局变量声明,作为一个语句,以分号结尾。 Lecture 12 高级用法(4)预编译指令
预编译命令作用和 C 差不多。有了预编译命令,就可以利用头文件提升代码易读性。
C 语言用 # 开头,而 system verilog 用 ` 表示开头。
用预编译可以达到的效果:
- 配置一些参数(效果类似 parameter)但是parameter 不用反引号。
- 根据不同参数,生成不同电路。不同于mux。
generate if
粒度为电路语句。而 ifdef
可以是任意粒度的。- 使用头文件,类似 package 语句。
- 使用宏封装一些功能。部分情况下可用
function
语句。
Lecture 13 抽象接口(5)interface
电路图清晰地表明了元件的每位输出是从哪个元件的输出得到的,而元件例化没法做到这一点。
- 例化不标出信号作为输入还是输出。
- 相关模块的例化代码可能隔得比较远。
同时,模块接口部分的代码,在语法上也可以改进。
- 不同模块可能复用一部分接口。
- 添加一个接口,需要修改多处代码。
Loading...