review josh-verilog-4, change hyperref styles

This commit is contained in:
2023-04-17 19:46:59 +08:00
parent 5f2488bfa9
commit e50c0bcfcc
6 changed files with 302 additions and 265 deletions
@@ -19,6 +19,7 @@ date: 2020-11-25 22:32:42
# 语法
`b = rcosdesign(beta,span,sps)`
`b = rcosdesign(beta,span,sps,shape)`
<!-- more -->
@@ -23,7 +23,7 @@ abbrlink: 460433dd
description: 本文阐述了 HDL 语言/设计方法的基本概念。主要介绍了数字系统建模方法的演变,引入了 HDL 语言的基本概念,对 Verilog HDL 和 VHDL、Verilog HDL 和 C 的联系与区别进行了说明,在最后引入了 HDL 的设计和验证流程,并对各个流程进行了简单介绍。
---
# 1. 设计方法的变迁<a id="01"></a>
# 1. 设计方法的变迁<a id="toc.1"></a>
随着微电子设计技术与工艺的发展,数字集成电路从电子管、晶体管、中小规模集成电路、超大规模集成电路(Very Large Scale Integrated Circuit, VLSIC)逐步发展到今天的专用集成电路(Application Specific Integrated Circuit, ASIC),愈发数字化的产品如计算机、手机、数字电视等都运用了复杂的专用数字集成电路。数字逻辑器件从简单的逻辑门到复杂的 SoC,种类繁多,提供了对复杂系统的灵活支撑。
@@ -51,9 +51,9 @@ description: 本文阐述了 HDL 语言/设计方法的基本概念。主要介
目前最成熟的综合工具是 RTL 级综合工具,它能将 RTL 级描述翻译并优化为门级网表。综合工具的产生支撑了直接从 RTL 级描述硬件电路,这种从门级描述抽象到 RTL 级描述数字电路是设计方法的又一次伟大飞跃。
从上面描述可以看到 HDL 语言是分层次的,关于上述 HDL 语言设计层次的含义在本文的[“HDL 的设计与验证流程”](#03)小节和 [《Part 3——描述方式和设计层次》的“设计层次”][]小节有详细论述。)
从上面描述可以看到 HDL 语言是分层次的,关于上述 HDL 语言设计层次的含义在本文的 [3. HDL 的设计与验证流程](#toc.3)小节和 [Part 3——描述方式和设计层次的 5. 设计层次][]小节有详细论述。
# 2. Verilog 语言的特点<a id="02"></a>
# 2. Verilog 语言的特点<a id="toc.2"></a>
## 2.1. Verilog 的由来
@@ -107,7 +107,7 @@ Verilog 语言是根据 C 语言发明而来的,因此 Verilog 具备了 C 语
Verilog 毕竟是硬件描述语言,在抽象层次上比 C 语言要差一些,语法不如 C 灵活,例如文件输入和输出方面,Verilog 的功能显然不如 C。为了克服 Verilog 高级抽象的缺陷,Verilog 的设计者们发明了 PLI。PLI 可以在仿真器中将 C 语言的程序和 Verilog 的程序互相通信,或者在 Verilog 中调用 C 语言的函数库,这样就大大扩展了 Verilog 语言的灵活性和高层次抽象的能力。开发时,一方面,硬件设计者使用 Verilog 进行硬件建模;另一方面,验证工程师却常常使用 C 来编写测试向量,然后通过 Verilog 的 PLI 将 Verilog 和 C 联系起来。这样,C 语言就很好地弥补了 Verilog 高层次建模的缺陷。
# 3. HDL 的设计与验证流程<a id="03"></a>
# 3. HDL 的设计与验证流程<a id="toc.3"></a>
HDL 的基本功能就是有效地描述并仿真硬件系统。在此部分,抛开具体的 PLD 或 ASIC 设计流程,从 HDL 语言层次入手,分析典型的 HDL 设计与验证流程。基于 HDL 的设计、仿真流程如[图 1-1](#fig.1-1) 所示。图中,虚线框表示的步骤可以根据项目的复杂度省略,而实线框表示的步骤为必须执行的步骤。
@@ -157,6 +157,6 @@ RTL 级综合指 **{% label prime@将 RTL 级 HDL 语言翻译成由与、或、
EDA 先锋工作室. *轻松成为设计高手——Verilog HDL 实用精解.* 北京航空航天大学出版社, 2012.
[《Part 3——描述方式和设计层次》的“设计层次”]: https://josh-gao.top/posts/fd117896.html#%E8%AE%BE%E8%AE%A1%E5%B1%82%E6%AC%A1
[Part 3——描述方式和设计层次的 5. 设计层次]: https://josh-gao.top/posts/fd117896.html#toc.5
[^1]: 最新的 Verilog HDL标准为 IEEE 1364-2005。
+14 -14
View File
@@ -199,7 +199,7 @@ endmodule
这种**在模块中实例化其他功能模块**的描述方式被称之为**结构化描述**。
## 2.2. 3 种描述方法
## 2.2. 3 种描述方法<a id="toc.2.2"></a>
从以上的描述可以看出 Verilog 语言的 3 种基本的描述方法(基本上所有的 Verilog 功能模块都是由这 3 种方式来描述):
@@ -215,9 +215,9 @@ endmodule
- 用户定义原语(UDP)实例化:实例化用户定义的原语。
在[《Part 3——描述方式和设计层次》][]中会详细介绍 Verilog 语言中的这 3 种描述方式。
在 [Part 3——描述方式和设计层次][]中会详细介绍 Verilog 语言中的这 3 种描述方式。
# 3. Verilog 的基本词法
# 3. Verilog 的基本词法<>
1. Verilog HDL 是一种**大小写敏感**的语言,这一点与 VHDL 不同,因此在书写的时候要格外注意。在 Verilog 语言中,**所有的关键字(又叫保留字)都为小写**。Verilog 的内部信号名(或称为标识符)使用大写和小写都可以。标识符可以是字母、数字、`$`(美元符号)和 `_`(下划线)任意组合,只要**第一个字符是字母或者下划线**即可。
@@ -419,7 +419,7 @@ Verilog 语言中的编译指令不止这几条,其他不常用的指令这里
- `Z` 表示高阻状态,也就是**没有任何驱动**,通常用来对**三态总线**进行建模。
在[第 7 节](#7)将提到 Verilog 语言中的变量类型。通常 `net` 型变量如果没有初始化,其值为 `Z`,`register` 型变量如果没有初始化,其值为 `X` 。这一点在仿真时显得比较有意义。
在[第 7 节](#toc.7)将提到 Verilog 语言中的变量类型。通常 `net` 型变量如果没有初始化,其值为 `Z`,`register` 型变量如果没有初始化,其值为 `X` 。这一点在仿真时显得比较有意义。
{% note warning %}
@@ -487,7 +487,7 @@ Message = "Hello World";
这样就将字符串常量存入到 `Message` 变量中。
# 7. 变量类型<a id=7></a>
# 7. 变量类型<a id="toc.7"></a>
在 Verilog 语言中,有两大变量类型:
@@ -518,7 +518,7 @@ Message = "Hello World";
线网类型主要用在连续赋值语句中,以及作为模块之间的互连信号。
在[《Part 3——描述方式和设计层次》][]中会详细阐述常用线网类型的使用方法。
在 [Part 3——描述方式和设计层次][]中会详细阐述常用线网类型的使用方法。
## 7.2. 寄存器类型
@@ -566,7 +566,7 @@ Message = "Hello World";
同时,在 Verilog 中,**不存可以对整个存储器赋值的语句**,必须对每个单元独立赋值。除非使用 `$readmemb` 或 `$readmemh` 系统任务从文件中读入整个或者部分存储器的数据。
> 在[《Part 7—— 逻辑验证与 testbench 编写》][]中将讨论如何从文件中读入数据给存储器赋值。
> 在 [Part 7—— 逻辑验证与 testbench 编写][]中将讨论如何从文件中读入数据给存储器赋值。
### 7.2.2. `integer` 类型
@@ -593,7 +593,7 @@ end
在下一小节中,将引入“驱动”和“赋值”两个概念,深入探讨两种变量的含义。
## 7.4. 驱动和赋值
## 7.4. 驱动和赋值<a id>="toc.7.4"</a>
为了更清楚地描述寄存器和线网变量的概念,将以上述[实例代码](#HelloVlogCode)中的语句来说明。首先,引入 Verilog 语言中两个重要的概念:驱动(Driving)和赋值(Assigning)。
@@ -637,7 +637,7 @@ reg A_xor_wire
不管采用哪种方式,所描述的是一样的组合逻辑电路。尤其是第二种描述,虽然其在语言中被定义为 `reg` 型,但并不是对应硬件上的触发器(flip-flop),而是 Verilog 语言仿真语义上的寄存器概念。
但是,在对实际电路中 D 触发器建模的时候,必须采用 `reg` 型的变量。[图 2-3](#fig.2-3)是 D 触发器的模型。
但是,在对实际电路中 D 触发器建模的时候,必须采用 `reg` 型的变量。[图 2-3](#fig.2-3) 是 D 触发器的模型。
<a id="fig.2-3"></a>
@@ -672,7 +672,7 @@ parameter xor_delay = 4;
前面介绍的 `` `define`` 是一种全局的定义,而 `parameter` 是出现在模块内部的**局部定义**,而且可以被**灵活改变**,这是 `parameter` 的一个重要特征。
在[《Part 3——描述方式和设计层次》的 4.2 小节][]中会详细探讨改变模块参数的方法。
在 [Part 3——描述方式和设计层次的 4.2 参数][]小节会详细探讨改变模块参数的方法。
# 9. Verilog 中的并发与顺序
@@ -695,7 +695,7 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
后续将会重点介绍 Verilog 语言中的这一并行特性,同时阐述 Verilog 的高级仿真原理,希望能帮助大家领会 Verilog 的语义精髓。
# 10. 操作数、操作符和表达式
# 10. 操作数、操作符和表达式<a id="toc.10"></a>
## 10.1. 操作符
@@ -984,7 +984,7 @@ $readmemh ("Read_In_File.txt", DataSource);
EDA 先锋工作室. *轻松成为设计高手——Verilog HDL 实用精解.* 北京航空航天大学出版社, 2012.
[Part 1——初识 HDL 设计方法]: https://josh-gao.top/posts/460433dd.html
[《Part 3——描述方式和设计层次》]: https://josh-gao.top/posts/fd117896.html
[Part 3——描述方式和设计层次]: https://josh-gao.top/posts/fd117896.html
[IEEE Std. 1364-2005]: https://standards.ieee.org/standard/1364-2005.html
[《Part 7—— 逻辑验证与 testbench 编写》]: https://josh-gao.top/posts/e060f513.html
[《Part 3——描述方式和设计层次》的 4.2 小节]: https://josh-gao.top/posts/fd117896.html#%E5%8F%82%E6%95%B0
[Part 7—— 逻辑验证与 testbench 编写]: https://josh-gao.top/posts/e060f513.html
[Part 3——描述方式和设计层次的 4.2 参数]: https://josh-gao.top/posts/fd117896.html#toc.4.2
+18 -18
View File
@@ -25,7 +25,7 @@ description: Verilog 语言可以用多种方式来描述硬件,同时,使
# 1. 描述方式
在[《Part 2——Verilog 语言基础》的第 3 小节][]中己经介绍过,Verilog 语言有 3 种最基本的描述方式.
在 [Part 2——Verilog 语言基础][]中己经介绍过,Verilog 语言有 3 种最基本的描述方式.
- 数据流描述,采用 `assign` 连续赋值语句;
- 行为描述,使用 `always` 语句或 `initial` 语句块中的过程赋值语句;
@@ -63,7 +63,7 @@ assign #1 A_xor_wire = eq0 ^ eq1;
1. **连续驱动**
在[《Part 2——Verilog 语言基础》的 7.4 驱动和赋值][]部分,已经解释了驱动和赋值之间的微妙区别。
在 [Part 2——Verilog 语言基础的 7.4 驱动和赋值][]部分,已经解释了驱动和赋值之间的微妙区别。
连续赋值语句是连续驱动的。也就是说,任何时刻输入的任何变化都将导致该语句的重新计算。
@@ -71,7 +71,7 @@ assign #1 A_xor_wire = eq0 ^ eq1;
由于仿真器中不会存储连续赋值语句中被赋值的变量值,因此该变量是线网类型(Net),不能是寄存器类型。需要记住,只有线网类型的变量才可以在 `assign` 语句中被赋值。
另外,线网类型的变量可以被多重驱动,也就是说,可以在多个连续赋值语句中驱动同一个线网。在 [2.4 驱动源线网](#drive)中将进一步介绍。但是,寄存器变量就不同了,它不能被不同的行为进程(例如 `always` 语句块)驱动。
另外,线网类型的变量可以被多重驱动,也就是说,可以在多个连续赋值语句中驱动同一个线网。在 [2.4 驱动源线网](#toc.2.4)小节中将进一步介绍。但是,寄存器变量就不同了,它不能被不同的行为进程(例如 `always` 语句块)驱动。
3. **使用 `assign` 对组合逻辑建模**
@@ -182,7 +182,7 @@ assign #(4:5:6, 3:4:5) A_xor_wire = eq0 ^ eq1;
另外,`assign` 语句中的延时特性通常是被逻辑综合工具忽略的。因为综合工具要将 Verilog 语言模型综合成逻辑电路,而逻辑电路的延时是由基本的单元库和走线延时决定的。用户无法对逻辑单元指定延时,但是,用户可以在综合和实现工具中加时序约束,让工具尽量满足设计的时序要求。
## 2.4. 驱动源线网<a id="drive"></a>
## 2.4. 驱动源线网<a id="toc.2.4"></a>
下面分为几种线网类型来描述当线网具有多重驱动源时的情况。
@@ -274,9 +274,9 @@ endmodule
![图 3-5 三态驱动总线电路](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-050-WireTri.png!sign){width=700px}
# 3. 行为描述<a id="03"><a>
# 3. 行为描述<a id="toc.3"><a>
在 [《Part 2——Verilog 语言基础》的第 2.2 小节][]中介绍过行为描述的概念。所谓行为描述,是指用语言描述电路的行为。行为描述的语句有两种:`initial` 和 `always` 语句。
在 [Part 2——Verilog 语言基础的 2.2 3 种描述方法][]中介绍过行为描述的概念。所谓行为描述,是指用语言描述电路的行为。行为描述的语句有两种:`initial` 和 `always` 语句。
## 3.1. 行为描述的语句格式
@@ -474,7 +474,7 @@ endmodule
要注意的是,目前多数综合工具还不支持 `wait` 语句,因此这个锁存器的功能只能在仿真时用,不能实现为具体的电路。
## 3.2. 过程赋值语句
## 3.2. 过程赋值语句<a id="toc.3.2"></a>
所谓过程赋值语句就是在 `initial` 和 `always` 语句块中的赋值语句。赋值对象只能是寄存器变量类型。右边的表达式可以是任意操作符的表达式。
@@ -697,7 +697,7 @@ end
在 `always` 以外的i变量和 `always` 里面定义的i变量属于**两个不同的变量,并不冲突**。它们在仿真的时候将占用两块不同的内存,类似于 C 语言中的静态局部变量。
## 3.4. 高级编程语旬
## 3.4. 高级编程语句<a id="toc.3.4"></a>
### 3.4.1. 为什么需要编程语句
@@ -1258,13 +1258,13 @@ Verilog 模块参数的这一特性非常有用,用户可以定义一个通用
使用上面这种参数直接带入法时,要注意一点,所有的参数都需要全部按顺序列出来,不能遗漏,也不能颠倒顺序,否则就容易对应不上。
# 5. 设计层次
# 5. 设计层次<a id=toc.5></a>
在前面几节中,介绍了 Verilog 的描述方式。
Verilog 语言是一种强大的硬件描述语言,可以支持多个设计层次。在这里将进行简单的介绍。
## 5.1. 系统级和行为级<a id=5.1></a>
## 5.1. 系统级和行为级<a id=toc.5.1></a>
Verilog 语言作为一种用户工具,提供给用户许多描述硬件的手段,如前面所述:数据流描述、行为描述(`always` 和 `initial` 语句)、结构化描述。同时,不同用户可以根据自己的需要,在不同抽象层次上对硬件进行描述。有如下设计层次金字塔供参考。
@@ -1282,7 +1282,7 @@ Verilog 语言作为一种用户工具,提供给用户许多描述硬件的手
4. 验证工程师:他们负责对设计的电路进行验证,他们编写的代码主要是用来产生激励,这些激励大部分需要的抽象层次更高,以使仿真的效率更高。然后在工具中对电路进行仿真,检查响应结果。这些代码不会实现为具体癭件,有些并不需要精确到时钟周期,而只是在软件的仿真工具中运行,实现一定的功能即可,称这种描述层次为行为级。
这里的行为级描述,不同于 [3. 行为描述](#03)中所述的“行为描述方式”。这里特指一种描述的抽象层次。
这里的行为级描述,不同于 [3. 行为描述](#toc.3)中所述的“行为描述方式”。这里特指一种描述的抽象层次。
下面举一个实例说明 RTL 级和行为级的区别,要实现的状态机一部分如[图 3-18](#fig.3-18) 所示。=
@@ -1361,7 +1361,7 @@ end
Verilog 设计电路最常用的设计层次就是 RTL 级。在 RTL 描述时,设计者需要关注寄存器的行为,其中保存着数据;同时需要关注寄存器和寄存器之间的组合逻辑功能,是否能满足功能需求和时序需求。RTL 级模型是严格精确到时钟周期的模型。
[《Part 4 —— RTL 概念与常用 RTL 建模》][]、[《Part 5 —— RTL 设计与编码指导》][]和[《Part 6—— 如何写好状态机》][]会重点介绍 RTL 设计的方法和技巧。
[Part 4 —— RTL 概念与常用 RTL 建模][]、[Part 5 —— RTL 设计与编码指导][]和[Part 6—— 如何写好状态机][]会重点介绍 RTL 设计的方法和技巧。
{% note info %}
@@ -1407,9 +1407,9 @@ Verilog 支持不同设计层次的混描述。
EDA 先锋工作室. *轻松成为设计高手——Verilog HDL 实用精解.* 北京航空航天大学出版社, 2012.
[《Part 2——Verilog 语言基础》的第 3 小节]: https://josh-gao.top/posts/fd117896.html#%E8%A1%8C%E4%B8%BA%E6%8F%8F%E8%BF%B0
[《Part 2——Verilog 语言基础》的 7.4 驱动和赋值]: https://josh-gao.top/posts/fd2ca242.html#%E9%A9%B1%E5%8A%A8%E5%92%8C%E8%B5%8B%E5%80%BC
[《Part 2——Verilog 语言基础》的第 2.2 小节]: https://josh-gao.top/posts/fd2ca242.html#%E7%A7%8D%E6%8F%8F%E8%BF%B0%E6%96%B9%E6%B3%95
[《Part 4 —— RTL 概念与常用 RTL 建模》]: https://josh-gao.top/posts/ecb88422.html
[《Part 5 —— RTL 设计与编码指导》]: https://josh-gao.top/posts/53b8b42e.html
[《Part 6—— 如何写好状态机》]: https://josh-gao.top/posts/d860a67e.html
[Part 2——Verilog 语言基础]: https://josh-gao.top/posts/fd2ca242.html
[Part 2——Verilog 语言基础的 2.2 3 种描述方法]: https://josh-gao.top/posts/fd2ca242.html#toc2.2
[Part 2——Verilog 语言基础的 7.4 驱动和赋值]: https://josh-gao.top/posts/fd2ca242.html#toc7.4
[Part 4 —— RTL 概念与常用 RTL 建模]: https://josh-gao.top/posts/ecb88422.html
[Part 5 —— RTL 设计与编码指导]: https://josh-gao.top/posts/53b8b42e.html
[Part 6—— 如何写好状态机]: https://josh-gao.top/posts/d860a67e.html
File diff suppressed because it is too large Load Diff
@@ -509,7 +509,7 @@ case (var)
# 2. 同步设计原则和多时钟处理
## 2.1 同步设计原则<a name="0201"></a>
## 2.1 同步设计原则<a name="toc.2.1"></a>
同步设计是 PLD 和 ASIC 设计的最重要原则。本小节首先阐释为什么在 PLD 设计中要采用同步时序设计,然后重点论述同步时序设计的要点。
@@ -550,7 +550,7 @@ case (var)
- 同步时序电路的延迟。同步时序设计中电路延迟最常用的设计方法是用分频或倍频的时钟或者同步计数器完成所需延迟。换句话说,同步时序电路的延时被当作一个电路逻辑来设计。对于**比较大的和特殊定时要求的延时,一般用高速时钟产生一个计数器,根据计数器的计数,控制延时**;对于**比较小的延时,可以用 D 触发器打一下**,这种做法**不仅使信号延时了一个时钟周期,而且完成了信号与时钟的初次同步**,在输入信号采样或增加时序约束余量时使用。另外许多初学者用行为级(Behavioral Level)方法描述延时,如 `#5 a<= 4'b0101;` 这种行为级描述方法常用于仿真测试激励,但是**在电路综合时会被忽略、并不能起到延时作用**。
## 2.2 亚稳态
## 2.2 亚稳态<a id="toc.2.2"></a>
在后续笔记中会介绍异步时钟域转换的问题,在谈这个话题之前,先分析一下什么是亚稳态,以及如何避免。
@@ -593,7 +593,7 @@ case (var)
在早期逻辑电路图设计阶段,有一些设计者养成了手工加入 Buffer 或者非门调整数据延迟的习惯,从而保证本级模块的时钟对上级模块数据的建立、保持时间的要求。这些做法目前主要应用的场合有两种:一是使用分立逻辑元件(如 74 系列)搭建数字逻辑电路;另一种是在 ASIC 设计领域。**目前使用分立逻辑元件搭建数字逻辑电路的场合一般为系统复杂度相对较低,系统灵活性要求不高的场合。**在上述场合使用分立逻辑器件设计数字逻辑电路,由于可以使用的调整延时的手段相对有限,而且采用插入 Buffer 、数字延迟逻辑甚至两个非门等手段调整采样的 Setup 和 Hold 时间是可以接受的。而 ASIC 设计领域采用这种方法是以严格的仿真和约束条件作为强力支持的。
正如 [2.1 同步设计原则](#0201)所述,**使用组合逻辑方法产生延迟,容易产生毛刺**,而且这种设计方法的**时序余量较差**,一旦外界条件变换(环境试验,特别是高低温试验),采样时序就有可能完全紊乱,造成电路瘫痪。另外,一旦芯片更新换代,或者移植到其他器件族的芯片上,采样时延必须重新调整,电路的可维护性和继承性都很差。
正如 [2.1 同步设计原则](#toc.2.1)所述,**使用组合逻辑方法产生延迟,容易产生毛刺**,而且这种设计方法的**时序余量较差**,一旦外界条件变换(环境试验,特别是高低温试验),采样时序就有可能完全紊乱,造成电路瘫痪。另外,一旦芯片更新换代,或者移植到其他器件族的芯片上,采样时延必须重新调整,电路的可维护性和继承性都很差。
2. 盲目使用时钟正负沿调整数据采样
@@ -649,7 +649,7 @@ case (var)
在后面的几节中,将详细谈谈设计和代码风格。
# 4. 结构层次和模块划分
# 4. 结构层次和模块划分<a id="toc.4"></a>
## 4.1 结构层次化编码
@@ -822,7 +822,7 @@ endmodule
## 6.2 Ripple Counter
所谓 Ripple Counter,即行波计数器,其结构为:一组寄存器级连,每个寄存器的输出端接到下一级寄存器的时钟管脚,这种计数器常常用于异步分频电路。早期的 PLD 设计经常使用 Ripple Counter 以节约芯片资源。但是由于 Ripple Counter 是一种典型的异步时序逻辑,正如前面“[同步设计原则](#0201)”所述,异步时序逻辑会带来各种各样的时序问题,**在同步时序电路设计中必须严格避免使用 Ripple Counter**。
所谓 Ripple Counter,即行波计数器,其结构为:一组寄存器级连,每个寄存器的输出端接到下一级寄存器的时钟管脚,这种计数器常常用于异步分频电路。早期的 PLD 设计经常使用 Ripple Counter 以节约芯片资源。但是由于 Ripple Counter 是一种典型的异步时序逻辑,正如前面“[同步设计原则](#toc.2.1)”所述,异步时序逻辑会带来各种各样的时序问题,**在同步时序电路设计中必须严格避免使用 Ripple Counter**。
## 6.3 时钟选择
@@ -843,7 +843,7 @@ endmodule
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-170-GatedClock.png!sign" width="800px" alt="门控时钟"/>
</div>
但是 Gated Clock 不是同步时序电路,其 Gating Logic(门控逻辑)会污染 Clock 的质量,通过控制门后会产生毛刺并使时钟的 Skew(偏斜)、Jitter(延时)等指标恶化。正如“[同步设计原则](#0201)” 一节所述,在同步时序电路中,应该尽量不使用 Gated Clock 。
但是 Gated Clock 不是同步时序电路,其 Gating Logic(门控逻辑)会污染 Clock 的质量,通过控制门后会产生毛刺并使时钟的 Skew(偏斜)、Jitter(延时)等指标恶化。正如“[同步设计原则](#toc.2.1)” 一节所述,在同步时序电路中,应该尽量不使用 Gated Clock 。
虽然有些材料指出当功耗成为主要矛盾时,可以使用门控时钟改进电路如[图 5-18](#fig.5-18) 所示的电路完成类似门控时钟的功能,但是笔者仍强烈建议在 PLD 设计中不要使用该图所示的门控时钟改进电路。虽然这个改进电路已经在较大程度上解决了门控电路产生的毛刺,但是请读者注意,这个电路工作的前提是时钟源Clock 的占空比(Duty Cycle)是非常理想的 50%,如果时钟的占空比不能保证 50%,则会产生许多有规律的毛刺信号。另外这个电路还有一个前提,那就是 Clock 与 Enable 信号的不布线 Skew 为 0,否则也会造成宽度为 Skew 的毛刺。
@@ -865,7 +865,7 @@ endmodule
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-190-EnableSynchronization.png!sign" width="500px" alt="同步使能端"/>
</div>
# 7. RTL 代码优化技巧
# 7. RTL 代码优化技巧<a id="toc.7"></a>
## 7.1 使用 Pipelining 技术优化时序