update caption in josh-verilog-1~3

This commit is contained in:
2023-04-17 09:52:22 +08:00
parent cd92265be1
commit 5f2488bfa9
7 changed files with 91 additions and 62 deletions
@@ -109,9 +109,11 @@ Verilog 语言是根据 C 语言发明而来的,因此 Verilog 具备了 C 语
# 3. HDL 的设计与验证流程<a id="03"></a> # 3. HDL 的设计与验证流程<a id="03"></a>
HDL 的基本功能就是有效地描述并仿真硬件系统。在此部分,抛开具体的 PLD 或 ASIC 设计流程,从 HDL 语言层次入手,分析典型的 HDL 设计与验证流程。基于 HDL 的设计、仿真流程如下图所示。图中,虚线框表示的步骤可以根据项目的复杂度省略,而实线框表示的步骤为必须执行的步骤。 HDL 的基本功能就是有效地描述并仿真硬件系统。在此部分,抛开具体的 PLD 或 ASIC 设计流程,从 HDL 语言层次入手,分析典型的 HDL 设计与验证流程。基于 HDL 的设计、仿真流程如[图 1-1](#fig.1-1) 所示。图中,虚线框表示的步骤可以根据项目的复杂度省略,而实线框表示的步骤为必须执行的步骤。
![基于 HDL 的设计、仿真流程](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-27-josh-verilog-part-1/2020-11-27-josh-verilog-part-1-010-DesignSimulationFlowChartBasedonHDL.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5){width=800px} <a id="fig.1-1"></a>
![图 1-1 基于 HDL 的设计、仿真流程](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-27-josh-verilog-part-1/2020-11-27-josh-verilog-part-1-010-DesignSimulationFlowChartBasedonHDL.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5){width=800px}
下面对一些关键设计步骤与概念进行展开。 下面对一些关键设计步骤与概念进行展开。
@@ -51,9 +51,11 @@ EDA 行业的先行者们发明了 Verilog 硬件描述语言,其最根本的
<a id="HelloVlog"></a> <a id="HelloVlog"></a>
首先看一个简单的如下图所示的电路(模块):`HelloVlog`。它可以是一个独立的设计,也可以是更大的系统的一个组成部分。 首先看一个简单的如[图 2-1](#fig.2-1) 所示的电路(模块):`HelloVlog`。它可以是一个独立的设计,也可以是更大的系统的一个组成部分。
![HelloVlog 模块](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-010-JoshVerilog.png!sign){width=800px} <a id="fig.2-1"></a>
![图 2-1 HelloVlog 模块](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-010-JoshVerilog.png!sign){width=800px}
该电路首先在两个 2 位的输入数据 `A_in[1:0]` 的和 `B_in[1:0]` 之间,由 `sel` 信号做二选一。后面是一个 2-4 译码电路,将输入的信号 `result[1:0]`解析成 `eq0`、`eql`、`eq2` 和 `eq3` 这4个信号,它们同时只有一个为 1。 该电路首先在两个 2 位的输入数据 `A_in[1:0]` 的和 `B_in[1:0]` 之间,由 `sel` 信号做二选一。后面是一个 2-4 译码电路,将输入的信号 `result[1:0]`解析成 `eq0`、`eql`、`eq2` 和 `eq3` 这4个信号,它们同时只有一个为 1。
@@ -621,24 +623,25 @@ always @(eq0 or eq1)
reg A_xor_wire reg A_xor_wire
``` ```
这两者描述的目的一样,都是一个异或门,如下图所示。 这两者描述的目的一样,都是一个异或门,如[图 2-2](#fig.2-2) 所示。
<a id=XorGate></a> <a id="fig.2-2"></a>
![异或门](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-020-XORGate.png!sign){width=700px} ![图 2-2 异或门](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-020-XORGate.png!sign){width=700px}
下面从语义上的角度探讨两种描述方式的不同。 下面从语义上的角度探讨两种描述方式的不同。
第一种描述方式使用 `assign` 语句,Verilog 中将其称为连续赋值语句(Continuously Assignment),实际上是**连续驱动**的过程。也就是说,在任意一个仿真时刻,当前时刻 `eq0` 和 `eq1` 相异或的结果决定了 `1ns` 以后(语句 `#1` 的延时控制)的线网变量 `A_xor_wire` 的值,**不管 `eq0` 和 `eq1` 变化与否,这个驱动过程一直存在**,因此称为连续驱动。(在仿真器中,线网变量是不占用仿真内存空间的。)如上[异或门图](#XorGate)中的时序所示,这个驱动过程在任意时刻都存在。 第一种描述方式使用 `assign` 语句,Verilog 中将其称为连续赋值语句(Continuously Assignment),实际上是**连续驱动**的过程。也就是说,在任意一个仿真时刻,当前时刻 `eq0` 和 `eq1` 相异或的结果决定了 `1ns` 以后(语句 `#1` 的延时控制)的线网变量 `A_xor_wire` 的值,**不管 `eq0` 和 `eq1` 变化与否,这个驱动过程一直存在**,因此称为连续驱动。(在仿真器中,线网变量是不占用仿真内存空间的。)如上[图 2-2](#fig.2-2) 中的时序所示,这个驱动过程在任意时刻都存在。
在第二种描述方式中使用了 `always` 语句,后面紧跟着一个敏感列表:`@(eq0 or eq1)` 因此,这个语句只有在 `eq0` 或 `eq1` 发生变化时才会执行。如上[异或门图](#XorGate)中,在时刻 2、3 和 6,该语句都将执行,将 `eq0` 和 `eq1` 赋值的结果延时 1ns 以后赋值给 `A_xor_wire` 变量。**在其他时刻,`A_xor_wire` 变量必须保持**。因此,**从仿真语义上讲,需要一个存储单元,也可以说是寄存器,来保存 `A_xor_wire` 变量的中间值**。这就是 Verilog 语言的“寄存器类型”变量的来历,而这个 `A_xor_wire` 变量首先需要定义为 `reg` 类型。 在第二种描述方式中使用了 `always` 语句,后面紧跟着一个敏感列表:`@(eq0 or eq1)` 因此,这个语句只有在 `eq0` 或 `eq1` 发生变化时才会执行。如[图 2-2](#fig.2-2) 中,在时刻 2、3 和 6,该语句都将执行,将 `eq0` 和 `eq1` 赋值的结果延时 1ns 以后赋值给 `A_xor_wire` 变量。**在其他时刻,`A_xor_wire` 变量必须保持**。因此,**从仿真语义上讲,需要一个存储单元,也可以说是寄存器,来保存 `A_xor_wire` 变量的中间值**。这就是 Verilog 语言的“寄存器类型”变量的来历,而这个 `A_xor_wire` 变量首先需要定义为 `reg` 类型。
不管采用哪种方式,所描述的是一样的组合逻辑电路。尤其是第二种描述,虽然其在语言中被定义为 `reg` 型,但并不是对应硬件上的触发器(flip-flop),而是 Verilog 语言仿真语义上的寄存器概念。 不管采用哪种方式,所描述的是一样的组合逻辑电路。尤其是第二种描述,虽然其在语言中被定义为 `reg` 型,但并不是对应硬件上的触发器(flip-flop),而是 Verilog 语言仿真语义上的寄存器概念。
但是,在对实际电路中 D 触发器建模的时候,必须采用 `reg` 型的变量。下图是 D 触发器的模型。 但是,在对实际电路中 D 触发器建模的时候,必须采用 `reg` 型的变量。[图 2-3](#fig.2-3)是 D 触发器的模型。
![D 触发器模型](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-030-DFlipFlop.png!sign){width=300px} <a id="fig.2-3"></a>
![图 2-3 D 触发器模型](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-030-DFlipFlop.png!sign){width=300px}
在上述[实例代码](#HelloVlogCode)中相应的描述如下: 在上述[实例代码](#HelloVlogCode)中相应的描述如下:
+71 -39
View File
@@ -47,9 +47,11 @@ description: Verilog 语言可以用多种方式来描述硬件,同时,使
## 2.2. 连续赋值语句 ## 2.2. 连续赋值语句
![一个电路模型](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-010-XORGate.png!sign){width=800px} <a id="fig.3-1"></a>
上图中的电路模型可以用如下的语句来描述: ![图 3-1 一个电路模型](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-010-XORGate.png!sign){width=800px}
[图 3-1](#fig.3-1) 中的电路模型可以用如下的语句来描述:
``` verilog ``` verilog
assign #1 A_xor_wire = eq0 ^ eq1; assign #1 A_xor_wire = eq0 ^ eq1;
@@ -81,9 +83,11 @@ assign #1 A_xor_wire = eq0 ^ eq1;
### 2.2.2. 实例 ### 2.2.2. 实例
![两个半加器和一个或门组成全加器](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-020-FullAdder.png!sign){width=800px} <a id="fig.3-2"></a>
在上图中,用两个半加器和一个或门组成一个全加器,这里将使用连续赋值语句描述这个电路。代码如下。 ![图 3-2 两个半加器和一个或门组成全加器](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-020-FullAdder.png!sign){width=800px}
在[图 3-2](#fig.3-2) 中,用两个半加器和一个或门组成一个全加器,这里将使用连续赋值语句描述这个电路。代码如下。
<a id="HalfAdder"></a> <a id="HalfAdder"></a>
@@ -218,9 +222,11 @@ assign WireOr = C & D;
endmodule endmodule
``` ```
逻辑综合以后,它具体对应的逻辑电路如下图所示。 逻辑综合以后,它具体对应的逻辑电路如[图 3-3](#fig.3-3) 所示。
![线或的功能](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-030-WireOr.png!sign){width=700px} <a id="fig.3-3"></a>
![图 3-3 线或的功能](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-030-WireOr.png!sign){width=700px}
同样,可以使用 `wand` 线网类型来将不同的输出“线与”在一起,如下: 同样,可以使用 `wand` 线网类型来将不同的输出“线与”在一起,如下:
@@ -238,9 +244,11 @@ assign WireAnd = C & D;
endmodule endmodule
``` ```
它对应的逻辑电路如下图所示。 它对应的逻辑电路如[图 3-4](#fig.3-4) 所示。
![线与的功能](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-040-WireAnd.png!sign){width=700px} <a id="fig.3-4"></a>
![图 3-4 线与的功能](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-040-WireAnd.png!sign){width=700px}
### 2.4.3. 三态总线功能 ### 2.4.3. 三态总线功能
@@ -260,9 +268,11 @@ assign WireTri = (en2_n) ? 1'bz : (C & D);
endmodule endmodule
``` ```
其实现的电路如下图所示。 其实现的电路如[图 3-5](#fig.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} <a id="fig.3-5"></a>
![图 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="03"><a>
@@ -350,9 +360,11 @@ end
#### 3.1.3.1. 事件语句(`@`)的用法 #### 3.1.3.1. 事件语句(`@`)的用法
![D 触发器模型](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-060-DFlipFlop.png!sign){width=600px} <a id="fig.3-6"></a>
要实现上图中这样一个 D 触发器,通常用以下代码: ![图 3-6 D 触发器模型](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-060-DFlipFlop.png!sign){width=600px}
要实现[图 3-6](#fig.3-6) 中这样一个 D 触发器,通常用以下代码:
``` verilog TYP_DFF.v ``` verilog TYP_DFF.v
module TYP_DFF (clk, D, Q); module TYP_DFF (clk, D, Q);
@@ -373,7 +385,7 @@ endmodule
由于 `always` 语句的特点,`always` 语句马上开始重新执行,当遇到 `@(posedge clk)` 语句时,进程再一次挂起,等待 `clk` 的上升沿到来,才继续往下执行。 由于 `always` 语句的特点,`always` 语句马上开始重新执行,当遇到 `@(posedge clk)` 语句时,进程再一次挂起,等待 `clk` 的上升沿到来,才继续往下执行。
这样,在 `always` 语句中使用 `@` 事件语句很好地模拟了触发器的行为。综合工具会马上将上述代码映射成上图中的 D 触发器。 这样,在 `always` 语句中使用 `@` 事件语句很好地模拟了触发器的行为。综合工具会马上将上述代码映射成[图 3-6](#fig.3-6) 中的 D 触发器。
同样的道理,采用如下的代码也可以得到一样的 D 触发器功能: 同样的道理,采用如下的代码也可以得到一样的 D 触发器功能:
@@ -494,9 +506,11 @@ always @(A_in or B_in or C_in) begin
end end
``` ```
设计者的根本目的是得到如下图所示的电路。 设计者的根本目的是得到如[图 3-7](#fig.3-7) 所示的电路。
![一个组合逻辑](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-070-ACombinationalLogic.png!sign){width=700px} <a id="fig.3-7"></a>
![图 3-7 一个组合逻辑](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-070-ACombinationalLogic.png!sign){width=700px}
在以上代码仿真时,正是利用了阻塞赋值的这一特点才模拟了该组合逻辑的行为。 在以上代码仿真时,正是利用了阻塞赋值的这一特点才模拟了该组合逻辑的行为。
@@ -561,9 +575,11 @@ always @(posedge clk) begin
end end
``` ```
其实现结果如下图: 其实现结果如[图 3-8](#fig.3-8):
![三级流水的寄存器](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-080-ThreeFlowStateRegister.png!sign){width=600px} <a id="fig.3-8"></a>
![图 3-8 三级流水的寄存器](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-080-ThreeFlowStateRegister.png!sign){width=600px}
正是利用了语句之间的非阻塞性,才实现了这个 3 级流水线的逻辑功能。 正是利用了语句之间的非阻塞性,才实现了这个 3 级流水线的逻辑功能。
@@ -636,9 +652,11 @@ begin
end end
``` ```
由于语句是顺序执行的,产生的波形如下图所示。 由于语句是顺序执行的,产生的波形如[图 3-9](#fig.3-9) 所示。
![顺序语句块的执行波形](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-090-SequentialWave.png!sign){width=500px} <a id="fig.3-9"></a>
![图 3-9 顺序语句块的执行波形](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-090-SequentialWave.png!sign){width=500px}
### 3.3.2. 并行语句组 `fork ... join` ### 3.3.2. 并行语句组 `fork ... join`
@@ -654,9 +672,11 @@ fork
join join
``` ```
由于其中的所有语句并行执行,也就是以上 4 条语句都是从 0 时刻开始同时执行的,产生的波形如下图。 由于其中的所有语句并行执行,也就是以上 4 条语句都是从 0 时刻开始同时执行的,产生的波形如[图 3-10](#fig.3-10)。
![并行语句块的执行波形](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-100-ParallelWave.png!sign){width=500px} <a id="fig.3-10"></a>
![图 3-10 并行语句块的执行波形](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-100-ParallelWave.png!sign){width=500px}
### 3.3.3. 语句组的标识符 ### 3.3.3. 语句组的标识符
@@ -712,9 +732,11 @@ always @(sel_a or sel_b or a or b or c) begin
end end
``` ```
它要实现的逻辑如下图。 它要实现的逻辑如[图 3-11](#fig.3-11)。
![`if ... else` 语句](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-110-IfElseStatement.png!sign){width=600px} <a id="fig.3-11"></a>
![图 3-11 `if ... else` 语句](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-110-IfElseStatement.png!sign){width=600px}
在 `if ... else` 语句中,条件是从上到下逐条检查的。因此,当满足一个条件时,就执行其后的语句,跳过 `else` 后面的语句、当所有条件都不满足,便执行最后一条 `else` 后面的语句。因此 `if ... else` 语句实际上是有优先级顺序的。 在 `if ... else` 语句中,条件是从上到下逐条检查的。因此,当满足一个条件时,就执行其后的语句,跳过 `else` 后面的语句、当所有条件都不满足,便执行最后一条 `else` 后面的语句。因此 `if ... else` 语句实际上是有优先级顺序的。
@@ -737,11 +759,11 @@ always @(sel or a or b or c) begin
end end
``` ```
由于,最后一个条件 `sel == 2'b11` 的语句没有被显式地写出,言下之意是,当 `sel` 为 `2'b11` 时,`q` 值需要保持不变。这个代码在综合时自然就会产生锁存器,如下图。 由于,最后一个条件 `sel == 2'b11` 的语句没有被显式地写出,言下之意是,当 `sel` 为 `2'b11` 时,`q` 值需要保持不变。这个代码在综合时自然就会产生锁存器,如[图 3-12](#fig.3-12)。
<a id="CombinationalLogicWithLatch"></a> <a id="fig.3-12"></a>
![产生锁存器](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-120-CombinationalLogicwithLatch.png!sign){width=800px} ![图 3-12 产生锁存器](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-120-CombinationalLogicwithLatch.png!sign){width=800px}
{% note warning %} {% note warning %}
@@ -764,11 +786,11 @@ always @(sel or a or b or c) begin
end end
``` ```
既然不关心 `sel` 为 `2'b11` 时 `q` 的值,那么有的综合工具就顺手将 `sel` 等于 `2'b11` 时 `q` 的值也赋值为 `c`,这样就避免了锁存器的产生。实现电路如下图。 既然不关心 `sel` 为 `2'b11` 时 `q` 的值,那么有的综合工具就顺手将 `sel` 等于 `2'b11` 时 `q` 的值也赋值为 `c`,这样就避免了锁存器的产生。实现电路如[图 3-13](#fig.3-13)。
<a id="CombinationalLogicWithoutLatch"></a> <a id="fig.3-13"></a>
![无锁存器的组合逻辑电路](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-130-CombinationalLogicwithoutLatch.png!sign){width=800px} ![图 3-13 无锁存器的组合逻辑电路](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-130-CombinationalLogicwithoutLatch.png!sign){width=800px}
然而,在描述时序逻辑时,通常将利用 `if` 语句的隐式条件对带时钟使能的 D 触发器建模。代码如下: 然而,在描述时序逻辑时,通常将利用 `if` 语句的隐式条件对带时钟使能的 D 触发器建模。代码如下:
@@ -781,9 +803,11 @@ always @(posedge clk or negedge rst_n) begin
end end
``` ```
以上语句表示在时钟正沿来临时,如果 `en` 为 1,则将 `a + b` 的值付给 `sum`。言下之意:如果 `en` 为 0,那么 `sum` 保持原值不变。因此,这里综合工具会把代码综合成一个时钟使能的寄存器,如下图所示。 以上语句表示在时钟正沿来临时,如果 `en` 为 1,则将 `a + b` 的值付给 `sum`。言下之意:如果 `en` 为 0,那么 `sum` 保持原值不变。因此,这里综合工具会把代码综合成一个时钟使能的寄存器,如[图 3-14](#fig.3-14) 所示。
![带时钟使能的 D 触发器](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-140-DFlipFlopClock.png!sign){width=800px} <a id="fig.3-14"></a>
![图 3-14 带时钟使能的 D 触发器](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-140-DFlipFlopClock.png!sign){width=800px}
其中,`en` 信号时 D 触发器的时钟使能端,`rst_n` 是 D 触发器的异步清零信号。 其中,`en` 信号时 D 触发器的时钟使能端,`rst_n` 是 D 触发器的异步清零信号。
@@ -806,7 +830,7 @@ end
在 `case` 语句中,`default:` 一条描述了所有没有明确说明的其他可能情况。比如,这里的 `default` 就包含了 `sel` 为 `2'b11`、`2'bzz` 和 `2'bxx` 等情况。 在 `case` 语句中,`default:` 一条描述了所有没有明确说明的其他可能情况。比如,这里的 `default` 就包含了 `sel` 为 `2'b11`、`2'bzz` 和 `2'bxx` 等情况。
以上的代码将实现如上的[无锁存器的组合逻辑电路](#CombinationalLogicWithoutLatch)。 以上的代码将实现如上的[无锁存器的组合逻辑电路](#fig.3-13)。
与 `if ... else` 语句不同的是,在 `case` 语句中,所有被判断的分支条件都具有一样的优先级。 与 `if ... else` 语句不同的是,在 `case` 语句中,所有被判断的分支条件都具有一样的优先级。
@@ -822,7 +846,7 @@ always @(sel or a or b or c) begin
end end
``` ```
这样,将会产生与如上的[带锁存器的组合逻辑电路](#CombinationalLogicWithLatch)。这是设计者不愿意看到的。 这样,将会产生与如上的[带锁存器的组合逻辑电路](#fig.3-12)。这是设计者不愿意看到的。
对于 `case` 语句,有两个派生语句,即 `casez` 及 `casex`。 对于 `case` 语句,有两个派生语句,即 `casez` 及 `casex`。
@@ -976,9 +1000,11 @@ endmodule
在以上代码中,实例化的 `or` 门原语是 Verilog 语言自带的电路,实例化的半加器模块则是用户自己设计的模块。 在以上代码中,实例化的 `or` 门原语是 Verilog 语言自带的电路,实例化的半加器模块则是用户自己设计的模块。
实现电路如下图。 实现电路如[图 3-15](#fig.3-15)。
![全加器](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-150-FullAdder.png!sign){width=800px} <a id="fig.3-15"></a>
![图 3-15 全加器](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-150-FullAdder.png!sign){width=800px}
以上内容提到了实例化基本门和其他模块。 以上内容提到了实例化基本门和其他模块。
@@ -1002,9 +1028,11 @@ endmodule
初学者经常犯这样一个错误,将寄存器变量驱动 `inout` 端口,导致编译出错。因为,只有线网类型可以驱动 `inout` 端口。 初学者经常犯这样一个错误,将寄存器变量驱动 `inout` 端口,导致编译出错。因为,只有线网类型可以驱动 `inout` 端口。
下图清楚地了模块端口在内部和外部的类型。 [图 3-16](#fig.3-16) 清楚地了模块端口在内部和外部的类型。
![模块实例端口连接规则](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-160-ModuleConnection.png!sign){width=800px} <a id="fig.3-16"></a>
![图 3-16 模块实例端口连接规则](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-160-ModuleConnection.png!sign){width=800px}
下面举例说明模块内部和外部的端口: 下面举例说明模块内部和外部的端口:
@@ -1240,7 +1268,9 @@ Verilog 语言是一种强大的硬件描述语言,可以支持多个设计层
Verilog 语言作为一种用户工具,提供给用户许多描述硬件的手段,如前面所述:数据流描述、行为描述(`always` 和 `initial` 语句)、结构化描述。同时,不同用户可以根据自己的需要,在不同抽象层次上对硬件进行描述。有如下设计层次金字塔供参考。 Verilog 语言作为一种用户工具,提供给用户许多描述硬件的手段,如前面所述:数据流描述、行为描述(`always` 和 `initial` 语句)、结构化描述。同时,不同用户可以根据自己的需要,在不同抽象层次上对硬件进行描述。有如下设计层次金字塔供参考。
![设计层次金字塔](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-170-DesignLevelPyramid.png!sign){width=600px} <a id="fig.3-17"></a>
![图 3-17 设计层次金字塔](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-170-DesignLevelPyramid.png!sign){width=600px}
下面简单介绍几种不同角色的工作特点,以及它们所处的设计层次: 下面简单介绍几种不同角色的工作特点,以及它们所处的设计层次:
@@ -1254,7 +1284,9 @@ Verilog 语言作为一种用户工具,提供给用户许多描述硬件的手
这里的行为级描述,不同于 [3. 行为描述](#03)中所述的“行为描述方式”。这里特指一种描述的抽象层次。 这里的行为级描述,不同于 [3. 行为描述](#03)中所述的“行为描述方式”。这里特指一种描述的抽象层次。
下面举一个实例说明 RTL 级和行为级的区别,要实现的状态机一部分如下图所示。 下面举一个实例说明 RTL 级和行为级的区别,要实现的状态机一部分如[图 3-18](#fig.3-18) 所示。=
<a id="fig.3-18"></a>
![一个简单的握手协议状态机](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-180-ASimpleHandshakingStateMachine.png!sign){width=500px} ![一个简单的握手协议状态机](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-30-josh-verilog-part-3/2020-11-30-josh-verilog-part-3-180-ASimpleHandshakingStateMachine.png!sign){width=500px}
@@ -24,12 +24,9 @@ categories:
- [Josh 的学习笔记, Verilog] - [Josh 的学习笔记, Verilog]
abbrlink: ecb88422 abbrlink: ecb88422
date: 2020-12-02 01:05:32 date: 2020-12-02 01:05:32
description: Verilog HDL 的基本功能之一是描述可综合的硬件电路。如何合理使用 Verilog HDL 描述高性能的可综合电路是 Verilog 系列学习笔记的目的,也是后续要讨论的主要问题。本文介绍了 RTL 和综合的基本概念,通过常用 RTL 电路模型来对可综合的 RTL 级描述方式建立整体性的认识。力图通过范例,逐步引导初学者建立可综合 RTL 子集的概念。
--- ---
Verilog HDL 的基本功能之一是描述可综合的硬件电路。如何合理使用 Verilog HDL 描述高性能的可综合电路是 Verilog 系列学习笔记的目的,也是后续要讨论的主要问题。
本文介绍了 RTL 和综合的基本概念,通过常用 RTL 电路模型来对可综合的 RTL 级描述方式建立整体性的认识。力图通过范例,逐步引导初学者建立可综合 RTL 子集的概念。
# 1. RTL 和综合 # 1. RTL 和综合
从[《Part 3 —— 描述方式和设计层次》的第 5 小节](https://josh-gao.top/posts/fd117896.html#5-%E8%AE%BE%E8%AE%A1%E5%B1%82%E6%AC%A1)可知,HDL 语言是分层次的。 从[《Part 3 —— 描述方式和设计层次》的第 5 小节](https://josh-gao.top/posts/fd117896.html#5-%E8%AE%BE%E8%AE%A1%E5%B1%82%E6%AC%A1)可知,HDL 语言是分层次的。
@@ -22,10 +22,9 @@ categories:
- [Josh 的学习笔记, Verilog] - [Josh 的学习笔记, Verilog]
abbrlink: 53b8b42e abbrlink: 53b8b42e
date: 2020-12-05 00:46:00 date: 2020-12-05 00:46:00
description: 在<a href="https://josh-gao.top/posts/ecb88422.html">《Part 4 —— RTL 概念与常用 RTL 建模》</a>中,通过具体的 RTL 建模建立了一些对 RTL 级描述的一些感性认识,本文将较深入地探讨一些 RTL 设计的基本规律。RTL 设计规律与方法是一个非常大的论题,在此不可能面面俱到,希望通过本文的介绍,引起大家的注意。如果大家能在日后的工作实践中,不断积累,有意识地积累基本设计原则、设计思想,将取得事半功倍的效果!
--- ---
在[《Part 4 —— RTL 概念与常用 RTL 建模》](https://josh-gao.top/posts/ecb88422.html)中,通过具体的 RTL 建模建立了一些对 RTL 级描述的一些感性认识,本文将较深入地探讨一些 RTL 设计的基本规律。RTL 设计规律与方法是一个非常大的论题,在此不可能面面俱到,希望通过本文的介绍,引起大家的注意。如果大家能在日后的工作实践中,不断积累,有意识地积累基本设计原则、设计思想,将取得事半功倍的效果!
# 1. 一般性指导原则 # 1. 一般性指导原则
RTL 级设计的评判标准有很多,如时序性能、所占面积、可测试性、可重要性、功耗、时钟域的分配、复位信号设计、是否与所用 EDA 工具匹配等。如果设计目标是在 FPGA 或 CPLD 等可编程逻辑器件上实现,则还需考虑是否能发挥这些 PLD 的结构特点等。根据以上所述这些目标的组合和优先级可以派生出很多不同的设计原则。这里仅仅讨论一般意义的指导原则。 RTL 级设计的评判标准有很多,如时序性能、所占面积、可测试性、可重要性、功耗、时钟域的分配、复位信号设计、是否与所用 EDA 工具匹配等。如果设计目标是在 FPGA 或 CPLD 等可编程逻辑器件上实现,则还需考虑是否能发挥这些 PLD 的结构特点等。根据以上所述这些目标的组合和优先级可以派生出很多不同的设计原则。这里仅仅讨论一般意义的指导原则。
@@ -22,10 +22,9 @@ tags:
- 三段式 - 三段式
categories: categories:
- [Josh 的学习笔记, Verilog] - [Josh 的学习笔记, Verilog]
description: 状态机是逻辑设计的重要内容,其设计水平直接反映工程师的逻辑功底,所以许多公司的硬件和逻辑工程师面试中,状态机设计几乎是必选题目。本文在引入状态机设计思想的基础上,重点讨论如何写好状态机。
--- ---
状态机是逻辑设计的重要内容,其设计水平直接反映工程师的逻辑功底,所以许多公司的硬件和逻辑工程师面试中,状态机设计几乎是必选题目。本文在引入状态机设计思想的基础上,重点讨论如何写好状态机。
# 1. 状态机的基本概念 # 1. 状态机的基本概念
本节的重点在于理解状态机的基本概念和应用场合。 本节的重点在于理解状态机的基本概念和应用场合。
@@ -26,12 +26,9 @@ categories:
- Verilog - Verilog
abbrlink: e060f513 abbrlink: e060f513
date: 2023-04-16 13:50:28 date: 2023-04-16 13:50:28
description: 验证是芯片设计过程中非常重要的一个环节。无缺陷的芯片不是设计出来的,而是验证出来的。验证的过程是否准确与完备,在一定程度上决定了一个芯片的命运。在芯片设计中,功能验证的方法主要有 3 种:<b>仿真</b>、<b>形式验证</b>以及<b>硬件加速</b>。本文重点介绍仿真的概念、仿真平台的搭建以及如何利用高效的仿真平台来验证设计等话题。
--- ---
验证是芯片设计过程中非常重要的一个环节。无缺陷的芯片不是设计出来的,而是验证出来的。验证的过程是否准确与完备,在一定程度上决定了一个芯片的命运。
在芯片设计中,功能验证的方法主要有 3 种:**仿真**、**形式验证**以及**硬件加速**。在本篇笔记中,将重点介绍仿真的概念、仿真平台的搭建以及如何利用高效的仿真平台来验证设计等话题。
# 1. 概述 # 1. 概述
## 1.1. 仿真和验证 ## 1.1. 仿真和验证