分类:RTL设计相关
如果将文章名称写成《一个资深验证工程师通过一篇文章告诉你如何设计寄存器》,那么这篇文章有可能会被传到各大BBS去,获取不错的点击量。但是,当我想到我身边曾有很多比我优秀的验证工程师,他们都没有如此自称时,我就觉得这个标题我实在承受不起,哈哈! 寄存器(域段)访问属性的概念 一个典型的寄存器定义,如下所示。 寄存名:系统配置寄存器[0xC800_0000] 域段名 | 域段范围 | 访问属性 | 默认值 | 描述 | rsv | 31-7 | RO | 0 | 保留 | video_format | 6-4 | RW | 0 | 启动核心数 0:rmvb 1:mpeg4 2:avi 3:3gp 4:flv 5:dat others:rsv | rsv | 3-1 | RO | 0 | 保留 | mode_type | 0 | RW | 0 | 0:正常模式 1:测试模式 |
域段的访问属性,是从处理器(如CPU)端来看的。以mode_type为例,该域段的访问属性为RW(读写),表示该域段的值既可以被处理器写入,也可以被处理器读出。一般情况下,寄存器域段的访问属性与寄存器的访问属性一致。对于寄存器中的保留域,一般处理器是无法操作保留域段的信息的,可以认为保留域只可以被读出默认值“0”,可以将保留域的访问属性标记为“RO(只读)”。 由于保留域的存在,如上例,“系统配置寄存器”的访问属性为RW,其中,域段mode_type和video_format的访问属性也是RW,但保留域的访问属性就是RO,即存在寄存器访问属性和域段访问属性不一致的情况。 为了描述方便,下文所有“寄存器访问属性”将特指为某个有效“域段的访问属性”。 寄存器访问结构 
如图所示,处理器(CPU)通过其总线Master访问逻辑设计的总线Slave。总线Slave解析寄存器总线访问,如果是写操作,一般转换为对逻辑处理的配置,如果是读操作,一般转换为读取逻辑处理的上报结果。 为了下文描述方便,将处理器写信息称为“数据”,而将逻辑设计内部存储的已有信息,称为“域段值”。 UVM定义的寄存器访问属性 UVM定义的寄存器访问属性共有25个。如果想一下记住25个访问属性,还是比较难的。因此,我们需要对访问属性先做一个归纳总结: 1、 所有包括R的访问属性,会将寄存器的“域段值”读出给处理器; 2、 所有包括W的访问属性,会将处理器的“数据”,传递给寄存器域段处理,但不一定是简单的赋值操作; 3、 读操作的处理范围是整个寄存器(因为读操作无法区分读哪个域段,不读哪个域段); 4、 写操作的处理范围可以是整个寄存器,也可以是某个域段,当需要区分域段时,需要通过1(或0)标记哪个域段信息被操作; 5、 所有包括“C”的访问,将清除(清0)对应处理范围的信息,处理范围可能是整个寄存器,也可能是整个域段; 6、 所有包括“S”的访问,将置位(置1)对应处理范围的信息,处理范围可能是整个寄存器,也可能是整个域段; 7、 所有包括“T”的访问,将翻转(0->1,1->0)对应处理范围的信息,处理范围可能是整个寄存器,也可能是整个域段; 如果您已经理解以上7点,那么我们可以继续学习UVM的寄存器属性了。 UVM定义的寄存器访问属性如下所示。 编号 | 访问属性 | 属性简述 | 对域段值的效果 | 对处理器的效果 | 写操作 | 读操作 | 读操作 | 1 | RO | 只读 | no effect | no effect | 读出域段值 | 2 | RW | 读写 | as-is | no effect | 读出域段值 | 3 | RC | 读清 | no effect | clears all bits | 读出域段值 | 4 | RS | 读置位 | no effect | sets all bits | 读出域段值 | 5 | WRC | 写/读清 | as-is | clears all bits | - | 6 | WRS | 写/读置位 | as-is | sets all bits | - | 7 | WC | 写清 | clears all bits | no effect | 读出域段值 | 8 | WS | 写置位 | sets all bits | no effect | 读出域段值 | 9 | WSRC | 写置位/读清 | sets all bits | clears all bits | - | 10 | WCRS | 写清/读置位 | clears all bits | sets all bits | - | 11 | W1C | 写1清 | 1:clears matching bit 0:no effect | no effect | 读出域段值 | 12 | W1S | 写1置位 | 1:sets matching bit 0:no effect | no effect | 读出域段值 | 13 | W1T | 写1翻转 | 1:toggles matching bit 0:no effect | no effect | 读出域段值 | 14 | W0C | 写0清 | 0:clears matching bit 1:no effect | no effect | 读出域段值 | 15 | W0S | 写0置位 | 0:sets matching bit 1:no effect | no effect | 读出域段值 | 16 | W0T | 写0翻转 | 0:toggles matching bit 1:no effect | no effect | 读出域段值 | 17 | W1SRC | 写1置位/读清 | 1:sets matching bit 0:no effect | clears all bits | - | 18 | W1CRS | 写1清/读置位 | 1:clears matching bit 0:no effect | sets all bits | - | 19 | W0SRC | 写0置位/读清 | 0:clears matching bit 1:no effect | clears all bits | - | 20 | W0CRS | 写0清/读置位 | 0:sets matching bit 1:no effect | sets all bits | - | 21 | WO | 只写 | as-is | error | 读错误告警 | 22 | WOC | 写清 | clears all bits | error | 读错误告警 | 23 | WOS | 写置位 | sets all bits | error | 读错误告警 | 24 | W1 | 写(1次) | 见备注 | no effect | 读出域段值 | 25 | WO1 | 只写(1次) | 见备注 | error | 读错误告警 |
备注:W1和WO1的意义“first oneafter HARD reset is as-is, other W have no effects”硬复位后的第一次写操作有效,其余写操作无效。 寄存器访问属性的应用 RW(读写) RW寄存器是逻辑设计中数量最多的寄存器,一般用于配置操作。其中的读操作是可测试性设计,写入的寄存器,处理器可以通过读取操作,判断写入信息是否正确。 
有“高人”曾建议,配置寄存器就应该采用“WO只写”方式,这样可以节省寄存器资源。我当时真的感到“天雷滚滚”!不怕被测试、软件,以及项目经理骂死,就这么设计好了。省的那点资源,不够费的功夫。 RO(只读) RO寄存器是逻辑设计中数量第二多的寄存器,一般用于状态指示,或者信息采样。 状态指示举例:当前的时钟是否锁定(PLL_LOCK);当前的状态机状态(FSM_State); 信息采样举例:当前处理数据的平均功率统计(averagepower)。

