跳转至

第四章 Verilog模块与函数

参考链接:

  1. TestBench基本写法与语法详解_testbench怎么写-CSDN博客
  2. 6.1 Verilog 函数 | 菜鸟教程

4.6 Verilog激励

一、TestBench简介

编写 TESTBENCH 的目的是为了对使用硬件描述语言设计的电路进行仿真验证,测试设计电路的功能、性能与设计的预期是否相符。通常,编写测试文件的过程如下:

• 产生模拟激励(波形); • 将产生的激励加入到被测试模块中并观察其响应; • 将输出响应与期望值相比较。

二、完整的TestBench的文件结构

通常而言,一个完整的TestBench文件的结构为

image-20250901000049664

其实 testbench 最基本的结构包括信号声明、激励和模块例化。

根据设计的复杂度,需要引入时钟和复位部分。当然更为复杂的设计,激励部分也会更加复杂。根据自己的验证需求,选择是否需要自校验和停止仿真部分。

当然,复位和时钟产生部分,也可以看做激励,所以它们都可以在一个语句块中实现。也可以拿自校验的结果,作为结束仿真的条件。

实际仿真时,可以根据自己的个人习惯来编写 testbench,这里只是做一份个人的总结。

基本的框架见下:

`timescale 仿真单位/仿真精度

module Test_bench();//通常无输入无输出

信号或变量声明定义
逻辑设计中输入对应 reg 
逻辑设计中输出对应 wire 
使用 initial  always 语句产生激励
例化待测试模块
监控和比较输出响应

endmodule

三、Testbench仿真举例

例如,使用verilog语言实现数据拼接,即将一个2bit数据拼接成8bit数据,其功能模块描述如下:

module  data_consolidation
    (
        input           clk ,
        input           rstn ,
        input [1:0]     din ,          //data in
        input           din_en ,
        output [7:0]    dout ,
        output          dout_en        //data out
     );

   // data shift and counter
    reg [7:0]            data_r ;
    reg [1:0]            state_cnt ;
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            state_cnt     <= 'b0 ;
            data_r        <= 'b0 ;
        end
        else if (din_en) begin
            state_cnt     <= state_cnt + 1'b1 ;    //数据计数
            data_r        <= {data_r[5:0], din} ;  //数据拼接
        end
        else begin
            state_cnt <= 'b0 ;
        end
    end
    assign dout          = data_r ;

    // data output en
    reg                  dout_en_r ;
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            dout_en_r       <= 'b0 ;
        end
        //计数为 3 且第 4 个数据输入时,同步输出数据输出使能信号
        else if (state_cnt == 2'd3 & din_en) begin  
            dout_en_r       <= 1'b1 ;
        end
        else begin
            dout_en_r       <= 1'b0 ;
        end
    end
    //这里不直接声明dout_en为reg变量,而是用相关寄存器对其进行assign赋值
    assign dout_en       = dout_en_r;

endmodule

4.7 IP核的使用

4.7.1 ILA IPcore

ILA,即Integrated Logic Analyzer,中文名叫集成逻辑分析仪。

一、ILA核的作用

它允许你:

  • 在 FPGA 上电运行时,抓取任意内部寄存器、总线、状态机、控制信号等的实时值
  • 设置触发条件(如:当 cnt == 100 时开始抓波形)
  • 把数据通过 JTAG 传回 Vivado 的 Hardware Manager 界面
  • 图形化查看波形,就像仿真波形一样!

二、ILA核的工作原理

你的设计逻辑
    ├── 信号A ───┐
    ├── 信号B ───┤
    └── 时钟CLK ─┼──→ [ ILA Core ] ←── JTAG ←→ Vivado Hardware Manager
                 │       (抓取+缓存)
                 └── 触发条件(可选)   
  • ILA Core 是一个嵌入在你设计中的“监控模块”
  • 它持续采样你指定的信号(在时钟上升沿)
  • 当满足触发条件时,把前后一段时间的数据存入 BRAM
  • 通过 JTAG 接口把数据传到电脑,在 Vivado 中显示波形

三、ILA核的设置参数

  1. 采样时钟(Capture Clock)

  2. 用来采样信号的时钟(必须是你设计中存在的时钟)

  3. 所有探针信号都在这个时钟沿采样

  4. 探针(Probes)

  5. 你想观察的信号(可多个)

  6. 每个探针可设置位宽(如 8-bit、32-bit)

  7. 采样深度(Sample Depth)

  8. 存储多少个采样点(如 1024、4096)

  9. 越大占 BRAM 越多,但能看更长时间

  10. 触发条件(Trigger Condition)

  11. 默认是“立即触发”或“手动触发”

  12. 可设置复杂条件:如 probe0[3:0] == 4'hA && probe1[0] == 1

四、ILA核的实际配置过程

添加ILA核

image-20250918185041860

设置位宽

image-20250918185316639