AHB-SRAM

0.代码理解

DUT

  • AHB总线传输数据位宽有8/16/32(HSIZE[3:0]:000-8bits,001-16bits,010-32bits),而ram不一定支持(这里每个ram支持数据位宽为8位),所以用了4块ram,每块ram对应一个byte。
  • 当AHB传来8bit数据时,可以选择四个ram中的任何一个进行存放;传来16bit数据时,可以选择BRAM0/1或者BRAM2/3这两种组合进行存放;传来32bit时,BRAM0~3依次存放第1-4byte。
  • 增加一个输入信号HSELBRAM——该信号控制使能ram块。
  • 存储器写入控制信号reg_wr_en[3:0]由下一次写入使能信号nxt_wr_en[3:0]赋值得到,决定要将数据写进哪个ram中。

VIP_lib

配置类

lvc_ahb_agent_configuration.sv和lvc_ahb_configuration.sv

  • agent配置类中有一个1bit变量is_active,其控制着master_agent中,drv的port与sqr的export的连接,以及向它俩传递vif。
变量定义类

lvc_ahb_defines.svh

  • 定义AHB传输data的最大宽度64bit,addr最大宽度32位。
ahb类型类

lvc_ahb_types.sv

  • 规定AHB信号所对应的二进制码。
    • Slave发给Master的4个传输状态:
      • OKEY:传输正常。
      • ERROR:传输错误。
      • RETRY:传输未完成,请求Master重新开始下一个传输,arbiter会继续使用通常的优先级
      • SPLIT:传输未完成,请求Master分离一次传输,arbiter会调整优先级方案,以便其他请求总线的主设备可以访问总线。
    • 当前4种传输类型:
      • IDLE:主设备占用总线,但没进行传输。
      • BUSY:主设备占用总线,但是Master在burst传输过程中还没有准备好进行下一次传输,先暂停一下。
      • NSEQ:表示一次单个数据的传输或者一次burst传输的第一个数据。
      • SEQ :burst传输接下来的数据。
    • 每一个transfer传输的数据大小:
      • BURST_SIZE(8~1024)但实际只能用到8/16/32
    • Burst传输类型:
      • 单个传输数据传输、任意长度的数据传输、打包4/8/16拍传输,四个地址是一个回环范围、4/8/16拍传输,地址是增加的。
    • 传输操作类型:读、写、空闲。
    • 传输状态类型:
      • INITIAL:表示该标志的默认状态。一旦节拍级传输开始,它就会被更新。
      • PARTIAL_ACCEPT:一旦每个节拍的地址被从机接受,状态就会从INITIAL变为PARTIAL_ACCEPT。
      • ACCEPT:一旦节拍级数据被从机接受,状态就会变为ACCEPT。
      • ABORTED:如果交易因Slave的ERROR/SPLIT或RETRY响应而被中止,或者在EBT的情况下,状态变为ABORT。
  • 规定一个限制每一次transfer数据大小的函数extract_valid_data,因为Slave(RAM)只能处理8/16/32bit的数据(变量定义类中:定义AHB传输data的最大宽度64bit)。
    • ✅ ​case语句对参数bsize(单个数据大小)判断:
      • 8bit:data右移0/8/16/24位,然后和8’hFF按位与。——分别对应存放进4个不同的ram块中。
      • 16bit:data右移0/16位,然后和16’hFF按位与。——分别对应存放低两个ram块或高两个ram块。
      • 32bit:和32’hFFFF按位与。
      • 其它位就报错。
ahb接口类

lvc_ahb_if.sv

  • 定义三个clocking_block:cb_mst、cb_slv、cb_mon
激励和组件类

先定义顶层的trans、drv、mon、sqr类。然后apb_master的trans、drv、mon、sqr类再继承与它们,apb_master的trans、mon、sqr类都没内容,主要是apb_master_drv。

lvc_ahb_transaction.sv

  • 定义了各个信号的默认值:burst_size为8bit,即每一拍中的一个数据为8bit;burst_type为单个传输…并将这些变量添加到域的自动化。
  • 定义一个increase_data函数,每次调用,data会新建一个比以上一个data长度多1的新动态数组,并把上一个data的值传进来,动态数组all_beat_response也是。也就是data动态数组中会包含一次burst中的所有数据,且all_beat_response动态数组也包含了在该次burst中slave返回给master的传输状态。