RC(读清) RC寄存器,读操作后,域段信息就被清除。应用RC寄存器的考虑因素包括: 从设计便利性考虑:一段时间的统计信息,如计数值,或者平均功率,读操作完成后,数据清零,重新统计; 从信息的重要性考虑:相对不是特别重要的信息,一般可以采用读清操作。 RC寄存器与RO寄存器的结构基本一致,仅多了一步清除操作。 RS(读置位) 与RC的应用场景类似,有时候计数器置位后,下一次计数则从0xffff直接跳到0,比较方便。但是,本能上不喜好这样的设计,没有任何特殊理由。 WC(写清) 主要与RC(读清)寄存器对比,相比较读清,写清可以在软件确信获取到信息后,再清除信息。需要注意的是,WC(写清)是与RC(读清)做选择,而不是和W1C(写1清)做选择。因为WC和RC都是对整个寄存器的操作,而W1C是对域段的操作,应用场景完全不同。 
W1C(写1清) 最常用于“中断状态指示寄存器”。

当中断发生时,逻辑发送中断“脉冲”给寄存器域段缓存。处理器收到中断线指示(中断使能场景)后,读取相应的“中断状态指示寄存器”,获取是哪个信息导致的中断。处理器依次处理中断对应信息,完成中断处理程序后,向对应域段的写1,清除对应域段。 
一般W1C寄存器,与某个RW寄存器的域段一一对应,该RW寄存器为“中断状态指示使能寄存器”,一个bit的使能,对应一个bit的中断状态指示。 写1清的好处是,仅操作对应域段,而不影响其他域段的中断信息。

W1C(写1清)要小心“电平指示”中断。 对于“脉冲”指示的中断,中断信息缓存在寄存器域段里,如果清中断,系统中就不再有中断指示。但是,对于“电平指示”的中断,仅仅清除寄存器域段中的指示是不够的,还需要清除逻辑处理发出的持续电平信号。否则,即使清除了寄存器域段中的中断指示,逻辑处理的中断电平又会立刻将寄存器中的中断指示拉起。导致最终陷入“清中断->重新拉起中断”的死循环。 
W1T(写1翻转) 一个非常有意思的寄存器访问属性,最常用于“总线测试寄存器”。举例如下: 
当“域段值”为8’hFF时,写入8’h55,读出8’hAA,证明总线(APB/AXI)读写正常。 W1(只写1次) 一般这样的寄存器应用于做“一次”操作的判断(flag)。应用该寄存器的需求分析: 1、 从便利性的角度分析:可以多个软件进程调用写,只要有一个写操作,写操作就记录,且屏蔽后续的写操作。在某些场景下,这样的设计会比较方便; 2、 从“安全性”的角度分析:某些特殊信息,如DDR初始化启动指示等,上电后,仅操作一次。 但是,从设计角度讲,这样的设计有些过于严格要求硬件,而放松软件。但是,硬件如何设计不合理,软件是没有办法挽回的。例如DDR初始化,可能在某些场景,需要执行两次,如果软复位操作不到对应寄存器,系统就可能挂死。因此,要慎用W1(只写1次)访问属性的寄存器。 其余寄存器访问属性 其余寄存器访问属性,不是特别常见,本文就不再赘述。虽然更多的寄存器属性,可以带来应用上的方便,但是也会带来理解上的障碍。从沟通的角度来看,我建议尽量少用不常见的寄存器属性。当然,哪些寄存器访问属性是常用的,哪些是不常用的,这个问题可以好好探讨。
欢迎您在“IC验证工程师交流群”讨论(推荐),或者在公众号留言(查看不及时)。扫描下方的二维码,加入“IC验证工程师交流群”。由于群人数超过100人,目前只能通过邀请加入群聊。想加群的,先加吴杉的微信号birdshanshan,并在备注中说明加入“IC验证工程师交流群”。或者请已经加入群聊的其他人拉入即可。 本文为原创,转载请注明出处:IC验证工程师
|