Synopsys验证VIP学习笔记(1)Memory模型用法

Synopsys的VIP(本文以AXI slave为例)提供了由svt_mem类表示的momory模型,在passive模式下其观测值与寄存器模型类似,会基于总线更新,在active模式下则由slave sequence更新。

在配置VIP时,首先要通过svt_axi_system_configuration::set_addr_range() 配置每个memory的地址范围,并且可以多次配置。这里在cust_svt_axi_system_configuration类中生成32bit地址的axi memory,第一个参数为slave编号,后两个参数为地址范围:

set_addr_range(0, 32'h0000_0000, 32'hffff_ffff);

基于transaction更新的active模式和基于总线更新的passive模式为前门访问,用法如下:

// svt_axi_slave_base_sequencet
if(req_resp.xact_type == svt_axi_slave_transaction::WRITE) begin
    put_write_transaction_data_to_mem(req_resp);
end
else begin
    get_read_data_from_mem_to_transaction(req_resp);
end

svt_mem提供了一些后门访问方法:

  • read()
  • write()
  • set_meminit()
  • load_mem()
  • save_mem()
  • clear()

可以用read()write() 实现基本的后门访问,这两个函数的原型如下:

function logic [SVT_MEM_MAX_DATA_WIDTH-1:0] 
svt_mem::read(bit [SVT_MEM_MAX_ADDR_WIDTH-1:0] addr, int set_lock = -1) 

function bit 
svt_mem::write(bit [(SVT_MEM_MAX_ADDR_WIDTH-1):0] addr = 0, 
			bit [(SVT_MEM_MAX_DATA_WIDTH-1):0] data = 0, 
			bit [(SVT_MEM_MAX_DATA_WIDTH/8-1):0] byteen = ~0, 
			int set_lock = -1) 

另外,axi slave本身提供了write_byte()read_byte() 两个按字节地址实现后门读写的方法,原型如下:

task svt_axi_slave_agent::write_byte(input bit[`SVT_AXI_MAX_ADDR_WIDTH-1:0] addr, bit[7:0] data);
task svt_axi_slave_agent::read_byte(input bit[`SVT_AXI_MAX_ADDR_WIDTH-1:0] addr, output bit[7:0] data);

load_mem() 可以将$readmemh格式的文件加载至mem模型中。
save_mem() 可用于dump memory至文件,data_wdth参数可用于指定数据位宽(需为2的幂且大于8,否则值为-1),enable_autosize_of_saveddata可实现高位补零,原型如下:

function bit
svt_mem::save_mem ( string filename, 
					int data_wdth = -1, 
					bit [SVT_MEM_MAX_ADDR_WIDTH-1:0] start_addr = 0, 
					bit [SVT_MEM_MAX_ADDR_WIDTH-1:0] end_addr = 1 << 64 - 1, 
					bit enable_autosize_of_saveddata = 0) 

set_meminit() 可以配置mem模型对未写过的地址返回一些特定值,以此实现mem的随机初始化,原型如下:

task 
svt_mem::set_meminit (svt_mem::meminit_enum meminit = UNKNOWNS,
				 	bit [SVT_MEM_MAX_DATA_WIDTH-1:0] meminit_value = 0, 
				 	bit [SVT_MEM_MAX_ADDR_WIDTH-1:0] meminit_address_offset = 0)

其中,参数meminit包含以下枚举类型:

  • UNKNOWNS
  • ZEROES
  • ONES
  • ADDRESS
  • VALUE
  • INCR
  • DECR
  • USER_PATTERN
  • RANDOM

将参数meminit指定为VALUE类型时,参数meminit_value值可指定其初始值,如配置所有未写过的地址初始值为随机64bit数:

axi_env.axi_system_env.slave[0].axi_slave_mem.set_meminit(svt_mem::VALUE, {$urandom,$urandom}, 0);

