芯片基础 | verilog基础学习(一)

avatar
作者
猴君
阅读量:3

单线

创建一个具有一个输入和一个输出的模块,其行为类似于导线。

与物理导线不同,Verilog中的导线(和其他信号)是有方向的。这意味着信息只能从一个方向流动,即从(通常是一个)源到汇(源也常被称为将值驱动到导线上的驱动器)。在Verilog的“连续赋值”(assign left_side = right_side;)中,右侧信号的值被驱动到左侧的导线上。该赋值是“连续的”,因为即使右侧的值发生变化,赋值也会一直持续。连续赋值不是一个一次性事件。

模块上的端口也有方向(通常是输入或输出)。输入端口由模块外部的东西驱动,而输出端口则驱动外部的东西。从模块内部来看,输入端口是驱动器或源,而输出端口是汇。

下面的图表说明了电路的每个部分如何与Verilog代码的每个位相对应。模块和端口声明创建了电路的黑色部分。你的任务是通过添加一个assign语句来创建一条导线(绿色)以将输入连接到输出。方框外的部分与你无关,但你应该知道,你的电路是通过将我们测试工具中的信号连接到你的顶级模块(top_module)的端口上来进行测试的。

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

在Verilog中,过程块(Procedural Block)是指用于描述硬件时序电路和组合电路行为的代码块。这些过程块主要通过always和initial关键字来定义,它们允许在仿真过程中按照特定的时序或条件执行一系列的语句。

module top_module( input in, output out ); 	assign out = in; endmodule 

四线

创建一个具有3个输入和4个输出的模块,其行为类似于导线,并实现以下连接:

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

下面的图表说明了电路的每个部分如何与Verilog代码的每个位相对应。从模块外部看,有三个输入端口和四个输出端口。

当你有多个assign语句时,它们在代码中出现的顺序并不重要。与编程语言不同,assign语句(“连续赋值”)描述的是事物之间的连接,而不是将一个值从一个事物复制到另一个事物的动作。

现在可能需要澄清的一个潜在混淆点:这里的绿色箭头代表导线之间的连接,但它们本身并不是导线。模块本身已经声明了7条导线(分别命名为a、b、c、w、x、y和z)。这是因为除非另有说明,否则输入和输出声明实际上会声明一条导线。编写input wire a与编写input a是等效的。因此,assign语句并没有创建导线,而是创建了已经存在的7条导线之间的连接。

module top_module(      input a,b,c,     output w,x,y,z ); 		assign w = a;     	assign x = b;       	assign y = b;      	assign z = c; endmodule 

非门

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

这个电路类似于导线,但有一个细微的差别。在从输入导线到输出导线的连接中,我们将实现一个反相器(或“非门”),而不是简单的导线。

使用assign语句。assign语句将连续地将in的取反结果驱动到out导线上。

module top_module(       input in,       output out   );      // 使用assign语句实现非门逻辑   assign out = ~in; // 如果in为1,out为0;如果in为0,out为1      endmodule 

与门

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

这个电路现在有三条导线(a、b和out)。导线a和b已经通过输入端口被赋予了值。但是,导线out目前没有被任何东西驱动。编写一个assign语句,使out输出a和b信号的与操作结果。

请注意,这个电路与非门非常相似,只是多了一个输入。如果你感觉它们有所不同,那是因为我开始描述信号是被驱动的(由连接到它的某个东西确定了一个已知的值)还是未被驱动的。输入导线是由模块外部的东西驱动的。assign语句将逻辑电平驱动到导线上。

正如你可能预期的那样,一条导线不能有多个驱动器(如果有多个,它的逻辑电平是什么?),而没有驱动器的导线将具有未定义的值(在合成硬件时通常被视为0)。

module top_module(      input a,      input b,      output out ); 	assign out = a & b; endmodule 

或非门(NOR gate)

创建一个实现或非门(NOR gate)的模块。或非门是一个输出被取反的或门。在Verilog中编写NOR函数时,需要两个操作符。

