从验证的角度看,register automation 流程一般如下:
- 按照一定格式编写寄存器文件
- 使用工具解析寄存器文件,生成verilog代码、test bench代码、c代码、说明文档
- 使用已生成的uvm reg文件,搭建寄存器模型
tools
csrCompiler是Semifore公司的寄存器自动产生工具。它支持输入csr语法文件或是csv格式excel文件,输出verilog文件、VHDL文件、word文档、HTML文件、c语言头文件、验证tb文件。
例如
输入文件csv
可得到verilog文件
也可得到doc文件
当然也可以运行如下命令,得到uvm reg文件
csrCompiler -t uvm demo.csv
uvm tb
拿到自动生成的uvm reg文件,里面会包含xxx_reg和demo_reg_block。
在base_test里面增加例化
1 | class base_test extends uvm_test; |
1 | class demo_virtual_sequencer extends uvm_sequencer; |
如果是在test里面,直接调用write就可以了
1 | uvm_status_e status; |
如果是在seq里面,就通过sqr来调用
1 | uvm_status_e status; |
前门写,会反映到总线上。
前门读,会反映到总线上,就算返回的值和预期不一样,也不会报错,比如先写1234,再读出来是4,也不会报错。
后门读,就直接访问内部信号了,如果没有这个内部信号,就会报错
1 | [UVM/DPI/HDL_GET] get: unable to locate hdl path(top.dut.xxx) |
最后来看下函数原型
read任务的原型是
1 | extern virtual task read(output uvm_status_e status, |
第一个参数表示读操作是否成功,第二个表示读取的数值,第三个是读取的方式,有UVM_FRONTDOOR和UVM_BACKDOOR。
write任务的原型是
1 | extern virtual task read(output uvm_status_e status, |
第一个参数表示读操作是否成功,第二个表示写入的数值,第三个是写入的方式,有UVM_FRONTDOOR和UVM_BACKDOOR。
另外还有两个后门操作,peek和poke。它们和write、read的区别是。wr函数会模仿dut的行为,而pp完全不管dut的行为。如对一个只读的寄存器进行写操作,write函数是写不进去的,而peek可以写进去。
1 | task uvm_reg::poke(output uvm_status_e status, |
镜像值,是最大可能与dut同步的值
期望值,是要写入的值。
Read/write操作,无论前门后门操作完成都会更新镜像值和期望值
Peek/poke操作,无论前门后门操作完成都会更新镜像值和期望值
get/set操作,set操作会更新期望值,但镜像值不会变化。get操作会返回寄存器模型中的期望值。
update操作,会见检查期望值和镜像值是否一致,如果不一致,就将期望值写入dut,并且更新镜像值,使其与期望值一致。