Verilog Language: Basics


Wire

在这次练习中,你将设计一个具有一个输入和一个输出的电路,该电路的行为类似于一根“导线”。尽管物理世界中的导线是双向传输信号的,但在 Verilog 中,信号(如 wire)是具有方向性的。信号只能从一个源流向一个接收端,这种方向性使得 Verilog 电路设计中的数据流明确且可控。

Verilog 中的 Wire(导线)

在 Verilog 中,wire 信号用于在电路中传递值,类似于现实世界中的导线。但与物理导线不同,Verilog 的 wire单向的,也就是说,信号从源(即驱动器)传输到接收端(即“接收器”)。你可以通过 assign 语句来实现这一点。assign 语句是 Verilog 中的连续赋值语句,它让信号在电路中不断传输,无论输入如何变化,输出都会随时更新。

连续赋值语句的基本格式:

assign left_side = right_side;

在这个语句中,右边的信号值(right_side)被持续驱动到左边的信号(left_side),这意味着只要右边的信号变化,左边的信号就会立即更新。

端口方向性

在 Verilog 模块中,端口有方向性,通常为 inputoutput

  • input 端口:该端口从模块外部接收信号,是一个源头或驱动器。
  • output 端口:该端口将信号发送到模块外部,是一个接收端。

在本练习中,我们的任务是创建一个模块 top_module,该模块有一个输入端 in 和一个输出端 out。输入信号 in 被看作是数据的驱动者(源),而 out 则是信号的接收端(汇)。我们需要通过 assign 语句,将 in 的值通过“导线”传递给 out

模块实现

为了实现一个简单的“导线”行为,实际上只需一行代码:使用 assign 语句将 in 赋值给 out,即将输入信号直接连接到输出。

Verilog 代码示例:

module top_module( input in, output out );
    assign out = in;  // 将输入信号in直接传递到输出out
endmodule

代码讲解

  • 模块声明:
    这里的 top_module 模块有两个端口:inoutinput in 表示输入端口 in,它从模块外部接收信号;output out 表示输出端口 out,它将信号传递到模块外部。

  • 连续赋值语句(assign):
    assign 语句用于将输入信号 in 直接传递给输出 out,实现了类似物理导线的功能。因为这是一个“连续赋值”,所以每当 in 的值发生变化时,out 的值也会立即更新。

重要概念

  • 连续赋值(Continuous Assignment):
    Verilog 的 assign 语句是用于描述硬件中信号的持续连接的。与在编程语言中不同,它不是一次性的操作,而是实时、连续地进行信号传递,这使得它特别适合硬件设计。

  • 信号方向性:
    在 Verilog 中,信号具有方向性,从输入流向输出,这确保了数据传输的明确性。设计电路时,理解并正确处理信号的方向性是非常重要的。

  • 端口映射:
    在模块中,输入信号是驱动源,而输出信号是接受端。在这个练习中,你的电路是通过 assign 实现了 inout 的单向数据传输。

通过这个练习,你将更熟悉 Verilog 中基本的 wire 概念和连续赋值语句的使用方式。这也是你理解更复杂电路设计(如组合逻辑和时序逻辑)的基础。


Wire4

在这一练习中,你需要创建一个包含3个输入和4个输出的 Verilog 模块。这个电路的功能与“导线”相似,但要在输入和输出之间创建多条信号连接。具体的连接关系是:

  • 输入 a 连接到输出 w
  • 输入 b 连接到输出 xy
  • 输入 c 连接到输出 z

通过这个练习,你将进一步理解 Verilog 中的信号连接和连续赋值语句的作用。

任务目标

任务要求你设计一个模块,它包含 3 个输入 (a, b, c) 和 4 个输出 (w, x, y, z)。你需要通过 assign 语句将输入信号连接到对应的输出信号。特别注意,输入 b 会同时连接到两个输出 xy,这是完全合法的,因为 assign 语句只是在信号之间建立连接,而不是复制信号的值。

image-20241021123958008

