关于APB驱动run_phase向DUT发送事务逻辑的技术疑问
UVM APB驱动常见问题解答
问题1:是否可以在driver类中手动设置Penable、Psel、Pready的值,还是需要在seq_item类中对这些信号进行随机化?
- Psel、Penable:必须由driver手动控制,不需要在seq_item中随机化。这两个是APB总线的控制信号,属于事务执行的时序细节,是driver按照APB协议状态机生成的,不属于事务本身的属性。
- Pready:这是DUT输出的响应信号,driver只需要采样它,不需要主动设置。
seq_item的核心作用是描述一个完整的事务请求,比如读写类型、目标地址、写数据、传输等待周期(可选)等。总线握手的控制信号是driver的职责,要严格遵循APB协议时序驱动,交给seq_item随机化会破坏协议规范性,也混淆了seq(事务发起)和driver(事务执行)的分层职责。特殊场景下(比如模拟异常时序),可以在seq_item中加配置参数让driver生成异常信号,但常规正常传输不需要这么做。
问题2:如何根据idle、setup、access等不同状态来设置这些信号的值?
APB协议状态机是固定的,driver需要根据状态切换精准控制信号,以下是标准状态处理逻辑:
各状态信号规则
- Idle(空闲状态)
- 无传输时保持此状态
- 信号设置:
Psel = 0,Penable = 0,Pwrite、Paddr、Pwdata可保持无效值
- Setup(建立状态)
- 发起新传输的第一个时钟周期进入此状态
- 信号设置:
Psel = 1,Penable = 0,同时设置Paddr(目标地址)、Pwrite(读写类型)、Pwdata(写操作时赋值)
- Access(访问状态)
- Setup状态的下一个时钟周期进入此状态
- 信号设置:
Psel = 1,Penable = 1,保持Paddr、Pwrite、Pwdata不变(写操作) - 等待DUT的
Pready信号:当Pready == 1时传输完成,读操作在此周期采样Prdata,写操作在此周期完成数据传输
- 连续传输
- 如果需要连续发起多个事务,传输完成后可直接进入下一个事务的Setup状态,无需回到Idle
修正后的driver run_phase示例代码
task run_phase(uvm_phase phase); forever begin seq_item_port.get_next_item(req); // 获取seq发送的事务 `uvm_info(get_type_name(), $sformatf("Received transaction: addr=0x%0h, write=%0b, wdata=0x%0h", req.P_addr, req.P_write, req.P_wdata), UVM_MEDIUM) // 1. 进入Idle状态(若之前已是Idle可跳过) @(posedge vif.P_clk); vif.P_selx <= 0; vif.P_enable <= 0; vif.P_write <= 0; // 2. 进入Setup状态 @(posedge vif.P_clk); vif.P_selx <= 1; vif.P_enable <= 0; vif.P_addr <= req.P_addr; vif.P_write <= req.P_write; if(req.P_write) begin vif.P_wdata <= req.P_wdata; end // 3. 进入Access状态,等待Pready @(posedge vif.P_clk); vif.P_enable <= 1; wait(vif.P_ready == 1); // 等待DUT响应 // 读操作:采样返回数据 if(!req.P_write) begin req.P_rdata <= vif.P_rdata; `uvm_info(get_type_name(), $sformatf("Read data: 0x%0h", req.P_rdata), UVM_MEDIUM) end // 4. 传输完成,回到Idle状态 @(posedge vif.P_clk); vif.P_selx <= 0; vif.P_enable <= 0; seq_item_port.item_done(req); // 通知seq事务完成,返回更新后的item(含读数据) end endtask
代码说明
- 用
forever循环持续处理seq发送的事务,而非固定次数的repeat - 严格遵循Idle→Setup→Access→Idle的状态流转
- 加入
Pready等待逻辑,符合APB协议握手要求 - 读操作时采样
Prdata并更新到req中返回给seq - 避免在driver中随机化req,事务随机化应由seq完成,driver只负责执行
内容的提问来源于stack exchange,提问作者BforB
相关产品推荐
相关产品推荐

