HDLBits_第1章_Verilog Language(已完结)

这篇博客详细介绍了Verilog语言的基础知识,包括基本的线性连接、非门、与门、或非门、异或非门的实现,以及向量、模块层级、过程和更多Verilog特性。内容涵盖了从简单的wire声明到复杂的模块设计,如优先编码器和加法器,以及条件操作符和位缩减运算符的应用。适合FPGA开发者学习Verilog语言的入门教程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1. Verilog Language

1.1 Basics

1.1.1 Simple wire

1.1.2 Four wires

1.1.3 Inverter 

1.1.4 AND gate

1.1.5 NOR gate

1.1.6 XNOR gate

1.1.7 Declaring wires

1.1.8 7458 chip

1.2 Vectors

1.2.1 Vectors

1.2.2 Vectors in more detail 

1.2.3 Vector part select 

1.2.4 Bitwise operators 

1.2.5 Four-input gates

1.2.6 Vector concatenation operator

1.2.7 Vector reversal

1.2.8 Replication operator

1.2.9 More replication

1.3 Modules:Hierarchy

1.3.1 Modules

1.3.2 Connecting ports by name

1.3.3 Connecting ports by name

1.3.4 Three modules

1.3.5 Modules and vectors

1.3.6 Adder 1 Module add

1.3.7 Adder 2 - Module fadd

1.3.8 Carry-select adder

1.3.9 Adder-subtractor

1.4 Procedures

1.4.1 Always blocks(combination)

1.4.2 Always blocks(clocked)

1.4.3 If statement

1.4.4 If statement latches

1.4.5 Case statement

1.4.6 Priority encoder

1.4.7 Priority encoder with casez

1.4.8 Avoiding latches

1.5 More Verilog Features

1.5.1 Conditional ternary operator

1.5.2 Reduction operators

1.5.3 Reduction: Even wider gates

1.5.4 Combinational for-loop:Vector reversal 2

1.5.5 Combinational for-loop:255bit population count

1.5.6 Generate for-loop:100bit binary adder2

1.5.7 Generate for-loop:100-Digit BCD adder


1. Verilog Language

1.1 Basics

1.1.1 Simple wire

Wire线网型

Create a module with one input and one output that behaves like a wire.

创建一个单输入单输出的模块,该行为类似于线连

Unlike physical wires, wires (and other signals) in Verilog are directional. This means information flows in only one direction, from (usually one) source to the sinks (The source is also often called a driver that drives a value onto a wire). In a Verilog "continuous assignment" (assign left_side = right_side;), the value of the signal on the right side is driven onto the wire on the left side. The assignment is "continuous" because the assignment continues all the time even if the right side's value changes. A continuous assignment is not a one-time event.

与物理连线不同,Verilog中的连线(或者信号)具有方向性。这意味着信息只向一个方向传输,从源端口流向接收端口(源也经常被成为将值驱动到线路上的驱动程序)。在Verilog的”连续赋值“中(assign left_side = right_side),右侧信号的值会被赋值到左侧信号的wire上。赋值是”连续的“,因为赋值一直在发生,只要右侧的值改变左侧是值也会立即改变。持续赋值不是一个时间的事件。

The ports on a module also have a direction (usually input or output). An input port is driven by something from outside the module, while an output port drives something outside. When viewed from inside the module, an input port is a driver or source, while an output port is a sink.

模块上的端口也有方向性(通常为输入端或输出端)。输入端口驱通过模块外部驱动,输出端口驱动其他模块。从模块内部看,输入端口是驱动信号或者源,而输出端口是接收端口

The diagram below illustrates how each part of the circuit corresponds to each bit of Verilog code. The module and port declarations create the black portions of the circuit. Your task is to create a wire (in green) by adding an assign statement to connect in to out. The parts outside the box are not your concern, but you should know that your circuit is tested by connecting signals from our test harness to the ports on your top_module.

下图说明了电路的每个部分如何对应于Verilog代码的每个比特位。模块和端口声明创建了电路图中的黑色部分。您的任务是通过添加一个assign语句来连接输入in和输出out。黑色方框外部的部分不是你所关心的内容,单你应该知道,你的电路时通过将我们的测试线束的信号连接到top_module上的端口来进行测试的。

In addition to continuous assignments, Verilog has three other assignment types that are used in procedural blocks, two of which are synthesizable. We won't be using them until we start using procedural blocks.

除了连续赋值,Verilog还有三种其他的用于程序块的赋值类型,其中两种是可综合的。我们在开始使用程序块之前,先不使用他们。

1.1.2 Four wires

Create a module with 3 inputs and 4 outputs that behaves like wires that makes these connections:

创建一个具有3输入4输出的模块,该模块功能实现下述线网连接:

a -> w
b -> x
b -> y
c -> z

The diagram below illustrates how each part of the circuit corresponds to each bit of Verilog code. From outside the module, there are three input ports and four output ports.

下图说明电路的每个部分对应Verilog的每个比特位。从模块外部看,有3个输入端口和4个输出端口。

