欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Verilog_Module

程序员文章站 2022-03-23 12:29:42
...

模块是实现特定功能的Verilog代码块。 可以将模块嵌入其他模块中,而较高级别的模块可以使用其输入和输出端口与其较低级别的模块进行通信。

Syntax

模块应包含在module和endmodule关键字内。 模块名称应该在module关键字之后给出,并且也可以声明端口的可选列表。 请注意,端口声明列表中声明的端口不能在模块主体内重新声明。

module <name> ([port_list]);
    // 模块内容
  endmodule
 
  //模块可以有一个空的端口列表
  module name;
    // 模块内容
  endmodule

所有变量声明,数据流语句,函数或任务以及较低的模块实例(如果有)都必须在module和endmodule关键字中定义。 同一文件中可以有多个具有不同名称的模块,并且可以按任何顺序定义。

Example

Verilog_Module
模块dff代表D触发器,其具有三个输入端口d,clk,rstn和一个输出端口q。 模块的内容描述了D触发器对于不同输入组合应如何表现。 在此,如果rstn为高电平,则输入d总是在时钟的上升沿分配给输出q,因为rstn为低电平有效复位。

// Module called "dff" has 3 inputs and 1 output port
module dff (   input       d,
              input       clk,
              input       rstn,
              output reg  q);
 
  // Contents of the module  
  always @ (posedge clk) begin
    if (!rstn)
      q <= 0;
    else 
      q <= d;
  end
endmodule
 

硬件原理图

在合成期间,该模块将转换为以下数字电路。
Verilog_Module
注意,您不能在模块之外编写任何代码

模块的目的是什么?

模块代表实现某些行为特征的设计单元,并将在综合过程中转换为数字电路。 可以将输入的任何组合提供给模块,并且它将提供相应的输出。 这允许相同的模块被重用以形成实现更复杂硬件的更大模块。

例如,上面显示的DFF可以链接形成一个移位寄存器。

module shift_reg (   input   d,
                    input    clk,
                    input   rstn,
                    output   q);
 
  wire [2:0] q_net;
  dff u0 (.d(d),         .clk(clk), .rstn(rstn), .q(q_net[0]));
  dff u1 (.d(q_net[0]), .clk(clk), .rstn(rstn), .q(q_net[1]));
  dff u2 (.d(q_net[1]), .clk(clk), .rstn(rstn), .q(q_net[2]));
  dff u3 (.d(q_net[2]), .clk(clk), .rstn(rstn), .q(q));
 
endmodule

硬件原理图

按Verilog RTL模块的描述,dff实例是通过连接连接在一起的。
Verilog_Module
从较小的块构建以形成较大的设计块,也可以执行相反的操作。 考虑将简单的GPU引擎分解为较小的组件,以便每个组件都可以表示为实现特定功能的模块。 下面显示的G​​PU引擎可以分为五个不同的子块,每个子块执行特定的功能。 总线接口单元将数据从外部输入到设计中,然后由另一个单元处理以提取指令。 其他单位沿线处理前一单位提供的数据。
Verilog_Module
每个子块可以表示为一个具有特定输入和输出信号集的模块,用于与其他模块通信,每个子块可以根据需要进一步划分为更细的块。

什么是顶层模块?

顶层模块是包含所有其他模块的模块。 *模块未在任何其他模块中实例化。

例如,设计模块通常在顶层测试平台模块内实例化,以便可以通过提供输入激励来运行仿真。 但是,testbench不会在任何其他模块中实例化,因为它是一个封装了其他所有内容的块,因此是顶层模块。

设计顶层

下面显示的设计代码具有一个称为design的顶层模块。 这是因为它包含需要其他所有子模块才能完成设计。 子模块可以具有更多的嵌套子模块,例如mod1内的mod3和mod2内的mod4。 无论如何,当实例化mod1和mod2时,所有这些都包含在顶层模块中。 因此,这使设计完整,并且是设计的顶层模块。

//---------------------------------
  //  Design code
  //---------------------------------
  module mod3 ( [port_list] );
    reg c;
    // Design code
  endmodule
 
  module mod4 ( [port_list] );
    wire a;
    // Design code
  endmodule
 
  module mod1 ( [port_list] );     // 这个名为“mod1”的模块包含两个实例
    wire   y;
 
    mod3   mod_inst1 ( ... );        //第一个实例是一个叫“mod3”的模块,它的名字叫“mod_inst1”
    mod3   mod_inst2 ( ... );     
  endmodule
 
  module mod2 ( [port_list] );   
    mod4   mod_inst1 ( ... );    
    mod4   mod_inst2 ( ... );    
  endmodule
 
  //*模块
  module design ( [port_list]);     // 从设计的角度来看,这是*模块
    wire   _net;
    mod1   mod_inst1   ( ... );       // 它包含所有其他模块和子模块
    mod2   mod_inst2   ( ... );
  endmodule

Testbench顶层

testbench模块包含激励以检查设计的功能,并且主要用于使用仿真工具进行功能验证。 因此,该设计被实例化并在testbench模块内称为d0。 从仿真器的角度来看,testbench是顶层模块。

 //-----------------------------------------------------------
  // Testbench code
  //从仿真的角度来看,这是*模块
  //因为在此模块中实例化了“设计”
  //-----------------------------------------------------------
  module testbench;                         
    design d0 ( [port_list_connections] );   
 
    // 其余的测试台代码
  endmodule

层次名称

当模块可以在内部相互实例化时,便形成了一种层次结构,因此顶层模块称为根。 由于给定模块内的每个较低的模块实例都需要具有不同的标识符名称,因此在访问信号时不会有任何歧义。 等级名称由这些标识符的列表构成,这些标识符用点分隔。 对于层次结构的每个级别。 使用特定信号的分层路径,可以在任何模块内访问任何信号。

  // 以上面显示的示例为顶层模块
  design.mod_inst1           // 访问模块实例mod_inst1
  design.mod_inst1.y           // mod_inst1内部的访问信号“ y”
  design.mod_inst2.mod_inst2.a    // mod4模块中的访问信号“ a”
 
  testbench.d0._net;           //从测试台访问设计模块中的*信号_net

参考文献:
【1】https://www.chipverify.com/verilog/verilog-modules

相关标签: # Building Blocks

推荐阅读