目录
1.target_address_and_slave_address_cg
3.bits7_or_bits10_addressing_cg
11.interrupt_hardware_outputs_cg
12.interrupt_tx_abort_sources_cg
功能覆盖率包含哪些?
1.target_address_and_slave_address_cg
对于TAR和SAR寄存器中值的采样,分为10BIT和7BIT地址进行采样,采样时只关心高bit位就行,因为一般高bit位容易被截取,所以采用wildcard bins来进行定义,无关的bit位采用x来代替:
covergroup target_address_and_slave_address_cg with function sample(bit[9:0]addr, string field);
option.name = "target_address_and_slave_address_cg";
TAR_BITS10: coverpoint addr[9:7] iff(field == "TAR"){
wildcard bins range1 = {3'b1xx};
wildcard bins range2 = {3'b0xx};
}
TAR_BITS7: coverpoint addr[6:0] iff(field == "TAR"){
wildcard bins range1 = {7'b1xx_xxxx};
wildcard bins range2 = {7'b0xx_xxxx};
}
SAR_BITS10: coverpoint addr[9:7] iff(field == "SAR"){
wildcard bins range1 = {3'b1xx};
wildcard bins range2 = {3'b0xx};
}
SAR_BITS7: coverpoint addr[6:0] iff(field == "SAR"){
wildcard bins range1 = {7'b1xx_xxxx};
wildcard bins range2 = {7'b0xx_xxxx};
}
endgroup
2.speed_modes_cg
对不同的速度模式进行采样,对应IC_CON[2:1]的SPEED域,还有对应的HCNT和LCNT,根据SSmode频率<=100Kb,FSmode<=400Kb,HSmode<=3.4Mb,来合理的设计边界的bin值,SSmode下:HCNT+LCNT>=100MHz/100Kb=1000
FSmode下:HCNT+LCNT>=100MHz/400Kb=250
HSmode下:HCNT+LCNT>=100MHz/3.4Mb~30
covergroup speed_modes_cg with function sample(bit[15:0] val, string field);
option.name = "speed_modes_cg";
SPEED: coverpoint val iff(field == "SPEED") {
bins standard = {1};
bins fast = {2};
bins high = {3};
}
// In SS mode, the frequency of SCL is 0 - 100 Kbs
// To ensure that there is no 0 rate in the actual situation and the sim
// does not time out, we just test 50 - 100 Kbs
// Refer to the period of i2c_clk 100 MHz
// Fastest:
// The count value is 100MHz / 100Kbs = 1000 = SS_SCL_HCNT + SS_SCL_LCNT
// Slowest:
// The count value is 100MHz / 50Kbs = 2000 = SS_SCL_HCNT + SS_SCL_LCNT
SS_SCL_HCNT: coverpoint val iff(field == "SS_SCL_HCNT") {
bins max = {[800:1000]};
bins min = {[500:600]};
}
SS_SCL_LCNT: coverpoint val iff(field == "SS_SCL_LCNT") {
bins max = {[800:1000]};
bins min = {[500:600]};
}
// In FS mode, the frequency of SCL is <= 400 Kbs
// To ensure frequency FS > SS, we just test 100 - 400 Kbs
// Refer to the period of i2c_clk 100MHz
// Fastest:
// The count value is 100MHz / 400Kbs = 250 = FS_SCL_HCNT + FS_SCL_LCNT
// Slowest:
// The count value is 100MHz / 100Kbs = 1000 = FS_SCL_HCNT + FS_SCL_LCNT
FS_SCL_HCNT: coverpoint val iff(field == "FS_SCL_HCNT") {
bins max = {[400:500]};
bins min = {[125:150]};
}
FS_SCL_LCNT: coverpoint val iff(field == "FS_SCL_LCNT") {
bins max = {[400:500]};
bins min = {[125:150]};
}
// In HS mode, the frequency of SCL is <= 3.4 Mbs
// To ensure frequency of HS, we test 1 - 3.4 Mbs
// Refer to the period of i2c_clk 100MHz
// Fastest:
// The count value is 100MHz / 3.4Mbs ~= 30 = HS_SCL_HCNT + HS_SCL_LCNT
// Slowest:
// The count value is 100MHz / 1Mbs = 100 = HS_SCL_HCNT + HS_SCL_LCNT
HS_SCL_HCNT: coverpoint val iff(field == "HS_SCL_HCNT") {
bins max = {[40:50]};
bins min = {[15:20]};
}
HS_SCL_LCNT: coverpoint val iff(field == "HS_SCL_LCNT") {
bins max = {[40:50]};
bins min = {[15:20]};
}
endgroup
3.bits7_or_bits10_addressing_cg
7bit地址和10bit地址的使能,对应的寄存器的域是IC_CON[4]IC_10BITADDR_MASTER。
covergroup bits7_or_bits10_addressing_cg with function sample(bit bits10);
option.name = "bits7_or_bits10_addressing_cg";
BITS7_OR_BITS10: coverpoint bits10{
bins bits7 = {0};
bins bits10 = {1};
}
endgroup
4.restart_condition_cg
restart的使能,对应寄存器域是IC_CON[5]IC_RESTART_EN。
covergroup restart_condition_cg with function sample(bit rt);
option.name = "restart_condition_cg";
RESTART: coverpoint rt {
bins disabled = {0};
bins enabled = {1};
}
endgroup
5.activity_cg
I2C处于的状态,需要查看两个域,一个是IC_STATUS[0]ACTIVITY,一个是IC_STATUS[5]MST_ACTIVITY。
covergroup activity_cg with function sample(bit act, string field);
option.name = "activity_cg";
ACTIVITY: coverpoint act iff(field == "ACTIVITY") {
bins idle = {0};
bins busy = {1};
}
MST_ACTIVITY: coverpoint act iff(field == "MST_ACTIVITY") {
bins idle = {0};
bins busy = {1};
}
endgroup
6.enabled_cg
I2C的使能信号,需要查看两个寄存器的域,一个是控制寄存器IC_ENABLE[0]ENABLE,一个是状态寄存器IC_ENABLE_STATUS[0]IC_EN。
covergroup enabled_cg with function sample(bit en, string field);
option.name = "enabled_cg";
ENABLE_CTRL: coverpoint en iff(field == "ENABLE") {
bins dis = {0};
bins en = {1};
}
ENABLE_STATUS: coverpoint en iff(field == "IC_EN") {
bins dis = {0};
bins en = {1};
}
endgroup
7.tx_fifo_status_cg
TX FIFO的状态通过状态寄存器IC_STATUS[1]TFNF和IC_STATUS[2]TFE来获取TX_FIFO是空还是满。
covergroup tx_fifo_status_cg with function sample(bit empty, bit nfull);
option.name = "tx_fifo_status_cg";
EMPTY: coverpoint empty {
bins empty = {1};
bins not_empty = {0};
}
NOT_FULL: coverpoint nfull {
bins not_full = {1};
bins full = {0};
}
endgroup
8.rx_fifo_status_cg
RX FIFO的状态通过状态寄存器IC_STATUS[3]RFNE和IC_STATUS[4]RFF来获取RX_FIFO是空还是满。
covergroup rx_fifo_status_cg with function sample(bit full, bit nempty);
option.name = "rx_fifo_status_cg";
FULL: coverpoint full {
bins full = {1};
bins not_full = {0};
}
NOT_EMPTY: coverpoint nempty {
bins not_empty = {1};
bins empty = {0};
}
endgroup
9.interrupt_status_cg
14个中断状态的检测,通过访问中断的状态寄存器IC_INTR_STAT来获取对应的中断。
covergroup interrupt_status_cg with function sample(bit[13:0] stat);
option.name = "interrupt_status_cg";
STATUS: coverpoint stat{
wildcard bins MASTER_ON_HOLD = {14'b1x_xxxx_xxxx_xxxx};
wildcard bins RESTART_DET = {14'bx1_xxxx_xxxx_xxxx};
wildcard bins GEN_CALL = {14'bxx_1xxx_xxxx_xxxx};
wildcard bins START_DET = {14'bxx_x1xx_xxxx_xxxx};
wildcard bins STOP_DET = {14'bxx_xx1x_xxxx_xxxx};
wildcard bins ACTIVITY = {14'bxx_xxx1_xxxx_xxxx};
wildcard bins RX_DONE = {14'bxx_xxxx_1xxx_xxxx};
wildcard bins TX_ABRT = {14'bxx_xxxx_x1xx_xxxx};
wildcard bins RD_REQ = {14'bxx_xxxx_xx1x_xxxx};
wildcard bins TX_EMPTY = {14'bxx_xxxx_xxx1_xxxx};
wildcard bins TX_OVER = {14'bxx_xxxx_xxxx_1xxx};
wildcard bins RX_FULL = {14'bxx_xxxx_xxxx_x1xx};
wildcard bins RX_OVER = {14'bxx_xxxx_xxxx_xx1x};
wildcard bins RX_UNDER = {14'bxx_xxxx_xxxx_xxx1};
}
endgroup
10.interrupt_clear_cg
对于中断的清除,采用对对应中断清除寄存器做读操作来进行,由于直接对寄存器的访问无法判断中断是否发生,所以需要在测试时,先判断中断是否发生,再进行中断的清除。
covergroup interrupt_clear_cg with function sample(bit clr, string field);
option.name = "interrupt_clear_cg";
CLR_INTR : coverpoint clr iff(field == "CLR_INTR") { bins clr = {1};}
CLR_RX_UNDER : coverpoint clr iff(field == "CLR_RX_UNDER") { bins clr = {1};}
CLR_RX_OVER : coverpoint clr iff(field == "CLR_RX_OVER") { bins clr = {1};}
CLR_TX_OVER : coverpoint clr iff(field == "CLR_TX_OVER") { bins clr = {1};}
CLR_RD_REQ : coverpoint clr iff(field == "CLR_RD_REQ") { bins clr = {1};}
CLR_TX_ABRT : coverpoint clr iff(field == "CLR_TX_ABRT") { bins clr = {1};}
CLR_RX_DONE : coverpoint clr iff(field == "CLR_RX_DONE") { bins clr = {1};}
CLR_ACTIVITY : coverpoint clr iff(field == "CLR_ACTIVITY") { bins clr = {1};}
CLR_STOP_DET : coverpoint clr iff(field == "CLR_STOP_DET") { bins clr = {1};}
CLR_START_DET : coverpoint clr iff(field == "CLR_START_DET") { bins clr = {1};}
CLR_GEN_CALL : coverpoint clr iff(field == "CLR_GEN_CALL") { bins clr = {1};}
endgroup
11.interrupt_hardware_outputs_cg
中断输出的硬件信号,检查中断输出端口的信号是否都拉高过。
covergroup interrupt_hardware_outputs_cg with function sample(bit[IC_INTR_NUM-1:0] intr);
option.name = "interrupt_hardware_outputs_cg";
INTERRUPT: coverpoint intr{
wildcard bins IC_RX_OVER_INTR_ID = {12'bxxxx_xxxx_xxx1};
wildcard bins IC_RX_UNDER_INTR_ID = {12'bxxxx_xxxx_xx1x};
wildcard bins IC_TX_OVER_INTR_ID = {12'bxxxx_xxxx_x1xx};
wildcard bins IC_TX_ABRT_INTR_ID = {12'bxxxx_xxxx_1xxx};
wildcard bins IC_RX_DONE_INTR_ID = {12'bxxxx_xxx1_xxxx};
wildcard bins IC_TX_EMPTY_INTR_ID = {12'bxxxx_xx1x_xxxx};
wildcard bins IC_ACTIVITY_INTR_ID = {12'bxxxx_x1xx_xxxx};
wildcard bins IC_STOP_DET_INTR_ID = {12'bxxxx_1xxx_xxxx};
wildcard bins IC_START_DET_INTR_ID = {12'bxxx1_xxxx_xxxx};
wildcard bins IC_RD_REQ_INTR_ID = {12'bxx1x_xxxx_xxxx};
wildcard bins IC_RX_FULL_INTR_ID = {12'bx1xx_xxxx_xxxx};
wildcard bins IC_GEN_CALL_INTR_ID = {12'b1xxx_xxxx_xxxx};
}
endgroup
12.interrupt_tx_abort_sources_cg
TX ABRT中断源的测试,对对应的IC_TX_ABRT_SOURCE进行访问。
covergroup interrupt_tx_abort_sources_cg with function sample(bit[16:0]src);
option.name = "interrupt_tx_abort_sources_cg";
ABORT_SOURCES: coverpoint src {
wildcard bins ABRT_USER_ABRT = {17'b1_xxxx_xxxx_xxxx_xxxx};
wildcard bins ABRT_SLVRD_INTX = {17'bx_1xxx_xxxx_xxxx_xxxx};
wildcard bins ABRT_SLV_ARBLOST = {17'bx_x1xx_xxxx_xxxx_xxxx};
wildcard bins ABRT_SLVFLUSH_TXFIFO = {17'bx_xx1x_xxxx_xxxx_xxxx};
wildcard bins ARB_LOST = {17'bx_xxx1_xxxx_xxxx_xxxx};
wildcard bins ABRT_MASTER_DIS = {17'bx_xxxx_1xxx_xxxx_xxxx};
wildcard bins ABRT_10B_RD_NORSTRT = {17'bx_xxxx_x1xx_xxxx_xxxx};
wildcard bins ABRT_SBYTE_NORSTRT = {17'bx_xxxx_xx1x_xxxx_xxxx};
wildcard bins ABRT_HS_NORSTRT = {17'bx_xxxx_xxx1_xxxx_xxxx};
wildcard bins ABRT_SBYTE_ACKDET = {17'bx_xxxx_xxxx_1xxx_xxxx};
wildcard bins ABRT_HS_ACKDET = {17'bx_xxxx_xxxx_x1xx_xxxx};
wildcard bins ABRT_GCALL_READ = {17'bx_xxxx_xxxx_xx1x_xxxx};
wildcard bins ABRT_GCALL_NOACK = {17'bx_xxxx_xxxx_xxx1_xxxx};
wildcard bins ABRT_TXDATA_NOACK = {17'bx_xxxx_xxxx_xxxx_1xxx};
wildcard bins ABRT_10ADDR2_NOACK = {17'bx_xxxx_xxxx_xxxx_x1xx};
wildcard bins ABRT_10ADDR1_NOACK = {17'bx_xxxx_xxxx_xxxx_xx1x};
wildcard bins ABRT_7B_ADDR_NOACK = {17'bx_xxxx_xxxx_xxxx_xxx1};
}
endgroup
13.sda_control_cg
SDA的建立时间和保持时间,访问控制寄存器IC_SDA_HOLD[15:0]IC_SDA_TX_HOLD和IC_SDA_HOLD[23:16]IC_SDA_RX_HOLD来获取作为transmitter和receiver的保持时间,保持时间发生在SCL拉低的器件,且保持时间最大不能超过SCL_LCNT-2。建立时间访问IC_SDA_SETUP[7:0]SDA_SETUP来获得。
covergroup sda_control_cg with function sample(bit[7:0]rxh, bit[15:0] txh, bit[7:0] stp, string field);
option.name = "sda_control_cg";
RX_HOLD: coverpoint rxh iff(field == "SDA_HOLD"){
bins MAX = {[100:$]};
bins NORMAL = {[10:99]};
bins MIN = {[1:9]};
}
TX_HOLD: coverpoint txh iff(field == "SDA_HOLD"){
bins MAX = {[100:$]};
bins NORMAL = {[10:99]};
bins MIN = {[1:9]};
}
SDA_SETUP: coverpoint stp iff(field == "SDA_SETUP") {
bins MAX = {[100:$]};
bins NORMAL = {[10:99]};
bins MIN = {[1:9]};
}
endgroup
14.timeout_counter_cg
通过访问REG_TIMEOUT_RST[3:0]REG_TIMEOUT_RST_rw来获得。
covergroup timeout_counter_cg with function sample(bit[3:0] cnt);
option.name = "timeout_counter_cg";
TIMEOUT_COUNTER: coverpoint cnt {
bins MAX = {[10:$]};
bins NORMAL = {[4:9]};
bins MIN = {[1:3]};
}
endgroup
如何进行采样?
首先是通过uvm_analysis_imp端口接收从APB、I2C的monitor监测到的数据,然后对write进来的lvc_apb_transfer进行判断,如果传输状态trans_status==ERROR,则直接return,否则利用使用get_reg_by_offset 函数通过寄存器地址得到对应的uvm_reg 指针,然后trigger前门访问的event。
在对reg采样的task do_sample_reg()中,要一直wait_trigger_data(tmp),等待event被触发,然后执行后面的操作。
通过get_name()来获得uvm_reg 指针所指向的寄存器的名称,然后采样,通过get()传入对应的阈值和域名。
对硬件信号的采样通过do_sample_signals()任务来实现,在intr信号发生改变时进行采样并传入intr信号值。