Verilog 中的信号连接

在 Verilog 中,assign 语句用于在信号之间建立持续连接,这意味着信号的连接是实时的,且输出会随着输入的变化而不断更新。多个 assign 语句的顺序不会影响信号的传输,因为这些语句只是描述连接,而不是像编程语言中的“赋值操作”那样按顺序执行。

注意事项:

  • Verilog 中,端口声明(inputoutput)本质上就是声明了 wire 类型信号,除非你明确指定其他信号类型。因此,你不需要再单独声明 wire,只需使用 assign 语句来描述这些信号之间的连接关系。
  • 连接一个输入信号到多个输出是合法的。Verilog 的设计逻辑允许一个信号驱动多个目的地(接收端)。

QQ_1729486911725

注:电路图由DigitalJS Online生成,对于本站中插入的电路图,输入方框黑色为选中1,白色为未选中0,红色为0,绿色为1

模块实现

这个模块的 Verilog 实现相对简单,只需通过四个 assign 语句来实现输入信号和输出信号之间的连接。

Verilog 代码示例:

module top_module( 
    input a, b, c,  // 三个输入信号
    output w, x, y, z  // 四个输出信号
);
    assign w = a;  // 输入a连接到输出w
    assign x = b;  // 输入b连接到输出x
    assign y = b;  // 输入b同时连接到输出y
    assign z = c;  // 输入c连接到输出z
endmodule

代码讲解

  • 模块声明:
    • input a, b, c:声明了三个输入信号 abc。这些输入信号将作为驱动源。
    • output w, x, y, z:声明了四个输出信号 wxyz。这些输出信号是电路的最终输出,将接收从输入传来的信号。
  • assign 语句:
    • assign w = a;:将输入信号 a 连接到输出 w。当 a 的值改变时,w 会实时更新为相同的值。
    • assign x = b;assign y = b;:输入 b 同时驱动 xy,这意味着 b 的值会同时影响 xy 的输出。
    • assign z = c;:将输入 c 连接到输出 z,实现信号的单向传递。

重要概念

  • 连续赋值:
    assign 语句用于在信号之间创建持续连接,它是硬件设计中的基础概念。信号的连接是动态的、连续的,当输入信号变化时,输出信号会自动更新。

  • 信号方向性:
    inputoutput 信号具有方向性,输入信号只能从外部传入模块,而输出信号将从模块中传递到外部。在这个例子中,abc 是输入信号,wxyz 是输出信号。

  • 多重连接:
    Verilog 允许一个输入信号驱动多个输出。例如,assign x = b;assign y = b; 就是一个输入 b 同时驱动 xy 的情况。这种多重连接在数字电路设计中是常见的。

这一练习通过实现多个输入输出之间的信号连接,帮助你加深对 Verilog 中 wireassign 语句的理解。通过定义简单的信号传递关系,你可以看到 Verilog 是如何高效地描述硬件行为的。


NOT gate

在这个练习中,你将设计一个模块实现基本的逻辑非门(NOT Gate)。与前面的“导线”模块类似,此电路仍然有一个输入和一个输出,但不同的是,你将输入信号的反向(取反值)赋给输出。非门是数字电路中的基本逻辑元件之一,它将输入的高电平(1)转换为低电平(0),将低电平(0)转换为高电平(1)。

NOT 门的工作原理

非门(NOT Gate) 或者反相器(Inverter),是逻辑电路中最基本的门之一。其功能是将输入信号取反,也就是说:

  • 如果输入信号为逻辑高电平 1,则输出为逻辑低电平 0
  • 如果输入信号为逻辑低电平 0,则输出为逻辑高电平 1

在 Verilog 中,你可以使用 ~ 操作符来对信号进行按位取反。这是一个标准的按位操作符,适用于任何位宽的信号。在这个练习中,我们的输入和输出信号都是单个位,因此使用 ~ 操作符来实现 NOT 门的功能非常合适。

任务目标

