Verilog 语法介绍 3

目录

DUT设计

Testbench

1. 端口声明

2.基本模块例化

3.激励生成与响应监控‌

4.assign语句‌:用于连接DUT端口与Testbench中的信号

5.保存波形

system task

XMR

Verilog 2001 new features


测试设计

DUT (Design Under Test)例化指的是将你要测试的设计模块实例化到测试平台(Testbench)中。设计模块到测试平台,一般有3个文件:

  1. design 有输入输出。
  2. testbench,  验证平台,没有输入输出。
  3. testcase 应用案例。产生激励,check 响应

三个模块的分工:testbench是最终的硬件部分,它将design 与tescaset 连接起来,使testcase生成的输入流向你想要测试的对象(design).

😀 如果把test放在 testbench 里,就是两个部分。vscode 配置的Verilog 仿真环境,基本就是两个文件:一个 design.v, 一个 design_testbench.v

模块testAdd生成了module halfAdd的输入,并显示更改。module halfAdd是design 的一部分。

$monitor, 监视器,变量一旦有变化,就会有打印。

Testbench

‌Verilog Testbench的编写主要涉及模块实例化、信号声明、激励生成和响应监控等步骤。‌

1. 端口声明
  • 连接到DUT(待测设计)的输入端口需声明为reg类型
  • DUT的输出端口需声明为wire类型。

2.基本模块例化

模块例化是将一个模块定义实例化为设计中的一个具体实例。基本语法如下:

module_name instance_name (
  .port_name(signal_name)
);
module_name:要例化的模块名称。
instance_name:实例的名称,需唯一。
port_name:模块的端口名称。
signal_name:连接到端口的信号名称。

端口连接方式推荐使用带名字的连接方式 .port_name(signal),可读性高,不易出错

举例:

 假设你有一个设计模块名为 my_module,它有如下端口定义:

module my_module (
    input      clk,
    input      rst_n,
    input  [7:0] data_in,
    output [7:0] data_out
);
    // 模块功能代码
endmodule
module tb_my_module;
    // 定义信号
    reg        clk,  rst_n;
    reg  [7:0] data_in;
    wire [7:0] data_out;

    // 实例化 DUT
    my_module uut (
        .clk     (clk),
        .rst_n   (rst_n),
        .data_in (data_in),
        .data_out(data_out)
    );

    // 其他测试逻辑,如时钟生成、复位控制、激励等

endmodule
3.激励生成与响应监控‌

        ‌初始块(initial)‌:用于生成测试激励。

        always块‌:用于生成时钟信号或复位信号等周期性激励

4.assign语句‌:用于连接DUT端口与Testbench中的信号
5.保存波形

例子:

// this is a latches example:0703 lily

