APB简介及verilog代码示例

  • Post author:
  • Post category:其他




APB的全称为




Advanced Peripheral Bus




,即先进外设接口,该总线主要用于和低速以及低功耗的外设通信,该总线中唯一的主设备为




APB Bridge




,而其它的外设均为从设备。其中,




APB Bridge




可以锁存总线所有的地址、数据和控制信号,并通过二级译码来产生




APB




从设备选择信号,通常




APB Bridge




本身挂在




AHB




等高速总线上,用于









桥接









低速的




APB




总线。



APB




规定所有的信号必须在时钟上升沿触发时进行传递



APB


总线最大支持


32bit


的数据位宽,拥有两个独立的数据通道,分别为读通道和写通道。由于


APB


的两个通道没有独立的握手信号,因此两个通道不会被同时使用。


1、APB


信号定义如下:

大体可以分为以下三组:

  1. 系统信号:PCLK(系统时钟)、PRESETn(系统复位,低有效);
  2. master信号:PADDR(地址信号,确定读写的地址)、PSELx(片选信号,拉出来接给搭载APB总线的slave,选中slave时,PSELx信号拉高)、PNEABLE(使能信号,在PSELx拉高一个周期后,必定拉高)、PWRITE(写使能信号,PWRITE为高时写有效,为低时读有效)、PWDATA(写数据);
  3. slave信号:PREADY(ready为高时,代表着一次APB数据传输的结束)、PRDATA(读数据)、PSLVERR(错误数据,由slave发出,具体逻辑由slave内部决定,当slave发现内部逻辑出现故障,譬如状态机状态出错、计数器数字异常等,slave都可以使用内部逻辑把该信号拉高,使得master接收到PSLVERR为高时,哪怕ready拉高表示APB结束了,也可以使master放弃该次传输或做出其他应对策略)。

2、APB写

传输



如文档所示,


APB


的写分为两种情况:





没有等待状态的写;





有等待状态的写。

  • 没有等待状态的写

对于APB协议来说,最快的写入或者读出一个数据的周期是两周期,先给地址,再写数据;或者先给地址,再读数据。APB 协议文档中,将上述这种传输方式分为两个阶段(phase),给地址的阶段称为Set up phase;紧接着下一周期PENABLE信号拉高,标志着进入写/读数据的阶段,该阶段称为Access phase。



一次没有等待状态的写传输如上图所示,计划写数据时,第一周期PSEL




拉高,表示选中某个




slave




,同时给出地址信息




Addr1




和写入数据信息




Data1




,紧接着下一周期,




PENABLE




信号拉高,




PREADY




信号也拉高,这时数据写入完成。

  • 有等待状态的写

在文档中,对有等待周期的APB写传输描述如上,即:

第一个周期的setup phase和write with no wait没有区别,psel拉高,penable为低;第二周期,penable拉高之后,进入access phase,进入access phase之后,penable不会拉低,直到pready为高标志着一次传输结束时,penable才会随着pready一起拉低。

3、APB读传输



APB


的读传输也分为两种情况:





没有等待状态的读;





有等待状态的读。

  • 没有等待状态的读

一次没有等待状态的读传输如上图所示,读状态和写状态不同,写数据时PWRITE=1,读数据时应该令PWRITE=0计划读数据时,第一周期PSEL拉高,表示选中某个slave,同时给出地址信息Addr1,紧接着下一周期,PENABLE信号拉高,PREADY信号也拉高,这时数据被读出,master接受到读出数据PRDATA。

  • 有等待状态的读

在文档中,对有等待周期的APB读传输描述如上,即:第一个周期的setup phase和read with no wait没有区别,psel拉高,penable为低;第二周期,penable拉高之后,进入access phase,进入access phase之后,penable不会拉低,直到pready为高,这时数据被读出,master接受到读出数据PRDATA,标志着一次传输结束,penable才会随着pready一起拉低。

4、示例代码:

module apbMBFM #(

parameter                   ADDR_BITS = 24,

parameter                   DATA_BITS = 32

) (

output  reg                     apb_psel                    ,

output  reg                     apb_pwrite                  ,

output  reg                     apb_penable                 ,

output  reg[ADDR_BITS-1:0]      apb_paddr                   ,

output  reg[DATA_BITS-1:0]      apb_pwdata                  ,

input   wire[DATA_BITS-1:0]     apb_prdata                  ,

input   wire                    apb_pready                  ,

input   wire                    apb_pslverr                 ,

input   wire                    clk                         ,

input   wire                    rst_n

);

always @(posedge clk or negedge rst_n) begin

if (rst_n == 1’b0) begin

apb_psel <=  1’h0;

apb_pwrite <=  1’h0;

apb_penable <=  1’h0;

apb_paddr <=  24’h0;

apb_pwdata <=  32’h0;

end

end

task apb_write;

input [ADDR_BITS-1:0]  addr;

input [DATA_BITS-1:0]  wdata;

begin

@(posedge clk);  //align clock delay

apb_penable = 1’h0;

apb_psel   = 1’h1;

apb_pwrite = 1’h1;

apb_paddr  = addr;

apb_pwdata = wdata;

@(posedge clk);

apb_penable = 1’h1;

@(posedge clk);

while (!apb_pready) begin

@(posedge clk);

end

apb_pwrite = 1’h0;

apb_psel   = 1’h0;

apb_penable = 1’h0;

apb_paddr  = 24’h0;

apb_pwdata = 32’h0;

//$display(“task apb_write addr=%0h, wdata=%0h\n”, addr, wdata);

end

endtask

task apb_read;

input [ADDR_BITS-1:0] addr;

output [DATA_BITS-1:0] rdata;

begin

@(posedge clk);  //align clock delay

apb_penable = 1’h0;

apb_psel   = 1’h1;

apb_pwrite = 1’h0;

apb_paddr  = addr;

@(posedge clk);

apb_penable = 1’h1;

@(posedge clk);

while (!apb_pready) begin

@(posedge clk);

end

rdata = apb_prdata;

apb_psel = 1’h0;

apb_penable = 1’h0;

apb_paddr = 24’h0;

//$display(“task pb_read addr=%0h, rdata=%0h\n”, addr, rdata);

end

endtask

5、波形图:



版权声明:本文为binfeng1987原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。