文章共1433字,阐述了AMBA APB协议读写信号状态机转换,以及用一个示例展示了APB协议的读写寄存器。通过和这几个寄存器交互,设计者可以将自定义的模块挂接到基于AMBA总线的SoC系统中。
APB是AMBA中相对比较简单的接口协议,用于连接低带宽,无需高性能流水线接口的外设。采用这种简单的协议,你可以轻松地将自定义外设挂在基于AMBA总线的SoC上。
许多APB外设都是慢速器件,例如UART、I2C等。一般SoC都是通过它们的寄存器进行访问。
APB每次传输至少需要两个周期,所有信号的转换仅在时钟的上升沿发生以便能够轻松地将APB外设集成到其他设计中。
APB还包括用于扩展APB传输的PREADY信号和用于指示传输失败的PSLVERR信号。
在APB协议中有两种类型的写传输:无等待写传输和有等待写传输。
无等待写传输:
在时钟的第一个上升沿,是Setup阶段,地址信号PADDR、数据信号PWDATA、写信号PWRITE和选择信号PSEL开始改变。
在随后的时钟沿之后,使能信号PENABLE拉高,表示进行Access阶段。地址信号PADDR、数据信号PWDATA、写信号PWRITE、选择信号PSEL在整个Access阶段都保持有效。
APB写传输在Access阶段结束时完成。使能信号PENABLE在传输结束时拉低,选择信号PSELx也拉低,除非后面紧接着另一个对该外设的传输。
有等待写传输:
在Access阶段,可以通过拉低PREADY来延长传输,这可确保对某些外设进行多周期访问。
建议在传输后不立即更改地址信号和写信号,在另一次访问之前保持稳定可以降低动态功耗。
在APB协议中有两种类型的读传输:无等待读传输和有等待读传输。
无等待读传输:
上图显示了无等待读传输。APB slave必须在读传输结束之前提供数据。
有等待读传输:
上图显示了PREADY信号如何扩展读传输。如果在Access阶段PREADY拉低,则读传输会延长。
下图是AMBA APB的工作流程
IDLE - 这是APB的默认状态。
SETUP- 当需要传输时,总线进入SETUP状态,其中相应的选择信号PSELx被置位。 总线仅在一个时钟周期内保持SETUP状态,并始终在时钟的下一个上升沿移至ACCESS状态。
**ACCESS **- 使能信号PENABLE在ACCESS状态下被置位。在从SETUP到ACCESS状态的转换期间,PADDR,PWRITE,PSELx和PWDATA信号必须保持稳定。
**从ACCESS状态退出由来自APB slave的PREADY信号控制。**如果APB slave将PREADY保持为低电平,则总线保持在ACCESS状态。如果APB slave将PREADY驱动为高电平,则退出ACCESS状态。
如果不再需要传输,则总线返回IDLE状态。如果紧跟着另一次传输则总线直接移动到SETUP状态。
根据上面的状态转换图可以很轻松地编写基于FSM的VerilogHDL。
下面是一个非状态机写法的APB slave 的verilog实例,大家可以在此基础上设计自己APB slave接口的自定义模块,将外设挂接到SoC上。
// Sample APB register code
其中,//system部分接口是系统全局信号用于复位和使能,//APB部分接口****是APB协议所需信号。
//Interface部分接口****是用于和自定义功能模块的接口寄存器即系统和模块之间交互桥梁。status32和status16全部为只读,control32和control16可读可写。
wire apb_write = psel & penable &pwrite;
wire apb_read = psel & ~pwrite;
apb\_write和apb\_read是为了满足APB协议做的读写控制,具体可以查阅APB协议官方文档
assign pready = 1'b1;
assign pslverr = 1'b0;
该APB slave模块只是对一些控制和状态寄存器进行读写,无等待传输同时不生成传输错误信号。
always @(posedge pclk or negedge reset_n)
begin
if (!reset_n)
begin
control32_wr <= 32'h0;
control16_wr <= 16'h0;
prdata <= 32'h0;
end
else if (enable)
begin
if (apb_write)
begin
case (paddr)
//4'h0:status32 read only
4'h4 : control32_wr <= pwdata;
//4'h8:status16 read only
4'hC : control16_wr <=pwdata[15:0];
endcase
end // write
if (apb_read)
begin
case (paddr)
4'h0: prdata <= status32;
4'h4: prdata <= control32_rd;
4'h8: prdata[15:0] <= status16;
4'hC: prdata[15:0] <=control16_rd;
endcase
end // read
else
prdata <= 32'h0; // so we can OR all busses
end
end
本文转载自公众号:芯片数字实验室
原文链接:
https://mp.weixin.qq.com/s/Jibq9vMpx-RbmrAF6ziXqg
未经作者同意,请勿转载!
推荐阅读
想了解更多内容,欢迎关注Arm ABMA总线专栏