module latches(        //design
    output Qsimple, Qclear, QpreClear,
    input D, ena1 ,ena2, clr, pre
);

    wire clr_n,pre_n,ena1_n;
    reg  QsimpleReg, QclearReg, QpreClearReg;

    assign clr_n=clr;
    assign pre_n=pre;
    assign ena1_n=ena1;

    assign #1 Qsimple=QsimpleReg;  //assign  并发执行
    assign #2 Qclear=QclearReg;
    assign #2 QpreClear=QpreClearReg;

    always @(D,ena1) begin  //latch1
        if (ena1 ==1'b1) 
        QsimpleReg <= D;  //功能定义里操作的都是内部信号
    end

    always @(D,ena1_n) begin  //latch2
      if(clr == 1'b1)
      QclearReg <= 1'b0;  // 非阻塞赋值,用在有时钟控制的逻辑
      else if (ena1_n == 1'b0)
      QclearReg <= D;  
    end

    always @(D, pre_n, ena2, clr_n) begin  //latch3
        `ifdef DC
        `elsr
        if (pre_n==1'b0 && clr_n =1'b0)
        $strobe(
            "\n *** Time=%04d,  pre_n=%01b  and clr_n=%01b asserted.\n"
        ); 
        `endif 

        if (clr_n==1'b0)  QpreClearReg <= 1'b0;
        else if (pre_n == 1'b0) QpreClearReg <= 1'b1;
        else if (ena2 == 1'b1)  QpreClearReg <= 0;           
    end

    endmodule//latches


//*****************以下是testbench ******************//

    module latchesTst; // Testbench
    wire QsimpleW,Qclearw,Qpreclearw,D,ena1,ena2,clr,pre;    //端口声明
    reg DReg,ena1Reg,ena2Reg,clrReg,preReg;

    assign D=DReg;                                       //assign 语句
    assign ena1 = ena1Reg;
    assign ena2 = ena2Reg;
    assign clr= clrReg;
    assign pre =preReg;

    always@(DReg)                                    //激励
    #15 DReg <= ~DReg;
    always@(ena2Reg)
    #10 ena2Reg <= ~ena2Reg;

    initial begin
     #0 DReg =1'b0;//The only time EVER to use '#0
        ena1Reg =1'b0;// without deep doubts!
        preReg= 1'b0;
        clrReg= 1'b0;

    #2.5 ena2Reg = 1'b0;
    #2.5 ena1Reg = 1'b1;

    #10 clrReg= 1'b1;
    #10 clrReg= 1'b0;
    #10 clrReg= 1'b1;
    #10 clrReg= 1'b0;
    
    #04 ena1Reg = 1'b0;
    #03 preReg= 1'b1;
    #10 preReg= 1'b0;
    #10 preReg= 1'b0;
    #10 clrReg= 1'b1;

    #10 preReg= 1'b0;
    #10 clrReg= 1'b0;
    #10 preReg= 1'b1;
    #10 clrReg = 1'b1;

    #04 ena1Reg = 1'b1;
    #01 preReg = 1'b1;
    #10 preReg= 1'b0;
    #10 preReg= 1'b0;

    #10 clrReg= 1'b1;
    #10 preReg= 1'b0;
    #10 clrReg= 1'b0;
    #10 preReg= 1'b1;
    #10 clrReg= 1'b1;

    #20 $finish;
end
    latches latchesInst1(                                //模块例化
        .Qsimple(Qsimplew),
        .Qclear(Qclearw),
        .QpreClear(QpreClearw),
        .D(D),
        .ena1(ena1),
        .ena2(ena2),
        .clr(clr),
        .pre(pre)
    );

initial                                                  //保存波形
    begin            
        $dumpfile("latches_tb.vcd");        //生成的波形 vcd文件名称
        $dumpvars(0, latchesTst);    //参与仿真的tb模块名称
    end 


    endmodule //latchesTst

运行后,选取latch1的波形:

    always @(D,ena1) begin

        if (ena1 ==1'b1)

        QsimpleReg <= D;  //功能定义里操作的都是内部信号

    end

task 和 function

task,  必须加begin ... end .......... 作用:写test case

task是一种用于定义可重用功能模块的方法。它可以看作是一个过程或子程序,可以在模块内部或外部调用。任务允许我们将一个复杂的操作分解成较小的模块,以提高代码的可读性和可维护性。

任务支持复杂的时序控制功能,这使得task成为了处理涉及时间延迟、事件触发以及同步操作的理想选择。#delays, @, wait 

调用方式: 任务是通过调用来执行的,并且只有在调用时才执行。如果定义了任务但没有调用它,那么这个任务是不会执行的

function.  特点:0 延迟。必须返回一个值,返回的变量= function name,   这里返回relocate。用作:design

  • 调用方式:
  • 用途:
    • Task: 适用于需要处理时序逻辑的场景,例如延迟、事件控制等⁠⁣ ⁠⁣
    • Function: 主要用于纯组合逻辑,替代简单的表达式操作。
system task

系统任务的使用方式与使用“task...endtask”构造定义的常规任务相同。它们之间的区别在于首字符,该字符始终为“$

$readmemh,读一个文件,初始化 memory

system function 

和function 相同,区别是有 $ 头:$ time 返回仿真时间,   $random

XMR

Verilog 具备一种机制,用于全局引用网络、寄存器、事件、任务和函数,该机制称为跨模块引用,或XMR。   比如 top.dut.xxx
跨模块引用,或有时称为层次化引用,可以有多种形式:

  • 模块内不同范围的引用
  • 模块之间的引用
  • 向下引用
  • 向上引用

Hierarchical Module

每个模块定义中都有一个静态作用域,可以用来定位任何标识符。例如,在以下示例中,

不同区域内 x 不一样

用A.D.x 访问

Verilog 2001 new features

input 类型 位宽 名字;

参数定义

列表,用 ,号 分割

vector

  • 定义:在Verilog中,向量(vector)是一组信号的集合,通常用于表示多位宽的数据。向量可以是wire或reg类型,声明时需要指定其位宽。例如,wire[3:0] vec;声明了一个4位宽的线网向量vec⁠⁣ ⁠⁣
  • 用途:向量常用于总线和多位数据处理,使得设计者能够方便地对一组信号进行操作。通过向量,可以简化代码并提高可读性。

array

二维数组表示   array_2D[127:0][127:0]。 访问某个元素 array_2D[8][8]

net and real 也可以放到数组里

 

传递参数,使用 . 进行访问  

#(.size(1), .width(12), .size(4096));

generate

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

search7

请为我点赞!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值