AMBA(Advanced Microcontroller Bus Architecture)
APB(Advanced Peripheral Bus):主要用在低速且低功率的外围,可针对外围设备作功率消耗及复杂接口的最佳化。
AHB(Advanced High-performance Bus):主要是针对高效率、高频宽及快速系统模块所设计的总线,它可以连接如微处理器、芯片上或芯片外的内存模块和DMA等高效率模块。
AXI(Advanced eXtensible Interface):高速度、高带宽,管道化互联,单向通道,只需要首地址,读写并行,支持乱序,支持非对齐操作,有效支持初始延迟较高的外设,连线非常多。
本章主要介绍APB总线
APB总线:
- 低速总线、低功耗
- 接口简单
- 在bridge中锁存地址信号和控制信号,送出片选信号给APB从设备
- 适用于多种外设
- 上升沿触发
APB 组成部分:
- AHB2APB Bridge
锁存所有的地址、数据和控制信号
进行二级译码来产生APB Slave选择信号 - 其他模块都是APB Slave
不是流水线方式传递数据
接口零功耗
APB总线信号
- PCLK
- PRESETn
- PADDR[31:0] ,地址总线,由设备总线的bridge单元驱动
- PSELx,从译码器的片选信号,到每一个总线从设备
- PENABLE,用于在设备总线上把所有访问按时间阶段进行
- PWRITE,高电平为写,低电平为读
- PRDATA
- PWDATA
写传输
由图所示,地址(PADDR)、写信号(PWRITE)、选择信号(PSEL)、写数据(PWDATA)在时钟上升沿之后同时有效。表明一次写传输的开始,传输的第一个时钟周期称为SETUP周期。在下个时钟上升沿使能信号(PENABLE)有效,紧接着就是ENABLE周期。而地址、写数据和控制信号需要在此期间保持有效。传输在ENABLE周期结束时完成,此时PENABLE变为低电平,PSEL也变为低电平。
读传输
由图所示,地址、写信号、选择信号的时序和写传输一样,即在读传输时,从设备必须在ENABLE周期提供数据,读数据在ENABLE周期结束的时钟上升沿被主设备采样。
多说无益,上代码!!!
示例:如下是一个APB_Slave 代码以及tb文件如下:
module apb_slave(
input psel,
input penable,
input [31:0] paddr,
input pwrite,
input presetn,
input pclk,
input [31:0] pwdata,
output reg [31:0] prdata);
reg [31:0] data1;
reg [31:0] data2;
reg [31:0] data3;
reg [31:0] data4;
//write and read
always@(posedge pclk or negedge presetn)
begin
if(!presetn)
begin
data1<=32'h0;
data2<=32'h0;
data3<=32'h0;
data4<=32'h0;
prdata<=32'h0000_0000;
end
else if(psel&&penable&&pwrite)
begin
case(paddr[7:0])
8'h00:data1<=pwdata;
8'h04:data2<=pwdata;
8'h08:data3<=pwdata;
8'h0c:data4<=pwdata;
endcase
end
else if (psel&&penable&&!pwrite)
begin
case(paddr[7:0])
8'h00:prdata<=data1;
8'h04:prdata<=data2;
8'h08:prdata<=data3;
8'h0c:prdata<=data4;
endcase
end
end
endmodule
module tb();
reg psel;
reg penable;
reg [31:0] paddr;
reg pwrite;
reg presetn;
reg pclk;
reg [31:0] pwdata;
wire [31:0] prdata;
apb_slave u1(
.psel(psel),
.penable(penable),
.paddr(paddr),
.pwrite(pwrite),
.presetn(presetn),
.pclk(pclk),
.pwdata(pwdata),
.prdata(prdata));
initial
begin
pclk=1;
forever #(20/2) pclk=~pclk;
end
initial
begin
presetn=0;
#(60) presetn=1;
end
//write test
initial
begin
#80 psel=1;
paddr=32'h0000_0100;
pwrite=1;
pwdata=32'd7200;
#20 penable=1;
#20 penable=0;
psel=0;
end
//read test
initial
begin
#200 psel=1;
paddr=32'h0000_0100;
pwrite=0;
#20 penable=1;
#20 penable=0;
psel=0;
end
endmodule
或者
module apb_slave(
input psel,
input penable,
input [7:0] paddr,
input pwrite,
input presetn,
input pclk,
input [31:0] pwdata,
output reg [31:0] prdata);
reg [31:0] data [256-1:0];
integer i;
//write and read
always@(posedge pclk or negedge presetn)
begin
if(!presetn)
begin
prdata<=32'h0000_0000;
for(i=0;i<=8'hff;i=i+1)
begin
data[i]<=32'h0;
end
end
else if(psel&&penable&&pwrite)
begin
data[paddr]<=pwdata;
end
else if (psel&&penable&&!pwrite)
begin
prdata<=data[paddr];
end
end
endmodule