UVM实战--加法器

这篇具有很好参考价值的文章主要介绍了UVM实战--加法器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

这里以UVM实战(张强)第二章为基础修改原有的DUT,将DUT修改为加法器,从而修改代码以使得更加深入的了解各个组件的类型和使用。

一. 组件的基本框架

UVM实战--加法器
和第二章的平台的主要区别点
(1)有两个transaction,一个为transaction_i,一个为transaction_o,由于DUT的输入输出值并不相同,输入为a,b,cin,输出为sum,cout。所以这里使用两个transaction,尤为注意my_model的输出需要使用transaction_o来运输。
(2)使用了两个monitor,一个为monitor_i,一个为monitor_o
(3)使用了两个agent,一个为agent_i,一个为agent_o,这样写is_active就不需要使用了

二.各个部分代码详解

2.1 DUT

module dut(
	input clk,
	input rst_n,
	
	input [7:0] a,
	input [7:0] b,
	input cin,
	input enable,
	
	output reg [7:0] sum,
	output reg cout
);

always @ (posedge clk or negedge rst_n)begin
if(!rst_n)begin
	sum <= 8'b0;
	cout <= 1'b0;
end
else if (enable)
	{cout,sum} <= a + b + cin;
else begin
	sum <= sum;
	cout <= cout;
end
end

2.2 my_driver

`ifndef MY_DRIVER__SV
`define MY_DRIVER__SV
class my_driver extends uvm_driver;
	virtual my_if vif;
	
	`uvm_component_utils(my_driver)
	function new(string name = "my_driver",uvm_component parent = null);
		super.new(name,parent);
	endfunction
	
	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))
			`uvm_fatal("my_driver","virtual interface must be set for vif!!!")
	endfunction

	extern task mian_phase(uvm_phase phase);
	extern task drive_one_pkt(my_transaction_i tr);
endclass

task my_driver::mian_phase(uvm_phase phase);
	vif.a <= 8'b0;
	vif.b <= 8,b0;
	vif.cin <= 1'b0;
	vif.enable <= 1'b0;
	while(1)begin
		seq_item_port.get_next_item(req);
		drive_one_pkt(req);
		seq_item_port.item_done();
	end
endtask
//(1)如何理解
task my_driver::drive_one_pkt(my_transcation_i tr);
	uvm_info("my_driver","begin to dirve one pkt",UVM_LOW);
	@(posedge vif.clk);
	vif.a <= tr.a;
	vif.b <= tr.b;
	vif.cin <= tr.cin;
	vif.enable <= 1'b1;
	`uvm_info("my_driver","end to drive one pkt",UVM_LOW);
endtask
`endif

(1)如何理解
这里只传递一个a,b,cin的值

2.3 my_transaction_i

`ifdenf MY_TRANSACTION_I__SV
`define MY_TRANSACTION_I__SV

class my_transaction_i extends uvm_sequence_item;
	
	rand bit [7:0] a;
	rand bit [7:0] b;
	rand bit cin;
	
	`uvm_object_utils_begin(my_transaction_i)
		`uvm_field_int(a,UVM_ALL_ON)
		`uvm_field_int(b,UVM_ALL_ON)
		`uvm_field_int(cin,UVM_ALL_ON)
	`uvm_object_utils_end

	function new(string name = "my_transaction_i");
		super.new();
	endfunction
endclass
`endif

2.4 my_transaction_o

`idndef MY_TRANSACTION_O__SV
`define MY_TRANSACTION_O__SV

class my_transaction_o extends uvm_sequence_item;
	
	 bit [7:0] sum;
	 bit cout;

	function new(string name = "my_transaction_o")
		super.new();
	endfunction
endclass
`endif

2.5 my_sequencer

`ifndef MY_SEQUENCER__SV
`define MY_SEQUENCER__SV

class my_sequencer extends uvm_sequencer #(my_transaction_i);
	
	function new(string name,uvm_component parent);
		super.new(name,parent);
	endfunction

	`uvm_component_utils(my_sequencer)
