前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SystemVerilog验证编写(1)

SystemVerilog验证编写(1)

作者头像
数字IC小站
发布2020-07-01 11:01:17
8190
发布2020-07-01 11:01:17
举报
文章被收录于专栏:数字IC小站数字IC小站

我错了。不立flag,不定期更新~

前面几次推送已经给出了FIFO的RTL综合设计和SV写法的ref模型

带选通信号的同步FIFO(重发)

带选通信号的同步FIFO(可综合RTL设计)

本次的Testbench就是基于这两次的代码,进行验证。

Testbench的常见组成模块如下,由复位、产生、发送、接收、计分板比对几个模块组成。

本次验证代码就是通过给上述两个FIFO发送相同的信号与指令内容,通过把两个FIFO的输出发送到check task中进行比对,确定RTL写法与时序是否正确,看其是否可以实现正确的功能。

首先要连接DUT模块和TB模块,那么使用interface接口进行连接。

一般来说,我们在接口中使用时钟块去同步TB中的信号,确定端口方向。

代码语言:javascript
复制
`timescale 1ns / 100ps

//******************************************************************

// Author:SJTU_chen
// Date: 2019/10/26
// Version: v1.0
// Module Name: fifo-interface
// Project Name: SystemVerilog Lab1

//*******************************************************************

interface fifo_io(input bit clock);
    logic           reset_n,valid_in,valid_out,valid_out1,ready_in,ready_in1;
    logic [63:0]    data_in;
    logic [1:0]     wstrb;
    logic [31:0]    data_out,data_out1;

    clocking cb @(posedge clock);
        default input #1ns output #1ns;
        output reset_n;
        output valid_in;
        output data_in;
        output wstrb;
        input  valid_out,valid_out1;
        input  data_out,data_out1;
        input  ready_in,ready_in1;
    endclocking: cb
    
    modport TB(clocking cb, output reset_n);

endinterface:fifo_io

在顶层模块中把其连接起来,部分代码如下:

代码语言:javascript
复制

`timescale 1ns / 100ps

//******************************************************************

// Author:SJTU_chen
// Date: 2019/10/26
// Version: v1.0
// Module Name: fifo-testbench_top
// Project Name: SystemVerilog Lab1

//*******************************************************************

module fifo_test_top();

    parameter simulation_cycle = 10;
    bit SystemClock = 0;

    fifo_io top_io(SystemClock);
    test t(top_io);

    fifo_dut    fifo_dut_inst(
        .clock(top_io.clock),
        .reset_n(top_io.reset_n),
        .valid_in(top_io.valid_in),
        .wstrb(top_io.wstrb),
        .data_in(top_io.data_in),
        .valid_out(top_io.valid_out),
        .ready_in(top_io.ready_in),
        .data_out(top_io.data_out)
    );

    fifo_ref    fifo_ref_inst(
        .clock(top_io.clock),
        .reset_n(top_io.reset_n),
        .valid_in(top_io.valid_in),
        .wstrb(top_io.wstrb),
        .data_in(top_io.data_in),
        .valid_out(top_io.valid_out1),
        .ready_in(top_io.ready_in1),
        .data_out(top_io.data_out1)
    );

    always begin
        #(simulation_cycle/2) SystemClock = ~SystemClock;
    end

endmodule

接下来就是编写TB模块了,如上图所示:

首先我们编写的是复位reset task模块:

代码语言:javascript
复制
  //task reset
    task reset();
        fi_io.reset_n       = 1'b0;
        fi_io.cb.wstrb      <= '0;
        fi_io.cb.valid_in  <= '1;
        fi_io.cb.data_in   <= '0;
        repeat(2) @fi_io.cb;
        fi_io.cb.reset_n   <= 1'b1;
        repeat(15) @fi_io.cb;

    endtask: reset

上述代码请仔细看,有点儿意思,很多同学的写法不是这样的,这个在Soc设计方法学课程中会讲到~

接下来就是gen task

代码语言:javascript
复制
//task gen
    task gen();
        send_data.delete();
        wstrb_quene.delete();
        repeat(120)
        begin
            wstrb_quene.push_back({$urandom});
            send_data.push_back({$urandom,$urandom});
        end
    endtask: gen

发送 send task:

代码语言:javascript
复制
  task send();
        send_payload();
    endtask:send

    task send_payload();
       // static int count = 0;
        static int pkts_checked = 0;
        while(send_data.size() != 0)
        begin
            if (pkts_checked < 80)
            begin
                    fi_io.cb.data_in <= send_data.pop_front();
                    fi_io.cb.wstrb <= wstrb_quene.pop_front();
                    fi_io.cb.valid_in <= $urandom;
                 //   count++;
            end
            else begin
                fi_io.cb.data_in <= send_data.pop_front();
                fi_io.cb.wstrb <= 2'b11;
                fi_io.cb.valid_in <= 1'b1;
             //   count++;
            end

        end
    endtask:send_payload

接收 task

代码语言:javascript
复制
 //task recv_dut
    task recv_dut();
        get_payload_fromdut();
    endtask: recv_dut

    //task recv_ref
    task recv_ref();
        get_payload_fromref();
    endtask: recv_ref

比对模块部分代码:

代码语言:javascript
复制
 function void check();

        string message;
        static int pkts_checked = 0;

        if (!compare(message)) begin
          $display("\n%m\n[ERROR]%t Packet #%0d %s\n", $realtime, pkts_checked++, message);
          $finish;
        end
        $display("[NOTE]%t Packet #%0d %s", $realtime, pkts_checked++, message);
    endfunction: check

通过以上比对,我们就可以看出dut设计是否正确,请注意,前提条件是保证我们设计的ref模型是没问题的。

最终的仿真截图如下:

下次,我们讲讲怎么使用面向对象的结构去验证~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数字IC小站 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档