When you have multiple assign statements, the order in which they appear in the code does not matter. Unlike a programming language, assign statements ("continuous assignments") describe connections between things, not the action of copying a value from one thing to another.

当你有多个赋值语句时,他们出现在代码中的顺序不重要。与编程语言不同,Verilog的赋值语句(连续赋值语句)描述硬件之间的连接,而不是将一个变量值复制到另一个变量的操作。

One potential source of confusion that should perhaps be clarified now: The green arrows here represent connections between wires, but are not wires in themselves. The module itself already has 7 wires declared (named a, b, c, w, x, y, and z). This is because input and output declarations actually declare a wire unless otherwise specified. Writing input wire a is the same as input a. Thus, the assign statements are not creating wires, they are creating the connections between the 7 wires that already exist.

现在应该澄清的一个容易混淆的潜在的数据源:这里的绿色箭头代表wire之间的连接关系,但实际并不是导线。模块本身已经声明了7个wire的连接(a,b,c,w,x,y,z),这是因为在input和output声明已经声明是wire,若有单独声明则另外讨论。代码中,input wire a和input a是一样的。因此,assign语句不是在创建连线wires,而是在创建7个已经存在的wires之间的联系。

 Expected solution length: Around 4 lines.

期望解决方案长度:4行。

1.1.3 Inverter 

Create a module that implements a NOT gate.

创建一个实现NOT门(非门)的模块。

This circuit is similar to wire, but with a slight difference. When making the connection from the wire in to the wire out we're going to implement an inverter (or "NOT-gate") instead of a plain wire.

这个电路类似与wire,但是有细微区别。当从线in连接到线out时,我们期望实现一个逆变器(非门),而不是不同的wire连接

Use an assign statement. The assign statement will continuously drive the inverse of in onto wire out.

使用赋值语句,赋值语句将连续驱动in的逆赋值给out

Expected solution length: Around 1 line. 

期待解决方案长度:1行

1.1.4 AND gate

Create a module that implements an AND gate.

创建一个实现AND gate(与门)的模块。

This circuit now has three wires (ab, and out). Wires a and b already have values driven onto them by the input ports. But wire out currently is not driven by anything. Write an assign statement that drives out with the AND of signals a and b.

这个电路有三条线(a,b和out)。wire a和b已经有输入端口驱动其数值。但是wire out目前不受任何驱动。写一个赋值语句,驱动out输出a和b的与计算。

Note that this circuit is very similar to the NOT gate, just with one more input. If it sounds different, it's because I've started describing signals as being driven (has a known value determined by something attached to it) or not driven by something. Input wires are driven by something outside the module. assign statements will drive a logic level onto a wire. As you might expect, a wire cannot have more than one driver (what is its logic level if there is?), and a wire that has no drivers will have an undefined value (often treated as 0 when synthesizing hardware).

注意,这个电路与NOT gate(非门)非常相似,只是多了一个输入。如果听起来不一样,是因为,我们已经开始描述信号驱动(有附加到他的某个东西决定的已知值),而不是通过某种东西驱动。输入线由模块外所驱动。赋值语句通过逻辑级驱动到线wire上。正如您说期望的,一个wire不能有多个驱动程序(如果有多个驱动,那驱动的逻辑是什么呢?),没有驱动程序的线路加ing有一个未定义的值(在综合硬件时通常被视为0)。

Expected solution length: Around 1 line.

期望解决方案长度:1行

1.1.5 NOR gate

Create a module that implements a NOR gate. A NOR gate is an OR gate with its output inverted. A NOR function needs two operators when written in Verilog.

创建一个实现NOR gate(或非门)的模块。或非门的输出是或门的倒置。在Verilog语言中,或非门函数需要两个操作符。