lvc_ahb_base_sequence.sv没内容

lvc_ahb_master_single_trans继承于lvc_ahb_base_sequence

  • 约束了传输操作类型只有读和写,没有idle。
  • body函数中,为req规定默认约束,然后调用get_response任务来检索响应,是阻塞的。
  • ✅如果是读操作,那么将rsp中data的[0]赋给data(这里是因为drv中将hrdata放进的data的[0]),然后打印req中的成员变量。

lvc_ahb_sequencer.sv没内容

lvc_ahb_driver.sv

  • 声明agent配置类对象和ahb虚接口。
  • run_phase中fork_join_none两个任务:get_and_drive、reset_listener
    • get_and_drive任务:port端口get seq产生的req,然后打印“我拿到item”,再调用drive_transfer任务(由其子类中定义)将req发送出去(通过接口给dut),然后req调用系统克隆函数,并转化子类句柄并赋给rsp,分别获取req的seq_id、trans_id并交给rsp(发送的单个数据id、数据包的id),然后将rsq消化掉。
    • reset_listener任务:由子类定义内容(就是复位所有信号)。

lvc_ahb_monitor.sv

  • 声明agent配置类对象和ahb虚接口和广播端口ap(与rkv_ahbram_subscriber相连)。
  • run_phase中fork_join_none一个任务:monitor_transactions
    • monitor_transactions任务中先声明了ahb_transaction类型对象t,又无限循环collect_transfer任务和将t写进广播端口(收集来自dut-aph的trans并广播发送出去):
      • collect_transfer任务:创建对象t实例,等待接口上ck_mon时钟块信号htrans(传输类型:nonseq/seq/idle/busy)为NSEQ,即burst传输的第一个数据或单个传输,便对该时钟块将dut-aph的信号(是burst传输的信息变量)采样。再无限循环monitor_valid_data任务(),遇到idle便打破该循环。
        • monitor_valid_data(检测有效数据)任务:等待接口上ck_mon时钟块信号hready信号为1,便对该时钟块将dut-aph的信号采样,t调用lvc_ahb_transaction中的increase_data函数(将每次burst的data和slave返回的状态保存到动态数组);并用int类型变量current_data_beat_num来存储当前data的个数;条件语句判断是读指令还是写指令,分别将hwdata/hrdata采集进动态数组data的对应位置,将采集到的hresp放进动态数组all_beat_response的对应位置。

lvc_ahb_master_driver.sv

  • drive_transfer任务不支持burst传输,仅支持单个数据传输。
    • 单个数据传输——分为初始读或写、受保护的读或写四种读写方式。(这里读写都是相对于ahb来说的,drv都是将信号驱动给ahb)
    • 初始的读或写——要先等待bus的grant,即要等接口上cb_mst时钟块的hgrant信号=1,dut的master准备好了,才能开始对它的读和写。
      • 写操作——就将t中各个变量驱动到接口,然后下一时钟块发送一个idle,然后将data驱动到dut。然后在clk下降沿检查hready是否=1,=1就继续走,不等1就一直在循环中,数据也不会写给slave。然后发送一个data后,将传输类型更新为NESQ,current_data_beat_num更新为0,hresp更新进all_beat_response数组中。
      • 读操作——前边和写操作一样,不同之处是要将t.data依次放在除[0]位的高位上,然后这次的hrdata放进t.data[0]。

lvc_ahb_master_agent.sv

  • 将mst_drv/mon/sqr和agent_cfg封装。

seq_lib

rkv_ahbram_base_element_sequence.sv

  • 内有一个简单的compare_data函数,进行读写数据的对比,并且每次会计数+1。

rkv_ahbram_single_read_seq.svrkv_ahbram_single_read_seq.sv

  • 继承于rkv_ahbram_base_element_sequence类。
  • 将lvc_ahb_master_single_trans类型seq的对象实例挂载到p_sequencer.ahb_mst_sqr,并约束xact为读或写。