endclass
`endif

2.6 my_if

`ifndef MY_IF__SV
`define MY_IF__SV

interface my_if(input clk, input rst_n);

	logic [7:0] a;
	logic [7:0] b;
	logic cin;
	logic enable;
	logic [7:0] sum;
	logic cout;
	
endinterface
`endif

2.7 my_monitor_i

`ifndef MY_MONITOR_I__SV
`define MY_MONITOR_I__SV

class my_monitor_i extends uvm_monitor;
	
	virtual my_if vif;
	
	uvm_analysis_port #(my_transaction) ap;

	`uvm_component_utils(my_monitor_i)
	function new(string name = "monitor_i",uvm_component parent = null);
		super.new(name,parent);
	endfunction
	
	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))
			`uvm_fatal("my_monitor","virtual interface must be set for vif!!!")
		ap = new("ap",this);
	endfunction
	
	extern task main_phase(uvm_phase phase);
	extern task drive_one_pkt(my_transaction_i tr);
endclass

task my_monitor::main_phase(uvm_phase phase);
	my_transaction_i tr;
	while(1) begin
		tr.new("tr");
		collect_one_pkt(tr);
		ap.write(tr);
	end
endtask
		
task my_monitor::collcet_one_pkt(my_transaction_i tr);
	`uvm_info("my_monitor","begin to collcet one pkt",UVM_LOW);	
	@(posedge vif.clk);
	tr.a <= vif.a;
	tr.b <= vif.b;
	tr.cin <= vif.cin;
	tr.enable <= 1'b1;
	`uvm_info("my_monitor","end to collcet one pkt",UVM_LOW);
endtask
`endif

2.8 my_monitor_o

`ifndef MY_MONITOR_O__SV
`define MY_MONITOR_O__SV
class my_monitor extends uvm_monitor_o
	
	virtual my_if vif;
	
	uvm_analysis_port #(my_transaction) ap;
	
	`uvm_component_port #(my_transaction) ap;
	function new(string name = "my_monitor_o",uvm_component parent = null);
		super.new(name,parent);
	endfunction

	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))
			`uvm_fatal("my_monitor","virtual interface must be set for vif!!!")
		ap = new("ap",this);
	endfunction
		
	extern task main_phase(uvm_phase phase);
	extern task collcet_one_pkt(my_transaction_i tr);
endclass

task my_monitor::main_phase (uvm_phase phase);
	my_transaction_o tr;
	while(1) begin
		tr = new("tr")
		collcet_one_pkt(tr);
		ap.write(tr);
	end
endtask

task my_monitor::collcet_one_pkt(my_transction_o tr);
	`uvm_info("my_monitor_o","begin to collcet one pkt",UVM_LOW);
	@(posedge vif.clk)
	tr.sum <= vif.sum;
	tr.cout <= vif.cout;
	`uvm_info("my_monitor_o","end to collcet one pkt",UVM_ALL);
endtask
`endif

2.9 my_agent_i

`ifndef MY_AGENT_I__SV
`define MY_AGENT_I__SV

class my_agent_i extends uvm_agent;
	my_sequencer sqr;
	my_driver    drv;
	my_monitor_i mon_i;
	
	`uvm_analysis_port #(my_transaction_i) ap;
	
	function new(string name,uvm_component parent);
		super.new(name,parent);
	endfunction

	extern virtual function void build_phase(uvm_phase phase);
	extern virtual function void conncet_phase(uvm_phase phase);
	
	`uvm_component_utils(my_agent_i)
endclass

function void my_agent_i::build_phase(uvm_phase phase);
	super.build_phase(phase);
	sqr = my_sequencer::type_id::create("sqr",this);
	drv = my_driver::type_id::create("drv",this);
	mon_i = my_monitor_i::type_id::create("mon_i",this);
endfunction

function void my_agent_i::conncet_phase(uvm_phase phase);
	super.conncet_phase(phase);
	drv_seq_item_port.conncet(sqr.seq_item_export);
	ap = mon.ap;
