精华内容
下载资源
问答
  • UART UVM验证平台平台搭建总结 tb_top是整个UVM验证平台的最顶层;tb_top中例化dut,提供时钟和复位信号,定义接口以及设置driver和monitor的virual interface,在intial中调用run_test() UVM入口函数。在基于uvm_...

    UART UVM验证平台平台搭建总结

              tb_top是整个UVM验证平台的最顶层;tb_top中例化dut,提供时钟和复位信号,定义接口以及设置driver和monitor的virual interface,在intial中调用run_test() UVM入口函数。在基于uvm_test扩展出base_test,根据测试用例再基于base_test扩展出各种各样的test.在扩展后的test中call sequence.

              在base_test中实例化env, env_config, 打印验证平台的拓扑结构uvm_top.print_topology,打印输出注册在factory中类factory.print()。在环境env的build_phase()阶段,实例化agent,reference model,scoreboard,checker,function coverage。在connetion_phase()将各个组件component通过TLM1.0 中的FIFO或analysis port连接起来。在agent中,实例化driver,monitor,sequencer,根据uvm_agent的is_active变量决定是否实例化driver和sequencer。在monitor和driver与DUT的信号层打交道,所以需要例化virtual interface. 除此之外,根据情况例化config,用congfig_db 配置相应的参数。从uvm_item_sequence派生成相应的transactions。

              整个UVM TB的如何函数是run_test()。UVM是基于事物级的验证方法学各个组件之间通过port, export, transport, analysis_port, analysis_export,imp(implement) 等来进行通信。搭建完验证平台后,大部分工作需要编写sequence(seq lib).

              uvm中有两种基本类:uvm_transaction,uvm_component(uvm_component其实也是从uvm_objection扩展而来)。uvm验证平台是基于uvm_component构建的树形结构;uvm_compent包括各种phase: build_phase, connect_phase, end_of_elaboration, start_of_simulation_phase, run_phase, pre_reset_phase, reset_phase, post_reset_phase , pre_congfigure_phase, configure_phase, post_configure_phase, pre_main_phase, main_phase, post_main_phase, pre_shutdown, shutdown_phase, post_shutdown_phase, extract_phase, chect_phase, report_phase, final_pahse等。uvm采用objection机制决定phase执行的时间raising_objection和drop_objection. 将uvm_sequence_item中比较复杂的约束可以放在per_randomize()和post_randomize()中。sequence包含pre_body(), body(), post_body()三个过程。

              验证平台需要自动化完成工作,用perl脚本搭建基本UVM验证平台框架,编写Makefile完成仿真工具和工作设置,以及在Makefile中调用参数化设置;还可使用$test$plusargs和$value$plusargs传入相应的参数。

    展开全文
  • 技术领域本发明涉及芯片设计验证领域,具体地说是一种实用性强、连接UVM验证平台搭建方法。背景技术:伴随着芯片集成度增加,各种通信与信号处理算法被集成到系统芯片中,这些算法通常需要先利用Matlab或Simulink...

    技术领域本发明涉及芯片设计验证领域,具体地说是一种实用性强、连接UVM验证平台的搭建方法。

    背景技术:

    伴随着芯片集成度增加,各种通信与信号处理算法被集成到系统芯片中,这些算法通常需要先利用Matlab或Simulink进性算法层的建模,然后利用Matlab自带的转换器转换成RTL代码,或者人工将Matlab代码转换为RTL代码,供系统芯片集成,仿真综合使用。这种转换过程,尤其是人工转换,需要确保其功能的正确性,也就是算法层与逻辑层的功能相一致。这就需要进性一些验证与测试。UVM验证方法是芯片验证业界最新研发的一种验证方法学。工程师用它可创建坚实、可重用、具互操作性的验证组件和验证平台。UVM提供基于SystemVerilog语言开发的一套库函数,工程师通过调用库可以省去自己从零开始开发验证环境的麻烦。此套方法已经在芯片开发的行业得到较广泛应用,它的受控随机数产生机制能大大提高验证效率,对于算法实现类的模块的验证尤其适用。UVM本身是针对SystemVerilog语言开发的,所以若想将这套验证环境与Matlab环境连接,还是需要解决一些具体问题的。为了有效的利用UVM验证方法的优点,来验证算法实现电路的功能,本发明构建一个验证平台中同时运行针对SystemVerilog的仿真以及Matlab模型的仿真。

    技术实现要素:

    本发明的技术任务是针对以上不足之处,提供一种实用性强、连接UVM验证平台的搭建方法。一种连接UVM验证平台的搭建方法,其搭建过程为:通过UVM验证平台产生激励,将激励同时发送给RTL代码被测对象以及Matlab模型,比较两者输出的一致性,来确认RTL代码的正确性。其具体搭建过程为:设置UVM验证平台;设置Matlab模型;通过SystemVerilog的动态程序接口DPI连接UVM验证平台与Matlab模型;设置仿真器及可控制仿真器的脚本,并运行验证平台。所述UVM验证平台内置计分板,该记分板里嵌入上述Matlab模型,该UVM验证平台产生激励数据包并发送给RTL代码被测对象,同时将此数据记录下来,发送给记分板;RTL代码被测对象再输出数据信号给UVM验证平台,UVM验证平台进行收集后也发送给记分板,记分板对两组数据流进性比较,判断是否正确。UVM验证平台里嵌入Matlab模型的具体过程为:首先实现SystemVerilog与Matlab的协同,两者的协同通过一个C程序的头文件来实现,即:通过Matlab自带的C函数库实现对Matlab的控制,调用Matlab的启动、关闭、输入输出;SystemVerilog的动态程序接口DPI直接导入和导出上述C函数库中的函数,从而实现通过SystemVerilog调用C程序然后控制Matlab,实现把Matlab模型嵌入UVM验证平台。所述仿真器包括逻辑仿真器和算法仿真器,并通过脚本实现对仿真器控制,来打开DPI的使能以及使Matlab工具与逻辑仿真器同时启动,以便完成验证平台的数据监测功能;通过使用SystemVerilogDPI连接UVM验证平台与Matlab模型使得逻辑仿真器与算法仿真器同时运行,保证了算法到逻辑映射转换的正确性。本发明的一种连接UVM验证平台的搭建方法,具有以下优点:本发明提供的一种连接UVM验证平台的搭建方法通过利用UVM验证平台产生激励,将激励同时发送给RTL代码被测对象以及高层次Matlab模型,比较两者输出的一致性来,来确认RTL代码的正确性,有效的利用UVM验证方法的优点,来验证算法实现电路的功能,能极大提高带有各种复杂算法的芯片验证的效率,缩短芯片开发周期,实用性强,易于推广。附图说明附图1为本发明的UVM验证平台示意图。附图2为UVM验证平台与Matlab模型的连接关系图。附图3为Matlab控制的C头文件图。附图4为Matlab控制的SystemVerilog调用过程图。具体实施方式下面结合附图和具体实施例对本发明作进一步说明。如附图1、图2所示,本发明的一种连接UVM验证平台的搭建方法,其搭建过程为:通过UVM验证平台产生激励,将激励同时发送给RTL代码被测对象以及高层次Matlab或simulink模型,比较两者输出的一致性,来确认RTL代码的正确性。其具体搭建过程为:设置UVM验证平台;设置Matlab模型;通过SystemVerilog的动态程序接口DPI连接UVM验证平台与Matlab模型;设置仿真器及可控制仿真器的脚本,并运行验证平台。所述UVM验证平台内置计分板,该记分板里嵌入上述Matlab模型,该UVM验证平台产生激励数据包并发送给RTL代码被测对象,同时将此数据记录下来,发送给记分板;RTL代码被测对象再输出数据信号给UVM验证平台,UVM验证平台进行收集后也发送给记分板,记分板对两组数据流进性比较,判断是否正确。与普通UVM验证平台不用的唯一一点是记分板里接入了一个Matlab模型,来运行被测对象的算法实现。为了让SystemVerilog实现的UVM验证平台与Matlab模型同时运行,需要正确的连接他们,图2表示了这种连接的实现。UVM验证平台里嵌入Matlab模型的具体过程为:首先实现SystemVerilog与Matlab的协同,两者的协同通过一个C程序的头文件来实现,即:通过Matlab自带的C函数库实现对Matlab的控制,调用Matlab的启动、关闭、输入输出,图3是这个C头文件的示例;SystemVerilog的动态程序接口DPI直接导入和导出上述C函数库中的函数,从而实现通过SystemVerilog调用C程序然后控制Matlab,实现把Matlab模型嵌入UVM验证平台,图4是SystemVerilog调用C控制Matlab的过程示例。所述仿真器包括逻辑仿真器和算法仿真器,并通过脚本实现对仿真器控制。对于不同的仿真器,也需要加入一些特别的仿真器控制指令,即上述控制脚本来打开DPI的使能以及使Matlab工具与逻辑仿真器同时启动,以便完成验证平台的数据监测功能。通过使用SystemVerilogDPI连接UVM验证平台与Matlab模型能使得逻辑仿真器与算法仿真器同时运行,保证了算法到逻辑映射转换的正确性,提高了开发效率。上述具体实施方式仅是本发明的具体个案,本发明的专利保护范围包括但不限于上述具体实施方式,任何符合本发明的一种连接UVM验证平台的搭建方法的权利要求书的且任何所述技术领域的普通技术人员对其所做的适当变化或替换,皆应落入本发明的专利保护范围。

    展开全文
  • 最近一个月在实习公司做回归测试,对公司的UVM平台用的比较熟练,就想着自己做一个DUT,然后搭建一个UVM验证平台。 首先,DUT是一个简单的32位的加法器,代码如下:alu.v module adder32_cla( input clk , ...

    最近一个月在实习公司做回归测试,对公司的UVM平台用的比较熟练,就想着自己做一个DUT,然后搭建一个UVM验证平台。

    首先,DUT是一个简单的32位的加法器,代码如下:alu.v

    module adder32_cla(
      input         clk     ,
      input         rst     ,
      input         enable  ,
      input  [31:0] a       ,
      input  [31:0] b       ,
      input         cin     ,
      output [31:0] sum_r   ,
      output        cout_r  
    );
    
      reg [31:0] sum_r  = 32'h00000000 ;
      reg        cout_r = 1'h0  ;
    
    always @(posedge clk or negedge rst) 
      begin
        if (!rst)
          begin
            sum_r  = 32'h00000000  ;
            cout_r =  1'h0          ;
          end
        else if(enable)
          begin 
            {cout_r,sum_r} <= a + b + cin;              
          end
        else
          begin               
            sum_r  <= sum_r  ;
            cout_r <= cout_r ;
          end                                   
      end    
      
    endmodule
    View Code

    UVM验证组件:

    1、top.sv

    `timescale 1ns/1ns
    
    `include "pkg.sv"
    `include "alu.v"
    
    module top();
    
    import uvm_pkg::*;
    `include "uvm_macros.svh"    
    my_if my_my_if();
         
    adder32_cla inst1 
    (
      .clk    (my_my_if.clk    ),
      .rst    (my_my_if.rst    ),
      .enable (my_my_if.enable ),
      .a      (my_my_if.a      ),
      .b      (my_my_if.b      ),
      .cin    (my_my_if.cin    ),
      .sum_r  (my_my_if.sum_r  ),
      .cout_r (my_my_if.cout_r )
    );
    initial  
      begin
             my_my_if.cin    = 1'b0         ;
             my_my_if.a      = 32'h00000000 ;
             my_my_if.b      = 32'h00000000 ;
             my_my_if.enable = 1'b1         ;
             my_my_if.rst    = 1'b0         ;
        #100 my_my_if.rst    = 1'b1         ;
      end
    initial
      begin
             my_my_if.clk   <= 1'b0        ;
            
        #500 my_my_if.clk   <= 1'b0        ;
        #500 my_my_if.clk   <= 1'b1        ;
    forever 
        #50  my_my_if.clk   = ~my_my_if.clk;
    end
    initial
      begin
        uvm_config_db#(virtual my_if)::set(null,"uvm_test_top.env.i_agt.drv","my_if",my_my_if);
        uvm_config_db#(virtual my_if)::set(null,"uvm_test_top.env.o_agt.mon","my_if",my_my_if);                         
        run_test();
      end    
    
    endmodule 
    View Code

    top.sv主要的作用是实例化DUT,和输入输出的interface,并且定义了时钟频率,传递了接口一连接TB,和run_test();用于启动UVM phase。

    2、my_test.sv

    `ifndef MY_TEST__SV
    `define MY_TEST__SV
    import uvm_pkg::*;
    `include "uvm_macros.svh"    
    `include "my_env.sv"
    class my_test extends uvm_test;
      my_env env;
      extern function new(string name="my_test",uvm_component parent=null);
      extern virtual function void build_phase(uvm_phase phase);
    `uvm_component_utils(my_test)
    endclass
    
    function my_test::new (string name="my_test",uvm_component parent=null);
      super.new(name,parent);
    endfunction
    function void my_test::build_phase(uvm_phase phase);
       super.build_phase(phase);
       env = my_env::type_id::create("env");
    endfunction
    
    `endif
    View Code

    my_test.sv派生于uvm_test,属于基类。在项目中,主要采用基类构建框架,继承类实现具体动作的方式来增加灵活性。

    3、my_env.sv

    `ifndef MY_ENV__SV
    `define MY_ENV__SV
    import uvm_pkg::*;
    `include "uvm_macros.svh"    
    `include "my_agent.sv"
    `include "my_scoreboard.sv"
    `include "my_model.sv"
    
    class my_env extends uvm_env;
      my_agent       i_agt ;              //my_driver functional
      my_agent       o_agt ;              //my_monitor functional
      my_model       mdl   ;
      my_scoreboard  scb   ;
      
      uvm_tlm_analysis_fifo  #(my_transaction) agt_scb_fifo;   //my_monitor
      uvm_tlm_analysis_fifo  #(my_transaction) agt_mdl_fifo;   //my_driver
      uvm_tlm_analysis_fifo  #(my_transaction) mdl_scb_fifo;   //my_model
      extern function new (string name,uvm_component parent);
      extern virtual function void build_phase(uvm_phase phase);
      extern virtual function void connect_phase(uvm_phase phase);
    `uvm_component_utils(my_env);
    endclass
    
    function my_env::new (string name,uvm_component parent);
    super.new(name,parent);
    endfunction
    
    function void my_env::build_phase(uvm_phase phase);
    super.build_phase(phase);
      i_agt = my_agent::type_id::create("i_agt",this);
      o_agt = my_agent::type_id::create("o_agt",this);
      i_agt.is_active = UVM_ACTIVE;
      o_agt.is_active = UVM_PASSIVE;
      mdl = my_model::type_id::create("mdl",this);
      scb = my_scoreboard::type_id::create("scb",this);
      agt_scb_fifo = new("agt_scb_fifo",this);
      agt_mdl_fifo = new("agt_mdl_fifo",this);
      mdl_scb_fifo = new(" mdl_scb_fifo",this);
    endfunction
    
    function void my_env::connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      i_agt.ap.connect(agt_mdl_fifo.analysis_export);
      mdl.port.connect(agt_mdl_fifo.blocking_get_export);
      mdl.ap.connect(mdl_scb_fifo.analysis_export);
      scb.exp_port.connect(mdl_scb_fifo.blocking_get_export);
      o_agt.ap.connect(agt_scb_fifo.analysis_export);
      scb.act_port.connect(agt_scb_fifo.blocking_get_export);
    
    endfunction
    `endif
    View Code

    my_env.sv的主要是agent scoreboard reference_model模块的实例化,和三个tlm_analysis_fifo,然后build_phase中type_id::create()模块,配置i/oagent,scoreboard model和new三个FIFO,之后connect_phase中,connect analysis_export和blocking_get_export。

    4、my_transaction.sv

    要传送的transaction

    import uvm_pkg::*;
    `include "uvm_macros.svh"    
    `ifndef MY_TRANSACTION__SV
    `define MY_TRANSACTION__SV
    class my_transaction extends uvm_sequence_item;
        rand bit        cin;
        rand bit [31:0] a,b;
        bit      [31:0] sum_r;
        bit             cout_r;
        
    extern function new (string name="my_transaction");
        `uvm_object_utils_begin(my_transaction)
          `uvm_field_int(cin,UVM_ALL_ON)
          `uvm_field_int(a,UVM_ALL_ON)
          `uvm_field_int(b,UVM_ALL_ON)
          `uvm_field_int(sum_r,UVM_ALL_ON)
          `uvm_field_int(cout_r,UVM_ALL_ON)
        `uvm_object_utils_end
    
    endclass
    
    function my_transaction::new (string name="my_transaction");
      super.new(name);
    endfunction
    `endif
    View Code

    主要包括各种内容以及uvm_object_utils,uvm_field_int的注册,参数约束和随机化。

    5、my_sequencer.sv

    发送transaction的sequencer

    `ifndef MY_SEQUENCER__SV
    `define MY_SEQUENCER__SV
    import uvm_pkg::*;
    `include "uvm_macros.svh"    
    `include "my_transaction.sv"
    `include "my_sequence.sv"
    
    class my_sequencer extends uvm_sequencer #(my_transaction);
      extern function new (string name,uvm_component parent);
      extern virtual function void build_phase(uvm_phase phase); 
    `uvm_component_utils(my_sequencer)
    endclass
    
    function my_sequencer::new (string name,uvm_component parent);
      super.new(name,parent);
    endfunction
    
    function void my_sequencer::build_phase(uvm_phase phase);
      super.build_phase(phase);
    endfunction
    
    `endif
    View Code

    负责把transaction类型的数据传送给sequence,里面内容很简单就一个注册和new函数。

    6、my_sequence.sv

    `ifndef MY_SEQUENCE__SV
    `define MY_SEQUENCE__SV
    import uvm_pkg::*;
    `include "uvm_macros.svh"    
    `include "my_transaction.sv"
    class  my_sequence extends uvm_sequence #(my_transaction); 
      my_transaction m_trans;
      `uvm_object_utils(my_sequence)
       extern function new(string name="my_sequence");
         virtual task body();
           if(starting_phase!=null)
             starting_phase.raise_objection(this);
             repeat(10)
             begin
               `uvm_do(m_trans)
             end
             #10000;
           if(starting_phase!=null)
             starting_phase.drop_objection(this);
         endtask
    endclass
    
    function  my_sequence::new(string name="my_sequence");
      super.new(name);
    endfunction
    
    `endif
    View Code

    sequence,用于产生激励,里面的objection机制用来控制验证平台的打开与关闭,需要在drop_objection之前先raise_objection。task_body中uvm_do(my_trans),在之前和之后要starting_phase.raise_objection(this)和starting_phase.drop_objection(this);

    7、my_driver.sv

    `ifndef MY_DRIVER__SV
    `define MY_DRIVER__SV
    import uvm_pkg::*;
    `include "uvm_macros.svh"    
    `include "my_transaction.sv"
    
    class my_driver extends uvm_driver #(my_transaction);     
          
         virtual my_if vif;//to DUT
    uvm_analysis_port #(my_transaction) ap;//the data is to reference model
    
    `uvm_component_utils(my_driver)
    
    
    extern function new (string name,uvm_component parent);
    extern virtual function void build_phase(uvm_phase phase);
    
    extern virtual task  main_phase(uvm_phase phase);
    extern virtual task  drive_one_pkt(my_transaction req);
    endclass
    
    function my_driver::new (string name,uvm_component parent);
    super.new(name,parent);
    endfunction
      
    function  void my_driver::build_phase(uvm_phase phase);
    super.build_phase(phase);
    if(!uvm_config_db#(virtual my_if)::get(this,"","my_if",vif))
    `uvm_fatal("my_driver","Error in Getting interface");
    ap=new("ap",this);
    
    endfunction
    
    task my_driver::main_phase(uvm_phase phase);
     my_transaction req;
    super.main_phase(phase);
      
        while(1)
           begin 
           seq_item_port.get_next_item(req);
                         
            drive_one_pkt(req);
             ap.write(req);
          seq_item_port.item_done();
        
        end
    endtask
    
    task my_driver::drive_one_pkt(my_transaction req);
    @vif.drv_cb;
        @vif.drv_cb
        begin
            vif.drv_cb.enable<=1'b1;
            vif.drv_cb.cin<=req.cin;
            vif.drv_cb.a<=req.a;
            vif.drv_cb.b<=req.b;
        end
            @vif.drv_cb;
        @vif.drv_cb vif.drv_cb.enable<=1'b0;
    
    endtask
    
    `endif
    View Code

    首先是virtual inf和build_phase中接受接口,否则fatal,然后main_phase中while(1)循环的get_next_item(req),调用发送函数发送req,返回item_done()。

    8、my_monitor.sv

    `ifndef MY_MONITOR__SV
    `define MY_MONITOR__SV
    import uvm_pkg::*;
    `include "uvm_macros.svh"
    `include "my_transaction.sv"    
    class my_monitor extends uvm_monitor;
      virtual my_if vif;
      uvm_analysis_port #(my_transaction) ap; //  to scoreboard
      extern function new (string name,uvm_component parent);
      extern virtual function void build_phase(uvm_phase phase);
      extern virtual task  main_phase(uvm_phase phase);
      extern virtual task  receive_one_pkt(ref my_transaction get_pkt);
    `uvm_component_utils(my_monitor)
    endclass
    
    function my_monitor::new (string name,uvm_component parent);
      super.new(name,parent);
    endfunction
    
    function  void my_monitor::build_phase(uvm_phase phase);
      super.build_phase(phase);
      if(!uvm_config_db#(virtual my_if)::get(this,"","my_if",vif))
      `uvm_fatal("my_monitor","Error in Getting interface");
      ap=new("ap",this);
    endfunction
    
    task my_monitor::main_phase(uvm_phase phase);
      my_transaction tr;
      super.main_phase(phase);
      while(1) begin
        tr=new();
        receive_one_pkt(tr);
        ap.write(tr);
      end
    endtask
    
    task my_monitor::receive_one_pkt(ref my_transaction get_pkt);
      @(negedge vif.drv_cb.enable);
        get_pkt.cout_r=vif.mon_cb.cout_r;
        get_pkt.sum_r=vif.mon_cb.sum_r;
    endtask
               
    `endif
    View Code

    主要是virtual inf和analysis_port,在build_phase中接受接口,mian_phase中while(1)的调用接受函数和和ap.write(tr)。

    9、my_agent.sv

    `ifndef MY_AGENT__SV
    `define MY_AGENT__SV
    import uvm_pkg::*;
    `include "uvm_macros.svh"    
    `include "my_transaction.sv"
    `include "my_sequence.sv"
    `include "my_sequencer.sv"
    `include "my_driver.sv"
    `include "my_monitor.sv"
    
    class my_agent extends uvm_agent;
      my_sequencer sqr;
      my_driver drv;
      my_monitor mon;
      extern function new (string name,uvm_component parent);
      extern virtual function void build_phase(uvm_phase phase);
      extern virtual function void connect_phase(uvm_phase phase);
    uvm_analysis_port #(my_transaction) ap;
    `uvm_component_utils_begin(my_agent)
      `uvm_field_object(sqr,UVM_ALL_ON)
      `uvm_field_object(drv,UVM_ALL_ON)
      `uvm_field_object(mon,UVM_ALL_ON)
    `uvm_component_utils_end
    endclass
    
    function my_agent::new (string name,uvm_component parent);
      super.new(name,parent);
    endfunction
    
    function void my_agent::build_phase(uvm_phase phase);
      super.build_phase(phase);
      if(is_active==UVM_ACTIVE )
        begin 
          sqr=my_sequencer::type_id::create("sqr",this);
          drv=my_driver::type_id::create("drv",this);
        end
        else begin
          mon=my_monitor::type_id::create("mon",this);
        end
    endfunction          
     
    function void my_agent::connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      
    if(is_active==UVM_ACTIVE )
        begin 
          drv.seq_item_port.connect(sqr.seq_item_export);
          this.ap=drv.ap;
        end
        else begin
          this.ap=mon.ap;
        end
    endfunction
    
    `endif
    View Code

    含有driver和monitor,在build_phase中如果UVM_ACTIVE,就例化drv和sqr,但都例化mon,在build_phase中如果UVM_ACTIVE就链接drv和sqr的接口。

    10、interface.sv

    `ifndef MY_INTERFACE__SV
    `define MY_INTERFACE__SV
    
    interface my_if;
        logic             clk,rst   ;
        logic             cin        ; 
        logic [31:0]   a          ; 
        logic [31:0]   b          ;
        logic             enable   ; 
        wire              cout_r   ;
        wire  [31:0]   sum_r   ;
          
    clocking drv_cb @(posedge clk);
        output enable,cin,a,b;
    endclocking
    
    clocking mon_cb @(posedge clk);
        input cout_r,sum_r;      
    endclocking
          
    endinterface
    `endif
    View Code

    interface里面就是接口,用于连接DUT和driver和monitor。

    12、my_model.sv

    就是参考模型(reference_model)

    `ifndef MY_MODEL__SV
    `define MY_MODEL__SV
    import uvm_pkg::*;
    `include "uvm_macros.svh"    
    `include "my_transaction.sv"
    class my_model extends uvm_component;
      uvm_blocking_get_port #(my_transaction)  port;   //from my_driver
      uvm_analysis_port  #(my_transaction)   ap;       //to scoreboard
      extern function new (string name,uvm_component parent);
      extern virtual function void build_phase(uvm_phase phase);
      extern virtual task  main_phase(uvm_phase phase);
      extern virtual task one_pkt(ref my_transaction pkt,ref my_transaction pkt2);
    `uvm_component_utils(my_model)
    endclass
    
    function my_model::new (string name,uvm_component parent);
      super.new(name,parent);
    endfunction
    
    function void my_model::build_phase(uvm_phase phase);
      super.build_phase(phase);
      port=new("port",this);
      ap=new("ap",this);
    endfunction
    
    task my_model::main_phase(uvm_phase phase);
      my_transaction tr,tr2;
      super.main_phase(phase);
      while(1) begin
        tr2=new();
        port.get(tr);
        one_pkt(tr2,tr);
        ap.write(tr2);
      end
    endtask
    
    task my_model::one_pkt(ref my_transaction pkt,ref my_transaction pkt2);
      bit [32:0] sum_total;
      begin
        sum_total=pkt2.a+pkt2.b+pkt2.cin;
        pkt.sum_r=sum_total[31:0];
        pkt.cout_r=sum_total[32];
      end
    endtask
    `endif
    View Code

    需要进的blocking_get_port和出的analysis_port两个,在build_phase中连接他们,在main_phase中则while1的,如果get_port.get()收到,就ana_port.write()这个tr。

    13、my_scoreboard.sv

    `ifndef MY_SCOREBOARD__SV
    `define MY_SCOREBOARD__SV
    import uvm_pkg::*;
    `include "uvm_macros.svh"    
    `include "my_transaction.sv"
    class my_scoreboard extends uvm_scoreboard;
    int pre_number=0;
    my_transaction expect_queue[$];
    uvm_blocking_get_port #(my_transaction) exp_port;//from my_reference
    uvm_blocking_get_port #(my_transaction) act_port;//from my_monitor
    `uvm_component_utils(my_scoreboard)
    extern function new (string name,uvm_component parent);
    extern virtual function void build_phase(uvm_phase phase);
    extern virtual task  main_phase(uvm_phase phase);
    endclass
    
    function my_scoreboard::new (string name,uvm_component parent);
      super.new(name,parent);
    endfunction
    
    function void my_scoreboard::build_phase(uvm_phase phase);
      super.build_phase(phase);
      exp_port=new("exp_port",this);
      act_port=new("act_port",this);
    endfunction
    task my_scoreboard::main_phase(uvm_phase phase);
      my_transaction get_expect,get_actual,tmp_tran;
      bit result;
      super.main_phase(phase);
    fork
      while (1)
      begin
          exp_port.get(get_expect);
          expect_queue.push_back(get_expect);
      end
      while (1) 
      begin                   
        act_port.get(get_actual);
        if(expect_queue.size>0)begin
          tmp_tran=expect_queue.pop_front();
          result=get_actual.compare(tmp_tran);
          if(result)  begin
            pre_number=pre_number+1;
            $display("compare SUCCESSFULLy:%0d",pre_number);
          end
          else begin
            $display("compare FAILED");
            $display("the expect pkt is");  
            tmp_tran.print();
            $display("the actual pkt is");  
            get_actual.print();
          end
        end
        else  begin
          $display("ERROR::Received from DUT,while Expect Queue is empty");
          get_actual.print();
         end
      end
    join
    
    endtask                
                            
    `endif
    View Code

    是两个get_port,在build_phase中new它们,首先对于exp端,while(1)的,只要get一个tr,就要在tr_queue中push进去一个,同时对于act端,while(1)的。只要get一个tr,就要从tr_queue中pop一个出来,进行比较。这个两个是fork join的,互不影响。

    14、my_case0.sv

    `ifndef MY_CASE0__SV
    `define MY_CASE0__SV
    import uvm_pkg::*;
    `include "uvm_macros.svh"    
    `include "my_test.sv"
      
    class my_case0 extends  my_test;
      `uvm_component_utils(my_case0) 
      extern function new(string name="my_case0",uvm_component parent=null);
      extern virtual function void build_phase(uvm_phase phase);  
    endclass
    
    function my_case0::new (string name="my_case0",uvm_component parent=null);
      super.new(name,parent);
    endfunction
    
    function void my_case0::build_phase(uvm_phase phase);
      super.build_phase(phase);
      uvm_config_db#(uvm_object_wrapper)::set(this,"env.i_agt.sqr.main_phase","default_sequence",my_sequence::type_id::get());
    endfunction
    
    `endif
    View Code

    my_case0.sv扩展于my_test.sv,在my_case0.sv的build_phase中传递sequence。

    至此,本UVM验证平台的各个组件就已经完成了,接下来有时间把Makefile脚本完善好上传,并在装有vcs和Verdi的虚拟机去运行,查看波形和查看覆盖率报告。

    目前还差的东西是在top.sv里面加上生成波形的语句。

    附录:pkt.v   导入整个验证平台

    `ifndef MY_INTERFACE__SV
    `define MY_INTERFACE__SV

    `include "interface.sv"
    `include "my_env.sv"
    `include "my_test.sv"
    `include "my_case0.sv"

    `endif

    欢迎讨论:QQ:447574829

    转载于:https://www.cnblogs.com/zhangxianhe/p/11279583.html

    展开全文
  • 该文档详细介绍利用UVM验证方法学库搭建system Verilog 测试验证平台的步骤和方法,我看完后感觉很好。能够很快入门UVM,是个不错的资料,分享给大家。
  • 上次更新完《IC验证"UVM验证平台"组成》后本打算不再更新…但有人反映要继续更新…继续连载…小编考虑到一个好的连续剧不能没有结尾,所以后期会持续更新ic验证的UVM相关内容… 今天更新一个最简单的验证平台,只有...

    上次更新完《IC验证"UVM验证平台"组成》后本打算不再更新…但有人反映要继续更新…继续连载…小编考虑到一个好的连续剧不能没有结尾,所以后期会持续更新ic验证的UVM相关内容…

    今天更新一个最简单的验证平台,只有driver的验证平台…

    driver是验证平台最基本的组件,是整个验证平台数据流的源泉。本节以一个简单的DUT为例,说明一个只有driver的UVM验 证平台是如何搭建的。

    最简单的验证平台,假设有如下的DUT定义:
    在这里插入图片描述
    在这里插入图片描述

    这个DUT的功能非常简单,通过rxd接收数据,再通过txd发送出去。其中rx_dv是接收的数据有效指示,tx_en是发送的数据有 效指示。这里所有例子都是基于这个DUT。

    UVM中的driver应该如何搭建?

    UVM是一个库,在这个库中,几乎所有的东西都是使用类(class)来实现的。driver、 monitor、reference model、scoreboard等组成部分都是类。类是像SystemVerilog这些面向对象编程语言中最伟大的发明之一,是面 向对象的精髓所在。类有函数(function),另外还可以有任务(task),通过这些函数和任务可以完成driver的输出激励功能,完 成monitor的监测功能,完成参考模型的计算功能,完成scoreboard的比较功能。类中可以有成员变量,这些成员变量可以控制类 的行为,如控制driver的行为等。当要实现一个功能时,首先应该想到的是从UVM的某个类派生出一个新的类,在这个新的类中 实现所期望的功能。所以,使用UVM的第一条原则是:验证平台中所有的组件应该派生自UVM中的类。

    UVM验证平台中的driver应该派生自uvm_driver,一个简单的driver如下例所示:

    在这里插入图片描述
    在这里插入图片描述

    这个driver的功能非常简单,只是向rxd上发送256个随机数据,并将rx_dv信号置为高电平。当数据发送完毕后,将rx_dv信号 置为低电平。

    上述代码中还出现了uvm_info宏。这个宏的功能与Verilog中display语句的功能类似,但是它比display语句更加强大。它有三个参数:

    第一个参数是字符串,用于把打印的信息归类;

    第二个参数也是字符串,是具体需要打印的信息;

    第三个参数则是冗余级别。

    在验证平台中,某些信息是非常关键的,这样的信息可以设置为UVM_LOW,而有些信息可有可无,就可以设置为 UVM_HIGH,介于两者之间的就是UVM_MEDIUM。UVM默认只显示UVM_MEDIUM或者UVM_LOW的信息,uvm_info宏打印的结果如下:

    UVM_INFO my_driver.sv (20 )@48500000
    :drv[my_driver]data is drived

    在uvm_info宏打印的结果中有如下几项:

    1.UVM_INFO关键字:表明这是一个uvm_info宏打印的结果。除了uvm_info宏外,还有uvm_error宏、uvm_warning宏,后文中 将会介绍。

    2.my_driver.sv(20):指明此条打印信息的来源,其中括号里的数字表示原始的uvm_info打印语句在my_driver.sv中的行号。

    3.48500000:表明此条信息的打印时间。

    4.drv:这是driver在UVM树中的路径索引。UVM采用树形结构,对于树中任何一个结点,都有一个与其相应的字符串类型的 路径索引。路径索引可以通过get_full_name函数来获取,把下列代码加入任何UVM树的结点中就可以得知当前结点的路径索引:

    $display(“the full name of current component is: %s”, get_full_name());

    [my_driver]:方括号中显示的信息即调用uvm_info宏时传递的第一个参数。

    data is drived:表明宏最终打印的信息。

    可见,uvm_info宏非常强大,它包含了打印信息的物理文件来源、逻辑结点信息(在UVM树中的路径索引)、打印时间、对信息的分类组织及打印的信息。读者在搭建验证平台时应该尽量使用uvm_info宏取代display语句。

    定义my_driver后需要将其实例化。这里需要注意类的定义与类的实例化的区别。所谓类的定义,就是用编辑器写下:

    classs A;

    endclass

    而所谓类的实例化指的是通过new创造出A的一个实例。如:

    A a_inst;
    a_inst = new();

    类的定义类似于在纸上写下一纸条文,然后把这些条文通知给SystemVerilog的仿真器:验证平台可能会用到这样的一个类, 请做好准备工作。而类的实例化在于通过new()来通知SystemVerilog的仿真器:请创建一个A的实例。仿真器接到new的指令 后,就会在内存中划分一块空间,在划分前,会首先检查是否已经预先定义过这个类,在已经定义过的情况下,按照定义中所指 定的“条文”分配空间,并且把这块空间的指针返回给a_inst,之后就可以通过a_inst来查看类中的各个成员变量,调用成员函数/任 务等。对大部分的类来说,如果只定义而不实例化,是没有任何意义的 [3];而如果不定义就直接实例化,仿真器将会报错。

    对my_driver实例化并且最终搭建的验证平台如下:
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    第2行把uvm_macros.svh文件通过include语句包含进来。这是UVM中的一个文件,里面包含了众多的宏定义,只需要包含一 次。

    第4行通过import语句将整个uvm_pkg导入验证平台中。只有导入了这个库,编译器在编译my_driver.sv文件时才会认识其中的 uvm_driver等类名。

    第24和25行定义一个my_driver的实例并将其实例化。注意这里调用new函数时,其传入的名字参数为drv,前文介绍uvm_info 宏的打印信息时出现的代表路径索引的drv就是在这里传入的参数drv。另外传入的parent参数为null,在真正的验证平台中,这个 参数一般不是null,这里暂且使用null。

    第26行显式地调用my_driver的main_phase。在main_phase的声明中,有一个uvm_phase类型的参数phase,在真正的验证平台 中,这个参数是不需要用户理会的。本节的验证平台还算不上一个完整的UVM验证平台,所以暂且传入null。

    第27行调用finish函数结束整个仿真,这是一个Verilog中提供的函数。

    运行这个例子,可以看到“data is drived”被输出了256次。


    通知:
    本章更新后将持续更新更新…
    如:
    加入factory机制
    加入objection机制
    加入virtual inteRFace
    加入transaction
    加入env
    加入monitor
    封装成agent
    加入reference model
    加入scoreboard
    加入field_automation机制…
    如果有任何疑问请在下方评论…

    展开全文
  • 该平台使用高级验证方法学(Universal Verification Methodology,UVM搭建验证平台的主要结构,并在验证平台中使用外接Matlab作为复杂数字信号处理的参考模型。介绍了功能验证平台的主要结构和组件的设计,详细...
  • 加入factory机制 上一节《IC验证"一个简单的UVM验证平台"是如何搭建的(五)》给出了一个只有driver、使用UVM搭建的验证平台。严格来说这根本就不算是UVM验证平台,因为UVM的特性几乎一 点都没有用到。像上节中my_...
  • 上次更新完《IC验证"UVM验证平台"组成》后本打算不再更新…但有人反映要继续更新…继续连载…小编考虑到一个好的连续剧不能没有结尾,所以后期会持续更新ic验证的UVM相关内容…今天更新一个最简单的验证平台,只有...
  • 在上一节中,**《IC验证"UVM验证平台加入factory机制"(六)》**虽然输出了“main_phase is called”,但是...细心的读者可能发现,在上节的例子中,并没有如**《IC验证"一个简单的UVM验证平台"是如何搭建的(五)》*
  • uvm验证平台中穿梭各个组件之间的基本信息单元是一个被称为transaction的数据对象,也就是我们前面所说的事物对象,就是transaction。 验证工程师需要根据不同的项目对项目中的事务进行建模,事物对象的类需要从...
  • UVM入门系列(四)----通过uvm_gen脚本快速搭建一般验证平台(下) 目录UVM入门系列(四)----通过uvm_gen脚本快速搭建一般验证平台(下)前言1、reference model2、scoreboard3、function coverage总结 前言 本篇...
  • 数字ic设计验证+uvm+sv

    2020-11-19 22:05:43
    数字ic设计相关的学习书籍,包含了验证+uvm+sv学习书籍的pdf,非常实用的入门书籍;sv语法;uvm验证平台搭建
  • 本发明涉及数字芯片的功能验证和验证方法学领域,尤其是一种基于UVM验证方法学的SPI验证方法,通过验证平台搭建,随机化激励的生成,功能覆盖率的收集,响应结果的自检等操作完成对SPI的功能验证。背景技术:近年...
  • UVM入门系列(一)----通过uvm_gen脚本快速搭建一般验证平台(上) 目录UVM入门系列(一)----通过uvm_gen脚本快速搭建一般验证平台(上)前言一、reference model二、scoreboard总结 前言 本篇博文继续之前博文的...
  • UVM入门系列----通过uvm_gen脚本快速搭建一般验证平台(一) 索引UVM入门系列----通过uvm_gen脚本快速搭建一般验证平台(一)序一、uvm_gen脚本二、代码的补全1.interface1.1.i_agent_if.sv(verf/tb/agent/i)1.2.o...
  • modelsim10.4 搭建uvm平台

    千次阅读 2016-10-13 22:30:29
    如果安装的是modelsim 10.4版本的话,软件自动的将UVM的库给编译好了,生成了.dll文件,供UVM验证使用。 在modelsim的安装目录下的 UVM-1.1d/win64下,就有一个uvm_dpi.dll。 以hello_world.sv这个例子为...

空空如也

空空如也

1 2 3 4 5
收藏数 81
精华内容 32
关键字:

uvm验证平台搭建