rkv_ahbram_base_virtual_sequence.sv

  • 例化了single读和写seq。
  • 定义了四个task:等待复位信号的上升沿task、等待复位信号的下升沿task,等待n个时钟cycle的task(n为输入参数)、wait_ready_for_stim任务中调用:等待复位信号的下升沿task和n=10的等待n个时钟cycle的task。
  • 其他seq都继承于rkv_ahbram_base_virtual_sequence。

rkv_ahbram_smoke_virt_seq.sv

  • 冒烟测试:
  • 当测试平台搭建好后,首先进行一个很基础、很简单的测试,确保测试平台可以正常运转。
  • 产生10个数据,addr[1:0]约束为0,因为lvc_ahb_transaction中规定默认data为8bits,所以这里约束8bit的数据要存放在SRAM0,即靠低位按字对齐存放。
  • 然后将读出的数据和写入的数据通过compare_data函数作比较。

rkv_ahbram_diff_haddr_virt_seq.sv

  • 不同HADDR的对齐读写测试:
  • 发送数据个数由rkv_ahbram_config.sv中的32bit变量addr_end控制。且地址addr的随机范围也在[addr_start: addr_end]之间。

rkv_ahbram_diff_hsize_virt_seq.sv

  • 不同HSIZE的对齐读写测试:
  • 相较于前两个测试都是传输8bits的数据,该测试增加对bsize的随机(8/16/32)然后产生100个数据。
  • 与前两个测试seq区别:在进行数据比较时,根据不同位(8/16)的数据,分别和32’hFF/32’hFFFF按位&之后再比较。是要保证读写数据是按低按字对齐的。

rkv_ahbram_haddr_word_unaligned_virt_seq.sv

  • 不同HSIZE的非对齐读写测试:
  • 相较于之前对其测试(用约束addr[1:0]为0,来限制数据对齐读写),该测试没有约束addr[1:0]为0。所以当数据为8bits时,可存放在SRAM0/1/2/3中任意一块。且约束当bsize为16时,addr[0] == 0,即16位的数据可存放在SRAM0/1或SRAM2/3中。

rkv_ahbram_reset_w2r_virt_seq.sv

  • 复位前后的读写功能测试:
  • 复位前,进行十次正常的读写操作,并将十个数据的地址写到一个队列addr_q[$]里,后边复位后再拿出来用,正常这些相应地址应该没有数据了,读出来的是32’hx。
  • 然后通过rkv_ahbram_if接口中定义的复位任务去复位AHB,停止向ram中读写。
  • 之后do_while循环(先开始循环,等while后条件不满足后退出循环,即存放地址的队列中addr拿完后退出),对之前的写入地址还是再次进行读操作,然后和32’hx进行对比。

cfg

env

rkv_ahbram_subscriber.sv

  • rkv_ahbram_scoreboard和rkv_ahbram_cov继承于rkv_ahbram_subscriber。
  • 定义uvm_analysis_imp与lvc_ahb_monitor相连,接收来自mon的数据,imp通过port调用write函数来接收数据(t)
  • 预留了两个任务:do_events_trigger()、do_listen_events()。

rkv_ahbram_scoreboard.sv

  • 继承于订阅者,其内置的write函数覆盖了父类中write函数,并通过is_addr_valid函数判断tr.addr是否有效(地址范围要在rkv_ahbram_cfg中规定的两个变量addr_start、addr_end之间),addr有效的话再判断tr.xact_type是读还是写操作。
  • 写操作——调用store_data_with_hburst函数:
    • 先判断tr.burst_type,是SINGLE的话就执行store_data_with_hsize函数,其他传输类型就报错(暂不支持)。
      • store_data_with_hsize函数中,根据数据size,再通过extract_current_beat_mem_data函数,将数据拿出来,再赋给scoreboard中定义的mem的相应地址位(按低位、按字节对齐存放)。
        • extract_current_beat_mem_data函数中,将data[0]的数据拿出来,赋值给mdata的对应字节位。
  • 读操作——调用check_data_with_hburst函数:
    • 先判断tr.burst_type,是SINGLE的话就执行check_data_with_hsize函数,其他传输类型就报错(暂不支持)。
      • check_data_with_hsize函数,将写进去的mdata和读出来的tdata进行对比。

