• MCDF实验2


     目录

     

    接口的使用

    仿真的结束

     类的例化和类的成员


     

    接口的使用

    问题1.1:可以看到之前的实验 channel initiator 发送的数据例如 valid 和 data 与时钟 clk 均在同一个变化沿,没有任何延迟,这种0延迟的数据发送不利于波形查看和阅读,因此在已有代码的基础上使用 intf.ck 的方式来做数据驱动,并且再观察波形,查看驱动的数据与时钟上升沿的延迟是多少?

    采用 intf.ck 来做数据驱动,代码如下:

    编辑

     

    编辑

    上升沿后1ns驱动数据

    波形如下:

     

    编辑

     

    问题1.2:为了更好地控制相邻数据之间的空闲间隔,引入一个变量 idle_cycles, 它表示相邻有效数据之间的间隔。已有代码会使得有效数据之间保持固定的一个空闲周期,我们需要使用 idle_cycles 变量, 来灵活控制有效数据之间的空闲周期。通过这个方法,在 tb 的 initial 块中我们通过方法 set_idle_cycles() 使得三个 channel initiator 的空闲周期变为 0, 即可以实现有效数据的连续发送。

    编辑

     

     当 idle_cycle = 0; 相邻数据之间就紧密发送,无间隔

    波形如下:

    编辑

    仿真的结束

    编辑

     编辑

    回顾 fork join 的知识: fork join 内部是并行执行的

    1.fork join:当fork join内部全部执行完之后,才会继续往下顺序执行;

    2.fork join_none:fork join_none语句块执行的同时,父线程会继续执行,即全部并行执行;

    3.fork join_any:执行到fork join_any内部语句时,当有任意一个语句执行完,那么后续的父类线程也会继续顺序执行。

    task automatic burst_test();
        // verification component initialization
        chnl0_gen.initialize(0);
        chnl1_gen.initialize(1);
        chnl2_gen.initialize(2);
        chnl0_init.set_name("chnl0_init");
        chnl1_init.set_name("chnl1_init");
        chnl2_init.set_name("chnl2_init");
        chnl0_init.set_idle_cycles(0);
        chnl1_init.set_idle_cycles(0);
        chnl2_init.set_idle_cycles(0);
        $display("burst_test initialized components");
        wait (rstn === 1'b1);
        repeat(5) @(posedge clk);
        $display("burst_test started testing DUT");
        // Please check the SV book for fork-join basic knowledge
        // and get understood it is for parallel thread running
        fork
            repeat(500) chnl0_init.chnl_write(chnl0_gen.get_data());
            repeat(500) chnl1_init.chnl_write(chnl1_gen.get_data());
            repeat(500) chnl2_init.chnl_write(chnl2_gen.get_data());
        join
        $display("basic_test finished testing DUT");
      endtask
    

    编辑

     

    task automatic fifo_full_test();
        // verification component initialization
        chnl0_gen.initialize(0);
        chnl1_gen.initialize(1);
        chnl2_gen.initialize(2);
        chnl0_init.set_name("chnl0_init");
        chnl1_init.set_name("chnl1_init");
        chnl2_init.set_name("chnl2_init");
        chnl0_init.set_idle_cycles(0);
        chnl1_init.set_idle_cycles(0);
        chnl2_init.set_idle_cycles(0);
        $display("fifo_full_test initialized components");
        wait (rstn === 1'b1);
        repeat(5) @(posedge clk);
        $display("fifo_full_test started testing DUT");
        fork
            repeat(500) chnl0_init.chnl_write(chnl0_gen.get_data());
            repeat(500) chnl1_init.chnl_write(chnl1_gen.get_data());
            repeat(500) chnl2_init.chnl_write(chnl2_gen.get_data());
        join_none
        fork
            wait(chnl0_init.intf.ch_margin == 'h20);
            wait(chnl1_init.intf.ch_margin == 'h20);
            wait(chnl2_init.intf.ch_margin == 'h20);
        join
        $display("fifo_full_test finished testing DUT");
      endtask

     

     类的例化和类的成员

     

    编辑

     

    编辑

    这里的例化 是类的例化 先声明句柄,再创建对象

      chnl_intf chnl0_if(.*);
      chnl_intf chnl1_if(.*);
      chnl_intf chnl2_if(.*);
    
      chnl_initiator chnl0_init;
      chnl_initiator chnl1_init;
      chnl_initiator chnl2_init;
      chnl_generator chnl0_gen;
      chnl_generator chnl1_gen;
      chnl_generator chnl2_gen;
      
      initial begin 
        // USER TODO 3.1
        // instantiate the components chn0/1/2_init chnl0/1/2_gen
    	chnl0_init = new("chnl0_init");
    	chnl1_init = new("chnl1_init");
    	chnl2_init = new("chnl2_init");
    	chnl0_gen = new(0);
    	chnl1_gen = new(1);
    	chnl2_gen = new(2);

    编辑

     

    / USER TODO 3.2
        // assign the interface handle to each chnl_initiator objects
    	chnl0_init.set_interface(chnl0_if);
    	chnl1_init.set_interface(chnl1_if);
    	chnl2_init.set_interface(chnl2_if);

    编辑

    
          basic_test();
    	  burst_test();
    	  fifo_full_test();
    	  $finish();

     完整的 initial 块就是

      initial begin 
        // USER TODO 3.1
        // instantiate the components chn0/1/2_init chnl0/1/2_gen
    	  chnl0_init = new("chnl0_init");
    	  chnl1_init = new("chnl1_init");
    	  chnl2_init = new("chnl2_init");
    	  chnl0_gen = new(0);
    	  chnl1_gen = new(1);
    	  chnl2_gen = new(2);
    
        // USER TODO 3.2
        // assign the interface handle to each chnl_initiator objects
    	  chnl0_init.set_interface(chnl0_if);
    	  chnl1_init.set_interface(chnl1_if);
    	  chnl2_init.set_interface(chnl2_if);
    
        // USER TODO 3.3
        // START TESTs
        $display("*****************all of tests have been finished********************");
        basic_test();
    	burst_test();
    	fifo_full_test();
    	$finish();
      end

     编辑

      class chnl_generator;
        chnl_trans trans[$];
        int num;
        int id;
        chnl_trans t  //这个句柄的位置
        function new(int n);
          this.id = n;
          this.num = 0;
          t = new();  // 这个创建对象实例的位置都应该放在下面的函数中
        endfunction
        function chnl_trans get_trans();
          //chnl_trans t = new();
          t.data = 'h00C0_0000 + (this.id<<16) + this.num;
          t.id = this.id;
          t.num = this.num;
          this.num++;
          this.trans.push_back(t);
          return t;
        endfunction
      endclass: chnl_generator

    trans[$]用于存放句柄。在function new(int n)中创建实例,三个chnl在初始化时只创建了一个实例,而在get_trans()函数中只有一个实例的话,不论data产生了多少,最终句柄都指向一个对象,只有一个数字,因为数据不断被覆盖直至最后一个。

    正确的是应该在get_trans()内创建实例,每次调用产生数据都会创建一个对象,并将句柄保存至trans[$]中,如果repeat(500),那么会产生500个句柄和500个不同的数据。


     


  • 相关阅读:
    C# 值类型调用ToString一定会装箱吗?
    JuiceFS 元数据引擎选型指南
    github小记(一):清除github在add或者commit之后缓存区
    vue 项目搭建的几种方式
    vscode python run code 中文乱码
    虚拟机安装 | 远程连接服务器
    STK 12.5.0发布
    后门程序3(补充)
    【Linux】在Xilinx平台上实现UVC Gadget(2)- 解决dwc3驱动bug
    【计算机网络】网络编程接口 Socket API 解读(6)
  • 原文地址:https://www.cnblogs.com/tianranjushi/p/16369097.html