1. 程式人生 > 其它 >電子錶設計與驗證(時鐘頻率選擇模組驗證)

電子錶設計與驗證(時鐘頻率選擇模組驗證)

技術標籤:筆記verilogsystemverilog

電子錶設計與驗證(時鐘頻率選擇模組驗證)

利用UVM搭建簡單驗證平臺

package div_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
 
class div_trans extends uvm_sequence_item;

rand int  div_n;
rand int  clk_out;
constraint divc{
                div_n inside {[10:50]};
               };

 `uvm_object_utils_begin
(div_trans) `uvm_field_int(div_n,UVM_ALL_ON) `uvm_field_int(clk_out,UVM_ALL_ON) `uvm_object_utils_end function new(string name = "div_trans"); super.new(name); endfunction endclass class div_driver extends uvm_driver #(div_trans); virtual div_inter intf; `uvm_component_utils
(div_driver) function new(string name = "div_driver", uvm_component parent); super.new(name,parent); endfunction function void set_interface(virtual div_inter intf); this.intf = intf; endfunction task run_phase (uvm_phase phase); super.run_phase(phase); fork this
.do_driver(); this.do_reset(); join endtask task do_driver(); div_trans req,rsp; forever begin repeat (100) @(posedge intf.clk) seq_item_port.get_next_item(req); this.write(req); void'($cast(rsp,req.clone())); rsp.set_sequence_id(req.get_sequence_id()); seq_item_port.item_done(rsp); end endtask task write(input div_trans t); intf.div_cb.div_n <= t.div_n; endtask task do_reset(); forever begin @(negedge intf.rstn); intf.div_cb.div_n <= 10; end endtask endclass class div_sequencer extends uvm_sequencer #(div_trans); `uvm_component_utils(div_sequencer) function new(string name = "div_sequencer", uvm_component parent); super.new(name,parent); endfunction endclass class div_sequence extends uvm_sequence #(div_trans); virtual div_inter intf; rand int div_n = -1; rand int clk_out = -1; `uvm_object_utils_begin(div_trans) `uvm_field_int(div_n,UVM_ALL_ON) `uvm_field_int(clk_out,UVM_ALL_ON) `uvm_object_utils_end function new (string name = "div_sequence"); super.new(name); endfunction function void set_interface (virtual div_inter intf); this.intf = intf; endfunction task body(); repeat (50) gen(); endtask task gen(); div_trans req,rsp; `uvm_do_with(req, { local::div_n >= 0 -> div_n == local::div_n; local::clk_out >= 0 -> clk_out == local::clk_out; }) get_response(rsp); endtask endclass typedef struct packed { int clk_out; } div_mon; class div_monitor extends uvm_monitor; local virtual div_inter intf; `uvm_component_utils(div_monitor) function new(string name = "div_monitor", uvm_component parent); super.new(name,parent); endfunction function void set_interface (virtual div_inter intf); this.intf = intf; endfunction task run_phase (uvm_phase phase); super.run_phase(phase); this.do_mon(); endtask task do_mon(); div_mon mon; forever begin @(posedge intf.clk); mon.clk_out = intf.div_cb.clk_out; `uvm_info(get_type_name(),$sformatf("monitored TIME hour 'h%8x ",mon.clk_out ),UVM_HIGH) end endtask endclass class div_agent extends uvm_agent; virtual div_inter intf; div_driver driver; div_monitor monitor; div_sequencer sequencer; `uvm_component_utils(div_agent) function new (string name = "div_agent", uvm_component parent); super.new(name,parent); endfunction function void build_phase (uvm_phase phase); super.build_phase(phase); driver = div_driver::type_id::create("driver",this); monitor = div_monitor::type_id::create("monitor",this); sequencer = div_sequencer::type_id::create("sequencer",this); endfunction function void connect_phase(uvm_phase phase); super.connect_phase(phase); driver.seq_item_port.connect(sequencer.seq_item_export); this.set_interface(intf); endfunction function void set_interface(virtual div_inter intf); this.intf = intf; driver.set_interface(intf); monitor.set_interface(intf); endfunction endclass class div_test extends uvm_test; div_agent agent; virtual div_inter intf; `uvm_component_utils(div_test) function new (string name = "div_test", uvm_component parent); super.new(name,parent); endfunction function void build_phase (uvm_phase phase); super.build_phase(phase); agent = div_agent::type_id::create("agent",this); if(!uvm_config_db#(virtual div_inter)::get(this,"","intf",intf)) begin `uvm_fatal("GETINTF","cannot get intf handle from config DB") end endfunction function void set_interface(virtual div_inter intf); this.intf = intf; agent.set_interface(intf); endfunction function void connect_phase (uvm_phase phase); super.connect_phase(phase); this.set_interface(intf); endfunction task run_phase (uvm_phase phase); div_sequence seq; phase.raise_objection(this); seq = new("seq"); seq.start(agent.sequencer); phase.drop_objection(this); endtask endclass endpackage

頂層模組

`timescale 1ns/1ps
import uvm_pkg::*;
`include "uvm_macros.svh"

interface div_inter(input clk, input rstn);
  logic clk_out;
  logic [31:0]div_n;
  clocking div_cb @(posedge clk);
    default input #1ns output #1ns;
    input clk_out;
    output div_n;
  endclocking
endinterface

module div_tb();
logic clk;
logic rstn;

  int_div dut(
              .clk     (clk)
             ,.rstn    (rstn)
             ,.clk_out (intf.clk_out)
             ,.div_n   (intf.div_n)
            );

initial begin
  clk <= 0;
  forever begin
    #5 clk <= ~clk;
  end
end

initial begin
  rstn <= 0;
  repeat (10) @(posedge clk)begin
    rstn <= 1;
  end
end

import div_pkg::*;

div_inter intf(.*);

initial begin
  uvm_config_db #(virtual div_inter)::set(uvm_root::get(),"uvm_test_top","intf",intf);
  run_test("div_test");
end
endmodule

模擬結果在這裡插入圖片描述