rkv_ahbram_cov.sv

  • 继承于订阅者,定义了两个覆盖组T1和T2,前者采集地址覆盖率,后者采集传输类型(SINGLE、INCR、WRAP4、INCR4)和SIZE覆盖率。
  • t1的ADDR覆盖点,对addr整个进行采样,定义了19个bin,各个bin取值范围分别是起始、终止、超出范围、和合法范围。BYTEACC覆盖点,对addr[1:0]进行采样。
  • t2的BURST_TYPE覆盖点和BURST_SIZE覆盖点,分别定义4个bin对传输类型和size进行采样。

rkv_ahbram_env.sv

  • build_phase中,通过config_db将rkv_ahbram_config和lvc_ahb_agent_configuration的实例对象,分别set进virt_sqr、cov、scb和anb_mst。
  • connect_phase中,及那个ahb_mst_sqr赋给virt_sqr中的ahb_mst_sqr;寄存器模型的map和adapter连接并挂到ahb_mst.sequencer上,并把rgm.map和adapter赋给predictor;ahb_mst.mon的广播端口item_observed_port与predictor、cov、scb相连(当ahb_mst.monitor一旦捕捉到有效trans,就会发送给predictor,然后predictor将trans交给adapter进行转换,转换后的寄存器模型有关信息更新到map中)。

test

rkv_ahbram_base_test.sv

  • 将起始和终止地址数值配置成:
cfg.addr_start = 32'h0;
cfg.addr_end = 32'h0000_FFFF;

tb

rkv_ahbram_if.sv

  • 该接口中定义一个控制复位的任务,形式参数nclks:控制等待nclks个时钟上升沿后拉低复位信号。然后再等5个时钟上升沿后将其拉高。

rkv_ahbram_tb.sv

  • 这里定义了两个接口,lvc_ahb_if和rkv_ahbram_if。前者是TB与DUT之间正常通信的接口,后者是专门为了测试复位后写和读功能的一个接口。后者是TB与DUT的顶层的接口,前者是TB与AHB的接口。

