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
相关产品推荐
相关产品推荐

