前言
基于代码和波形理解关于覆盖率相关的test内容,也增进了对I2C协议的认识。
1.rkv_i2c_master_address_cg_test
主体为rkv_i2c_master_address_cg_virt_seq,测试内容是,DUT作为master, 7bit/10bit寻址正确/错误的目标地址;以及DUT作为slave,配置从机地址。
分别设置7/10bit主机传输模式,每种模式下均设置了四个地址,检测正常和异常传输情况。正常情况下传输的数据均为8’b1111 0001,异常下数据为8’b1111 0010;正常情况下传输的地址为设定的四个地址(依次对应’h273, 'h333, 'h73, 'h1b3),异常传输的地址通过对正常下地址加1来完成(依次对应’h274, 'h334, 'h74, 'h1b4)。
在四种地址下,配置了IC_SAR寄存器。
-
访问0x00寄存器(IC_CON寄存器),写入‘h7d(111 1101),即配置IC_CON[0]为1,以启用DW_apb_i2c为master模式;配置IC_CON[2:1]为10,以设置速度模式为快速模式;**配置IC_CON[3]为1,以设置作为slave地址位宽为10bit;配置IC_CON[4]为1,以设置作为master地址位宽为10bit;**配置IC_CON[5]为1,打开restart;配置IC_CON[6]为1,以禁用slave模式;高位均置为0,IC_CON[7]为0表示无论是否被寻址到,都产生STOP DET中断;IC_CON[8]为0表示默认TX EMPTY中断行为;IC_CON[9]为0表示当RX_FIFO满时溢出;IC_CON[10]为0表示无论是不是master模式都产生STOP DET;
-
访问0x1c寄存器(IC_FS_SCL_HCNT寄存器),写入’hc8(十进制200);
-
访问0x20寄存器(IC_FS_SCL_LCNT寄存器),写入’hc8(十进制200);7 bit address master![7bit address0
-
访问0x00寄存器(IC_CON控制寄存器),写入’h6d(110 1101),即配置IC_CON[0]为1,以启用DW_apb_i2c为master模式;配置IC_CON[2:1]为10,以设置速度模式为快速模式;**配置IC_CON[3]为1,以设置作为slave地址位宽为10bit;配置IC_CON[4]为0,以设置作为master地址位宽为7bit;**配置IC_CON[5]为1,打开restart;配置IC_CON[6]为1,以禁用slave模式;高位均置为0,IC_CON[7]为0表示无论是否被寻址到,都产生STOP DET中断;IC_CON[8]为0表示默认TX EMPTY中断行为;IC_CON[9]为0表示当RX_FIFO满时溢出;IC_CON[10]为0表示无论是不是master模式都产生STOP DET;
-
访问0x04寄存器**(IC_TAR目标地址寄存器),写入’h273**;
-
访问0x6c寄存器(IC_ENABLE寄存器),写入’h1;
-
访问0x70寄存器(IC_STATUS寄存器),读取’h6(110),I2C处于被禁用状态;
-
访问0x10寄存器(IC_DATA_CMD寄存器),写入’hf1(1111 0001);随后观测到I2C总线上依次出现START信号,地址字节(1110 011 0+ACK),数据字节(1111 0001+ACK),STOP信号;
-
访问0x6c寄存器(IC_ENABLE寄存器),写入’h0;
-
访问0x04寄存器**(IC_TAR目标地址寄存器),写入’h274**;
-
访问0x6c寄存器(IC_ENABLE寄存器),写入’h1;
-
访问0x70寄存器(IC_STATUS寄存器),读取’h6(110),I2C处于被禁用状态;
-
访问0x10寄存器(IC_DATA_CMD寄存器),写入’hf2(11110010),随后观测到I2C总线上依次出现RESTART信号,地址字节(1110 1000+NACK),STOP信号。
-
且出现TX ABRT中断,访问0x80寄存器(IC_TX_ABRT_SOURCE发送中断源寄存器),读取到’h1,表明主机在7bit地址传输模式,且第一个7地址字节未被任何从机识别,与14步中的信息一致;
-
访问0x34寄存器,读取到’h750(111 0101 0000),第10、9、8、6、4bit为高,依次对应START, STOP, ACTIVITY, TX_ABRT, TX_EMPTY位中断;
-
访问0x54寄存器(TX ABRT中断清除寄存器),读取为’h1,清除TX_ABRT中断;
-
访问0x6c寄存器(IC_ENABLE寄存器),写入’h0;
至此,完成7bit下address[0]下的正常传输+异常传输;后面的address[3:1]传输步骤与其一样,除了地址的变化;完成7 bit addressing下的传输后,开始10 bit addressing的传输;
10 bit address master
- 访问0x00寄存器(IC_CON控制寄存器),写入’h6d(110 1101),即配置IC_CON[0]为1,以启用DW_apb_i2c为master模式;配置IC_CON[2:1]为10,以设置速度模式为快速模式;**配置IC_CON[3]为1,以设置作为slave地址位宽为10bit;配置IC_CON[4]为0,以设置作为master地址位宽为7bit;**配置IC_CON[5]为1,打开restart;配置IC_CON[6]为1,以禁用slave模式;高位均置为0,IC_CON[7]为0表示无论是否被寻址到,都产生STOP DET中断;IC_CON[8]为0表示默认TX EMPTY中断行为;IC_CON[9]为0表示当RX_FIFO满时溢出;IC_CON[10]为0表示无论是不是master模式都产生STOP DET;
- 访问0x04寄存器**(IC_TAR目标地址寄存器),写入’h273**;
- 访问0x6c寄存器(IC_ENABLE寄存器),写入’h1;
- 访问0x70寄存器(IC_STATUS寄存器),读取’h6(110),I2C处于被禁用状态;
- 访问0x10寄存器(IC_DATA_CMD寄存器),写入’hf1(1111 0001);随后观测到I2C总线上依次出现START信号,地址字节(1111 010 0+ACK/ 0111 0011+ACK),数据字节(1111 0001+ACK),STOP信号;
- 访问0x6c寄存器(IC_ENABLE寄存器),写入’h0;
- 访问0x04寄存器**(IC_TAR目标地址寄存器),写入’h274**;
- 访问0x6c寄存器(IC_ENABLE寄存器),写入’h1;
- 访问0x70寄存器(IC_STATUS寄存器),读取’h6(110),I2C处于被禁用状态;
- 访问0x10寄存器(IC_DATA_CMD寄存器),写入’hf2(1111 0010),随后观测到I2C总线上依次出现RESTART信号,地址字节(1111 0100+NACK),STOP信号。
- 且出现TX ABRT中断,访问0x80寄存器(IC_TX_ABRT_SOURCE发送中断源寄存器),读取到’h2,表明主机在10 bit地址传输模式,且第一个10地址字节未被任何从机识别,与10步中的信息一致;
- 访问0x34寄存器,读取到’h750(111 0101 0000),第10、9、8、6、4bit为高,依次对应START, STOP, ACTIVITY, TX_ABRT, TX_EMPTY位中断;
- 访问0x54寄存器(TX ABRT中断清除寄存器),读取为’h1,清除TX_ABRT中断;
- 访问0x6c寄存器(IC_ENABLE寄存器),写入’h0;
至此,完成10bit下address[0]下的正常传输+异常传输;后面的address[3:1]传输步骤与其一样,除了地址的变化;
代码如下
`uvm_do_on_with(apb_cfg_seq,
p_sequencer.apb_mst_sqr,
{SPEED == 2;
IC_FS_SCL_HCNT == 200;
IC_FS_SCL_LCNT == 200;
})
for(i=0;i<2;i++) begin
`uvm_do_on_with(apb_cfg_seq,
p_sequencer.apb_mst_sqr,
{
IC_10BITADDR_MASTER == i;//7 bit(0) or 10 bit(1)
})
if(i == 1) cfg.i2c_cfg.slave_cfg[0].enable_10bit_addr = 1;
foreach(address[j]) begin//每种地址下需要重新配置
cfg.i2c_cfg.slave_cfg[0].slave_address = address[j];
env.i2c_slv.reconfigure_via_task(cfg.i2c_cfg.slave_cfg[0]);
//正常传输 `uvm_do_on_with(apb_user_address_check_seq,p_sequencer.apb_mst_sqr,{ADDR == address[j];})
`uvm_do_on_with(apb_write_packet_seq,
p_sequencer.apb_mst_sqr,
{packet.size() == 1;
packet[0] == 8'b11110001;
})
`uvm_do_on(i2c_slv_write_resp_seq,p_sequencer.i2c_slv_sqr)
//异常传输 `uvm_do_on_with(apb_user_address_check_seq,p_sequencer.apb_mst_sqr,{ADDR == (address[j] + 1'b1);})
`uvm_do_on_with(apb_write_packet_seq,
p_sequencer.apb_mst_sqr,
{packet.size() == 1;
packet[0] == 8'b11110010;
})
tx_abrt_check();
rgm.IC_ENABLE.ENABLE.set(0);
rgm.IC_ENABLE.update(status);
#10us;
end
end
两种传输模式下的总结
完成了master模式下传输的测试,最后还对slave模式的地址进行了设置
- 访问0x08寄存器(IC_SAR从机地址寄存器),写入’h273,对应address[0];
- 访问0x6c寄存器(IC_ENABLE寄存器),写入’h1;
- 访问0x6c寄存器(IC_ENABLE寄存器),写入’h0;
- 访问0x08寄存器(IC_SAR从机地址寄存器),写入’h333,对应address[1];
- 访问0x6c寄存器(IC_ENABLE寄存器),写入’h1;
- 重复步骤3-5,对address[2], address[3]进行写入(第一个地址没有对0X6c寄存器写入0是因为在前面的master模式下的传输,最后一步已经将其设置为0)
关于此test的困惑点(暂时未解):
a. 在10bit address master模式下,错误传输的地址是在正确地址上加1得来的,但并未引起高两位的变化,那么为什么是在第一个地址字节就收到NACK?
b. IC_CON[3]配置始终为1,即slave地址位宽始终为10bit,要配置7bit下的地址不是应该将其置为0吗?
2.rkv_i2c_master_enabled_cg_test
part1:配置
-
访问0x00寄存器(IC_CON寄存器),写入’h6d(110 1101),即配置IC_CON[0]为1,以启用DW_apb_i2c为master模式;配置IC_CON[2:1]为10,以设置速度模式为快速模式;**配置IC_CON[3]为1,以设置作为slave地址位宽为10bit;配置IC_CON[4]为0,以设置作为master地址位宽为7bit;**配置IC_CON[5]为1,打开restart;配置IC_CON[6]为1,以禁用slave模式;高位均置为0,IC_CON[7]为0表示无论是否被寻址到,都产生STOP DET中断;IC_CON[8]为0表示默认TX EMPTY中断行为;IC_CON[9]为0表示当RX_FIFO满时溢出;IC_CON[10]为0表示无论是不是master模式都产生STOP DET;
-
访问0x04寄存器(IC_TAR目标地址寄存器),写入’h333(11 0011 0011);
-
访问0x1c寄存器(IC_FS_SCL_HCNT快速高计数寄存器),写入’hc8(对应十进制200);
-
访问0x20寄存器(IC_FS_SCL_LCNT快速低计数寄存器),写入’hc8(对应十进制200);
part2:禁止使能后再进行写操作
由于IC_ENABLE[0]上电默认为0,通过set修改期望值,使用update发现期望值和镜像值相同,所以没有观测到对0x6c寄存器的写操作;在对IC_DATA_CMD进行写操作前会先访问0x70寄存器通过mirror方法读取TX FIFO状态 -
访问0x70寄存器(IC_STATUS状态寄存器),读取到6(110),TX FIFO为空;
-
访问0x10寄存器(IC_DATA_CMD寄存器),写入’hf0(1111 0000);
-
访问0x70寄存器(IC_STATUS状态寄存器),读取到6(110),TX FIFO为空;
part3:使能后进行写操作,在发送到I2C之前禁止使能
- 访问0x6c寄存器(IC_ENABLE寄存器),写入’h1;
- 访问0x70寄存器(IC_STATUS状态寄存器),读取到6(110),TX_FIFO为空;
- 访问0x10寄存器(IC_DATA_CMD寄存器),写入’hf1(1111 0001);
- 访问0x70寄存器(IC_STATUS状态寄存器),读取到’h2(10),TX_FIFO非空;
- 访问0x10寄存器(IC_DATA_CMD寄存器),写入’hf2(1111 0010);
- 访问0x70寄存器(IC_STATUS状态寄存器),读取到’h2(10),TX_FIFO非空;
- 访问0x6c寄存器(IC_ENABLE寄存器),写入’h0(写入0后TX_FIFO和RX_FIFO都被刷新);
- 再访问0x70寄存器(IC_STATUS状态寄存器),所以读取到’h6(110),TX_FIFO变为空;
- 访问0x10寄存器(IC_DATA_CMD寄存器),写入’h100(1 0000 0000),表示要读取数据0000 0000;
- 10μs后访问0x70寄存器(IC_STATUS状态寄存器),读取到’h6(110),TX_FIFO为空,I2C处于被禁用状态;
part4:在数据接收时禁止使能 - 访问0x6c寄存器(IC_ENABLE寄存器),写入’h1;
- 访问0x70寄存器(IC_STATUS状态寄存器),读取到’h6(110),TX_FIFO为空,I2C处于被禁用状态;
- 访问0x10寄存器(IC_DATA_CMD寄存器),写入’h100(1 0000 0000),表示要读取数据0000 0000(apb_noread1),将数据写入IC_dATA_CMD用于读操作时,DW_APB_I2C会忽略,当读取此寄存器时,数据位将返回在DW_APB_I2C接口上接收的数据;
- 访问0x70寄存器(IC_STATUS状态寄存器),读取到’h2(10),TX_FIFO非空;
- 访问0x10寄存器(IC_DATA_CMD寄存器),写入’h100(1 0000 0000),表示要读取数据0000 0000(apb_noread2);
- 访问0x70寄存器(IC_STATUS状态寄存器),读取到’h2(10),TX_FIFO非空;
- 访问0x10寄存器(IC_DATA_CMD寄存器),写入’h100(1 0000 0000),表示要读取数据0000 0000(apb_noread3);
- 访问0x70寄存器(IC_STATUS状态寄存器),读取到’h2(10),TX_FIFO非空;随后对此寄存器持续访问,直到I2C总线上观测到START信号,0x70寄存器读取值变为’h23(100011),表明master FSM处于activity状态,RX_FIFO为空,TX_FIFO非空非满;观测到总线0110 011 1+ACK(地址字节),0000 1111+ACK,接着发生RX_FULL中断,0x70寄存器读取值变为’h2f(101111),TX_FIFO为空,RX_FIFO不为空,表明数据发送完成,已经接收到数据;
- 访问 0x6c寄存器(IC_ENABLE寄存器),写入’h0(RX_FIFO和TX_FIFO被刷新),此后会发生数据丢失,因为APB总线还没来得及从I2C上获取数据ENABLE就成为0,那么之后都无法把数据放进RX_FIFO;
- 访问0x70寄存器(IC_STATUS状态寄存器),读取到’h27(100111),表明master FSM处于activity状态,RX_FIFO为空,TX_FIFO为空;
注释:持续访问0x70寄存器对应代码中的mirror操作,直到RX_FIFO非空。此阶段第一个读数据是0000 1111,后两个都是0。主机对最后一个0000 0000发送NACK,因为对于master receiver的7地址传输如下图
part5:使能后进行写操作(正常传输过程)
- 访问0x6c寄存器(IC_ENABLE寄存器),写入’h1;
- 访问0x70寄存器,读取’h27(100111),表明master FSM处于activity状态,RX_FIFO为空,TX_FIFO为空;
- 访问0x10寄存器(IC_DATA_CMD寄存器),写入’hf1(1111 0001);
- 访问0x70寄存器读取值变为’h23(100011),表明master FSM处于activity状态,RX_FIFO为空,TX_FIFO非空非满;
其间在I2C总线上观测到数据字节(0000 0000+ACK),随后发生RX_FULL中断,开始下一个数据字节(0000 0000)传送; - 访问0x70寄存器读取值变为’h2f(101111),TX_FIFO为空,RX_FIFO不为空(接收到0000 0000),已经接收到数据;I2C上继续传输数据(0000 0000+NACK),
- 随后出现正常传输信号,RESTART信号,地址字节(0110 0110+ACK),数据字节(1111 0001+ACK),STOP信号;最后访问0x70寄存器,读取到’he(1110),表明RX_FIFO,TX_FIFO为空,master FSM处于idle状态。
总结
关于覆盖率的测试用例十分复杂,因为要考虑各种异常场景,需要花时间理解了再学着写,加油呀!