`ifndef APB_IF_SV
`define APB_IF_SV
// 定义一个名为 apb_if 的接口,该接口包含了 APB 总线的所有信号和一些控制标志
interface apb_if (input clk, input rstn);
// APB 总线信号
logic [31:0] paddr; // 地址
logic pwrite; // 写使能
logic psel; // 选择信号
logic penable; // 使能信号
logic [31:0] pwdata; // 写数据
logic [31:0] prdata; // 读数据
// 控制标志
bit has_checks = 1; // 是否启用检查
bit has_coverage = 1; // 是否启用覆盖率收集
// 实际信号 (用户自定义)
// USER: Add interface signals
// Master 端的时钟块
clocking cb_mst @(posedge clk);
// USER: Add clocking block detail
// 设置默认的输入输出延迟为 1ps
default input #1ps output #1ps;
// Master 端输出信号
output paddr, pwrite, psel, penable, pwdata;
// Master 端输入信号
input prdata;
endclocking : cb_mst
// Slave 端的时钟块
clocking cb_slv @(posedge clk);
// USER: Add clocking block detail
// 设置默认的输入输出延迟为 1ps
default input #1ps output #1ps;
// Slave 端输入信号
input paddr, pwrite, psel, penable, pwdata;
// Slave 端输出信号
output prdata;
endclocking : cb_slv
// Monitor 端的时钟块
clocking cb_mon @(posedge clk);
// USER: Add clocking block detail
// 设置默认的输入输出延迟为 1ps
default input #1ps output #1ps;
// Monitor 端输入信号
input paddr, pwrite, psel, penable, pwdata, prdata;
endclocking : cb_mon
// 覆盖率和断言 (用户自定义)
// USER: Add assertions/coverage here
// APB 命令覆盖率分组
covergroup cg_apb_command @(posedge clk iff rstn); // 仅在复位释放后采样
// 覆盖 pwrite 信号
pwrite: coverpoint pwrite{
type_option.weight = 0; // 设置权重为 0,表示所有 bin 的权重相同
bins write = {1}; // 写操作 bin
bins read = {0}; // 读操作 bin
}
// 覆盖 psel 信号
psel : coverpoint psel{
type_option.weight = 0; // 设置权重为 0
bins sel = {1}; // 选择 bin
bins unsel = {0}; // 未选择 bin
}
// 覆盖 pwrite 和 psel 的组合
cmd : cross pwrite, psel{
bins cmd_write = binsof(psel.sel) && binsof(pwrite.write); // 写命令 bin
bins cmd_read = binsof(psel.sel) && binsof(pwrite.read); // 读命令 bin
bins cmd_idle = binsof(psel.unsel); // 空闲 bin
}
endgroup
// APB 事务时序覆盖率分组
covergroup cg_apb_trans_timing_group @(posedge clk iff rstn); // 仅在复位释放后采样
// 覆盖 psel 信号的时序
psel: coverpoint psel{
bins single = (0 => 1 => 1 => 0); // 单次事务
bins burst_2 = (0 => 1 [*4] => 0); // 2 次 burst 事务
bins burst_4 = (0 => 1 [*8] => 0); // 4 次 burst 事务
bins burst_8 = (0 => 1 [*16] => 0); // 8 次 burst 事务
bins burst_16 = (0 => 1 [*32] => 0); // 16 次 burst 事务
bins burst_32 = (0 => 1 [*64] => 0); // 32 次 burst 事务
}
// 覆盖 penable 信号的时序
penable: coverpoint penable {
bins single = (0 => 1 => 0 [*2:10] => 1); // 单次事务
bins burst = (0 => 1 => 0 => 1); // burst 事务
}
endgroup
// APB 写和读顺序覆盖率分组
covergroup cg_apb_write_read_order_group @(posedge clk iff (rstn && penable)); // 仅在复位释放且使能时采样
// 覆盖 pwrite 信号的顺序
write_read_order: coverpoint pwrite{
bins write_write = (1 => 1); // 连续写操作
bins write_read = (1 => 0); // 写后读操作
bins read_write = (0 => 1); // 读后写操作
bins read_read = (0 => 0); // 连续读操作
}
endgroup
// 实例化覆盖率分组,方便使用
initial begin
automatic cg_apb_command cg0 = new();
automatic cg_apb_trans_timing_group cg1 = new();
automatic cg_apb_write_read_order_group cg2 = new();
end
endinterface : apb_if
`endif // APB_IF_SV
这段代码定义了一个 APB 总线接口,并包含了三个 covergroup 用于收集覆盖率数据:
cg_apb_command: 收集 APB 命令 (pwrite 和 psel) 的覆盖率。
cg_apb_trans_timing_group: 收集 APB 事务时序的覆盖率,例如单次事务和不同长度的 burst 事务。
cg_apb_write_read_order_group: 收集 APB 写和读操作顺序的覆盖率。
接口还定义了 master、slave 和 monitor 的 clocking block,以及一些控制标志。 [*n] 在 bins 定义中表示重复 n 次。 iff rstn 表示只有在 rstn 为高电平(非复位状态)时才进行采样。 has_checks 和 has_coverage 是可配置的标志位,允许用户启用或禁用检查和覆盖率收集。 automatic 用于声明局部变量,在函数结束时自动释放内存。 这个接口定义了 APB 总线的信号和覆盖率收集机制,方便在 UVM 验证环境中复用。