endfunction
`endif

2.10 my_agent_o

`ifndef MY_AGENT_O__SV
`define MY_AGENT_O__SV

class my_agent_o extends uvm_agent;
	my_sequencer sqr;
	my_driver    drv;
	my_monitor_o mon_o;

	`uvm_analysis_port #(my_transaction_o) ap;
	
	function new(string name,uvm_component parent);
		super.new(name,parent);
	endfunction
	
	extern virtual function void build_phase(uvm_phase phase);
	extern virtual function void conncet_phase(uvm_phase phase);
	
	`uvm_component_utils(my_agent_o)
endclass

function void my_agent_o::build_phase(uvm_phase phase);
	super.build_phase(phase);
	mon_o = my_monitor_o::type_id::create("mon",this);
endfunction

function void my_agent_o::conncet_phase(uvm_phase phase);
	super.conncet_phase(phase);
	ap = mon.ap;
endfunction
`endif

2.11 my_model

`ifndef MY_MODEL__SV
`define MY_MODEL__SV

class my_model extends uvm_component;
	
	uvm_blocking_get_port #(my_transaction) port;
	uvm_analysis_port #(my_transaction) ap;
	
	
	extern function new(string name,uvm_component parent);
	extern function void build_phase(uvm_phase phase);
	extern virtual task main_phase(uvm_phase phase);
	`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_i tr;
	my_transaction_o tr2;
	bit [8:0] sum_total;
	super.main_phase(phase);
	while(1)begin
		port.get(tr);
		tr2 = new("tr2");
		sum_total = tr.a+tr.b+tr.cin;
		tr2.sum = sum_total[7:0];
		tr2.cout = sum_total[8];
		`uvm_info("my_model", "get transactions, add and print it:", UVM_LOW)
      	tr2.print();
		ap.write(tr2);
	end
endtask
`endif

2.12 my_scoreboard

`ifndef MY_SCOREBOARD__SV
`define MY_SCOREBOARD__SV
class my_scoreboard extends uvm_scoreboard;
   my_transaction  expect_queue[$];
   uvm_blocking_get_port #(my_transaction_i)  exp_port;
   uvm_blocking_get_port #(my_transaction_o)  act_port;
   `uvm_component_utils(my_scoreboard)

   extern function new(string name, uvm_component parent = null);
   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 = null);
   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_i  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 
               `uvm_info("my_scoreboard", "Compare SUCCESSFULLY", UVM_LOW);
            end
            else begin
               `uvm_error("my_scoreboard", "Compare FAILED");
               $display("the expect pkt is");
               tmp_tran.print();
               $display("the actual pkt is");
               get_actual.print();
            end
         end
         else begin
            `uvm_error("my_scoreboard", "Received from DUT, while Expect Queue is empty");
            $display("the unexpected pkt is");
            get_actual.print();
         end 
      end
   join
endtask
`endif

2.13 base_test

`ifndef BASE_TEST__SV
`define BASE_TEST__SV

class base_test extends uvm_test;

   my_env         env;
   
   function new(string name = "base_test", uvm_component parent = null);
      super.new(name,parent);
   endfunction
   
   extern virtual function void build_phase(uvm_phase phase);
   extern virtual function void report_phase(uvm_phase phase);
   `uvm_component_utils(base_test)
endclass


function void base_test::build_phase(uvm_phase phase);
   super.build_phase(phase);
   env  =  my_env::type_id::create("env", this); 
endfunction

function void base_test::report_phase(uvm_phase phase);
   uvm_report_server server;
   int err_num;
   super.report_phase(phase);

   server = get_report_server();
   err_num = server.get_severity_count(UVM_ERROR);

   if (err_num != 0) begin
      $display("TEST CASE FAILED");
   end
   else begin
      $display("TEST CASE PASSED");
   end
endfunction

`endif

2.14 my_env

`ifndef MY_ENV__SV
`define MY_ENV__SV