你需要实现一个 Verilog 模块 top_module,它包含一个输入 in 和一个输出 out。通过 assign 语句,将输入 in 的反向赋给输出 out,从而实现 NOT 门的逻辑功能。

QQ_1729486474818

Verilog 代码实现

使用 assign 语句,可以简单地实现输入信号的反向传递。assign out = ~in; 将连续地将输入信号 in 的反相值传递到输出 out

完整的 Verilog 代码:

module top_module( 
    input in,      // 输入信号
    output out     // 输出信号
);
    assign out = ~in;  // 实现NOT门:将输入的反相值赋给输出
endmodule

代码讲解

  • 模块声明:
    • input in:声明输入端口 in,它是一个1位宽的信号。
    • output out:声明输出端口 out,它也是一个1位宽的信号。
  • assign 语句:
    • assign out = ~in;assign 是连续赋值语句,它将 in 信号的反向值(通过 ~ 操作符实现)赋给 out,确保 out 始终为 in 的逻辑反值。

重要概念

  • 连续赋值:
    assign 语句在 Verilog 中用于在信号之间建立持续的逻辑连接。这意味着当 in 的值发生变化时,out 会立即更新为其取反值。与顺序编程语言不同,assign 语句是实时且持续的。

  • 按位取反(NOT 操作):
    Verilog 使用 ~ 操作符来表示按位取反,这意味着对于输入 in~in 将得到其反向值。在单个位的情况下,~0 变成 1,而 ~1 变成 0

  • NOT 门逻辑:
    NOT 门是数字逻辑中的基础元件,它是实现更复杂逻辑电路的基本单元。通过理解 NOT 门的工作原理,能帮助你设计更多的组合逻辑电路。


AND gate

在这个练习中,你将实现一个与门(AND Gate)的 Verilog 模块。与之前的 NOT 门不同,AND 门有两个输入信号,它的输出信号是基于这两个输入信号的逻辑与操作。如果两个输入都为逻辑高(1),输出才为逻辑高,否则输出为逻辑低(0)。

AND 门的工作原理

与门(AND Gate) 是数字电路中最基本的逻辑门之一,它的行为如下:

  • 两个输入信号都为逻辑高电平(1)时,输出为逻辑高电平(1)。
  • 如果任意一个输入为逻辑低电平(0),输出为逻辑低电平(0)。

在 Verilog 中,使用 & 操作符来表示按位与操作。对于两个信号 ab,表达式 a & b 将计算它们的逻辑与值。

任务描述

你需要创建一个模块 top_module,它有两个输入信号 ab,以及一个输出信号 out。通过 assign 语句,计算 ab 的逻辑与,并将结果赋给 out

QQ_1729486862876

Verilog 代码实现

与 NOT 门类似,我们可以通过简单的一行 assign 语句实现 AND 门逻辑。assign out = a & b; 将两个输入信号的逻辑与结果持续传递到输出。

完整的 Verilog 代码:

module top_module( 
    input a,      // 输入信号 a
    input b,      // 输入信号 b
    output out    // 输出信号 out
);
    assign out = a & b;  // 将 a 和 b 的按位与结果赋给 out
endmodule

代码讲解

  • 模块声明:
    • input a, input b:声明了两个输入信号 ab。这两个信号是与门的输入,它们的值由模块外部驱动。
    • output out:声明了输出信号 out,它将接收 ab 逻辑与的结果。
  • assign 语句:
    • assign out = a & b;:使用 & 操作符对输入信号 ab 进行按位与操作,并将结果赋给输出信号 out。这是一条连续赋值语句,意味着只要 ab 发生变化,out 将立即更新为新的逻辑与结果。

