You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AMBA APB从机PREADY信号生成时机及传输相关设计问询

AMBA APB从机PREADY信号设计详解

作为经常搞APB外设设计的工程师,我来给你拆解一下PREADY信号的设计逻辑,这可是APB从机和主机同步的核心关键:

一、从机该什么时候生成PREADY?

APB的传输分为**setup(建立)和access(访问)**两个阶段,PREADY的响应时机完全绑定在access阶段:

  • 无等待的正常传输:当主机进入access阶段(也就是PSEL和PENABLE同时为高)的同一个时钟周期里,你的从机已经准备好完成读/写操作了,直接把PREADY拉高就行。这种情况下整个传输在一个access周期内就完成了。
  • 需要等待的慢传输:如果从机没办法在当前access周期内搞定操作(比如要读内部的慢RAM、等外设完成初始化或者采样),那就先把PREADY保持低电平。这时候主机会一直维持PENABLE和PSEL的高电平,进入等待状态,直到你的从机准备好后把PREADY拉高,传输才会结束。

二、设计PREADY置高时必须考虑的场景

这些细节很容易踩坑,一定要注意:

  • 读写操作的不同要求:
    • 写操作:得确保PDATA的数据已经被正确锁存到从机内部的寄存器或者外设模块里,再拉高PREADY。比如有些外设需要2-3个周期处理写入的数据,那就等处理完再置高,别着急。
    • 读操作:必须等要返回的PRDATA完全准备好(比如从Flash里读出来了、ADC的采样数据就绪了),再拉高PREADY,不然主机会读到无效数据。
  • 地址有效性校验:只有当PSEL为高,并且PADDR落在当前从机的有效地址范围内时,才需要响应PREADY。如果地址不匹配,你可以直接拉高PREADY同时置高PSLVERR(错误信号),告诉主机这是非法访问,传输结束但出错了。
  • 多周期操作的状态跟踪:如果从机内部有需要多个时钟周期的任务(比如DMA传输、加密运算),一定要做个小状态机来跟踪进度,等任务完成后再把PREADY拉高,别让主机一直等或者提前结束。
  • 低功耗唤醒场景:如果从机平时在低功耗模式,被主机通过APB唤醒时,得先完成内部模块的唤醒初始化,等所有电路都就绪了再拉高PREADY,不然会导致传输数据出错。
  • 错误处理逻辑:当从机检测到非法操作(比如权限不足、寄存器写保护),别憋着,拉高PREADY的同时把PSLVERR置高,让主机知道这次传输出问题了——哪怕出错,也要用PREADY来结束当前传输周期。

三、数据传输和PREADY的关系

没错,只有当PREADY为高电平时,APB的读/写传输才算真正完成:

  • 写操作:主机在PENABLE和PREADY同时为高的那个时钟周期,会把PDATA上的数据写入从机的目标寄存器/外设。
  • 读操作:主机也是在这个双高的时钟周期,采样从机输出的PRDATA,完成数据读取。
    要是PREADY一直低,主机会卡在access阶段,直到你把PREADY拉高,传输才会往下走。

给你贴个简单的状态机伪代码参考,方便你理解:

always @(posedge PCLK or negedge PRESETn) begin
  if (!PRESETn) begin
    pready <= 1'b0;
    current_state <= IDLE;
  end else begin
    case(current_state)
      IDLE: begin
        // 进入setup阶段
        if (PSEL && !PENABLE) begin
          current_state <= SETUP;
          pready <= 1'b0;
        end
      end
      SETUP: begin
        // 进入access阶段
        if (PSEL && PENABLE) begin
          if (internal_module_ready) begin
            // 内部就绪,完成传输
            pready <= 1'b1;
            current_state <= IDLE;
          end else begin
            // 内部未就绪,进入等待
            pready <= 1'b0;
            current_state <= WAIT_FOR_READY;
          end
        end
      end
      WAIT_FOR_READY: begin
        if (internal_module_ready) begin
          pready <= 1'b1;
          current_state <= IDLE;
        end else begin
          pready <= 1'b0;
        end
      end
    endcase
  end
end

内容的提问来源于stack exchange,提问作者Payal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:06:32