class my_env extends uvm_env;

   my_agent_i    i_agt;
   my_agent_o    o_agt;
   my_model      mdl;
   my_scoreboard scb;
   
   uvm_tlm_analysis_fifo #(my_transaction_o) agt_scb_fifo;
   uvm_tlm_analysis_fifo #(my_transaction_i) agt_mdl_fifo;
   uvm_tlm_analysis_fifo #(my_transaction_o) mdl_scb_fifo;
   
   function new(string name = "my_env", uvm_component parent);
      super.new(name, parent);
   endfunction

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      i_agt = my_agent_i::type_id::create("i_agt", this);
      o_agt = my_agent_o::type_id::create("o_agt", this);

      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

   extern virtual function void connect_phase(uvm_phase phase);
   
   `uvm_component_utils(my_env)
endclass

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

2.15 my_case0

`ifndef MY_CASE0__SV
`define MY_CASE0__SV
class case0_sequence extends uvm_sequence #(my_transaction_i);
   my_transaction_i m_trans;

   function  new(string name= "case0_sequence");
      super.new(name);
   endfunction 
   
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (10) begin
         `uvm_do(m_trans)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask

   `uvm_object_utils(case0_sequence)
endclass


class my_case0 extends base_test;

   function new(string name = "my_case0", uvm_component parent = null);
      super.new(name,parent);
   endfunction 
   extern virtual function void build_phase(uvm_phase phase); 
   `uvm_component_utils(my_case0)
endclass


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", 
                                           case0_sequence::type_id::get());
endfunction

`endif

top_tb

`timescale 1ns/1ps
`include "uvm_macros.svh" 

import uvm_pkg::*; 
`include "my_if.sv"
`include "my_transaction_i.sv"
`include "my_transaction_o.sv"
`include "my_sequencer.sv"
`include "my_driver.sv"
`include "my_monitor_i.sv"
`include "my_monitor_o.sv"
`include "my_agent_i.sv"
`include "my_agent_o.sv"
`include "my_model.sv"
`include "my_scoreboard.sv"
`include "my_env.sv"
`include "base_test.sv"
`include "my_case0.sv"

module top_tb;

reg clk;
reg rst_n;
reg [7:0] a;
reg [7:0] b;
reg cin;
reg enable;
wire [7:0] sum;
wire cout;

my_if input_if(clk, rst_n);
my_if output_if(clk, rst_n);

dut my_dut(.clk(clk),                
           .rst_n(rst_n),
           .a(input_if.a),
           .b(input_if.b),
           .cin(input_if.cin),
           .enable(input_if.enable)
           .sum(output_if.sum),
           .cout(output_if.cout));

initial begin           
   clk = 0;
   forever begin
      #100 clk = ~clk;
   end
end

initial begin
   rst_n = 1'b0;
   #1000;
   rst_n = 1'b1;
end

initial begin           
   run_test();
end

initial begin
	a = 8'b00000000;
	b = 8'b00000000;
	cin = 1'b0;
	enable = 1'b1;
end

initial begin
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.drv", "vif", input_if);
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.mon_i", "vif", input_if);
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.o_agt.mon_o", "vif", output_if);
end

endmodule

三.调试

注意:

这里我后来发现忽略了一些问题,这个问题我原本以为是个小问题,可后来当在这段代码中加入寄存器之后,发现这个问题出现了三次。
UVM_ERROR my_scorboard.sv(52) @ 100000: uvm_test_top.env.scb [my_scoreboard] Received from DUT,while Except Queue is empty
这个问题放在这里,这周有时间的话解决,读者会的可直接评论。

分析:

原因:monitor_i和monitor_o都没有加使能控制,这使得monitor_o会上来就采样,但是此时driver并没有采样,那么导致在scoreboard里面无法进行比较,从而导致出错。

解决方法:

1)使用两个使能:enable,enable1,enable控制monitor输入,enable1控制monitor输出。
(2)对于enable的赋值,在driver中进行,对于enable1的赋值,在DUT中进行,也就是结果输出之后,enable1拉高。

修改后的一些代码

3.1 DUT

module dut(
	input clk,
	input rst_n,
	input [7:0] a,
	input [7:0] b,
	input cin,
	input enable,
	
	output reg cout,
	output reg [7:0] sum,
	output reg enable1
);

always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		sum <= 8'b0;
		cout <= 1'b0;
	end
	else if(enable)begin
		{cout,sum} <= a+b+cin;
		enable1 <= 1'b1;
	end
	else begin
		sum <= sum;
		cout <= cout;
	end
end

endmodule

3.2 my_driver.sv

`ifndef MY_DRIVER__SV
`define MY_DRIVER__SV
class my_driver extends uvm_driver;
	virtual my_if vif;
	
	`uvm_component_utils(my_driver)
	function new(string name = "my_driver",uvm_component parent = null);
		super.new(name,parent);
	endfunction
	
	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))
			`uvm_fatal("my_driver","virtual interface must be set for vif!!!")
	endfunction

	extern task mian_phase(uvm_phase phase);
	extern task drive_one_pkt(my_transaction_i tr);
endclass

task my_driver::mian_phase(uvm_phase phase);
	vif.a <= 8'b0;
	vif.b <= 8,b0;
	vif.cin <= 1'b0;
	vif.enable <= 1'b0;
	while(!vif.rst_n)begin
		@(posedge vif.clk);
	end
	while(1)begin
		seq_item_port.get_next_item(req);
		drive_one_pkt(req);
		seq_item_port.item_done();
	end
endtask
//(1)如何理解
task my_driver::drive_one_pkt(my_transcation_i tr);
	uvm_info("my_driver","begin to dirve one pkt",UVM_LOW);
	@(posedge vif.clk);
	vif.a <= tr.a;
	vif.b <= tr.b;
	vif.cin <= tr.cin;
	vif.enable <= 1'b1;
	@(posedge vif.clk)
	vif.enable <= 1'b0;
	`uvm_info("my_driver","end to drive one pkt",UVM_LOW);
