11

story · 2020年06月30日

数字IC设计总线系列之APB实例解析

APB是AMBA中相对比较简单的接口协议。

采用这种简单的协议,你可以轻松地将自定义外设挂在AMBA总线上。

许多APB外设都是慢速器件,例如UART。一般SoC都是通过它们的寄存器进行访问。

下面是一个APB slave 的verilog实例,大家可以在此基础上,设计自己APB slave接口的自定义模块控制器.

// Sample APB register code
// Standard read/write registers
// Adress offset from psel:
//  0x00 : 32 bit read of status32 port
//  0x04 : 32 bit read & write control32 port
//  0x08 : 16 bit status
//         and 16 bit read & write control16 port
//  0x0C : 8 bit status8
//          and 8 bit read & write control8port
module apb_regs1 (
   //system
   //APB
   //Interface
);
...
endmodule

其中,

// system
  input             reset_n,
  input             enable,  // clock gating

是系统复位和使能信号

// APB
  input             pclk,
  input      [ 3:0] paddr,   // ls 2 bits are unused 
  input             pwrite,
   input             psel,
  input             penable,
  input      [31:0] pwdata,
  output reg [31:0] prdata,
  output            pready,
  output            pslverr,

是APB slave的接口信号

// Interface
  input      [31:0] status32,
  input      [15:0] status16,
  input      [ 7:0] status8,
  output reg [31:0] control32,
  output reg [15:0] control16,
  output reg [ 7:0] control8

是一个自定义模块的寄存器,其中status32是read\_only

wire apb_write = psel & penable &pwrite;
wire apb_read  = psel & ~pwrite;

apb\_write和apb\_read是为了满足APB协议做的读写控制。apb\_read信号产生和apb\_write不同,具体原因可以查阅APB协议官方文档

assign pready = 1'b1;
assign pslverr = 1'b0;

该APB slave模块只是对一些控制和状态寄存器进行读写,是无等待传输,同时不生成传输错误信号。

always @(posedge pclk or negedge reset_n)
  begin
     if (!reset_n)
     begin
        control32 <= 32'h0;
        control16 <= 16'h1234; // reset/initial value
        control8  <=  8'h0;
        prdata    <= 32'h0;
     end // reset
     else if (enable)
     begin
        if (apb_write)
        begin
           case (paddr)
         //4'h0 :  status32 read only 
           4'h4 : control32 <= pwdata;
           4'h8 : control16 <= pwdata[15:0];
           4'hC : control8  <=pwdata[7:0];
           endcase
        end // write
        if (apb_read)
        begin
           case (paddr)
           4'h0 : prdata <= status32;
           4'h4 : prdata <= control32; 
           4'h8 : prdata <= {status16,control16};
           4'hC : prdata <={8'h0,status8,8'h0,control8};
           endcase
        end // read
        else
           prdata <= 32'h0; // so we can OR all busses
     end // clocked
  end // always

对不同的寄存器做了地址分配,其中status32寄存器只读

然后我们在Testbench里例化APB slave和一个APB master 模型,对该APB slave模块进行验证。

apb_bus0.read(16'h00,32'h9c4e9a31);
apb_bus0.write(16'h04,32'h11223344);
apb_bus0.write(16'h08,32'hAABB);
apb_bus0.write(16'h0C,32'hDD);
apb_bus0.read(16'h04,32'h11223344);
apb_bus0.read(16'h08,32'h7832AABB);
apb_bus0.read(16'h0C,32'h002a00DD);

本文转载自公众号:芯片数字实验室
原文链接:
https://zhuanlan.zhihu.com/p/84590739
未经作者同意,请勿转载!

推荐阅读
想了解更多内容,欢迎关注Arm ABMA总线专栏
推荐阅读
关注数
7870
内容数
81
Arm AMBA协议集,APB,AHB,AXI,CHI等相关公开课回放及文章
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息