重要概念

  • 连续赋值语句:
    assign 语句在 Verilog 中用于在信号之间创建持续连接。这里,assign out = a & b; 表示 out 始终为 ab 逻辑与的结果。只要输入信号 ab 发生变化,输出 out 会实时更新。

  • 与操作(AND Operation):
    Verilog 中使用 & 操作符进行按位与操作。对于每个位的比较,只有两个输入都为 1 时,结果才为 1。否则,结果为 0

  • 驱动信号:
    输入信号 ab 是由模块外部驱动的,它们的值由外部系统确定。输出信号 out 则是由 assign 语句驱动,它基于 ab 的逻辑与结果。当输入信号驱动的值变化时,输出信号也会相应更新。

  • 单一驱动规则:
    在 Verilog 中,每个 wire(导线)只能有一个驱动器。如果多个驱动器尝试驱动同一信号,可能会产生冲突并导致不确定的输出。在这个例子中,out 只有一个驱动器——通过 assign 语句驱动。


NOR gate

在这次练习中,你将实现一个NOR 门,这是一个OR 门的反相版本。NOR 门的输出只有在两个输入都为低电平(0)时才会输出高电平(1),而在其他情况下都会输出低电平(0)。本质上,NOR 门是对 OR 门输出的取反操作。

NOR 门的工作原理

NOR 门OR 门 的输出再取反。具体逻辑如下:

  • 如果两个输入信号 ab 都为逻辑低电平 0,NOR 门的输出为逻辑高电平 1
  • 如果其中任意一个输入为逻辑高电平 1,NOR 门的输出为逻辑低电平 0

NOR 门可以通过两步操作实现:

  1. 计算 ab 的逻辑或(a | b),表示 OR 操作。
  2. 将 OR 操作的结果取反(~(a | b))。

Verilog 中的 NOR 门

在 Verilog 中,使用 | 操作符来表示 OR 操作,使用 ~ 操作符来表示取反。因此,NOR 门可以通过组合这两个操作符实现。

任务描述

你需要实现一个 Verilog 模块 top_module,它有两个输入 ab,以及一个输出 out。通过 assign 语句,将 ab 的 OR 结果取反,并将最终结果赋给 out

QQ_1729490427420

Verilog 代码实现

使用 assign 语句来描述 NOR 门逻辑,通过 ~(a | b) 实现 OR 操作后的取反。

完整的 Verilog 代码:

module top_module( 
    input a,      // 输入信号 a
    input b,      // 输入信号 b
    output out    // 输出信号 out
);
    assign out = ~(a | b);  // 计算 a 和 b 的 OR,并取反得到 NOR
endmodule

代码讲解

  • 模块声明:
    • input a, input b:声明两个输入信号 ab,它们将作为 NOR 门的输入。
    • output out:声明输出信号 out,它将接收 ab 的 NOR 结果。
  • assign 语句:
    • assign out = ~(a | b);:使用 OR 操作符 | 计算 ab 的逻辑或,然后用取反操作符 ~ 取反,从而得到 NOR 门的输出。

重要概念

  • 连续赋值(Continuous Assignment):
    assign 语句是 Verilog 中描述组合逻辑的关键,它为 out 提供了一个持续的逻辑表达式,随着输入信号 ab 的变化,输出 out 会实时更新。

  • 按位操作符:
    • |:表示 OR 操作,它对两个输入信号进行逐位比较,只要有一个输入为 1,结果就是 1
    • ~:表示取反操作,它将 OR 操作的结果反转,即将 0 变为 1,将 1 变为 0
  • 组合逻辑:
    该电路是一个简单的组合逻辑电路,没有存储元素或状态变化。当输入信号 ab 变化时,输出 out 会根据逻辑关系立即更新。这种“记忆无关”的逻辑在硬件设计中被称为组合逻辑。

XNOR gate

在这个练习中,你需要实现一个 XNOR 门,即“同或门”。这是一个逻辑门,它在输入相同时输出高电平(1),在输入不同时输出低电平(0)。XNOR 门的行为可以理解为 XOR 门的输出再取反。

XNOR 门的工作原理

XNOR 门(同或门)是 XOR 门(异或门)的反相版,具体逻辑如下:

  • 如果两个输入 ab 相同(都为 0 或都为 1),则输出为逻辑高电平 1
  • 如果两个输入 ab 不同(一个为 0,一个为 1),则输出为逻辑低电平 0