endtask
`endif

3.3 my_monitor_i.sv

`ifndef MY_MONITOR_I__SV
`define MY_MONITOR_I__SV

class my_monitor_i extends uvm_monitor;
	
	virtual my_if vif;
	
	uvm_analysis_port #(my_transaction_i) ap;

	`uvm_component_utils(my_monitor_i)
	function new(string name = "monitor_i",uvm_component parent = null);
		super.new(name,parent);
	endfunction
	
	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))
			`uvm_fatal("my_monitor","virtual interface must be set for vif!!!")
		ap = new("ap",this);
	endfunction
	
	extern task main_phase(uvm_phase phase);
	extern task drive_one_pkt(my_transaction_i tr);
endclass

task my_monitor::main_phase(uvm_phase phase);
	my_transaction_i tr;
	while(1) begin
		tr.new("tr");
		collect_one_pkt(tr);
		ap.write(tr);
	end
endtask
		
task my_monitor::collcet_one_pkt(my_transaction_i tr);
while(1) begin
	@(posedge vif.clk);
	if(vif.enable) break;
end
	`uvm_info("my_monitor","begin to collcet one pkt",UVM_LOW);	
	@(posedge vif.clk);
	tr.a <= vif.a;
	tr.b <= vif.b;
	tr.cin <= vif.cin;
	`uvm_info("my_monitor","end to collcet one pkt",UVM_LOW);
endtask
`endif

3.4 my_monitor_o.sv

`ifndef MY_MONITOR_O__SV
`define MY_MONITOR_O__SV
class my_monitor_o extends uvm_monitor
	
	virtual my_if vif;
	
	uvm_analysis_port #(my_transaction_o) ap;
	
	`uvm_component_port #(my_transaction_o) ap;
	function new(string name = "my_monitor_o",uvm_component parent = null);
		super.new(name,parent);
	endfunction

	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))
			`uvm_fatal("my_monitor","virtual interface must be set for vif!!!")
		ap = new("ap",this);
	endfunction
		
	extern task main_phase(uvm_phase phase);
	extern task collcet_one_pkt(my_transaction_i tr);
endclass

task my_monitor::main_phase (uvm_phase phase);
	my_transaction_o tr;
	while(1) begin
		tr = new("tr")
		collcet_one_pkt(tr);
		ap.write(tr);
	end
endtask

