目录
1.1实现apb_master_driver的drive_transfer()
1.3编写apb_master_monitor中的collect_transfer()
1.2编写apb_master_sequence中的apb_master_write_seq::body()任务
1.4编写apb_slave_driver的drive_response()
这里涉及的是VIP的开发和MCDF用APB改造。
MCDF改造
所有的接口都发生了改变,对应在硬件中都做了修改。
APB接口
特点是一总(AHB或者AXI)多从,1总通过APB桥发放到后面的多从slave;2个clk完成1次W/R操作,用状态机表示为idle->setup->enable
验证环境的改造
由于接口几乎全部被更新,所以mcdf这一层的接口和tb的接口也需要做相应的更改。
这里似乎没有涉及到env的问题,等下看看具体代码。
实战任务
直接看到APB部分的文件夹,可以看到文件数量大大增加,采取了`include的方式将文件分开了。
apb_pkg只有简单的几行代码,信息都包含在别的文件中。
`ifndef APB_PKG_SV
`define APB_PKG_SV
package apb_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "apb.svh"
endpackage : apb_pkg
`endif // `ifndef APB_PKG_SV
apb_pkg include了apb.svh,而后者include了主从的各个组件的sv和svh文件。
`ifndef APB_SVH
`define APB_SVH
`include "apb_transfer.sv"
`include "apb_config.sv"
`include "apb_master_driver.svh"
`include "apb_master_monitor.svh"
`include "apb_master_sequencer.svh"
`include "apb_master_agent.svh"
`include "apb_slave_driver.svh"
`include "apb_slave_monitor.svh"
`include "apb_slave_sequencer.svh"
`include "apb_slave_agent.svh"
`include "apb_master_driver.sv"
`include "apb_master_monitor.sv"
`include "apb_master_sequencer.sv"
`include "apb_master_agent.sv"
`include "apb_master_seq_lib.sv"
`include "apb_slave_driver.sv"
`include "apb_slave_monitor.sv"
`include "apb_slave_sequencer.sv"
`include "apb_slave_agent.sv"
`include "apb_slave_seq_lib.sv"
`endif // `ifndef APB_SVH
在apb_tb中,include了test.svh和if.sv,要跑起仿真只需要编译pkg和tb即可(其他文件都被include了,其实也会被编译到)。tb只做了接口的配置
`timescale 1ps/1ps
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "apb_tests.svh"
`include "apb_if.sv"
module apb_tb;
bit clk, rstn;
initial begin
fork
begin
forever #5ns clk = !clk;
end
begin
#100ns;
rstn <= 1'b1;
#100ns;
rstn <= 1'b0;
#100ns;
rstn <= 1'b1;
end
join_none
end
apb_if intf(clk, rstn);
initial begin
uvm_config_db#(virtual apb_if)::set(uvm_root::get(), "uvm_test_top.env.mst", "vif", intf);
uvm_config_db#(virtual apb_if)::set(uvm_root::get(), "uvm_test_top.env.slv", "vif", intf);
run_test("apb_single_transaction_test");
end
endmodule
在apb_if中,包括了接口+时钟块,覆盖组covergroup。接口信号按照时序图给出,时钟块分为master和slave,信号的方向互补,monitor的时钟块所有信号都是input。
这里又遇到覆盖率收集的问题,复习一下。定义覆盖组后再initial块中例化各个覆盖组。
https://mp.csdn.net/mp_blog/creation/editor/125731520
`ifndef APB_IF_SV
`define APB_IF_SV
interface apb_if (input clk, input rstn);
logic [31:0] paddr;
logic pwrite;
logic psel;
logic penable;
logic [31:0] pwdata;
logic [31:0] prdata;
// Control flags
bit has_checks = 1;
bit has_coverage = 1;
// Actual Signals
// USER: Add interface signals
clocking cb_mst @(posedge clk);
// USER: Add clocking block detail
default input #1ps output #1ps;
output paddr, pwrite, psel, penable, pwdata;
input prdata;
endclocking : cb_mst
clocking cb_slv @(posedge clk);
// USER: Add clocking block detail
default input #1ps output #1ps;
input paddr, pwrite, psel, penable, pwdata;
output prdata;
endclocking : cb_slv
clocking cb_mon @(posedge clk);
// USER: Add clocking block detail
default input #1ps output #1ps;
input paddr, pwrite, psel, penable, pwdata, prdata;
endclocking : cb_mon
// Coverage and assertions to be implemented here.
// USER: Add assertions/coverage here
// APB command covergroup
covergroup cg_apb_command @(posedge clk iff rstn);
pwrite: coverpoint pwrite{
type_option.weight = 0;
bins write = {1};
bins read = {0};
}
psel : coverpoint psel{
type_option.weight = 0;
bins sel = {1};
bins unsel = {0};
}
cmd : cross pwrite, psel{
bins cmd_write = binsof(psel.sel) && binsof(pwrite.write);
bins cmd_read = binsof(psel.sel) && binsof(pwrite.read);
bins cmd_idle = binsof(psel.unsel);
}
endgroup
// APB transaction timing group
covergroup cg_apb_trans_timing_group @(posedge clk iff rstn);
psel: coverpoint psel{
bins single = (0 => 1 => 1 => 0);
bins burst_2 = (0 => 1 [*4] => 0);
bins burst_4 = (0 => 1 [*8] => 0);
bins burst_8 = (0 => 1 [*16] => 0);
bins burst_16 = (0 => 1 [*32] => 0);
bins burst_32 = (0 => 1 [*64] => 0);
}
penable: coverpoint penable {
bins single = (0 => 1 => 0 [*2:10] => 1);
bins burst = (0 => 1 => 0 => 1);
}
endgroup
// APB write & read order group
covergroup cg_apb_write_re