在 Verilog 中,可以通过组合 XOR 操作符 ^ 和取反操作符 ~ 实现 XNOR 门的逻辑。

Verilog 中的 XNOR 门

使用 XOR 操作符 ^ 进行异或操作后,再使用取反操作符 ~ 可以得到 XNOR 的逻辑。表达式 ~(a ^ b) 表示 ab 的异或结果取反,从而实现 XNOR 的功能。

任务描述

你需要实现一个 Verilog 模块 top_module,该模块包含两个输入 ab,以及一个输出 out。通过 assign 语句将 ab 的异或结果取反,并将该结果赋给 out,从而实现 XNOR 门的逻辑。

QQ_1729490354138

Verilog 代码实现

通过 assign 语句,你可以在一行代码中实现 XNOR 门逻辑。使用 ~(a ^ b) 来表示两个输入的异或结果取反。

完整的 Verilog 代码:

module top_module( 
    input a,      // 输入信号 a
    input b,      // 输入信号 b
    output out    // 输出信号 out
);
    assign out = ~(a ^ b);  // 实现XNOR门:对 a 和 b 的异或结果取反
endmodule

代码讲解

  • 模块声明:
    • input a, input b:声明两个输入信号 ab,它们是 XNOR 门的输入。
    • output out:声明输出信号 out,它将接收 ab 的 XNOR 结果。
  • assign 语句:
    • assign out = ~(a ^ b);:使用 XOR 操作符 ^ 计算 ab 的异或结果,并使用取反操作符 ~ 来得到 XNOR 逻辑的输出。只要 ab 相同,输出 out 将为 1;否则,输出为 0

重要概念

  • 连续赋值(Continuous Assignment):
    assign 语句用于将 XNOR 的逻辑连接到输出 out。这是 Verilog 中实现组合逻辑电路的主要方式,输出会根据输入信号的变化实时更新。

  • XOR 和 XNOR 操作:
    • ^:表示 XOR 操作,异或门在两个输入不同时输出 1,在输入相同时输出 0
    • ~:表示取反操作符,~(a ^ b) 将 XOR 操作的结果取反,从而实现 XNOR 门的逻辑。
  • 组合逻辑:
    该模块没有记忆或状态的变化,是一个典型的组合逻辑电路,输出仅依赖于当前的输入信号。当输入变化时,输出立即响应并更新。

Wire Declaration

在 Verilog 设计中,电路的复杂度随着逻辑组件的增加而提升,简单的输入和输出已经无法描述所有的电路行为。为了连接内部组件,必须使用导线(wire)。在 Verilog 中,导线用于传递信号,并且在模块体内部使用时需要显式声明。导线不能存储值,只能用于传递信号。

导线的声明和使用

当电路变复杂时,导线用于连接内部组件。Verilog 中的 wire 是一种信号类型,它只传递信号,并不存储数据。通常,当需要一个中间信号来传递逻辑运算结果时,就会使用 wire。这些导线必须在模块中声明,并且可以通过 assign 语句为其赋值。

示例代码解析

以下是一个简单的 Verilog 模块示例,它展示了如何声明和使用导线来连接逻辑组件:

module top_module (
    input in,              // 声明输入信号 "in"
    output out             // 声明输出信号 "out"
);

    wire not_in;           // 声明一个中间导线 "not_in"

    assign out = ~not_in;  // 创建一个 NOT 门:将 not_in 的反相结果赋给 out
    assign not_in = ~in;   // 创建另一个 NOT 门:将 in 的反相结果赋给 not_in

endmodule   // 模块结束