task my_monitor::collcet_one_pkt(my_transction_o tr);
while(1) begin
	@(posedge vif.clk)
	if(vif.enable1) break;
end
	`uvm_info("my_monitor_o","begin to collcet one pkt",UVM_LOW);
	@(posedge vif.clk)
	tr.sum <= vif.sum;
	tr.cout <= vif.cout;
	`uvm_info("my_monitor_o","end to collcet one pkt",UVM_ALL);
endtask
`endif

3.5 my_if

`ifndef MY_IF__SV
`define MY_IF__SV

interface my_if(input clk, input rst_n);

	logic [7:0] a;
	logic [7:0] b;
	logic cin;
	logic enable;
	wire enable1;
	wire [7:0] sum;
	wire cout;
	
endinterface
`endif

3.6 top_tb

`timescale 1ns/1ps
`include "uvm_macros.svh" 

import uvm_pkg::*; 
`include "my_if.sv"
`include "my_transaction_i.sv"
`include "my_transaction_o.sv"
`include "my_sequencer.sv"
`include "my_driver.sv"
`include "my_monitor_i.sv"
`include "my_monitor_o.sv"
`include "my_agent_i.sv"
`include "my_agent_o.sv"
`include "my_model.sv"
`include "my_scoreboard.sv"
`include "my_env.sv"
`include "base_test.sv"
`include "my_case0.sv"

module top_tb;

reg clk;
reg rst_n;
reg [7:0] a;
reg [7:0] b;
reg cin;
reg enable;
wire enable1
wire [7:0] sum;
wire cout;

my_if input_if(clk, rst_n);
my_if output_if(clk, rst_n);

dut my_dut(.clk(clk),                
           .rst_n(rst_n),
           .a(input_if.a),
           .b(input_if.b),
           .cin(input_if.cin),
           .enable(input_if.enable),
           .enable1(output_if.enable1),
           .sum(output_if.sum),
           .cout(output_if.cout));

initial begin           
   clk = 0;
   forever begin
      #100 clk = ~clk;
   end
end

initial begin
   rst_n = 1'b0;
   #1000;
   rst_n = 1'b1;
end

initial begin           
   run_test();
end

initial begin
	a = 8'b00000000;
	b = 8'b00000000;
	cin = 1'b0;
	enable = 1'b1;
end

initial begin
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.drv", "vif", input_if);
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.mon_i", "vif", input_if);
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.o_agt.mon_o", "vif", output_if);
end

endmodule

思考

将DUT我们换一下,看看是否同样可行

module dut(
	input clk,
	input rst_n,
	input [7:0] a,
	input [7:0] b,
	input cin,
	input enable,
	
	output reg cout,
	output reg[7:0] sum,
	output reg enable1
);

always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		sum <= 8'b0;
		cout <= 1'b0;
		enable <= 1'b0;
	end
	else begin
		{cout,sum} <= a+b+cin;
		enable1 <= enable;
	end
end

endmodule

答案是运行结果是相同,至于为什么呢会有这个想法呢,主要来自于UVM实战第二章例子的想法,那么为什么可行我说不清楚,有明白的可以评论一下。文章来源地址https://www.toymoban.com/news/detail-457149.html