An assign statement drives a wire (or "net", as it's more formally called) with a value. This value can be as complex a function as you want, as long as it's a combinational (i.e., memory-less, with no hidden state) function. An assign statement is a continuous assignment because the output is "recomputed" whenever any of its inputs change, forever, much like a simple logic gate.

赋值语句驱动带有值的线(更正式的叫法是:网)。这个值可以是你想要的任意复杂的函数,只要他是一个组合函数(即无内存,无隐藏状态)。赋值语句是连续的赋值,因为只要输入input改变,输出output就会被重新计算,就像一个简单的逻辑门一样。

Expected solution length: Around 1 line. 

期望解决方案长度:1行

1.1.6 XNOR gate

异或非门、同或门

Create a module that implements an XNOR gate.

创建一个模块,实现异或非门。

Expected solution length: Around 1 line. 

期待解决方案长度:1行

1.1.7 Declaring wires

The circuits so far have been simple enough that the outputs are simple functions of the inputs. As circuits become more complex, you will need wires to connect internal components together. When you need to use a wire, you should declare it in the body of the module, somewhere before it is first used. (In the future, you will encounter more types of signals and variables that are also declared the same way, but for now, we'll start with a signal of type wire).

到目前为止,电路已经足够简单,输出是输入的简单函数。随着电路越来越复杂,你将需要用wire去把内部元件连接到一起。当你需要使用wire时,你应该在模块主体中,首次使用它之前,事先中声明。(在将来,你将会遇到更多类型的信号和变量,它们也以相同的方式被声明,但是现在,我们将从信号类型wire开始入手)。

举例:

In the above module, there are three wires (in, out, and not_in), two of which are already declared as part of the module's input and output ports (This is why you didn't need to declare any wires in the earlier exercises). The wire not_in needs to be declared inside the module. It is not visible from outside the module. Then, two NOT gates are created using two assign statements. Note that it doesn't matter which of the NOT gates you create first: You still end up with the same circuit.

在上述模块中,有三条wire(in,out和not_in),其中两个已经被声明为模块输入和输出端口的一部分(这就是为什么你不需要在早期练习中不需要声明的原因)。线not_in需要在模块内部被声明。not_in在模块外部是不可见的。然后,使用assign赋值语句创建两个NOT gate非门。先创建那个非门并不重要:你最终会综合出相同的电路。

练习:

Implement the following circuit. Create two intermediate wires (named anything you want) to connect the AND and OR gates together. Note that the wire that feeds the NOT gate is really wire out, so you do not necessarily need to declare a third wire here. Notice how wires are driven by exactly one source (output of a gate), but can feed multiple inputs.

实现以下电路。创建两条中间wire(命名任意),将AND与门和OR或门连接在一起。注意,为NOT非门提供的wire实际是wire out,所以你不必再声明第三根wire了。请注意wires是如何通过一个源来驱动的(门的输出),但可以馈送多个输入。

If you're following the circuit structure in the diagram, you should end up with four assign statements, as there are four signals that need a value assigned.

如果你遵循图中的电路结构,你应该使用4个assign,因为有4个信号需要赋值

(Yes, it is possible to create a circuit with the same functionality without the intermediate wires.)

(是的,可以在没有中间导线的情况下创建具有相同功能的电路。)

 

1.1.8 7458 chip

The 7458 is a chip with four AND gates and two OR gates. This problem is slightly more complex than 7420.

7458是一个有四个AND与门和两个OR或门的芯片。这个问题比7420稍微复杂一点。

Create a module with the same functionality as the 7458 chip. It has 10 inputs and 2 outputs. You may choose to use an assign statement to drive each of the output wires, or you may choose to declare (four) wires for use as intermediate signals, where each internal wire is driven by the output of one of the AND gates. For extra practice, try it both ways.

创建一个模块,使之与7458芯片具有相同的功能。你可以选择使用赋值语句去驱动每个输出线,你也可以选择声明四个wire作为中间信号,其中每个内部线由一个AND与门的输出驱动。作为额外联系,两种方法都试试。

Expected solution length: Around 2–10 lines.

期待解决方案长度:2-10行

1.2 Vectors

1.2.1 Vectors

Vectors are used to group related signals using one name to make it more convenient to manipulate. For example, wire [7:0] w; declares an 8-bit vector named w that is functionally equivalent to having 8 separate wires.

向量用于将相关信号进行分组,使用一个名称,使其操作更方便。例如,wire [7:0] w;声明了一个8位向量,命名为w,其功能相当于8条wire。

Notice that the declaration of a vector places the dimensions before the name of the vector, which is unusual compared to C syntax. However, the part select has the dimensions after the vector name as you would expect.

注意,与c语言不同,声明向量的时候将长度[7:0]放在向量的名称w之前。然而,正如你期待的那样,part select的尺寸再向量名称之后。

wire [99:0] my_vector; // Declare a 100-element vector

//该句声明一个包含100个元素的向量。

assign out = my_vector[10]; // Part-select one bit out of the vector

//只选择向量的一部分,只选择该向量的一个bit位的数值进行连续赋值,其中的第11根wire。

Build a circuit that has one 3-bit input, then outputs the same vector, and also splits it into three separate 1-bit outputs. Connect output o0 to the input vector's position 0, o1 to position 1, etc.

构建一个电路,具有3bit的输入,然后输出相同的向量,将其分成三个单独的比特位进行输出。将输出o0连接到输入向量的第0位,将o1连接到输入向量的第1位,以此类推。

In a diagram, a tick mark with a number next to it indicates the width of the vector (or "bus"), rather than drawing a separate line for each bit in the vector.

图中可知,旁边带有数字的标记表示向量(或总线)的位宽,而不是为向量中的每个位单独接线。

 

1.2.2 Vectors in more detail 

Vectors are used to group related signals using one name to make it more convenient to manipulate. For example, wire [7:0] w; declares an 8-bit vector named w that is equivalent to having 8 separate wires.

向量用于将相关信号进行分组,使用一个名称,使其操作更方便。例如,wire [7:0] w;声明了一个8位向量,命名为w,其功能相当于8条wire。

Declaring Vectors

声明向量

Vectors must be declared:

向量必须被声明:

type [upper:lower] vector_name;

数据类型 [高位:低位] 向量名;

type specifies the datatype of the vector. This is usually wire or reg. If you are declaring a input or output port, the type can additionally include the port type (e.g., input or output) as well. Some examples:

type指定的向量

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值