2019年2月17日 11:10:50
年前 到现在 学习了下 Verilog , 这次效率比较高,估计是因为方法比较正确
不写读书总结了, 因为那样只是 重复书上的知识点,现在 假设我要给别人 讲 明白这个东西 , 我 应该怎么讲, 课程大纲 应该是 什么样子的 , 基于 这样的假设 来写下 总结
首先,对 Verilog 的 总体认识 要到位, Verilog 是所谓硬件描述语言。 那硬件是什么东西? 这里的硬件是指 数字电路, 或者说 逻辑电路。不是硬盘、光驱或者 主板 这些硬件。而 CPU 或者 某些 特定功能的数字芯片 属于这样的逻辑电路。
那 逻辑电路具体 怎么回事? 即, 基于逻辑门 搭建的电路, 更具体的认识 需要阅读 专门书籍, 这里强烈 推荐 美国人 Charles 写的《编码-隐匿在计算机软硬件背后的语言》 。 作者是大牛,这书 堪称神书, 能把 一般的计算机组成原理或者 计算机体系结构 教程上那些 枯燥的东西 讲得 非常生动, 而不失 准确性 。 这就 很难得!
对于学习Verilog,看《编码》 这个书,需要理解如下知识 : 二进制和布尔代数、二进制逻辑、 逻辑门、 使用逻辑门实现加法器和减法器 。然后就是 重中之重: 反馈和触发器。 这个地方 要理解 计数器、D 触发器、锁存器。 因为这关系到 所谓 时序电路 的概念,尤其是所谓 上升沿、下降沿的概念。。前面的加法器属于所谓 组合 电路。简单说下就是 组合 电路就像是 数学中函数,输出完全由当前输入决定,而 时序电路的输出 和 之前的输入也有关系,就是和时间线上的信息有关系,所以叫时序电路。
看明白了这个书, 再看 Verilog 就容易多了,因为涉及到的基础概念都已经明白了。 这里推荐 《Verilog HDL 数字设计与综合》这个教材,比较薄, 而且书的第一部分就把Verilog语言讲得差不多了,也就150页左右。
所谓数字设计,就是 数字电路设计。 最初 人们直接基于 逻辑门进行电路搭建, 就是像 《编码》里面讲的那样, 使用 与门、或门 这些 基本的逻辑门 实现 诸如 加法、触发器这些功能。 当然, 这样效率 太低了。 为了提高效率, 人们 设计了 Verilog 这样的硬件描述语言来 描述 整个数字电路应该如何搭建, 也就是所谓建模。
当然, 使用Verilog 语言进行 电路设计, 也可以基于不同的抽象层次来进行。 比如, 依然 可以 基于 语言中的 逻辑门 来设计, 这种做法就是 书中第 5 章所谓的 门级建模, 即 基于逻辑门 来设计整个电路。 此时, 编写的 Verilog 代码中就是 对 and / or / xor 这些门 进行 操作。
Verilog 语言 自然就得提供 所支持的 基础的 逻辑门 。 即 门级原语 所谓 原语,就是说 语言已经自带这些门 , 设计者无需 实现, 即可使用这些 原语 来构建 数字电路。 比如
and a1(OUT, IN1, IN2)
就是一个 与门实例, 两个输入为 IN1 和 IN2, 输出为 OUT。
使用 门 进行 建模,比较直观, 但工作量大,容易出错。所以,需要基于更高层次的抽象进行建模。
比门更高一层的抽象就是书中 第六章 数据流建模, 即 设计者 通过Verilog语言 对 寄存器直接的数据流动和处理 进行 描述, 来实现 对电路的描述。 自然, 就需要工具 把这种 描述 转换 门级结构, 才能把电路物理化。 这种转换就是所谓 逻辑综合。
本章核心内容是 对 wire 变量的赋值、 表达式、操作符、操作数。很类似C语言的一部分了。比如
wire out = in1 & in2
直接 实现 一个与运算, 无需 使用 门 进行构建了。
操作数 就是 Verilog支持的 一些 常量 和变量类型, 操作符 就是 对这些操作数 进行何种运算。 表达式由 操作符 和 操作数构成。 这三个元素 就是 数据流建模 的基础。
内容较多的部分是 操作符, 有 如下类别: 算术运算、逻辑运算、关系运算、位运算、缩减运算、 赋值和拼接、 条件运算符。 学过C语言就会觉得很简单。
书中例 6.8 给出了一个 基于 位运算实现 的D触发器。 这里代码体现为 若干位运算表达式。 如果是 基于门,那么代码中 就应该是 像书中图 6.4 那样, 描述 这个触发器 由 哪些逻辑门构成 以及 这些逻辑门 如何进行连接。
更高一层次的抽象 就是 所谓行为级建模,可以认为是 算法层次的描述。这个层次的实现类似C语言编程,会利用 if /else/ case/ while/for 这些 特性进行 描述。 但也要注意描述硬件电路 和 描述软件功能存在 的重大区别。 在数字设计领域, RTL(register transfer level) 寄存器传输级, 通常是指 数据流建模 和 行为级 建模的 结合。
主要内容有:
initial 从时间0开始执行,只执行一次。 alway则循环进行执行,可以想象为电路上电以后, 只要不断电, 就持续运作。比如 一个时钟,处于周期性变化状态,直至断电。
其他的细节这里不说了。
第8章 是函数和任务, 函数和任务用于 抽取 公共部分,以反复使用。区别在于 函数用于 表示纯粹的组合逻辑, 只有一个输出。并且这个输出是用 函数名隐含的同名寄存器变量来实现的。所以函数没有输出变量。 因为用于表示纯粹的组合逻辑, 所以 函数内 不能有时序和控制相关的东西。
任务Task用于替代 普通的 Verilog 代码, 所以 任务的编写 约束很少。
两者的共同约束有:内部不能声明 wire变量, 只能使用行为级语句, 但不能有 always 和 initial块。
最后一个重点, 使用 Verilog 描述电路,基本单元 是所谓的 模块 module。 可以大概理解为 生物由细胞构成。 每个模块实现特定的功能。 这类似与写C语言代码时 ,整个程序由 一个个函数组成。第四章 讲了 模块相关的东西, 但 模块实例化的过程在第2章第4节中讲的, 对初学者不友好。 学过面向对象编程的话 比较容易理解这个概念。
第9章 讲的是 一些 辅助操作,比如条件编译、系统任务、仿真时间单位等等。
大概就这么多了,剩下的就是 实践了。
仿真器 使用 iverilog , 比较好使。 看到波形图正确 就 一切操作OK 了。iverilog的下载和使用可以参考
这篇文章
#编译
iverilog -o led.out led.v tb.v
// 生成波形
vvp led.out
// 查看波形
gtkwave wave.vcd