到了这里,关于UVM实战--加法器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【FPGA】Verilog:BCD 加法器的实现 | BCD 运算 | Single-level 16 bit 超前进位加法器 | 2-level 16-bit 超前进位加法器

    0x00 BCD 运算 在 BCD 中,使用4位值作为操作数,但由于只表示 0 到 9 的数字,因此只使用 0000 到 1001 的二进制数,而不使用 1010 到 1111 的二进制数(don\\\'t care)。 因此,不能使用常规的 2\\\'complement 运算来计算,需要额外的处理:如果 4 位二进制数的运算结果在 1010 到 1111 的范围

    2024年02月05日
    浏览(48)
  • 【FPGA】Verilog:二进制并行加法器 | 超前进位 | 实现 4 位二进制并行加法器和减法器 | MSI/LSI 运算电路

    0x00 并行加法器和减法器 如果我们要对 4 位加法器和减法器进行关于二进制并行运算功能,可以通过将加法器和减法器以 N 个并行连接的方式,创建一个执行 N 位加法和减法运算的电路。 4 位二进制并行加法器 4 位二进制并行减法器

    2024年02月05日
    浏览(58)
  • 加法器电路

    图3 图三中,由虚短知: V- = V+ = 0 ……a 由虚断及基尔霍夫定律知,通过R2与R1的电流之和等于通过R3的电流,故 (V1 – V-)/R1 + (V2 – V-)/R2 = (V- –Vout)/R3 ……b 代入a式,b式变为V1/R1 + V2/R2 = Vout/R3 如果取R1=R2=R3,则上式变为-Vout=V1+V2,这就是传说中的加法器了。 图4 请看图四。因为

    2024年02月14日
    浏览(36)
  • Quartus 入门 —— 加法器

    这里使用的 intel 的 芯片为 EP4CE115F29C7 的开发板,软件使用的是 Quartus(Quartus Prime 18.1) 的版本 首先点击新建项目: 下面我们就直接点击下一步到芯片选择部分: 这里我们需要选择 Cyclone IV E 的 EP4CE115F29C7 芯片 然后这里我们选择使用 ModelSim-Altera 进行仿真,然后我们直接点击下

    2024年02月08日
    浏览(40)
  • 运算放大电路(三)-加法器

    加法器 由虚短知: V- = V+ = 0 ……a 由虚断及基尔霍夫定律知,通过R2与R1的电流之和等于通过R3的电流,故 (V1 – V-)/R1 + (V2 – V-)/R2 = (Vout – V-)/R3 ……b 代入a式,b式变为 V1/R1 + V2/R2 = Vout/R3 如果取 R1=R2=R3 则上式变为 Vout=V1+V2 这就是传说中的加法器了。 因为虚断,运放同向端没

    2024年02月04日
    浏览(56)
  • Verilog实现超前进位加法器

    在CPU等对性能要求较高的电路中,一般都会采用超前进位加法器,因为超前进位加法器的延时相对来说比较小。下面讲述超前进位加法器的原理: 我们知道,一个三输入,二输出的全加器,其逻辑关系为 S = A ⊕ B ⊕ C i n S=Aoplus Boplus C_{in} S = A ⊕ B ⊕ C in ​ C o u t = ( A B ) ∣

    2023年04月08日
    浏览(40)
  • 使用FPGA实现逐级进位加法器

    逐级进位加法器就是将上一位的输出作为下一位的进位输入,依次这样相加。下面以一个8位逐级进位加法器给大家展示。 我增加了电路结构,应该很容易理解吧。 下面我也列举了一位加法器,可以看下。 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity adder1 is

    2024年04月23日
    浏览(34)
  • 用加法器实现补码的加/减运算

    目录 1.原码的加减运算 (1)原码的加/减法运算 (2)溢出判断 (3)符号扩展 2.加法器原理 3.加法器实现补码的加减运算 1.原码的加减运算 (1)原码的加/减法运算 正+正---绝对值做加法,结果为正 负+负---绝对值做加法,结果为负 正+负---绝对值大的减绝对值小的,符号同绝

    2024年01月18日
    浏览(52)
  • 用面包板搭建4bit加法器

    4bit加法器是一种数字电路,用于将两个 4 bit的二进制数相加,生成一个 4 bit的和。实验目的如下: (1)学习数字电路的基本概念和实现方法 (2)熟悉 4 bit加法器的设计和实现原理 (3)学会使用数字电路仿真工具模拟和验证电路的功能 (4)使用晶体管搭建一个4bit加法器电

    2024年02月03日
    浏览(43)
  • 2-1、地址加法器CS:IP

    语雀原文链接 一个CPU由运算器、控制器、寄存器等器件构成,这些器件靠内部总线相连。 运算器进行信息处理 寄存器进行信息储存 控制器控制各种器件进行工作 内部总线连接各种器件,在它们之间进行数据的传递 内部总线实现CPU内部各个器件之间的联系,外部总线实现

    2024年02月04日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包