assign语句用于将一个值驱动到导线(或更正式地称为“网络”)上。这个值可以是你想要的任何复杂函数,只要它是一个组合逻辑(即无记忆功能,没有隐藏状态)函数。assign语句是一个连续赋值,因为每当任何输入发生变化时,输出就会“重新计算”,这种计算是永无止境的,类似于一个简单的逻辑门。

module top_module(      input a,      input b,      output out );     assign out = ~(a|b); endmodule  

异或非门(XNOR gate)

创建一个实现异或非门(XNOR gate)的模块。

module top_module(        input a,        input b,        output out );          // 使用assign语句实现异或非门逻辑       // 输出out是输入a和b的异或操作的取反,即当a和b相同时,out为1;当a和b不同时,out为0       assign out = ~(a ^ b);      endmodule 

Wire 声明

声明导线

到目前为止,电路已经足够简单,输出仅仅是输入的简单函数。

随着电路变得更加复杂,你将需要导线来连接内部组件。

当你需要使用导线时,你应该在模块的主体中声明它,在首次使用它之前的某个位置。

(在将来,你会遇到更多类型的信号和变量,它们也以相同的方式声明,但现在,我们将从类型为导线的信号开始。)

module top_module (     input in,              // Declare an input wire named "in"     output out             // Declare an output wire named "out" );      wire not_in;           // Declare a wire named "not_in"      assign out = ~not_in;  // Assign a value to out (create a NOT gate).     assign not_in = ~in;   // Assign a value to not_in (create another NOT gate).  endmodule   // End of module "top_module" 

在上述模块中,有三个导线(in、out和not_in),其中两个已经作为模块的输入和输出端口的一部分进行了声明(这就是为什么你在之前的练习中不需要声明任何导线的原因)。

导线not_in需要在模块内部进行声明。它在模块外部是不可见的。

然后,使用两个assign语句创建了两个非门

注意,你先创建哪个非门并不重要:你最终会得到相同的电路。

练习

实现以下电路。创建两个中间导线(命名随意)来连接与门(AND gate)和或门(OR gate)。

请注意,供给非门(NOT gate)的导线实际上就是输出导线(out),所以你并不一定要在这里声明第三条导线。

请注意,导线正是由一个源(门的输出)驱动的,但可以供给多个输入。

如果你按照图中的电路结构来,你应该会用到四个assign语句,因为有四个信号需要赋值。

(是的,不使用中间导线也可以创建一个具有相同功能的电路。)

`default_nettype none module top_module(     input a,     input b,     input c,     input d,     output out,     output out_n   );  	 	wire out_1, out_2; 	assign out_n = ~out; 	assign out = out_1 | out_2; 	assign out_1 = a & b; 	assign out_2 = c & d;  endmodule  

7458

7458 是一个包含四个与门和两个或门的芯片。这个问题比 7420 稍微复杂一些。

创建一个与 7458 芯片功能相同的模块。它有 10 个输入和 2 个输出。你可以选择使用 assign 语句来驱动每个输出导线,或者选择声明(四个)导线作为中间信号使用,其中每条内部导线都由一个与门的输出驱动。

为了额外练习,你可以尝试两种方法。

one

module top_module (      input p1a, p1b, p1c, p1d, p1e, p1f,     output p1y,     input p2a, p2b, p2c, p2d,     output p2y );  	assign p1y = (p1a & p1b & p1c) | (p1d & p1e & p1f); 	assign p2y = (p2a & p2b) | (p2c & p2d);  endmodule 

two

module top_module (      input p1a, p1b, p1c, p1d, p1e, p1f,     output p1y,     input p2a, p2b, p2c, p2d,     output p2y ); 	wire a,b,c,d;     assign a = (p1a & p1b & p1c);     assign b = (p1d & p1e & p1f);     assign c = (p2a & p2b);     assign d = (p2c & p2d); 	assign p1y = a | b; 	assign p2y = c | d;  endmodule  

内容来自:https://hdlbits.01xz.net/wiki/7458

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!