代码解释

  • 输入和输出端口
    输入端 in 和输出端 out 是电路的输入输出接口。它们是模块定义的一部分,不需要额外声明。

  • 中间导线 not_in 的声明
    wire not_in; 声明了一个中间信号(导线)not_in。这是一个只在模块内部使用的信号,无法被外部访问。

  • 连续赋值语句(assign
    使用 assign 语句来为 outnot_in 赋值。Verilog 中的 assign连续赋值语句,意味着输出信号在输入信号改变时会实时更新。

    • assign out = ~not_in;:将 not_in 的值取反并赋给输出 out
    • assign not_in = ~in;:将输入 in 的值取反并赋给中间信号 not_in

实现练习中的电路

你需要实现一个电路,它包含两个 AND 门、一个 OR 门和一个 NOT 门。为了连接这些逻辑组件,需要声明两个中间导线,用来传递 AND 门的中间结果。最终,OR 门将这两个中间结果组合,生成输出 out,而 out_nout 的反相结果。

电路结构

  • 输入信号 ab 通过一个 AND 门 生成中间信号。
  • 输入信号 cd 通过另一个 AND 门 生成另一个中间信号。
  • 这两个中间信号通过 OR 门 连接,生成最终的输出 out
  • 最后,输出 out 通过 NOT 门 生成反向输出 out_n

img

QQ_1729490197933

Verilog 代码实现

根据这一逻辑,可以编写如下的 Verilog 代码:

`default_nettype none
module top_module(
    input a,      // 输入信号 a
    input b,      // 输入信号 b
    input c,      // 输入信号 c
    input d,      // 输入信号 d
    output out,   // 输出信号 out
    output out_n  // 反向输出信号 out_n
);

    // 声明中间导线 ab 和 cd
    wire ab, cd;

    // 计算 a 和 b 的 AND
    assign ab = a & b;

    // 计算 c 和 d 的 AND
    assign cd = c & d;

    // 将 ab 和 cd 通过 OR 门连接,得到输出 out
    assign out = ab | cd;

    // 计算 out 的反向输出 out_n
    assign out_n = ~out;

endmodule

代码讲解

  • 模块声明:
    • input a, input b, input c, input d:声明 4 个输入信号。
    • output out, output out_n:声明 2 个输出信号,其中 out 是组合逻辑输出,out_nout 的反向输出。
  • 导线声明:
    • wire ab, cd:声明两个中间导线 abcd,分别用于存储两个 AND 门的中间结果。
  • 逻辑操作:
    • assign ab = a & b;:计算输入 ab 的逻辑与(AND)。
    • assign cd = c & d;:计算输入 cd 的逻辑与(AND)。
    • assign out = ab | cd;:将两个 AND 门的结果 abcd 通过 OR 操作连接,得到输出 out
    • assign out_n = ~out;:将输出 out 取反,得到 out_n

重要概念

  • 导线声明:
    中间导线 abcd 用于存储 AND 门的中间结果。在 Verilog 中,当你需要存储某个逻辑运算的中间结果时,必须显式声明导线。

  • 逻辑门连接:
    两个 AND 门分别计算 a & bc & d,然后 OR 门对这两个中间结果进行逻辑或运算。NOT 门用于将 OR 门的输出取反。

  • 连续赋值:
    使用 assign 语句,信号的赋值是连续的,输出信号会随着输入信号的变化立即更新。


7458 芯片 Verilog 实现

7458 是一个集成电路芯片,包含四个 AND 门 和两个 OR 门。这个问题要求我们用 Verilog 实现 7458 芯片的功能。芯片有 10 个输入和 2 个输出,功能上需要通过多路 AND 和 OR 逻辑操作生成输出。

问题分析

  • 输入信号
    • 第一组信号有 6 个输入:p1a, p1b, p1c, p1d, p1e, p1f
    • 第二组信号有 4 个输入:p2a, p2b, p2c, p2d
  • 输出信号
    • p1y:由两组 3 输入 AND 门的输出通过 OR 门连接得出。
    • p2y:由两组 2 输入 AND 门的输出通过 OR 门连接得出。

img

实现思路

你可以有两种方式来实现这个模块:

  1. 直接用 assign 语句驱动输出:直接将 AND 和 OR 的逻辑表达式写在 assign 语句中,不使用中间导线。
  2. 使用中间导线:先用 assign 语句计算出中间的 AND 结果,存储在导线中,再用 OR 操作将中间结果连接到输出。

这两种方法都可以实现 7458 芯片的功能,下面我们将分别使用这两种方法来实现。

方法 1:直接用 assign 语句

QQ_1729490073903

这是最直接的方法,在 assign 语句中写出所有逻辑表达式。

module top_module ( 
    input p1a, p1b, p1c, p1d, p1e, p1f,  // 输入信号
    output p1y,                           // 输出信号 p1y
    input p2a, p2b, p2c, p2d,             // 输入信号
    output p2y                            // 输出信号 p2y
);

    // 第一组 AND 和 OR 运算,直接通过表达式生成 p1y
    assign p1y = (p1a & p1b & p1c) | (p1d & p1e & p1f);

    // 第二组 AND 和 OR 运算,生成 p2y
    assign p2y = (p2a & p2b) | (p2c & p2d);

endmodule

代码解释

  • 第一行assign p1y = (p1a & p1b & p1c) | (p1d & p1e & p1f);
    • 这里我们直接对输入 p1a, p1b, p1c 进行 3 输入 AND 运算,并与 p1d, p1e, p1f 的 AND 运算结果做 OR 运算,将结果赋给输出 p1y
  • 第二行assign p2y = (p2a & p2b) | (p2c & p2d);
    • 对第二组信号 p2a, p2b 进行 AND 运算,p2c, p2d 也进行 AND 运算,再将两个结果用 OR 连接,输出为 p2y

这种方法简洁直接,将每个输出的逻辑关系在一行代码中表达出来,适合简单的逻辑电路。

方法 2:使用中间导线

QQ_1729490128676

在这种方法中,我们首先使用 assign 语句计算出中间结果(AND 操作),并将其存储在导线中,之后再使用 OR 操作得到输出。

module top_module ( 
    input p1a, p1b, p1c, p1d, p1e, p1f,  // 输入信号
    output p1y,                           // 输出信号 p1y
    input p2a, p2b, p2c, p2d,             // 输入信号
    output p2y                            // 输出信号 p2y
);

    // 声明中间导线
    wire p1abc, p1def, p2ab, p2cd;

    // 计算 p1 的中间结果
    assign p1abc = p1a & p1b & p1c;  // p1a, p1b, p1c 的 AND 结果
    assign p1def = p1d & p1e & p1f;  // p1d, p1e, p1f 的 AND 结果

    // 使用 OR 门将中间结果连接到 p1y
    assign p1y = p1abc | p1def;

    // 计算 p2 的中间结果
    assign p2ab = p2a & p2b;         // p2a, p2b 的 AND 结果
    assign p2cd = p2c & p2d;         // p2c, p2d 的 AND 结果

    // 使用 OR 门将中间结果连接到 p2y
    assign p2y = p2ab | p2cd;

endmodule

代码解释

  • 中间导线的声明
    • wire p1abc, p1def, p2ab, p2cd; 声明四个中间导线,用于存储各个 AND 操作的结果。
  • 逻辑运算
    • assign p1abc = p1a & p1b & p1c;assign p1def = p1d & p1e & p1f; 计算第一组输入的 AND 结果,并存储在 p1abcp1def 中。
    • assign p1y = p1abc | p1def; 使用 OR 操作将中间导线的值传递给输出 p1y
    • 对第二组输入 p2a, p2b, p2c, p2d 同样使用 AND 和 OR 逻辑,得到输出 p2y

两种实现方式的比较

  1. 方法 1(直接 assign
    • 优点:代码简洁、直观,适合简单电路。
    • 缺点:当电路复杂时,直接在 assign 语句中表达复杂逻辑可能导致代码可读性下降。
  2. 方法 2(使用中间导线)
    • 优点:通过引入中间导线,可以更清晰地表达电路的各个部分,尤其在更复杂的设计中,便于调试和扩展。
    • 缺点:代码稍显冗长,适合更复杂的电路设计。