INCRDECR类型可以使初始值递增或递减,同时参数meminit_value值指定了最小地址的初始值。
ADDRESS类型可使未写过的地址读出其地址值,并可通过参数meminit_address_offset指定一个偏移量。
USER_PATTERN类型可使未写过的地址读出通过load_mem函数加载到内存的数据。
RANDOM类型可使未写过的地址每次读出随机值。

可以在scoreboard中声明svt_mem类句柄以实现对VIP的后门访问,注意传递句柄时需要在合适的phase中,因为UVM中build_phase是自上而下而其他phase是自下而上,至少要在VIP创建svt_mem后再传递,否则仿真可能会报"[NOA] Null object access"错误。

参考资料:VC Verification IP AMBA AXI UVM User Guide R-2020.09

### 关于DDR仿真的技术资料、教程和工具 #### DDR仿真概述 DDR(Double Data Rate)内存的仿真通常涉及验证其接口逻辑的功能性和时序特性。为了实现这一目标,工程师们常依赖EDA工具以及厂商提供的IP核来进行功能测试和性能评估。Xilinx提供了专门用于DDR控制器设计的MIG(Memory Interface Generator)IP核[^1]。 #### MIG IP核及其仿真支持 MIG IP核不仅简化了DDR控制流程的设计复杂度,还内置了大量的仿真模型和支持文件。这些资源可以帮助开发者快速搭建并验证DDR系统的功能性与时序匹配情况。具体来说: - **功能仿真**:通过VHDL或Verilog描述的语言级建模,能够模拟DDR控制器的行为模式。这一步骤主要关注数据流路径上的正确性,而不考虑实际物理层的具体延迟参数。 - **时序仿真**:此阶段引入精确的时间约束条件来检验信号传输过程中是否存在违反规定的情况。例如,在读取操作期间是否有足够的稳定窗口时间让接收端捕捉到来自存储器的数据位序列[^2]。 #### 推荐的技术文档与教程 以下是几类重要的参考资料供参考学习之用: - Xilinx官方发布的《UG583 - LogiCORE IP Memory Interface Solutions》手册详细介绍了如何配置使用MIG生成各种类型的动态随机存取存储器解决方案,并附带丰富的实例说明指导用户完成整个开发周期内的各项任务包括但不限于综合编译下载调试等环节。 - 另外还有针对特定型号如Zynq系列器件所编写的应用指南(APG),它们会进一步细化讲解有关该平台架构特点下的最佳实践方法论等内容。 - 对于初学者而言,《【FPGA】DDR3学习笔记(二)丨从SDRAM到DDR3丨MIG IP核设计》一文中提到的实际案例分析非常有价值,它涵盖了从基础概念理解直到最终项目实施全过程中的关键技术要点解析。 #### 常见使用的仿真工具列表 目前行业内主流可选用作DDR相关工作的软件环境有以下几个选项可供选择: - ModelSim/Questa Sim: Mentor Graphics出品的支持多标准协议验证的强大波形查看编辑工具集;特别适合做高层次抽象级别以上的纯RTL代码质量保障工作。 - Vivado Simulator: 自家产品线内部集成的一体化解方案之一,专为加速基于赛灵思硬件描述语言项目的进展速度而打造而成。 - Synopsys VCS: 商业化程度极高的一款高性能C++/System Verilog混合编程风格兼容型引擎驱动程序包组合形式呈现给客户群体作为购买决策依据考量因素之一考虑进去的话可能会更加稳妥一些吧! ```python # 示例Python脚本展示自动化运行Modelsim命令行版进行批处理作业的方式 import subprocess def run_modelsim_simulation(tcl_script_path): try: result = subprocess.run(['vsim', '-c', '-do', tcl_script_path], check=True, text=True) print(result.stdout) except subprocess.CalledProcessError as e: print(f"An error occurred while running the simulation: {e}") if __name__ == "__main__": script_file = "./simulate_ddr.tcl" run_modelsim_simulation(script_file) ```
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小破同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值