1.AHB VIP及TB框架的实现

  • VCS有自带的模板生成工具:UVM Template Generator (UVM)User Guide
  • terminal中输入指令,使用模板生成工具:uvmgen
  • lvc——列正verification component,就是列正自动化平台的组件(模板自动生成的组件)。
  • 条件编译选项:“idndef defin ifdef enif”
    • ifndef 的含义:即 “if not defined”,也就是说,当文件编译到这一行,如果这个文件还没有被编译过,也就是首次编译,就会执行后续的 `define xxx这句话,把后续的代码定义一次。反之,则不会再重复编译。
    • ifdef 的含义:即"if defined",与 ifndef 的作用相反,如果已经编译过,那么则继续执行后面的代码。
    • enif 的含义:出现 ifndef 或者 ifdef 作为开头,程序块的末尾就需要有 endif 作为结束的标识。
  • lvc_ahb_master_sequencer和lvc_ahb_slave_sequencer中间会有公共相同的部分,那么把公共的部分抽取到一个lvc_ahb_sequencer,作为父类。
  • 文件夹列表:
    • cfg cov env seq_lib sim tb test vip_lb
  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ahb-sram指的是高级外围总线(AHB)和静态随机存储器(SRAM)之间的接口设计和验证。 AHB-SRAM设计验证主要关注于确保AHB总线和SRAM之间的通信正常和可靠。设计验证的过程包括以下几个关键步骤: 1. 规划设计验证策略:在开始验证之前,需要明确定义验证目标和计划。确定验证所需资源、验证方法和验证环境等。 2. 静态验证:进行静态验证以评估设计的一致性和正确性。这可以通过使用模拟和仿真工具来完成,以验证设计的逻辑功能是否符合规格要求。 3. 动态验证:通过建立高级仿真模型或使用硬件描述语言(HDL)编写测试程序,进行动态验证。这些测试程序模拟了实际使用AHB-SRAM接口的情况,验证了设计和实现是否能够正确地处理各种读写操作和异常情况。 4. 性能验证:通过使用性能评估工具和技术,测试和验证设计在处理大量数据时的吞吐量、延迟和带宽等性能指标。这有助于确保AHB-SRAM设计能够满足系统需求。 5. 集成验证:将AHB-SRAM设计与其他子系统和外设集成,验证设计在整个系统中的功能和性能。这涉及到集成测试和系统级仿真,以确保整个系统的一致性和稳定性。 6. 错误排查和调试:在设计验证过程中,可能会发现各种问题和错误。需要进行适当的排查和调试,以找出问题的原因,并修复设计中的错误。 通过上述步骤的设计验证过程,可以最大程度地确保AHB-SRAM设计在实际应用中的正确性和可靠性。这样可以提高系统的稳定性和性能,并降低后续开发和维护的风险和成本。 ### 回答2: AHB(SRAM)设计验证是对AHB(SRAM)的硬件设计进行验证的过程。AHB指的是高级外设总线(Advanced High-performance Bus),是一种用于处理器与外设之间的通信的总线协议。SRAM指的是静态随机存取存储器(Static Random-access Memory),是一种常见的计算机内存存储单元。 AHB-SRAM的设计验证旨在确保这个硬件设计符合AHB协议,并能够正确地存储和读取数据。验证过程一般包括以下几个步骤: 1. 设计规划:确定设计验证的目标和范围,编写验证计划和验证测试案例。 2. 功能验证:通过对设计电路进行功能仿真,验证设计的各项功能是否满足需求。通过使用一些特定的设计验证工具,对设计电路进行输入和输出的模拟,以验证逻辑电路的正确性。 3. 性能验证:通过对设计电路进行性能仿真,验证设计的时序和时钟频率是否满足要求。通过模拟各种情况下的数据存储和读取操作,检测潜在的性能瓶颈。 4. 物理验证:通过对设计电路进行物理验证,验证设计的布局和连线是否符合物理设计规范和约束条件。通过使用专业的物理验证工具,检查电路中是否存在物理故障,如电气连接问题、时序冲突等。 5. 集成验证:将设计电路与其他相关组件进行集成,验证整个系统的功能和性能。 AHB-SRAM设计验证是一个非常关键的步骤,它能够检测和纠正设计中的错误和问题,确保最终设计的可靠性和稳定性。只有通过了验证的设计才能进行后续的制造和生产。同时,设计验证还能够提供设计改进和优化的反馈,以便进一步提高设计的性能和效果。 ### 回答3: AHB(SRAM)是一种特定类型的静态随机存取存储器设计,用于在系统总线上进行数据传输和存储。设计验证是确保设计的功能和性能符合规范和需求的过程。 AHB-SRAM设计验证的目标是验证AHB-SRAM的功能正确性、数据的一致性和性能方面的指标。验证过程通常包括以下几个步骤: 1. 功能验证:通过编写测试用例,验证AHB-SRAM在不同的读写操作下是否能够正确地读写数据。测试用例需要覆盖各种读写情况,包括随机读写、顺序读写等。同时还需要测试错误情况下的处理机制,比如写入冲突、读取无效地址等。通过功能验证可以确保AHB-SRAM能够按照规定的操作进行数据的读写。 2. 数据一致性验证:在多核系统中,多个处理器可能同时访问AHB-SRAM。数据一致性验证的目标是验证在多个处理器同时读写AHB-SRAM时,数据的一致性是否能够保持。验证过程中需要考虑读写操作的时序和数据同步机制,确保在多个处理器之间进行数据交换时不会出现数据冲突或数据丢失的情况。 3. 性能验证:AHB-SRAM的性能指标包括读写延迟和带宽。性能验证的目标是通过测试用例和性能评估工具来验证AHB-SRAM能够在规定的时钟周期内完成读写操作,并能够满足带宽需求。性能验证可以帮助确定系统中AHB-SRAM的使用限制和资源分配。 通过上述验证步骤,可以确保AHB-SRAM设计的正确性和性能符合预期。验证过程需要仔细设计测试用例和评估工具,同时需要对设计进行仿真和调试,以确保设计的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值