验证平台的interface是连接验证平台agent和待验证设计(DUV)之间的接口。一般情况下,1个agent仅包括1个interface,而1个interface仅受1个时钟控制。在定义agent时,将这个时钟作为interface的输入,而不是interface的成员变量(请允许我用成员变量这个词)。所有interface的成员变量,基于interface的时钟来驱动或采样。
为了更清晰的对不同应用场景下的接口信号属性进行分类,以及更安全的对接口信号进行驱动和采样,可以在interface中定义clocking block,同时设置input/output delay。
以上是每本SystemVerilog的语法书都会讲到的内容。
语法书会告诉我们可以怎么做,但是不涉及遇到实际问题时,应该怎么做。
第一个案例:双沿触发的interface(如图中“数据”)。一般新员工会犯的错误是没有修改clocking block的输入时钟事件。
语法书上举的例子经常是上升沿触发@posedge,即当使用该clocking block时,不管你在driver和monitor中是否正确的应用了@posedge,@negedge触发,都会仅在@posedge时才起作用。
在双沿触发的场景时,如果还设置clocking block的时钟事件为@posedge,就会导致时序错乱。双沿触发的场景应将clocking block的时钟事件设为@即可。
第二个案例:1个逻辑输入时钟模块送来的2个时钟,1个用于数据处理,1个用于全局同步。
如果按照1个agent仅有1个interface,而1个interface仅输入1个时钟来分析,那么2个时钟就需要定义2个agent。但是,如果这2个agent分别实现的数据处理与全局同步功能在业务上强相关,那么这两个agent想配合到一起,实现起来会相当复杂。
如果1个agent连接2个interface,从语法上推导是可行的。不过,这样要求该agent的driver和monitor都例化两个virtual interface与2个interface对接,代码还不够简洁。
考虑这样的一个事实,这2组信号虽然在接口层面独立,但是在业务层面耦合,将其看成1个interface在业务上比较合理。那如何解决多时钟域的问题呢?实现起来是这样的:依然是1个interface连接1个agent;该interface输入2个时钟,分别定义各时钟的clocking block;agent的driver和monitor分别基于不同的clocking block来处理2组对外信号,而在driver和monitor内部则将2组信号配合起来。
第三个案例:这是个逻辑思维的问题。1个agent存在2种模式:在第1种模式时,使用时钟芯片送来的时钟处理数据;在第2种模式时,该agent会将时钟芯片送来的时钟再送出给对端逻辑,然后对端逻辑基于该时钟的采样,反馈1个时钟给该agent,该agent基于对端逻辑的反馈时钟处理数据。
从2种模式的时钟源来看,都可以看成是时钟芯片的送来时钟。那么,该agent的interface是否就应该仅输入1个时钟了?其实不然。当对端逻辑将agent送出的时钟采样后,再送出的时钟已经是一个异步时钟了,即不能看成和时钟芯片的时钟是同一个时钟。
此时,该interface应该定义2个clocking block,在模式1使用时钟芯片送来的时钟的clocking block,在模式2使用对端逻辑送来的时钟的clocking block。
当然,保险起见,需要检查对端逻辑是否正确输出了时钟,如果在某些未预期的场景下没有输出时钟,验证平台应该报错。
以上分析了一些典型案例,如双沿时钟,多时钟域时钟的场景,某些业务应该会更为复杂。但是,总结以上3个案例,明确不同时钟域的信息使用不同的clocking block或不同的interface,然后在耦合和去耦之间做出权衡,相信您的interface能够设计的简洁而有效。