信号名称:
读写流程:
1、IDLE:系统初始化状态,此时没有传输操作,也没有选中任何从模块。
2、SETUP:启动状态,当有传输要进行时,PSELx=1,,PENABLE=0,系统进入SETUP状态,并只会在SETUP状态停留一个周期。当PCLK的下一个上升沿到来时,系统进入ENABLE状态。
3、ENABLE:在总线进入SETUP状态的下一个时钟上升沿处,需将PENABLE信号拉高进入ENABLE状态。在这个上升处,master必须保持PADDR、PSEL、PWRITE不变。传输也只会在ENABLE状态维持一个周期,在经过SETUP与ENABLE状态之后就已完成。之后如果没有传输要进行,就进入IDLE状态等待;如果有连续的传输,则进入SETUP状态。
写时序:
在T1时刻,PSEL拉高,此时PWRITE为高,进入写入状态。在PENABLE为1时,将PWDATA总线上数据写到对应寄存器或者数据存储器。当PREADY信号拉高,表示一次写入完成,总线返回到初始状态等待PSEL拉高。PWDATA总线上数据会一直保持上一次写入时状态,直到下一次写操作为止。
当PREADY信号一直处于低电平状态,总线则进入等待状态,此时PSEL与PENABLE处于置高状态,等待PREADY信号拉高。如下图时序所示
读时序:
在T2时刻,PSEL拉高,此时PWRITE为低,此时进入读状态。在PENABLE为1时,将待读取数据置到PRDATA总线,在PENABLE下降沿时刻,将PRDATA总线数据从AXI-LITE总线读回。
APB总线在各总线中时序控制比较简便,而且可以分出多个控制接口,根据从机基地址进行对应控制即可,需要注意的是PREADY信号需要进行拉高来表示一次写入的完成,否则总线会一直处于占用状态,无法再进行其他读写操作。
总线在使用会遇到各种各样的问题,因为本身总线控制信号较少,所以在使用中会进行各种各样的更新,在IP设置时可以看到APB3和APB4的选择。
APB(Advance Peripheral Bus)是AMBA总线的一部分,从1998年第一版至今共有3个版本。
AMBA 2 APB Specfication:定义最基本的信号interface, 读写transfer, APB bridge, APB slave.
AMBA 3 APB:增加定义信号PREADY, PSLVERR来完成对wait state和Error reporting的功能。
AMBA 4 APB:增加定义信号PPROT, PSTRB来支持secure, supervisor和sparse data transfer的功能。
完整代码如下:
module apb_wr (
input wire PCLK,
input wire [31:0] PADDR,
input wire PWRITE,
input wire PSEL,
input wire PENABLE,
input wire [31:0] PWDATA,
input wire rst_n,
input wire [31:0] RDATA,
output wire PSLVERR,
output wire [31:0] PRDATA,
output reg [31:0] WDATA
);
/* user signal define */
reg [3:0] state;
parameter apb_idle = 4'd0,
apb_wr = 4'd1,
apb_rd = 4'd2,
apb_rd1 = 4'd3;
/* APB BUS wr sequential */
assign PSLVERR = 1'b0;
assign PRDATA = RDATA;
always@(posedge PCLK or negedge rst_n)
begin
if(rst_n==1'b0)
begin
WDATA <= 'h0;
state <= apb_idle;
end
else
begin
case(state)
/* wait for wr start */
apb_idle:begin
if(PSEL==1'b1)
begin
if(PWRITE==1'b1)
begin
state <= apb_wr;
end
else
begin
state <= apb_rd;
PRDATA <= RDATA;
end
end
else
begin
state <= apb_idle;
end
end
/* PWRITE=1 is write ,wait for the PENABLE */
apb_wr:begin
if(PENABLE)
begin
state <= apb_idle;
WDATA <= PWDATA;
end
else
begin
state <= apb_wr;
end
end
/* PWRITE=0 is read ,wait for the PENABLE */
apb_rd:begin
if(PENABLE==1'b1)
begin
state <= apb_idle;
end
else
begin
state <= apb_rd;
end
end
default:begin
state <= apb_idle;
end
endcase
end
end
endmodule