`timescale 1ns/1ps
`define PKT_RECV_IDLE 0
`define PKT_RECV_START 1
`define PKT_RECV_RECV 2
`define PKT_RECV_VALID 3
`define PKT_RECV_END 4
`define PKT_SENT_IDLE 0
`define PKT_SENT_VALID 1
`define PKT_SENT_END 2
`define PKT_SENT_FIN 3
module dut(
clk ,
rst_n ,
addr ,
din ,
rw ,
enable ,
dout ,
txd ,
tx_vld ,
rxd ,
rx_vld
);
input clk ;
input rst_n ;
input [7:0 ] addr ;
input [31:0] din ;
input rw ;
input enable ;
output [31:0] dout ;
input [7:0 ] rxd ;
input rx_vld ;
output [7:0 ] txd ;
output tx_vld ;
wire clk ;
wire rst_n ;
wire [7:0 ] addr ;
wire [31:0] din ;
wire rw ;
wire enable ;
reg [31:0] dout ;
wire [7:0 ] rxd ;
wire rx_vld ;
reg [7:0 ] txd ;
reg tx_vld ;
wire write ;
wire read ;
wire [31:0] config_reg ;
reg pkt_en;
reg [31:0] min_pkt_size ;
reg [31:0] max_pkt_size ;
reg [7:0 ] mem[0:512];
reg [9:0 ] mem_wr_ptr;
reg [9:0 ] mem_rd_ptr;
reg [9:0 ] need_to_sent_pkt_size;
reg [9:0 ] sending_pkt_size;
reg [2:0 ] pkt_recv_status;
reg [1:0 ] pkt_sent_status;
reg new_pkt;
reg one_pkt_sent;
reg [1:0 ] pkt_no;
assign write = (rw == 1'b0 && enable == 1'b1);
assign read = (rw == 1'b1 && enable == 1'b1);
assign config_reg = {31'h0, pkt_en};
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
pkt_en <= 1'b0;
end
else begin
if((addr == 8'h0) && (write == 1'b1)) begin
pkt_en <= din[0];
end
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
min_pkt_size <= 32'd64;
end
else begin
if((addr == 8'h4) && (write == 1'b1)) begin
if((din[9:0] >= 64) && (din[9:0] < max_pkt_size[9:0]))
min_pkt_size[9:0] <= din[9:0];
end
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
max_pkt_size <= 32'd512;
end
else begin
if((addr == 8'h8) && (write == 1'b1)) begin
if((din[9:0] <= 512) && (din[9:0] > min_pkt_size[9:0]))
max_pkt_size[9:0] <= din[9:0];
end
end
end
always @(*) begin
case(addr)
8'h0 : dout = config_reg;
8'h4 : dout = min_pkt_size;
8'h8 : dout = max_pkt_size;
default : dout = 32'h0;
endcase
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
pkt_recv_status <= 'h0;
pkt_recv_status <= `PKT_RECV_IDLE;
mem_wr_ptr <= 8'h0;
new_pkt <= 1'b0;
end
else begin
case(pkt_recv_status)
`PKT_RECV_IDLE: begin
mem_wr_ptr <= 8'h0;
if((rx_vld == 1'b1) && (pkt_en == 1'b1)) begin
mem_wr_ptr <= mem_wr_ptr + 1;
mem[mem_wr_ptr] <= rxd;
if(rxd != 8'h55) begin
pkt_recv_status <= `PKT_RECV_END;
end
else begin
pkt_recv_status <= `PKT_RECV_START;
end
end
end
`PKT_RECV_START: begin
if(rx_vld == 1'b1) begin
mem_wr_ptr <= mem_wr_ptr + 1;
mem[mem_wr_ptr] <= rxd;
if(rxd != 8'hd5) begin
pkt_recv_status <= `PKT_RECV_END;
end
else begin
pkt_recv_status <= `PKT_RECV_RECV;
end
end
else begin
pkt_recv_status <= `PKT_RECV_END;
end
end
`PKT_RECV_RECV: begin
if(rx_vld == 1'b1) begin
if(mem_wr_ptr == max_pkt_size) begin
pkt_recv_status <= `PKT_RECV_END;
end
else begin
mem_wr_ptr <= mem_wr_ptr + 1;
pkt_recv_status <= `PKT_RECV_RECV;
mem[mem_wr_ptr] <= rxd;
end
end
else begin
pkt_recv_status <= `PKT_RECV_VALID;
end
end
`PKT_RECV_VALID: begin
if(mem_wr_ptr >= min_pkt_size) begin
new_pkt <= 1'b1;
need_to_sent_pkt_size <= mem_wr_ptr;
end
pkt_recv_status <= `PKT_RECV_END;
end
`PKT_RECV_END: begin
new_pkt <= 1'b0;
if(rx_vld == 1'b0) begin
pkt_recv_status <= `PKT_RECV_IDLE;
end
end
default : begin
end
endcase
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
pkt_sent_status <= `PKT_SENT_IDLE;
pkt_sent_status <= 'h0;
mem_rd_ptr <= 'h0;
sending_pkt_size <= 'h0;
txd <= 'h0;
tx_vld <= 1'b0;
one_pkt_sent <= 1'b0;
end
else begin
case(pkt_sent_status)
`PKT_SENT_IDLE: begin
if(pkt_no > 0) begin
pkt_sent_status <= `PKT_SENT_VALID;
sending_pkt_size <= need_to_sent_pkt_size;
mem_rd_ptr <= 'h0;
end
end
`PKT_SENT_VALID: begin
if(mem_rd_ptr < sending_pkt_size) begin
mem_rd_ptr <= mem_rd_ptr + 1;
txd <= mem[mem_rd_ptr];
tx_vld <= 1'b1;
end
else begin
pkt_sent_status <= `PKT_SENT_END;
txd <= 'h0;
tx_vld <= 1'b0;
end
end
`PKT_SENT_END: begin
pkt_sent_status <= `PKT_SENT_FIN;
one_pkt_sent <= 1'b1;
end
`PKT_SENT_FIN: begin
pkt_sent_status <= `PKT_SENT_IDLE;
one_pkt_sent <= 1'b0;
end
default: begin
end
endcase
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
pkt_no <= 'h0;
end
else begin
if(new_pkt == 1'b1) begin
pkt_no <= pkt_no + 1;
end
else if(one_pkt_sent == 1'b1) begin
pkt_no <= pkt_no - 1;
end
end
end
endmodule
`define PKT_RECV_IDLE 0
`define PKT_RECV_START 1
`define PKT_RECV_RECV 2
`define PKT_RECV_VALID 3
`define PKT_RECV_END 4
`define PKT_SENT_IDLE 0
`define PKT_SENT_VALID 1
`define PKT_SENT_END 2
`define PKT_SENT_FIN 3
module dut(
clk ,
rst_n ,
addr ,
din ,
rw ,
enable ,
dout ,
txd ,
tx_vld ,
rxd ,
rx_vld
);
input clk ;
input rst_n ;
input [7:0 ] addr ;
input [31:0] din ;
input rw ;
input enable ;
output [31:0] dout ;
input [7:0 ] rxd ;
input rx_vld ;
output [7:0 ] txd ;
output tx_vld ;
wire clk ;
wire rst_n ;
wire [7:0 ] addr ;
wire [31:0] din ;
wire rw ;
wire enable ;
reg [31:0] dout ;
wire [7:0 ] rxd ;
wire rx_vld ;
reg [7:0 ] txd ;
reg tx_vld ;
wire write ;
wire read ;
wire [31:0] config_reg ;
reg pkt_en;
reg [31:0] min_pkt_size ;
reg [31:0] max_pkt_size ;
reg [7:0 ] mem[0:512];
reg [9:0 ] mem_wr_ptr;
reg [9:0 ] mem_rd_ptr;
reg [9:0 ] need_to_sent_pkt_size;
reg [9:0 ] sending_pkt_size;
reg [2:0 ] pkt_recv_status;
reg [1:0 ] pkt_sent_status;
reg new_pkt;
reg one_pkt_sent;
reg [1:0 ] pkt_no;
assign write = (rw == 1'b0 && enable == 1'b1);
assign read = (rw == 1'b1 && enable == 1'b1);
assign config_reg = {31'h0, pkt_en};
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
pkt_en <= 1'b0;
end
else begin
if((addr == 8'h0) && (write == 1'b1)) begin
pkt_en <= din[0];
end
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
min_pkt_size <= 32'd64;
end
else begin
if((addr == 8'h4) && (write == 1'b1)) begin
if((din[9:0] >= 64) && (din[9:0] < max_pkt_size[9:0]))
min_pkt_size[9:0] <= din[9:0];
end
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
max_pkt_size <= 32'd512;
end
else begin
if((addr == 8'h8) && (write == 1'b1)) begin
if((din[9:0] <= 512) && (din[9:0] > min_pkt_size[9:0]))
max_pkt_size[9:0] <= din[9:0];
end
end
end
always @(*) begin
case(addr)
8'h0 : dout = config_reg;
8'h4 : dout = min_pkt_size;
8'h8 : dout = max_pkt_size;
default : dout = 32'h0;
endcase
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
pkt_recv_status <= 'h0;
pkt_recv_status <= `PKT_RECV_IDLE;
mem_wr_ptr <= 8'h0;
new_pkt <= 1'b0;
end
else begin
case(pkt_recv_status)
`PKT_RECV_IDLE: begin
mem_wr_ptr <= 8'h0;
if((rx_vld == 1'b1) && (pkt_en == 1'b1)) begin
mem_wr_ptr <= mem_wr_ptr + 1;
mem[mem_wr_ptr] <= rxd;
if(rxd != 8'h55) begin
pkt_recv_status <= `PKT_RECV_END;
end
else begin
pkt_recv_status <= `PKT_RECV_START;
end
end
end
`PKT_RECV_START: begin
if(rx_vld == 1'b1) begin
mem_wr_ptr <= mem_wr_ptr + 1;
mem[mem_wr_ptr] <= rxd;
if(rxd != 8'hd5) begin
pkt_recv_status <= `PKT_RECV_END;
end
else begin
pkt_recv_status <= `PKT_RECV_RECV;
end
end
else begin
pkt_recv_status <= `PKT_RECV_END;
end
end
`PKT_RECV_RECV: begin
if(rx_vld == 1'b1) begin
if(mem_wr_ptr == max_pkt_size) begin
pkt_recv_status <= `PKT_RECV_END;
end
else begin
mem_wr_ptr <= mem_wr_ptr + 1;
pkt_recv_status <= `PKT_RECV_RECV;
mem[mem_wr_ptr] <= rxd;
end
end
else begin
pkt_recv_status <= `PKT_RECV_VALID;
end
end
`PKT_RECV_VALID: begin
if(mem_wr_ptr >= min_pkt_size) begin
new_pkt <= 1'b1;
need_to_sent_pkt_size <= mem_wr_ptr;
end
pkt_recv_status <= `PKT_RECV_END;
end
`PKT_RECV_END: begin
new_pkt <= 1'b0;
if(rx_vld == 1'b0) begin
pkt_recv_status <= `PKT_RECV_IDLE;
end
end
default : begin
end
endcase
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
pkt_sent_status <= `PKT_SENT_IDLE;
pkt_sent_status <= 'h0;
mem_rd_ptr <= 'h0;
sending_pkt_size <= 'h0;
txd <= 'h0;
tx_vld <= 1'b0;
one_pkt_sent <= 1'b0;
end
else begin
case(pkt_sent_status)
`PKT_SENT_IDLE: begin
if(pkt_no > 0) begin
pkt_sent_status <= `PKT_SENT_VALID;
sending_pkt_size <= need_to_sent_pkt_size;
mem_rd_ptr <= 'h0;
end
end
`PKT_SENT_VALID: begin
if(mem_rd_ptr < sending_pkt_size) begin
mem_rd_ptr <= mem_rd_ptr + 1;
txd <= mem[mem_rd_ptr];
tx_vld <= 1'b1;
end
else begin
pkt_sent_status <= `PKT_SENT_END;
txd <= 'h0;
tx_vld <= 1'b0;
end
end
`PKT_SENT_END: begin
pkt_sent_status <= `PKT_SENT_FIN;
one_pkt_sent <= 1'b1;
end
`PKT_SENT_FIN: begin
pkt_sent_status <= `PKT_SENT_IDLE;
one_pkt_sent <= 1'b0;
end
default: begin
end
endcase
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
pkt_no <= 'h0;
end
else begin
if(new_pkt == 1'b1) begin
pkt_no <= pkt_no + 1;
end
else if(one_pkt_sent == 1'b1) begin
pkt_no <= pkt_no - 1;
end
end
end
endmodule
./env/cpu_interface_env/cpu_interface.svi
`ifndef __CPU_INTERFACE_SVI__
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk, input logic rst_n);
logic [7:0 ] addr ;
logic [31:0] din ;
logic rw ;
logic enable ;
logic [31:0] dout ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output rw ;
output enable ;
output dout ;
input din ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
`define __CPU_INTERFACE_SVI__
interface cpu_interface (input logic clk, input logic rst_n);
logic [7:0 ] addr ;
logic [31:0] din ;
logic rw ;
logic enable ;
logic [31:0] dout ;
clocking cb @(posedge clk);
default input #1 output #1;
output addr ;
output rw ;
output enable ;
output dout ;
input din ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
./env/cpu_interface_env/cpu_transaction.sv
`ifndef __CPU_TRANSACTION_SV__
`define __CPU_TRANSACTION_SV__
class cpu_transaction extends uvm_sequence_item;
typedef enum {READ, WRITE} rw_type;
rand logic [7:0] addr;
rand rw_type rw;
rand logic [31:0] dout;
logic [31:0] din = 32'h0;
extern function new(string name = "CPU Transaction");
`uvm_object_utils_begin(cpu_transaction)
`uvm_field_int(addr, UVM_ALL_ON)
`uvm_field_enum(rw_type, rw, UVM_ALL_ON)
`uvm_field_int(dout, UVM_ALL_ON)
`uvm_object_utils_end
endclass
function cpu_transaction::new(string name = "CPU Transaction");
super.new(name);
endfunction
`endif
`define __CPU_TRANSACTION_SV__
class cpu_transaction extends uvm_sequence_item;
typedef enum {READ, WRITE} rw_type;
rand logic [7:0] addr;
rand rw_type rw;
rand logic [31:0] dout;
logic [31:0] din = 32'h0;
extern function new(string name = "CPU Transaction");
`uvm_object_utils_begin(cpu_transaction)
`uvm_field_int(addr, UVM_ALL_ON)
`uvm_field_enum(rw_type, rw, UVM_ALL_ON)
`uvm_field_int(dout, UVM_ALL_ON)
`uvm_object_utils_end
endclass
function cpu_transaction::new(string name = "CPU Transaction");
super.new(name);
endfunction
`endif
./env/cpu_interface_env/cpu_sequencer.sv
`ifndef __CPU_SEQUENCER_SV__
`define __CPU_SEQUENCER_SV__
`include "cpu_transaction.sv"
class cpu_sequencer extends uvm_sequencer #(cpu_transaction);
`uvm_component_utils(cpu_sequencer)
function new(string name, uvm_component parent=null);
super.new(name, parent);
endfunction
endclass
`endif
`define __CPU_SEQUENCER_SV__
`include "cpu_transaction.sv"
class cpu_sequencer extends uvm_sequencer #(cpu_transaction);
`uvm_component_utils(cpu_sequencer)
function new(string name, uvm_component parent=null);
super.new(name, parent);
endfunction
endclass
`endif
./env/cpu_interface_env/cpu_driver.sv
`ifndef __CPU_DRIVER_SV__
`define __CPU_DRIVER_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
class cpu_driver extends uvm_driver #(cpu_transaction);
protected virtual cpu_interface cpu_vif;
`uvm_component_utils(cpu_driver)
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern task main_phase(uvm_phase phase);
task reset_phase(uvm_phase phase);
super.reset_phase(phase);
phase.raise_objection(this);
cpu_vif.cb.addr <= 'h0;
cpu_vif.cb.dout <= 'h0;
cpu_vif.cb.rw <= 1'b0;
cpu_vif.cb.enable <= 1'b0;
@(posedge cpu_vif.rst_n);
repeat(10) @(cpu_vif.cb);
phase.drop_objection(this);
endtask;
virtual protected task get_and_drive();
forever begin
cpu_transaction cpu_tr;
seq_item_port.get_next_item(cpu_tr);
//cpu_tr.print();
@(cpu_vif.cb);
cpu_vif.cb.addr <= cpu_tr.addr;
cpu_vif.cb.dout <= cpu_tr.dout;
if(cpu_tr.rw == cpu_transaction::WRITE) begin
cpu_vif.cb.rw <= 1'b0;
end
else begin
cpu_vif.cb.rw <= 1'b1;
end
cpu_vif.cb.enable <= 1'b1;
@(cpu_vif.cb);
cpu_vif.cb.enable <= 1'b0;
//`uvm_do_callbacks(cpu_driver, cpu_driver_cbs, driver_post_transactor(this, cpu_tr))
seq_item_port.item_done();
end
endtask
endclass
//class cpu_driver_cbs extends uvm_callback;
//virtual task driver_pre_transactor(cpu_driver xactor, cpu_transaction cpu_tr); endtask
//virtual task driver_post_transactor(cpu_driver xactor, cpu_transaction cpu_tr); endtask
//endclass
function cpu_driver::new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void cpu_driver::build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual cpu_interface)::get(this, "", "cpu_vif", cpu_vif)) begin
`uvm_fatal("NOVIF", {"virutal interface must be set for: ", get_full_name(), ".cpu_vif"});
end
endfunction
task cpu_driver::main_phase(uvm_phase phase);
super.main_phase(phase);
`uvm_info(get_full_name(),$sformatf(" CPU Driver"), UVM_MEDIUM)
fork
get_and_drive();
join
endtask
`endif
`define __CPU_DRIVER_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
class cpu_driver extends uvm_driver #(cpu_transaction);
protected virtual cpu_interface cpu_vif;
`uvm_component_utils(cpu_driver)
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern task main_phase(uvm_phase phase);
task reset_phase(uvm_phase phase);
super.reset_phase(phase);
phase.raise_objection(this);
cpu_vif.cb.addr <= 'h0;
cpu_vif.cb.dout <= 'h0;
cpu_vif.cb.rw <= 1'b0;
cpu_vif.cb.enable <= 1'b0;
@(posedge cpu_vif.rst_n);
repeat(10) @(cpu_vif.cb);
phase.drop_objection(this);
endtask;
virtual protected task get_and_drive();
forever begin
cpu_transaction cpu_tr;
seq_item_port.get_next_item(cpu_tr);
//cpu_tr.print();
@(cpu_vif.cb);
cpu_vif.cb.addr <= cpu_tr.addr;
cpu_vif.cb.dout <= cpu_tr.dout;
if(cpu_tr.rw == cpu_transaction::WRITE) begin
cpu_vif.cb.rw <= 1'b0;
end
else begin
cpu_vif.cb.rw <= 1'b1;
end
cpu_vif.cb.enable <= 1'b1;
@(cpu_vif.cb);
cpu_vif.cb.enable <= 1'b0;
//`uvm_do_callbacks(cpu_driver, cpu_driver_cbs, driver_post_transactor(this, cpu_tr))
seq_item_port.item_done();
end
endtask
endclass
//class cpu_driver_cbs extends uvm_callback;
//virtual task driver_pre_transactor(cpu_driver xactor, cpu_transaction cpu_tr); endtask
//virtual task driver_post_transactor(cpu_driver xactor, cpu_transaction cpu_tr); endtask
//endclass
function cpu_driver::new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void cpu_driver::build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual cpu_interface)::get(this, "", "cpu_vif", cpu_vif)) begin
`uvm_fatal("NOVIF", {"virutal interface must be set for: ", get_full_name(), ".cpu_vif"});
end
endfunction
task cpu_driver::main_phase(uvm_phase phase);
super.main_phase(phase);
`uvm_info(get_full_name(),$sformatf(" CPU Driver"), UVM_MEDIUM)
fork
get_and_drive();
join
endtask
`endif
./env/cpu_interface_env/cpu_monitor.sv
`ifndef __CPU_MONITOR_SV__
`define __CPU_MONITOR_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
//typedef class cpu_monitor;
//class cpu_monitor_cbs extends uvm_callback;
// virtual function void trans_observed(cpu_monitor xactor, cpu_transaction cycle);
// endfunction
//endclass
class cpu_monitor extends uvm_monitor;
virtual cpu_interface cpu_vif;
bit checks_enable = 1;
bit coverage_enable = 1;
uvm_analysis_port #(cpu_transaction) item_collected_port;
`uvm_component_utils_begin(cpu_monitor)
`uvm_field_int(checks_enable, UVM_DEFAULT)
`uvm_field_int(coverage_enable, UVM_DEFAULT)
`uvm_component_utils_end
function new (string name, uvm_component parent);
super.new(name, parent);
item_collected_port = new("item_collected_port", this);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual cpu_interface)::get(this, "", "cpu_vif", cpu_vif)) begin
`uvm_fatal("NOVIF",{"virtual interface must be set for: ", get_full_name(), ".cpu_vif"});
end
endfunction
virtual protected task collect_transactions();
@(posedge cpu_vif.rst_n);
forever begin
cpu_transaction cpu_tr = new();
do begin
@(cpu_vif.cb);
end while(cpu_vif.enable == 1'b0);
cpu_tr.din = cpu_vif.din;
cpu_tr.addr = cpu_vif.addr;
if(cpu_vif.rw == 1'b0) begin
cpu_tr.rw = cpu_transaction::WRITE;
end
else begin
cpu_tr.rw = cpu_transaction::READ;
end
cpu_tr.dout = cpu_vif.dout;
//`uvm_do_callbacks(cpu_monitor, cpu_monitor_cbs, trans_observed(this,cpu_tr))
item_collected_port.write(cpu_tr);
end
endtask
virtual task main_phase(uvm_phase phase);
super.main_phase(phase);
`uvm_info(get_full_name(),$sformatf(" CPU Monitor"), UVM_MEDIUM)
fork
collect_transactions();
join
endtask
virtual function void report_phase(uvm_phase phase);
super.report_phase(phase);
endfunction
endclass
`endif
`define __CPU_MONITOR_SV__
`include "cpu_interface.svi"
`include "cpu_transaction.sv"
//typedef class cpu_monitor;
//class cpu_monitor_cbs extends uvm_callback;
// virtual function void trans_observed(cpu_monitor xactor, cpu_transaction cycle);
// endfunction
//endclass
class cpu_monitor extends uvm_monitor;
virtual cpu_interface cpu_vif;
bit checks_enable = 1;
bit coverage_enable = 1;
uvm_analysis_port #(cpu_transaction) item_collected_port;
`uvm_component_utils_begin(cpu_monitor)
`uvm_field_int(checks_enable, UVM_DEFAULT)
`uvm_field_int(coverage_enable, UVM_DEFAULT)
`uvm_component_utils_end
function new (string name, uvm_component parent);
super.new(name, parent);
item_collected_port = new("item_collected_port", this);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual cpu_interface)::get(this, "", "cpu_vif", cpu_vif)) begin
`uvm_fatal("NOVIF",{"virtual interface must be set for: ", get_full_name(), ".cpu_vif"});
end
endfunction
virtual protected task collect_transactions();
@(posedge cpu_vif.rst_n);
forever begin
cpu_transaction cpu_tr = new();
do begin
@(cpu_vif.cb);
end while(cpu_vif.enable == 1'b0);
cpu_tr.din = cpu_vif.din;
cpu_tr.addr = cpu_vif.addr;
if(cpu_vif.rw == 1'b0) begin
cpu_tr.rw = cpu_transaction::WRITE;
end
else begin
cpu_tr.rw = cpu_transaction::READ;
end
cpu_tr.dout = cpu_vif.dout;
//`uvm_do_callbacks(cpu_monitor, cpu_monitor_cbs, trans_observed(this,cpu_tr))
item_collected_port.write(cpu_tr);
end
endtask
virtual task main_phase(uvm_phase phase);
super.main_phase(phase);
`uvm_info(get_full_name(),$sformatf(" CPU Monitor"), UVM_MEDIUM)
fork
collect_transactions();
join
endtask
virtual function void report_phase(uvm_phase phase);
super.report_phase(phase);
endfunction
endclass
`endif
./env/cpu_interface_env/cpu_agent.sv
`ifndef __CPU_AGENT_SV__
`define __CPU_AGENT_SV__
`include "cpu_sequencer.sv"
`include "cpu_driver.sv"
`include "cpu_monitor.sv"
class cpu_agent extends uvm_agent;
cpu_sequencer cpu_sqr;
cpu_driver cpu_drv;
cpu_monitor cpu_mon;
`uvm_component_utils_begin(cpu_agent)
`uvm_field_object(cpu_sqr, UVM_ALL_ON)
`uvm_field_object(cpu_drv, UVM_ALL_ON)
`uvm_field_object(cpu_mon, UVM_ALL_ON)
`uvm_component_utils_end
function new(string name, uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
cpu_sqr = cpu_sequencer::type_id::create("cpu_sqr", this);
cpu_drv = cpu_driver::type_id::create("cpu_drv", this);
cpu_mon = cpu_monitor::type_id::create("cpu_mon", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
cpu_drv.seq_item_port.connect(cpu_sqr.seq_item_export);
endfunction
endclass
`endif
`define __CPU_AGENT_SV__
`include "cpu_sequencer.sv"
`include "cpu_driver.sv"
`include "cpu_monitor.sv"
class cpu_agent extends uvm_agent;
cpu_sequencer cpu_sqr;
cpu_driver cpu_drv;
cpu_monitor cpu_mon;
`uvm_component_utils_begin(cpu_agent)
`uvm_field_object(cpu_sqr, UVM_ALL_ON)
`uvm_field_object(cpu_drv, UVM_ALL_ON)
`uvm_field_object(cpu_mon, UVM_ALL_ON)
`uvm_component_utils_end
function new(string name, uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
cpu_sqr = cpu_sequencer::type_id::create("cpu_sqr", this);
cpu_drv = cpu_driver::type_id::create("cpu_drv", this);
cpu_mon = cpu_monitor::type_id::create("cpu_mon", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
cpu_drv.seq_item_port.connect(cpu_sqr.seq_item_export);
endfunction
endclass
`endif
./env/cpu_interface_env/cpu_scoreboard.sv
`ifndef __CPU_SCOREBOARD_SV__
`define __CPU_SCOREBOARD_SV__
`include "cpu_transaction.sv"
class cpu_scoreboard extends uvm_scoreboard;
uvm_analysis_imp#(cpu_transaction, cpu_scoreboard) item_collected_export;
protected bit disable_scoreboard = 0;
int sbd_error = 0;
logic [31:0] cpu_reg [7:0];
integer error_no = 0;
integer total_no = 0;
`uvm_component_utils_begin(cpu_scoreboard)
`uvm_field_int(disable_scoreboard, UVM_DEFAULT)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
for(int i=0; i<128 data-blogger-escaped-begin="" data-blogger-escaped-br="" data-blogger-escaped-i="" data-blogger-escaped-nbsp=""> cpu_reg[i] = 32'h0;
end
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
item_collected_export = new("item_collected_export", this);
endfunction
virtual function void write(cpu_transaction tr);
if(!disable_scoreboard) begin
compare(tr);
end
endfunction : write
protected function void compare(cpu_transaction data);
cpu_transaction tr;
string message;
$cast(tr, data);
if(tr.rw == cpu_transaction::WRITE) begin
cpu_reg[tr.addr] = tr.din;
end
else if(tr.rw == cpu_transaction::READ) begin
if(cpu_reg[tr.addr] != tr.din) begin
message = $psprintf("[Error] %t Comparision result is not correct\n", $realtime);
message = { message, $psprintf("cpu_reg[%d] = %0h, tr.din = %0h\n", tr.addr, cpu_reg[tr.addr], tr.din) };
$display(message);
error_no++;
end
else begin
$display("[Note] %t comparison correct", $realtime);
end
end
else begin
$display("[Error] tr.rw can only be READ or WRITE");
error_no++;
end
endfunction
virtual function void report_phase(uvm_phase phase);
super.report_phase(phase);
$dipslay(phase.get_state());
if(!disable_scoreboard) begin
`uvm_info(get_type_name(), $sformatf("Reporting scoreboard information...\n%s", this.sprint()), UVM_LOW)
end
endfunction
endclass
//class cpu_driver_sb_callback extends cpu_driver_callback;
// cpu_scoreboard cpu_sb;
//
// function new(cpu_scoreboard cpu_sb);
// this.cpu_sb = cpu_sb;
// endfunction
//
// virtual task driver_post_transactor(cpu_driver xactor, ref cpu_transaction cpu_tr);
// cpu_sb.compare(cpu_tr);
// endtask
//endclass
`endif
`define __CPU_SCOREBOARD_SV__
`include "cpu_transaction.sv"
class cpu_scoreboard extends uvm_scoreboard;
uvm_analysis_imp#(cpu_transaction, cpu_scoreboard) item_collected_export;
protected bit disable_scoreboard = 0;
int sbd_error = 0;
logic [31:0] cpu_reg [7:0];
integer error_no = 0;
integer total_no = 0;
`uvm_component_utils_begin(cpu_scoreboard)
`uvm_field_int(disable_scoreboard, UVM_DEFAULT)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
for(int i=0; i<128 data-blogger-escaped-begin="" data-blogger-escaped-br="" data-blogger-escaped-i="" data-blogger-escaped-nbsp=""> cpu_reg[i] = 32'h0;
end
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
item_collected_export = new("item_collected_export", this);
endfunction
virtual function void write(cpu_transaction tr);
if(!disable_scoreboard) begin
compare(tr);
end
endfunction : write
protected function void compare(cpu_transaction data);
cpu_transaction tr;
string message;
$cast(tr, data);
if(tr.rw == cpu_transaction::WRITE) begin
cpu_reg[tr.addr] = tr.din;
end
else if(tr.rw == cpu_transaction::READ) begin
if(cpu_reg[tr.addr] != tr.din) begin
message = $psprintf("[Error] %t Comparision result is not correct\n", $realtime);
message = { message, $psprintf("cpu_reg[%d] = %0h, tr.din = %0h\n", tr.addr, cpu_reg[tr.addr], tr.din) };
$display(message);
error_no++;
end
else begin
$display("[Note] %t comparison correct", $realtime);
end
end
else begin
$display("[Error] tr.rw can only be READ or WRITE");
error_no++;
end
endfunction
virtual function void report_phase(uvm_phase phase);
super.report_phase(phase);
$dipslay(phase.get_state());
if(!disable_scoreboard) begin
`uvm_info(get_type_name(), $sformatf("Reporting scoreboard information...\n%s", this.sprint()), UVM_LOW)
end
endfunction
endclass
//class cpu_driver_sb_callback extends cpu_driver_callback;
// cpu_scoreboard cpu_sb;
//
// function new(cpu_scoreboard cpu_sb);
// this.cpu_sb = cpu_sb;
// endfunction
//
// virtual task driver_post_transactor(cpu_driver xactor, ref cpu_transaction cpu_tr);
// cpu_sb.compare(cpu_tr);
// endtask
//endclass
`endif
./env/cpu_interface_env/cpu_env.sv
`ifndef __CPU_ENV_SV__
`define __CPU_ENV_SV__
`include "cpu_agent.sv"
`include "cpu_scoreboard.sv"
class cpu_env extends uvm_env;
cpu_agent cpu_agt;
cpu_scoreboard cpu_sb;
protected virtual interface cpu_interface cpu_vif;
//`uvm_component_utils_begin(cpu_env)
// //`uvm_field_object(cpu_sb, UVM_ALL_ON)
//`uvm_component_utils_end
`uvm_component_utils(cpu_env)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
cpu_agt = cpu_agent::type_id::create("cpu_agt", this);
cpu_sb = cpu_scoreboard::type_id::create("cpu_sb", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
cpu_agt.cpu_mon.item_collected_port.connect(cpu_sb.item_collected_export);
endfunction : connect_phase
task run_phase(uvm_phase phase);
super.run_phase(phase);
endtask
endclass
`endif
`define __CPU_ENV_SV__
`include "cpu_agent.sv"
`include "cpu_scoreboard.sv"
class cpu_env extends uvm_env;
cpu_agent cpu_agt;
cpu_scoreboard cpu_sb;
protected virtual interface cpu_interface cpu_vif;
//`uvm_component_utils_begin(cpu_env)
// //`uvm_field_object(cpu_sb, UVM_ALL_ON)
//`uvm_component_utils_end
`uvm_component_utils(cpu_env)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
cpu_agt = cpu_agent::type_id::create("cpu_agt", this);
cpu_sb = cpu_scoreboard::type_id::create("cpu_sb", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
cpu_agt.cpu_mon.item_collected_port.connect(cpu_sb.item_collected_export);
endfunction : connect_phase
task run_phase(uvm_phase phase);
super.run_phase(phase);
endtask
endclass
`endif
./env/packet_env/packet_interface.svi
`ifndef __PACKET_INTERFACE_SVI__
`define __PACKET_INTERFACE_SVI__
interface packet_interface (input logic clk, input logic rst_n);
logic [7:0] rxd ;
logic rx_vld ;
logic [7:0] txd ;
logic tx_vld ;
clocking cb @(posedge clk);
default input #1 output #1;
output txd ;
output tx_vld ;
input rxd ;
input rx_vld ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
`define __PACKET_INTERFACE_SVI__
interface packet_interface (input logic clk, input logic rst_n);
logic [7:0] rxd ;
logic rx_vld ;
logic [7:0] txd ;
logic tx_vld ;
clocking cb @(posedge clk);
default input #1 output #1;
output txd ;
output tx_vld ;
input rxd ;
input rx_vld ;
endclocking
modport master(clocking cb, output rst_n);
endinterface
`endif
./env/packet_env/packet_transaction.sv
`ifndef __PACKET_TRANSACTION_SV__
`define __PACKET_TRANSACTION_SV__
class packet_transaction extends uvm_sequence_item;
typedef enum {GOOD, BAD} head_type;
typedef enum {LONG, SHORT, NORMAL} packet_length;
rand head_type pkt_head_type ;
rand packet_length pkt_packet_length ;
rand logic [15:0] header ;
rand logic [7:0 ] payload[$] ;
rand logic [6:0 ] frame_interval;
extern function new(string name = "Packet Transaction");
function void byte2pkt(ref logic[7:0] data[$]);
if(data.size() >= 2) begin
header[15:8] = data.pop_front();
header[7:0] = data.pop_front();
end
foreach(data[i]) begin
payload.push_back(data[i]);
end
endfunction
`uvm_object_utils_begin(packet_transaction)
`uvm_field_enum(head_type, pkt_head_type, UVM_ALL_ON | UVM_NOCOMPARE)
`uvm_field_enum(packet_length, pkt_packet_length, UVM_ALL_ON | UVM_NOCOMPARE)
`uvm_field_int(header, UVM_ALL_ON)
`uvm_field_queue_int(payload, UVM_ALL_ON)
`uvm_field_int(frame_interval, UVM_ALL_ON | UVM_NOCOMPARE)
`uvm_object_utils_end
constraint con_head_type {
solve pkt_head_type before header;
pkt_head_type dist {GOOD := 5, BAD := 1};
(pkt_head_type == GOOD) -> (header == 16'h55d5);
(pkt_head_type == BAD) -> (header inside {[0:16'h55d4], [16'h55d6:16'hffff]});
}
constraint con_pkt_len {
solve pkt_packet_length before payload;
pkt_packet_length dist {LONG := 1, SHORT := 1, NORMAL := 5};
(pkt_packet_length == LONG) -> (payload.size() inside {[0:49]});
(pkt_packet_length == SHORT) -> (payload.size() inside {[50:500]});
(pkt_packet_length == NORMAL) -> (payload.size() inside {[501:600]});
}
constraint con_frame_interval {
frame_interval inside {[96:200]};
}
virtual function bit do_compare (uvm_object rhs, uvm_comparer comparer);
packet_transaction rhs_;
do_compare = super.do_compare(rhs,comparer);
$cast(rhs_,rhs);
do_compare &= comparer.compare_field_int("Header", header, rhs_.header, 16);
do_compare &= comparer.compare_field_int("Payload Size", payload.size(), rhs_.payload.size(), 64);
if(do_compare) begin
foreach (rhs_.payload[i]) begin
do_compare &= comparer.compare_field_int("Payload", payload[i], rhs_.payload[i], 8);
end
end
endfunction
function uvm_object clone();
packet_transaction tr = new();
tr.copy(this);
return tr;
endfunction
function void do_copy (uvm_object rhs);
packet_transaction rhs_;
super.do_copy(rhs);
$cast(rhs_, rhs);
header = rhs_.header;
foreach(rhs_.payload[i]) begin
payload.push_back(rhs_.payload[i]);
end
endfunction
endclass
function packet_transaction::new(string name = "Packet Transaction");
super.new(name);
endfunction
`endif
`define __PACKET_TRANSACTION_SV__
class packet_transaction extends uvm_sequence_item;
typedef enum {GOOD, BAD} head_type;
typedef enum {LONG, SHORT, NORMAL} packet_length;
rand head_type pkt_head_type ;
rand packet_length pkt_packet_length ;
rand logic [15:0] header ;
rand logic [7:0 ] payload[$] ;
rand logic [6:0 ] frame_interval;
extern function new(string name = "Packet Transaction");
function void byte2pkt(ref logic[7:0] data[$]);
if(data.size() >= 2) begin
header[15:8] = data.pop_front();
header[7:0] = data.pop_front();
end
foreach(data[i]) begin
payload.push_back(data[i]);
end
endfunction
`uvm_object_utils_begin(packet_transaction)
`uvm_field_enum(head_type, pkt_head_type, UVM_ALL_ON | UVM_NOCOMPARE)
`uvm_field_enum(packet_length, pkt_packet_length, UVM_ALL_ON | UVM_NOCOMPARE)
`uvm_field_int(header, UVM_ALL_ON)
`uvm_field_queue_int(payload, UVM_ALL_ON)
`uvm_field_int(frame_interval, UVM_ALL_ON | UVM_NOCOMPARE)
`uvm_object_utils_end
constraint con_head_type {
solve pkt_head_type before header;
pkt_head_type dist {GOOD := 5, BAD := 1};
(pkt_head_type == GOOD) -> (header == 16'h55d5);
(pkt_head_type == BAD) -> (header inside {[0:16'h55d4], [16'h55d6:16'hffff]});
}
constraint con_pkt_len {
solve pkt_packet_length before payload;
pkt_packet_length dist {LONG := 1, SHORT := 1, NORMAL := 5};
(pkt_packet_length == LONG) -> (payload.size() inside {[0:49]});
(pkt_packet_length == SHORT) -> (payload.size() inside {[50:500]});
(pkt_packet_length == NORMAL) -> (payload.size() inside {[501:600]});
}
constraint con_frame_interval {
frame_interval inside {[96:200]};
}
virtual function bit do_compare (uvm_object rhs, uvm_comparer comparer);
packet_transaction rhs_;
do_compare = super.do_compare(rhs,comparer);
$cast(rhs_,rhs);
do_compare &= comparer.compare_field_int("Header", header, rhs_.header, 16);
do_compare &= comparer.compare_field_int("Payload Size", payload.size(), rhs_.payload.size(), 64);
if(do_compare) begin
foreach (rhs_.payload[i]) begin
do_compare &= comparer.compare_field_int("Payload", payload[i], rhs_.payload[i], 8);
end
end
endfunction
function uvm_object clone();
packet_transaction tr = new();
tr.copy(this);
return tr;
endfunction
function void do_copy (uvm_object rhs);
packet_transaction rhs_;
super.do_copy(rhs);
$cast(rhs_, rhs);
header = rhs_.header;
foreach(rhs_.payload[i]) begin
payload.push_back(rhs_.payload[i]);
end
endfunction
endclass
function packet_transaction::new(string name = "Packet Transaction");
super.new(name);
endfunction
`endif
./env/packet_env/packet_sequencer.sv
`ifndef __PACKET_SEQUENCER_SV__
`define __PACKET_SEQUENCER_SV__
`include "packet_transaction.sv"
class packet_sequencer extends uvm_sequencer #(packet_transaction);
`uvm_component_utils(packet_sequencer)
function new(string name, uvm_component parent=null);
super.new(name, parent);
endfunction
endclass
`endif
`define __PACKET_SEQUENCER_SV__
`include "packet_transaction.sv"
class packet_sequencer extends uvm_sequencer #(packet_transaction);
`uvm_component_utils(packet_sequencer)
function new(string name, uvm_component parent=null);
super.new(name, parent);
endfunction
endclass
`endif
./env/packet_env/packet_driver.sv
`ifndef __PACKET_DRIVER_SV__
`define __PACKET_DRIVER_SV__
`include "packet_interface.svi"
`include "packet_transaction.sv"
class packet_driver extends uvm_driver #(packet_transaction);
virtual packet_interface pkt_vif;
uvm_analysis_port #(packet_transaction) drv2sb_port;
`uvm_component_utils(packet_driver)
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern task main_phase(uvm_phase phase);
task reset_phase(uvm_phase phase);
super.reset_phase(phase);
phase.raise_objection(this);
pkt_vif.cb.tx_vld <= 1'b0;
pkt_vif.cb.txd <= 8'h0;
@(posedge pkt_vif.rst_n);
repeat(10) @(pkt_vif.cb);
phase.drop_objection(this);
endtask;
virtual protected task get_and_drive();
forever begin
int delay;
packet_transaction pkt_tr;
packet_transaction cb_pkt_tr;
seq_item_port.get_next_item(pkt_tr);
//pkt_tr.display();
//cb_pkt_tr = pkt_tr.copy();
//`callback_macro(packet_driver_callback, driver_pre_transactor(this, cb_pkt_tr, drop))
drv2sb_port.write(pkt_tr);
@(pkt_vif.cb);
pkt_vif.cb.tx_vld <= 1'b1;
pkt_vif.cb.txd <= pkt_tr.header[15:8];
@(pkt_vif.cb);
pkt_vif.cb.txd <= pkt_tr.header[7:0];
foreach(pkt_tr.payload[i]) begin
@(pkt_vif.cb);
pkt_vif.cb.txd <= pkt_tr.payload[i];
end
if(pkt_tr.frame_interval > pkt_tr.payload.size())
delay = pkt_tr.frame_interval;
else
delay = pkt_tr.payload.size();
repeat(delay) begin
@(pkt_vif.cb);
pkt_vif.cb.tx_vld <= 1'b0;
end
seq_item_port.item_done();
end
endtask
endclass
//class packet_driver_callback extends transactor_callback;
// virtual task driver_pre_transactor (packet_driver xactor, ref packet_transaction pkt_tr, ref bit drop);
// endtask
// virtual task driver_post_transactor (packet_driver xactor, ref packet_transaction pkt_tr);
// endtask
//endclass
function packet_driver::new(string name, uvm_component parent);
super.new(name, parent);
drv2sb_port = new("drv2sb_port", this);
endfunction
function void packet_driver::build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual packet_interface)::get(this, "", "pkt_vif", pkt_vif)) begin
`uvm_fatal("NOVIF", {"virutal interface must be set for: ", get_full_name(), ".pkt_vif"});
end
endfunction
task packet_driver::main_phase(uvm_phase phase);
super.main_phase(phase);
`uvm_info(get_full_name(),$sformatf(" Packet Driver"), UVM_MEDIUM)
fork
get_and_drive();
join
endtask
`endif
`define __PACKET_DRIVER_SV__
`include "packet_interface.svi"
`include "packet_transaction.sv"
class packet_driver extends uvm_driver #(packet_transaction);
virtual packet_interface pkt_vif;
uvm_analysis_port #(packet_transaction) drv2sb_port;
`uvm_component_utils(packet_driver)
extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern task main_phase(uvm_phase phase);
task reset_phase(uvm_phase phase);
super.reset_phase(phase);
phase.raise_objection(this);
pkt_vif.cb.tx_vld <= 1'b0;
pkt_vif.cb.txd <= 8'h0;
@(posedge pkt_vif.rst_n);
repeat(10) @(pkt_vif.cb);
phase.drop_objection(this);
endtask;
virtual protected task get_and_drive();
forever begin
int delay;
packet_transaction pkt_tr;
packet_transaction cb_pkt_tr;
seq_item_port.get_next_item(pkt_tr);
//pkt_tr.display();
//cb_pkt_tr = pkt_tr.copy();
//`callback_macro(packet_driver_callback, driver_pre_transactor(this, cb_pkt_tr, drop))
drv2sb_port.write(pkt_tr);
@(pkt_vif.cb);
pkt_vif.cb.tx_vld <= 1'b1;
pkt_vif.cb.txd <= pkt_tr.header[15:8];
@(pkt_vif.cb);
pkt_vif.cb.txd <= pkt_tr.header[7:0];
foreach(pkt_tr.payload[i]) begin
@(pkt_vif.cb);
pkt_vif.cb.txd <= pkt_tr.payload[i];
end
if(pkt_tr.frame_interval > pkt_tr.payload.size())
delay = pkt_tr.frame_interval;
else
delay = pkt_tr.payload.size();
repeat(delay) begin
@(pkt_vif.cb);
pkt_vif.cb.tx_vld <= 1'b0;
end
seq_item_port.item_done();
end
endtask
endclass
//class packet_driver_callback extends transactor_callback;
// virtual task driver_pre_transactor (packet_driver xactor, ref packet_transaction pkt_tr, ref bit drop);
// endtask
// virtual task driver_post_transactor (packet_driver xactor, ref packet_transaction pkt_tr);
// endtask
//endclass
function packet_driver::new(string name, uvm_component parent);
super.new(name, parent);
drv2sb_port = new("drv2sb_port", this);
endfunction
function void packet_driver::build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual packet_interface)::get(this, "", "pkt_vif", pkt_vif)) begin
`uvm_fatal("NOVIF", {"virutal interface must be set for: ", get_full_name(), ".pkt_vif"});
end
endfunction
task packet_driver::main_phase(uvm_phase phase);
super.main_phase(phase);
`uvm_info(get_full_name(),$sformatf(" Packet Driver"), UVM_MEDIUM)
fork
get_and_drive();
join
endtask
`endif
./env/packet_env/packet_monitor.sv
`ifndef __PACKET_MONITOR_SV__
`define __PACKET_MONITOR_SV__
`include "packet_interface.svi"
`include "packet_transaction.sv"
class packet_monitor extends uvm_monitor;
virtual packet_interface pkt_vif;
bit checks_enable = 1;
bit coverage_enable = 1;
uvm_analysis_port #(packet_transaction) mon2sb_port;
`uvm_component_utils_begin(packet_monitor)
`uvm_field_int(checks_enable, UVM_DEFAULT)
`uvm_field_int(coverage_enable, UVM_DEFAULT)
`uvm_component_utils_end
function new (string name, uvm_component parent);
super.new(name, parent);
mon2sb_port = new("mon2sb_port", this);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual packet_interface)::get(this, "", "pkt_vif", pkt_vif))
`uvm_fatal("NOVIF",{"virtual interface must be set for: ", get_full_name(), ".pkt_vif"});
endfunction
virtual task main_phase(uvm_phase phase);
super.main_phase(phase);
`uvm_info(get_full_name(),$sformatf(" Packet Monitor"), UVM_MEDIUM)
fork
collect_transactions();
join
endtask
virtual protected task collect_transactions();
//or wait for the global reset
@(pkt_vif.cb);
while(pkt_vif.cb.rx_vld !== 1'b0) begin
@(pkt_vif.cb);
end
forever begin
logic [7:0] rxd[$];
packet_transaction pkt_tr = new();
@(pkt_vif.cb);
while(pkt_vif.cb.rx_vld == 1'b0) begin
@(pkt_vif.cb);
end
while(pkt_vif.cb.rx_vld == 1'b1) begin
rxd.push_back(pkt_vif.cb.rxd);
@(pkt_vif.cb);
end
pkt_tr.byte2pkt(rxd);
//pkt_tr.display("Monitor");
//`callback_macro(packet_monitor_callback, monitor_post_transactor(this, pkt_tr))
mon2sb_port.write(pkt_tr);
end
endtask
virtual function void report_phase(uvm_phase phase);
super.report_phase(phase);
endfunction
endclass
//class packet_monitor_callback extends transactor_callback;
// virtual task monitor_pre_transactor (packet_monitor xactor, ref packet_transaction pkt_tr, ref bit drop);
// endtask
// virtual task monitor_post_transactor (packet_monitor xactor, ref packet_transaction pkt_tr);
// endtask
//endclass
`endif
`define __PACKET_MONITOR_SV__
`include "packet_interface.svi"
`include "packet_transaction.sv"
class packet_monitor extends uvm_monitor;
virtual packet_interface pkt_vif;
bit checks_enable = 1;
bit coverage_enable = 1;
uvm_analysis_port #(packet_transaction) mon2sb_port;
`uvm_component_utils_begin(packet_monitor)
`uvm_field_int(checks_enable, UVM_DEFAULT)
`uvm_field_int(coverage_enable, UVM_DEFAULT)
`uvm_component_utils_end
function new (string name, uvm_component parent);
super.new(name, parent);
mon2sb_port = new("mon2sb_port", this);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual packet_interface)::get(this, "", "pkt_vif", pkt_vif))
`uvm_fatal("NOVIF",{"virtual interface must be set for: ", get_full_name(), ".pkt_vif"});
endfunction
virtual task main_phase(uvm_phase phase);
super.main_phase(phase);
`uvm_info(get_full_name(),$sformatf(" Packet Monitor"), UVM_MEDIUM)
fork
collect_transactions();
join
endtask
virtual protected task collect_transactions();
//or wait for the global reset
@(pkt_vif.cb);
while(pkt_vif.cb.rx_vld !== 1'b0) begin
@(pkt_vif.cb);
end
forever begin
logic [7:0] rxd[$];
packet_transaction pkt_tr = new();
@(pkt_vif.cb);
while(pkt_vif.cb.rx_vld == 1'b0) begin
@(pkt_vif.cb);
end
while(pkt_vif.cb.rx_vld == 1'b1) begin
rxd.push_back(pkt_vif.cb.rxd);
@(pkt_vif.cb);
end
pkt_tr.byte2pkt(rxd);
//pkt_tr.display("Monitor");
//`callback_macro(packet_monitor_callback, monitor_post_transactor(this, pkt_tr))
mon2sb_port.write(pkt_tr);
end
endtask
virtual function void report_phase(uvm_phase phase);
super.report_phase(phase);
endfunction
endclass
//class packet_monitor_callback extends transactor_callback;
// virtual task monitor_pre_transactor (packet_monitor xactor, ref packet_transaction pkt_tr, ref bit drop);
// endtask
// virtual task monitor_post_transactor (packet_monitor xactor, ref packet_transaction pkt_tr);
// endtask
//endclass
`endif
./env/packet_env/packet_agent.sv
`ifndef __PACKET_AGENT_SV__
`define __PACKET_AGENT_SV__
`include "packet_sequencer.sv"
`include "packet_driver.sv"
`include "packet_monitor.sv"
class packet_agent extends uvm_agent;
packet_sequencer pkt_sqr;
packet_driver pkt_drv;
packet_monitor pkt_mon;
`uvm_component_utils_begin(packet_agent)
`uvm_field_object(pkt_sqr, UVM_ALL_ON)
`uvm_field_object(pkt_drv, UVM_ALL_ON)
`uvm_field_object(pkt_mon, UVM_ALL_ON)
`uvm_component_utils_end
function new(string name, uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
pkt_sqr = packet_sequencer::type_id::create("pkt_sqr", this);
pkt_drv = packet_driver::type_id::create("pkt_drv", this);
pkt_mon = packet_monitor::type_id::create("pkt_mon", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
pkt_drv.seq_item_port.connect(pkt_sqr.seq_item_export);
endfunction
endclass
`endif
`define __PACKET_AGENT_SV__
`include "packet_sequencer.sv"
`include "packet_driver.sv"
`include "packet_monitor.sv"
class packet_agent extends uvm_agent;
packet_sequencer pkt_sqr;
packet_driver pkt_drv;
packet_monitor pkt_mon;
`uvm_component_utils_begin(packet_agent)
`uvm_field_object(pkt_sqr, UVM_ALL_ON)
`uvm_field_object(pkt_drv, UVM_ALL_ON)
`uvm_field_object(pkt_mon, UVM_ALL_ON)
`uvm_component_utils_end
function new(string name, uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
pkt_sqr = packet_sequencer::type_id::create("pkt_sqr", this);
pkt_drv = packet_driver::type_id::create("pkt_drv", this);
pkt_mon = packet_monitor::type_id::create("pkt_mon", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
pkt_drv.seq_item_port.connect(pkt_sqr.seq_item_export);
endfunction
endclass
`endif
./env/packet_env/packet_rm.sv
`ifndef __PACKET_RM_SV__
`define __PACKET_RM_SV__
class packet_rm extends uvm_component;
logic [9:0] min_pkt_size;
logic [9:0] max_pkt_size;
`uvm_component_utils_begin(packet_rm)
`uvm_field_int(min_pkt_size, UVM_DEFAULT)
`uvm_field_int(max_pkt_size, UVM_DEFAULT)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(int)::get(this, "", "min_pkt_size", min_pkt_size);
uvm_config_db#(int)::get(this, "", "max_pkt_size", max_pkt_size);
if(min_pkt_size == 0) begin
min_pkt_size = 32'd64;
end
if(max_pkt_size == 0) begin
max_pkt_size = 32'd512;
end
endfunction
extern function bit packet_process(ref packet_transaction pkt_tr);
endclass
function bit packet_rm::packet_process(ref packet_transaction pkt_tr);
if(pkt_tr == null) begin
return 0;
end
if(pkt_tr.header != 16'h55d5) begin
return 0;
end
if(pkt_tr.payload.size() < min_pkt_size - 2 || pkt_tr.payload.size() > max_pkt_size - 2) begin
return 0;
end
return 1;
endfunction
`endif
`define __PACKET_RM_SV__
class packet_rm extends uvm_component;
logic [9:0] min_pkt_size;
logic [9:0] max_pkt_size;
`uvm_component_utils_begin(packet_rm)
`uvm_field_int(min_pkt_size, UVM_DEFAULT)
`uvm_field_int(max_pkt_size, UVM_DEFAULT)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(int)::get(this, "", "min_pkt_size", min_pkt_size);
uvm_config_db#(int)::get(this, "", "max_pkt_size", max_pkt_size);
if(min_pkt_size == 0) begin
min_pkt_size = 32'd64;
end
if(max_pkt_size == 0) begin
max_pkt_size = 32'd512;
end
endfunction
extern function bit packet_process(ref packet_transaction pkt_tr);
endclass
function bit packet_rm::packet_process(ref packet_transaction pkt_tr);
if(pkt_tr == null) begin
return 0;
end
if(pkt_tr.header != 16'h55d5) begin
return 0;
end
if(pkt_tr.payload.size() < min_pkt_size - 2 || pkt_tr.payload.size() > max_pkt_size - 2) begin
return 0;
end
return 1;
endfunction
`endif
./env/packet_env/packet_scoreboard.sv
`ifndef __PACKET_SCOREBOARD_SV__
`define __PACKET_SCOREBOARD_SV__
`include "packet_transaction.sv"
`include "packet_rm.sv"
`uvm_analysis_imp_decl(_rcvd_pkt)
`uvm_analysis_imp_decl(_sent_pkt)
class packet_scoreboard extends uvm_scoreboard;
uvm_analysis_imp_rcvd_pkt #(packet_transaction, packet_scoreboard) mon2sb_port;
uvm_analysis_imp_sent_pkt #(packet_transaction, packet_scoreboard) drv2sb_port;
packet_rm pkt_rm;
packet_transaction ref_pkt_tran[$];
integer error_no = 0;
integer send_no = 0;
integer receive_no = 0;
protected bit disable_scoreboard = 0;
int sbd_error = 0;
`uvm_component_utils_begin(packet_scoreboard)
`uvm_field_int(disable_scoreboard, UVM_DEFAULT)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
mon2sb_port = new("mon2sb", this);
drv2sb_port = new("drv2sb", this);
pkt_rm = packet_rm::type_id::create("pkt_rm", this);
endfunction
virtual function void report_phase(uvm_phase phase);
if(!disable_scoreboard) begin
`uvm_info(get_type_name(), $sformatf("Reporting scoreboard information...\n%s", this.sprint()), UVM_LOW)
end
endfunction
virtual function void write_rcvd_pkt(input packet_transaction pkt_tr);
receive_no++;
if(ref_pkt_tran.size() > 0) begin
packet_transaction ref_pkt_tr = ref_pkt_tran.pop_front();
if(pkt_tr.compare(ref_pkt_tr)) begin
uvm_report_info(get_type_name(), $psprintf("Sent packet and received packet matched"), UVM_LOW);
end
else begin
error_no++;
uvm_report_error(get_type_name(), $psprintf("Sent packet and received packet mismatched"), UVM_LOW);
sbd_error = 1;
end
display("[PKT][RECV]");
end
else begin
error_no++;
display("[PKT][RECV][RECV PKT > SEND PKT]");
sbd_error = 1;
uvm_report_error(get_type_name(), $psprintf("No more packets to in the expected queue to compare"), UVM_LOW);
end
endfunction
virtual function void write_sent_pkt(input packet_transaction pkt_tr);
bit drop;
packet_transaction cb_pkt_tr;
if(!pkt_rm.packet_process(pkt_tr)) begin
drop = 1;
end
else begin
$cast(cb_pkt_tr, pkt_tr.clone());
ref_pkt_tran.push_back(pkt_tr);
send_no++;
drop = 0;
display("[PKT][SEND]");
end
endfunction
function display(string prefix);
`uvm_info(get_type_name(), $sformatf("%s Send: %d, Receive: %d, Error: %d", prefix, send_no, receive_no, error_no), UVM_NONE);
endfunction
endclass
`endif
`define __PACKET_SCOREBOARD_SV__
`include "packet_transaction.sv"
`include "packet_rm.sv"
`uvm_analysis_imp_decl(_rcvd_pkt)
`uvm_analysis_imp_decl(_sent_pkt)
class packet_scoreboard extends uvm_scoreboard;
uvm_analysis_imp_rcvd_pkt #(packet_transaction, packet_scoreboard) mon2sb_port;
uvm_analysis_imp_sent_pkt #(packet_transaction, packet_scoreboard) drv2sb_port;
packet_rm pkt_rm;
packet_transaction ref_pkt_tran[$];
integer error_no = 0;
integer send_no = 0;
integer receive_no = 0;
protected bit disable_scoreboard = 0;
int sbd_error = 0;
`uvm_component_utils_begin(packet_scoreboard)
`uvm_field_int(disable_scoreboard, UVM_DEFAULT)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
mon2sb_port = new("mon2sb", this);
drv2sb_port = new("drv2sb", this);
pkt_rm = packet_rm::type_id::create("pkt_rm", this);
endfunction
virtual function void report_phase(uvm_phase phase);
if(!disable_scoreboard) begin
`uvm_info(get_type_name(), $sformatf("Reporting scoreboard information...\n%s", this.sprint()), UVM_LOW)
end
endfunction
virtual function void write_rcvd_pkt(input packet_transaction pkt_tr);
receive_no++;
if(ref_pkt_tran.size() > 0) begin
packet_transaction ref_pkt_tr = ref_pkt_tran.pop_front();
if(pkt_tr.compare(ref_pkt_tr)) begin
uvm_report_info(get_type_name(), $psprintf("Sent packet and received packet matched"), UVM_LOW);
end
else begin
error_no++;
uvm_report_error(get_type_name(), $psprintf("Sent packet and received packet mismatched"), UVM_LOW);
sbd_error = 1;
end
display("[PKT][RECV]");
end
else begin
error_no++;
display("[PKT][RECV][RECV PKT > SEND PKT]");
sbd_error = 1;
uvm_report_error(get_type_name(), $psprintf("No more packets to in the expected queue to compare"), UVM_LOW);
end
endfunction
virtual function void write_sent_pkt(input packet_transaction pkt_tr);
bit drop;
packet_transaction cb_pkt_tr;
if(!pkt_rm.packet_process(pkt_tr)) begin
drop = 1;
end
else begin
$cast(cb_pkt_tr, pkt_tr.clone());
ref_pkt_tran.push_back(pkt_tr);
send_no++;
drop = 0;
display("[PKT][SEND]");
end
endfunction
function display(string prefix);
`uvm_info(get_type_name(), $sformatf("%s Send: %d, Receive: %d, Error: %d", prefix, send_no, receive_no, error_no), UVM_NONE);
endfunction
endclass
`endif
./env/packet_env/packet_env.sv
`ifndef __PACKET_ENV_SV__
`define __PACKET_ENV_SV__
`include "packet_agent.sv"
`include "packet_scoreboard.sv"
class packet_env extends uvm_env;
packet_agent pkt_agt;
packet_scoreboard pkt_sb;
virtual packet_interface pkt_vif;
`uvm_component_utils(packet_env)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
pkt_agt = packet_agent::type_id::create("pkt_agt", this);
pkt_sb = packet_scoreboard::type_id::create("pkt_sb", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
pkt_agt.pkt_drv.drv2sb_port.connect(pkt_sb.drv2sb_port);
pkt_agt.pkt_mon.mon2sb_port.connect(pkt_sb.mon2sb_port);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
endtask
endclass
`endif
`define __PACKET_ENV_SV__
`include "packet_agent.sv"
`include "packet_scoreboard.sv"
class packet_env extends uvm_env;
packet_agent pkt_agt;
packet_scoreboard pkt_sb;
virtual packet_interface pkt_vif;
`uvm_component_utils(packet_env)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
pkt_agt = packet_agent::type_id::create("pkt_agt", this);
pkt_sb = packet_scoreboard::type_id::create("pkt_sb", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
pkt_agt.pkt_drv.drv2sb_port.connect(pkt_sb.drv2sb_port);
pkt_agt.pkt_mon.mon2sb_port.connect(pkt_sb.mon2sb_port);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
endtask
endclass
`endif
./env/system_virtual_sequencer.sv
`ifndef __SYSTEM_VIRTUAL_SEQUENCER_SV__
`define __SYSTEM_VIRTUAL_SEQUENCER_SV__
`include "cpu_sequencer.sv"
`include "packet_sequencer.sv"
class system_virtual_sequencer extends uvm_sequencer;
cpu_sequencer cpu_sqr;
packet_sequencer pkt_sqr;
`uvm_component_utils(system_virtual_sequencer)
function new (string name="system_virtual_sequencer", uvm_component parent=null);
super.new(name, parent);
endfunction
endclass
`endif
`define __SYSTEM_VIRTUAL_SEQUENCER_SV__
`include "cpu_sequencer.sv"
`include "packet_sequencer.sv"
class system_virtual_sequencer extends uvm_sequencer;
cpu_sequencer cpu_sqr;
packet_sequencer pkt_sqr;
`uvm_component_utils(system_virtual_sequencer)
function new (string name="system_virtual_sequencer", uvm_component parent=null);
super.new(name, parent);
endfunction
endclass
`endif
./env/env.sv
`ifndef __ENV_SV__
`define __ENV_SV__
`include "cpu_env.sv"
`include "packet_env.sv"
`include "system_virtual_sequencer.sv"
class env extends uvm_env;
cpu_env u_cpu_env;
packet_env u_pkt_env;
system_virtual_sequencer sys_vir_sqr;
`uvm_component_utils(env)
function new(string name, uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
u_cpu_env = cpu_env::type_id::create("u_cpu_env", this);
u_pkt_env = packet_env::type_id::create("u_packet_env", this);
sys_vir_sqr = system_virtual_sequencer::type_id::create("sys_vir_sqr", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
sys_vir_sqr.cpu_sqr = u_cpu_env.cpu_agt.cpu_sqr;
sys_vir_sqr.pkt_sqr = u_pkt_env.pkt_agt.pkt_sqr;
endfunction
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
endtask
endclass
`endif
`define __ENV_SV__
`include "cpu_env.sv"
`include "packet_env.sv"
`include "system_virtual_sequencer.sv"
class env extends uvm_env;
cpu_env u_cpu_env;
packet_env u_pkt_env;
system_virtual_sequencer sys_vir_sqr;
`uvm_component_utils(env)
function new(string name, uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
u_cpu_env = cpu_env::type_id::create("u_cpu_env", this);
u_pkt_env = packet_env::type_id::create("u_packet_env", this);
sys_vir_sqr = system_virtual_sequencer::type_id::create("sys_vir_sqr", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
sys_vir_sqr.cpu_sqr = u_cpu_env.cpu_agt.cpu_sqr;
sys_vir_sqr.pkt_sqr = u_pkt_env.pkt_agt.pkt_sqr;
endfunction
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
endtask
endclass
`endif
./sequence/cpu_interface_sequence/cpu_base_sequence.sv
`ifndef _CPU_BASE_SEQUENCE_SV__
`define _CPU_BASE_SEQUENCE_SV__
virtual class cpu_base_sequence extends uvm_sequence #(cpu_transaction);
function new(string name="cpu_base_sequence");
super.new(name);
set_automatic_phase_objection(1);
endfunction
endclass
class read_word_seq extends cpu_base_sequence;
function new(string name="read_word_seq");
super.new(name);
endfunction
`uvm_object_utils(read_word_seq)
rand logic [7:0] raddr;
virtual task body();
`uvm_do_with(req, {req.addr == raddr; req.rw == cpu_transaction::READ; req.dout == 32'h0;} )
endtask
endclass
class write_word_seq extends cpu_base_sequence;
function new(string name="write_word_seq");
super.new(name);
endfunction
`uvm_object_utils(write_word_seq)
rand logic [7:0] waddr;
rand logic [31:0] wdout;
virtual task body();
`uvm_do_with(req, {req.addr == waddr; req.rw == cpu_transaction::WRITE; req.dout == wdout;} )
endtask
endclass
`endif
`define _CPU_BASE_SEQUENCE_SV__
virtual class cpu_base_sequence extends uvm_sequence #(cpu_transaction);
function new(string name="cpu_base_sequence");
super.new(name);
set_automatic_phase_objection(1);
endfunction
endclass
class read_word_seq extends cpu_base_sequence;
function new(string name="read_word_seq");
super.new(name);
endfunction
`uvm_object_utils(read_word_seq)
rand logic [7:0] raddr;
virtual task body();
`uvm_do_with(req, {req.addr == raddr; req.rw == cpu_transaction::READ; req.dout == 32'h0;} )
endtask
endclass
class write_word_seq extends cpu_base_sequence;
function new(string name="write_word_seq");
super.new(name);
endfunction
`uvm_object_utils(write_word_seq)
rand logic [7:0] waddr;
rand logic [31:0] wdout;
virtual task body();
`uvm_do_with(req, {req.addr == waddr; req.rw == cpu_transaction::WRITE; req.dout == wdout;} )
endtask
endclass
`endif
./sequence/cpu_interface_sequence/cpu_sequence.sv
`ifndef __CPU_WRITE_AND_READ_SV__
`define __CPU_WRITE_AND_READ_SV__
`include "cpu_base_sequence.sv"
class cpu_write_and_read extends cpu_base_sequence;
read_word_seq r_seq;
write_word_seq w_seq;
logic [9:0] min_pkt_size;
logic [9:0] max_pkt_size;
`uvm_declare_p_sequencer(system_virtual_sequencer)
`uvm_object_utils(cpu_write_and_read)
function new(string name="cpu_write_and_read");
super.new(name);
uvm_config_db#(int)::get(uvm_root::get(), "", "min_pkt_size", min_pkt_size);
uvm_config_db#(int)::get(uvm_root::get(), "", "max_pkt_size", max_pkt_size);
if(min_pkt_size == 0) begin
min_pkt_size = 32'd64;
end
if(max_pkt_size == 0) begin
max_pkt_size = 32'd512;
end
endfunction : new
virtual task body();
`uvm_do_on_with(w_seq, p_sequencer.cpu_sqr, {w_seq.waddr == 8'h4; w_seq.wdout == 'd65;})
`uvm_do_on_with(r_seq, p_sequencer.cpu_sqr, {r_seq.raddr == 8'h4;})
`uvm_do_on_with(w_seq, p_sequencer.cpu_sqr, {w_seq.waddr == 8'h8; w_seq.wdout == 'd500;})
`uvm_do_on_with(r_seq, p_sequencer.cpu_sqr, {r_seq.raddr == 8'h8;})
`uvm_do_on_with(w_seq, p_sequencer.cpu_sqr, {w_seq.waddr == 8'h0; w_seq.wdout == 'h1;})
`uvm_do_on_with(r_seq, p_sequencer.cpu_sqr, {r_seq.raddr == 8'h0;})
endtask : body
endclass
class cpu_write_and_read1 extends cpu_base_sequence;
read_word_seq r_seq;
write_word_seq w_seq;
logic [9:0] min_pkt_size;
logic [9:0] max_pkt_size;
`uvm_object_utils(cpu_write_and_read1)
function new(string name="cpu_write_and_read1");
super.new(name);
uvm_config_db#(int)::get(uvm_root::get(), "", "min_pkt_size", min_pkt_size);
uvm_config_db#(int)::get(uvm_root::get(), "", "max_pkt_size", max_pkt_size);
if(min_pkt_size == 0) begin
min_pkt_size = 32'd64;
end
if(max_pkt_size == 0) begin
max_pkt_size = 32'd512;
end
endfunction : new
virtual task body();
`uvm_do_with(w_seq, {w_seq.waddr == 8'h4; w_seq.wdout == 'd65;})
`uvm_do_with(r_seq, {r_seq.raddr == 8'h4;})
`uvm_do_with(w_seq, {w_seq.waddr == 8'h8; w_seq.wdout == 'd500;})
`uvm_do_with(r_seq, {r_seq.raddr == 8'h8;})
`uvm_do_with(w_seq, {w_seq.waddr == 8'h0; w_seq.wdout == 'h1;})
`uvm_do_with(r_seq, {r_seq.raddr == 8'h0;})
endtask : body
endclass
`endif
`define __CPU_WRITE_AND_READ_SV__
`include "cpu_base_sequence.sv"
class cpu_write_and_read extends cpu_base_sequence;
read_word_seq r_seq;
write_word_seq w_seq;
logic [9:0] min_pkt_size;
logic [9:0] max_pkt_size;
`uvm_declare_p_sequencer(system_virtual_sequencer)
`uvm_object_utils(cpu_write_and_read)
function new(string name="cpu_write_and_read");
super.new(name);
uvm_config_db#(int)::get(uvm_root::get(), "", "min_pkt_size", min_pkt_size);
uvm_config_db#(int)::get(uvm_root::get(), "", "max_pkt_size", max_pkt_size);
if(min_pkt_size == 0) begin
min_pkt_size = 32'd64;
end
if(max_pkt_size == 0) begin
max_pkt_size = 32'd512;
end
endfunction : new
virtual task body();
`uvm_do_on_with(w_seq, p_sequencer.cpu_sqr, {w_seq.waddr == 8'h4; w_seq.wdout == 'd65;})
`uvm_do_on_with(r_seq, p_sequencer.cpu_sqr, {r_seq.raddr == 8'h4;})
`uvm_do_on_with(w_seq, p_sequencer.cpu_sqr, {w_seq.waddr == 8'h8; w_seq.wdout == 'd500;})
`uvm_do_on_with(r_seq, p_sequencer.cpu_sqr, {r_seq.raddr == 8'h8;})
`uvm_do_on_with(w_seq, p_sequencer.cpu_sqr, {w_seq.waddr == 8'h0; w_seq.wdout == 'h1;})
`uvm_do_on_with(r_seq, p_sequencer.cpu_sqr, {r_seq.raddr == 8'h0;})
endtask : body
endclass
class cpu_write_and_read1 extends cpu_base_sequence;
read_word_seq r_seq;
write_word_seq w_seq;
logic [9:0] min_pkt_size;
logic [9:0] max_pkt_size;
`uvm_object_utils(cpu_write_and_read1)
function new(string name="cpu_write_and_read1");
super.new(name);
uvm_config_db#(int)::get(uvm_root::get(), "", "min_pkt_size", min_pkt_size);
uvm_config_db#(int)::get(uvm_root::get(), "", "max_pkt_size", max_pkt_size);
if(min_pkt_size == 0) begin
min_pkt_size = 32'd64;
end
if(max_pkt_size == 0) begin
max_pkt_size = 32'd512;
end
endfunction : new
virtual task body();
`uvm_do_with(w_seq, {w_seq.waddr == 8'h4; w_seq.wdout == 'd65;})
`uvm_do_with(r_seq, {r_seq.raddr == 8'h4;})
`uvm_do_with(w_seq, {w_seq.waddr == 8'h8; w_seq.wdout == 'd500;})
`uvm_do_with(r_seq, {r_seq.raddr == 8'h8;})
`uvm_do_with(w_seq, {w_seq.waddr == 8'h0; w_seq.wdout == 'h1;})
`uvm_do_with(r_seq, {r_seq.raddr == 8'h0;})
endtask : body
endclass
`endif
./sequence/packet_sequence/packet_base_sequence.sv
`ifndef _PACKET_BASE_SEQUENCE_SV__
`define _PACKET_BASE_SEQUENCE_SV__
virtual class packet_base_sequence extends uvm_sequence #(packet_transaction);
function new(string name="packet_base_sequence");
super.new(name);
set_automatic_phase_objection(1);
endfunction
endclass
class send_one_pkt_seq extends packet_base_sequence;
function new(string name="send_one_pkt_seq");
super.new(name);
endfunction
`uvm_object_utils(send_one_pkt_seq)
rand packet_transaction::head_type pkt_head_type ;
rand packet_transaction::packet_length pkt_packet_length ;
rand logic [6:0 ] frame_interval ;
virtual task body();
`uvm_do_with(req, {req.pkt_head_type == pkt_head_type; req.pkt_packet_length == pkt_packet_length; req.frame_interval == frame_interval;} )
endtask
endclass
`endif
`define _PACKET_BASE_SEQUENCE_SV__
virtual class packet_base_sequence extends uvm_sequence #(packet_transaction);
function new(string name="packet_base_sequence");
super.new(name);
set_automatic_phase_objection(1);
endfunction
endclass
class send_one_pkt_seq extends packet_base_sequence;
function new(string name="send_one_pkt_seq");
super.new(name);
endfunction
`uvm_object_utils(send_one_pkt_seq)
rand packet_transaction::head_type pkt_head_type ;
rand packet_transaction::packet_length pkt_packet_length ;
rand logic [6:0 ] frame_interval ;
virtual task body();
`uvm_do_with(req, {req.pkt_head_type == pkt_head_type; req.pkt_packet_length == pkt_packet_length; req.frame_interval == frame_interval;} )
endtask
endclass
`endif
./sequence/packet_sequence/packet_sequence.sv
`ifndef __PACKET_SEND_PACKETS_SV__
`define __PACKET_SEND_PACKETS_SV__
`include "packet_base_sequence.sv"
class packet_send_packets extends packet_base_sequence;
int itr = 100;
send_one_pkt_seq pkt_seq;
`uvm_declare_p_sequencer(system_virtual_sequencer)
`uvm_object_utils(packet_send_packets)
function new(string name="packet_send_packets");
super.new(name);
endfunction
virtual task body();
//void'(uvm_config_db#(int)::get(null,get_full_name(),"itr", itr));
`uvm_info(get_type_name(), $sformatf("%s starting...itr = %0d", get_sequence_path(), itr), UVM_NONE);
for(int i = 0; i < itr; i++) begin
`uvm_do_on(pkt_seq, p_sequencer.pkt_sqr)
end
endtask : body
endclass
class packet_send_packets1 extends packet_base_sequence;
int itr = 100;
send_one_pkt_seq pkt_seq;
`uvm_object_utils(packet_send_packets1)
function new(string name="packet_send_packets1");
super.new(name);
endfunction
virtual task body();
//void'(uvm_config_db#(int)::get(null,get_full_name(),"itr", itr));
`uvm_info(get_type_name(), $sformatf("%s starting...itr = %0d", get_sequence_path(), itr), UVM_NONE);
for(int i = 0; i < itr; i++) begin
`uvm_do(pkt_seq)
end
endtask : body
endclass
`endif
`define __PACKET_SEND_PACKETS_SV__
`include "packet_base_sequence.sv"
class packet_send_packets extends packet_base_sequence;
int itr = 100;
send_one_pkt_seq pkt_seq;
`uvm_declare_p_sequencer(system_virtual_sequencer)
`uvm_object_utils(packet_send_packets)
function new(string name="packet_send_packets");
super.new(name);
endfunction
virtual task body();
//void'(uvm_config_db#(int)::get(null,get_full_name(),"itr", itr));
`uvm_info(get_type_name(), $sformatf("%s starting...itr = %0d", get_sequence_path(), itr), UVM_NONE);
for(int i = 0; i < itr; i++) begin
`uvm_do_on(pkt_seq, p_sequencer.pkt_sqr)
end
endtask : body
endclass
class packet_send_packets1 extends packet_base_sequence;
int itr = 100;
send_one_pkt_seq pkt_seq;
`uvm_object_utils(packet_send_packets1)
function new(string name="packet_send_packets1");
super.new(name);
endfunction
virtual task body();
//void'(uvm_config_db#(int)::get(null,get_full_name(),"itr", itr));
`uvm_info(get_type_name(), $sformatf("%s starting...itr = %0d", get_sequence_path(), itr), UVM_NONE);
for(int i = 0; i < itr; i++) begin
`uvm_do(pkt_seq)
end
endtask : body
endclass
`endif
./sequence/system_sequence.sv
`ifndef __SYSTEM_SEQUENCE_SV__
`define __SYSTEM_SEQUENCE_SV__
`include "cpu_transaction.sv"
`include "cpu_sequence.sv"
`include "packet_sequence.sv"
//class cpu_rw_and_send_pkts extends uvm_sequence #(uvm_sequence_item);
class cpu_rw_and_send_pkts extends cpu_base_sequence;
cpu_write_and_read cpu_rw;
packet_send_packets send_pkts;
`uvm_object_utils(cpu_rw_and_send_pkts)
function new(string name="cpu_write_and_read");
super.new(name);
cpu_rw = new("cpu configuration");
send_pkts = new("send packets");
endfunction
virtual task body();
`uvm_do(cpu_rw)
`uvm_do(send_pkts)
endtask
endclass
class cpu_rw_and_send_pkts1 extends cpu_base_sequence;
cpu_write_and_read1 cpu_rw;
packet_send_packets1 send_pkts;
`uvm_declare_p_sequencer(system_virtual_sequencer)
`uvm_object_utils(cpu_rw_and_send_pkts1)
function new(string name="cpu_rw_and_send_pkts1");
super.new(name);
cpu_rw = new("cpu configuration");
send_pkts = new("send packets");
endfunction
virtual task body();
`uvm_do_on(cpu_rw, p_sequencer.cpu_sqr)
`uvm_do_on(send_pkts, p_sequencer.pkt_sqr)
endtask
endclass
`endif
`define __SYSTEM_SEQUENCE_SV__
`include "cpu_transaction.sv"
`include "cpu_sequence.sv"
`include "packet_sequence.sv"
//class cpu_rw_and_send_pkts extends uvm_sequence #(uvm_sequence_item);
class cpu_rw_and_send_pkts extends cpu_base_sequence;
cpu_write_and_read cpu_rw;
packet_send_packets send_pkts;
`uvm_object_utils(cpu_rw_and_send_pkts)
function new(string name="cpu_write_and_read");
super.new(name);
cpu_rw = new("cpu configuration");
send_pkts = new("send packets");
endfunction
virtual task body();
`uvm_do(cpu_rw)
`uvm_do(send_pkts)
endtask
endclass
class cpu_rw_and_send_pkts1 extends cpu_base_sequence;
cpu_write_and_read1 cpu_rw;
packet_send_packets1 send_pkts;
`uvm_declare_p_sequencer(system_virtual_sequencer)
`uvm_object_utils(cpu_rw_and_send_pkts1)
function new(string name="cpu_rw_and_send_pkts1");
super.new(name);
cpu_rw = new("cpu configuration");
send_pkts = new("send packets");
endfunction
virtual task body();
`uvm_do_on(cpu_rw, p_sequencer.cpu_sqr)
`uvm_do_on(send_pkts, p_sequencer.pkt_sqr)
endtask
endclass
`endif
./test/test.sv
`ifndef __TEST_SV__
`define __TEST_SV__
`include "env.sv"
`include "cpu_sequence.sv"
`include "packet_sequence.sv"
`include "system_sequence.sv"
class base_test extends uvm_test;
env tb_env;
bit test_pass = 1;
uvm_table_printer printer;
`uvm_component_utils(base_test)
function new(string name="base_test", uvm_component parent=null);
super.new(name, parent);
uvm_config_db#(int)::set(uvm_root::get(), "*", "min_pkt_size", 'd65);
uvm_config_db#(int)::set(uvm_root::get(), "*", "max_pkt_size", 'd500);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
tb_env = env::type_id::create("tb_env", this);
printer = new();
endfunction
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
`uvm_info(get_type_name(),$sformatf("Printing the test topology :\n%s", this.sprint(printer)), UVM_LOW)
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
endtask
function void extract_phase(uvm_phase phase);
super.extract_phase(phase);
if(tb_env.u_cpu_env.cpu_sb.sbd_error || tb_env.u_pkt_env.pkt_sb.sbd_error || tb_env.u_pkt_env.pkt_sb.ref_pkt_tran.size() != 0) begin
test_pass = 0;
end
endfunction
function void report_phase(uvm_phase phase);
super.report_phase(phase);
if(test_pass) begin
`uvm_info(get_type_name(), "** UVM TEST PASSED **", UVM_NONE)
end
else begin
`uvm_error(get_type_name(), "** UVM TEST FAIL **")
end
endfunction
endclass
class test extends base_test;
`uvm_component_utils(test)
function new(string name="test", uvm_component parent=null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
cpu_rw_and_send_pkts cpu_and_pkt;
super.build_phase(phase);
cpu_and_pkt = cpu_rw_and_send_pkts::type_id::create();
uvm_config_db#(uvm_sequence_base)::set(this, "tb_env.sys_vir_sqr.main_phase", "default_sequence", cpu_and_pkt);
endfunction
endclass
class test3 extends base_test;
`uvm_component_utils(test3)
function new(string name="test3", uvm_component parent=null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
cpu_rw_and_send_pkts1 cpu_and_pkt;
super.build_phase(phase);
cpu_and_pkt = cpu_rw_and_send_pkts1::type_id::create();
uvm_config_db#(uvm_sequence_base)::set(this, "tb_env.sys_vir_sqr.main_phase", "default_sequence", cpu_and_pkt);
endfunction
endclass
`endif
`define __TEST_SV__
`include "env.sv"
`include "cpu_sequence.sv"
`include "packet_sequence.sv"
`include "system_sequence.sv"
class base_test extends uvm_test;
env tb_env;
bit test_pass = 1;
uvm_table_printer printer;
`uvm_component_utils(base_test)
function new(string name="base_test", uvm_component parent=null);
super.new(name, parent);
uvm_config_db#(int)::set(uvm_root::get(), "*", "min_pkt_size", 'd65);
uvm_config_db#(int)::set(uvm_root::get(), "*", "max_pkt_size", 'd500);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
tb_env = env::type_id::create("tb_env", this);
printer = new();
endfunction
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
`uvm_info(get_type_name(),$sformatf("Printing the test topology :\n%s", this.sprint(printer)), UVM_LOW)
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
endtask
function void extract_phase(uvm_phase phase);
super.extract_phase(phase);
if(tb_env.u_cpu_env.cpu_sb.sbd_error || tb_env.u_pkt_env.pkt_sb.sbd_error || tb_env.u_pkt_env.pkt_sb.ref_pkt_tran.size() != 0) begin
test_pass = 0;
end
endfunction
function void report_phase(uvm_phase phase);
super.report_phase(phase);
if(test_pass) begin
`uvm_info(get_type_name(), "** UVM TEST PASSED **", UVM_NONE)
end
else begin
`uvm_error(get_type_name(), "** UVM TEST FAIL **")
end
endfunction
endclass
class test extends base_test;
`uvm_component_utils(test)
function new(string name="test", uvm_component parent=null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
cpu_rw_and_send_pkts cpu_and_pkt;
super.build_phase(phase);
cpu_and_pkt = cpu_rw_and_send_pkts::type_id::create();
uvm_config_db#(uvm_sequence_base)::set(this, "tb_env.sys_vir_sqr.main_phase", "default_sequence", cpu_and_pkt);
endfunction
endclass
class test3 extends base_test;
`uvm_component_utils(test3)
function new(string name="test3", uvm_component parent=null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
cpu_rw_and_send_pkts1 cpu_and_pkt;
super.build_phase(phase);
cpu_and_pkt = cpu_rw_and_send_pkts1::type_id::create();
uvm_config_db#(uvm_sequence_base)::set(this, "tb_env.sys_vir_sqr.main_phase", "default_sequence", cpu_and_pkt);
endfunction
endclass
`endif
./env/top.sv
`timescale 1ns/1ps
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "cpu_interface.svi"
`include "packet_interface.svi"
`include "test.sv"
module top;
parameter clock_cycle = 10;
logic clk;
logic rst_n;
cpu_interface cpu_intf(clk, rst_n);
packet_interface pkt_intf(clk, rst_n);
dut u_dut (
.clk (clk ) ,
.rst_n (rst_n ) ,
.addr (cpu_intf.addr ) ,
.rw (cpu_intf.rw ) ,
.enable (cpu_intf.enable ) ,
.din (cpu_intf.dout ) ,
.dout (cpu_intf.din ) ,
.txd (pkt_intf.rxd ) ,
.tx_vld (pkt_intf.rx_vld ) ,
.rxd (pkt_intf.txd ) ,
.rx_vld (pkt_intf.tx_vld )
);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(clock_cycle/2) clk = ~clk;
end
end
initial begin
rst_n = 1'b1;
repeat(10) @(posedge clk);
rst_n = 1'b0;
repeat(10) @(posedge clk);
rst_n = 1'b1;
end
initial begin
uvm_config_db#(virtual cpu_interface)::set(uvm_root::get(), "*", "cpu_vif", cpu_intf);
uvm_config_db#(virtual packet_interface)::set(uvm_root::get(), "*", "pkt_vif", pkt_intf);
run_test();
end
`ifdef WAVE_ON
initial begin
//$dumpfile("wave.vcd");
//$dumpvars(0, top);
end
`endif
endmodule
`include "uvm_macros.svh"
import uvm_pkg::*;
`include "cpu_interface.svi"
`include "packet_interface.svi"
`include "test.sv"
module top;
parameter clock_cycle = 10;
logic clk;
logic rst_n;
cpu_interface cpu_intf(clk, rst_n);
packet_interface pkt_intf(clk, rst_n);
dut u_dut (
.clk (clk ) ,
.rst_n (rst_n ) ,
.addr (cpu_intf.addr ) ,
.rw (cpu_intf.rw ) ,
.enable (cpu_intf.enable ) ,
.din (cpu_intf.dout ) ,
.dout (cpu_intf.din ) ,
.txd (pkt_intf.rxd ) ,
.tx_vld (pkt_intf.rx_vld ) ,
.rxd (pkt_intf.txd ) ,
.rx_vld (pkt_intf.tx_vld )
);
initial begin
$timeformat(-9, 1, "ns", 10);
clk = 0;
forever begin
#(clock_cycle/2) clk = ~clk;
end
end
initial begin
rst_n = 1'b1;
repeat(10) @(posedge clk);
rst_n = 1'b0;
repeat(10) @(posedge clk);
rst_n = 1'b1;
end
initial begin
uvm_config_db#(virtual cpu_interface)::set(uvm_root::get(), "*", "cpu_vif", cpu_intf);
uvm_config_db#(virtual packet_interface)::set(uvm_root::get(), "*", "pkt_vif", pkt_intf);
run_test();
end
`ifdef WAVE_ON
initial begin
//$dumpfile("wave.vcd");
//$dumpvars(0, top);
end
`endif
endmodule
./script/do.tcl
add wave -r /*
run -all
exit
run -all
exit
./script/Makefile
ifeq ($(GUI), 1)
GUI_ARG = -gui
endif
PROJECT_DIR = /mnt/uvm
RTL_DIR = $(PROJECT_DIR)/rtl
RTL = $(RTL_DIR)/dut.v
TB_DIR = $(PROJECT_DIR)/env
INCDIR = +incdir+$(TB_DIR)
CPU_INTF_TB_DIR = $(TB_DIR)/cpu_interface_env
INCDIR += +incdir+$(CPU_INTF_TB_DIR)
PKT_TB_DIR = $(TB_DIR)/packet_env
INCDIR += +incdir+$(PKT_TB_DIR)
SEQUENCE_DIR = $(PROJECT_DIR)/sequence
INCDIR += +incdir+$(SEQUENCE_DIR)
CPU_SEQUENCE_DIR = $(SEQUENCE_DIR)/cpu_interface_sequence
INCDIR += +incdir+$(CPU_SEQUENCE_DIR)
PACKET_SEQUENCE_DIR = $(SEQUENCE_DIR)/packet_sequence
INCDIR += +incdir+$(PACKET_SEQUENCE_DIR)
UVM_TB_TOP = $(TB_DIR)/top.sv
TEST_DIR = $(PROJECT_DIR)/test
TEST_FILE = $(TEST_DIR)/test.sv
INCDIR += +incdir+$(TEST_DIR)
COMPILE_LOG_ARG = -l vcs.log
WAVE_ARG = +define+WAVE_ON=1
UVM_COMPILE_ARG = +incdir+/mnt/uvm/uvm-1.2/src /mnt/uvm/uvm-1.2/src/uvm.sv
COMPILE_ARG = -sv -novopt
COMPILE_ARG += $(UVM_COMPILE_ARG) $(INCDIR) $(COMPILE_LOG_ARG) $(WAVE_ARG)
RUN_LOG_ARG = -l simv.log
SCRIPT_DIR = $(PROJECT_DIR)/script
RUN_TCL = $(SCRIPT_DIR)/do.tcl
RUN_ARG = $(RUN_LOG_ARG) $(GUI_ARG)
RUN_ARG += +UVM_TESTNAME=test +UVM_VERBOSITY=UVM_FULL -c -novopt -sv_lib lib/uvm_dpi work.top -do $(RUN_TCL) -wlf wave.wlf
SEED = 1
MIT_HOME = /home/tools/questasim/questasim/include
UVM_DPI_DIR = /mnt/uvm/uvm-1.2/src/dpi
UVM_DPI_FILE = /mnt/uvm/uvm-1.2/src/dpi/uvm_dpi.cc
UVM_DPI_COMPILE_ARG = -m32 -fPIC -DQUESTA -g -W -shared
UVM_DPI_COMPILE_ARG += -I$(MIT_HOME) -I$(UVM_DPI_DIR) $(UVM_DPI_FILE)
default: test
test: lib/uvm_dpi.so compile run
run:
vsim $(RUN_ARG)
compile:
if [ ! -d work ]; then vlib work; fi;
vlog $(COMPILE_ARG) $(UVM_TB_TOP) $(RTL)
lib/uvm_dpi.so:
if [ ! -d lib ]; then mkdir lib; fi
g++ $(UVM_DPI_COMPILE_ARG) -o $@
clean:
rm -rf simv simv.* *log