一文详解AHB-Lite协议

描述

一、AHB-Lite协议介绍

AHB(Advanced High-performance Bus)高速总线,接高速master设备,APB(Advanced Peripheral Bus)外设总线,用来接低速slave,AHB主要用于高性能模块(如CPU、DMA和DSP等)之间的连接,一个master可以有多个slave,AHB和APB之间通过一个AHB2APB桥转接。这里是实现一个AHB-Lite协议,相较于AHB-APB总线协议,AHB-Lite只有单主机,且没有HBUSREQ和HGRANT信号,同时从设备信号接口也简单许多。

二、系统框架介绍

接口

主设备Master0利用AHB-Lite总线协议通过AHB Bridge访问四个APB从设备Slave0、Slave、Slave2和Slave3。每个从设备的地址空间如下:

Slave0: 0x0000_0000 ~ 0x0000_00ff;

Slave1: 0x0000_0100 ~ 0x0000_01ff;

Slave2: 0x0000_0200 ~ 0x0000_02ff;

Slave3: 0x0000_0300 ~ 0x0000_03ff;

令从设备地址空间的下边界为其地址的基址,假设每个从设备中有可访问APB寄存器16个,位宽均为32比特,16个寄存器的访问地址计算方式为 基址 +寄存器编号左移2位(byte 偏移)

主设备接口的数据读写采用AHB-Lite总线协议,并遵循如下时序规范:

接口

从设备读写遵循APB时序规范:

接口

三、代码设计

模块里包含Master 、Slave、Bridge设计

代码如下:

//-------------------------

//File Name:AHB_APB.v

//Designer:Liang Genyuan

//-------------------------

module AHB_APB(

HCLK,

HRESETn,

HWRITE,

HADDR,

HWDATAin,

HRDATA,

PRDATAin,

PWDATA

);

input HCLK;

input HRESETn;

input HWRITE;

input [31:0] HADDR;

input [31:0] HWDATAin;

input [31:0] PRDATAin;

output[31:0] HRDATA;

output[31:0] PWDATA;

reg          PCLK;

wire         PRESETn;

wire          PWRITE;

reg          PSEL;

reg          PENABLE;

wire[31:0]    PADDR; 

reg[31:0]    PWDATA;

reg[31:0] PRDATA;

reg[31:0]    HWDATA;

reg[31:0]    HRDATA;

reg         PSELS0;

reg         PSELS1;

reg         PSELS2;

reg         PSELS3;

reg[31:0] HADDR_Reg;

reg HWRITE_Reg;

reg[3:0]  HSEL_Reg;

reg[31:0] HWDATA_Reg;

reg[31:0] PRDATA_Reg;

reg HREADY;

reg   [3:0] state_c     ;

reg   [3:0] state_n     ;

parameter  IDLE = 4'b0000 ;

parameter  SETUP = 4'b0001;

parameter  ENABLE = 4'b0010 ;

//PCLK二分频

always @(posedge HCLK) begin

if(!HRESETn)begin

PCLK<=0;

end

else if(HCLK==1'b1)begin

PCLK<=~PCLK;

end

end

//slave选择

`define S0BASE 4'b0000

`define S1BASE 4'b0001

`define S2BASE 4'b0010

`define S3BASE 4'b0011

wire[3:0] HSEL; 

assign HSEL = HADDR[11:8];

always  @(*)begin

if(!HRESETn) begin

PSELS0 = 1'b0;

PSELS1 = 1'b0;

PSELS2 = 1'b0;

PSELS3 = 1'b0;

end 

case (HSEL)

`S0BASE : 

PSELS0 = 1'b1;

`S1BASE :

PSELS1 = 1'b1;    

`S2BASE : 

PSELS2 = 1'b1;

`S3BASE : 

PSELS3 = 1'b1;

endcase 

end

//slave读写

wire[5:0]   reg_num;

reg [3:0]   PSELx;

assign reg_num= PADDR[7:2];

assign PRESETn=HRESETn;

assign PADDR=HADDR_Reg;

assign PWRITE=HWRITE_Reg;

always @(posedge PCLK or negedge PRESETn) begin

if(!PRESETn)begin

PWDATA<=0;

PRDATA<=0;

end

else if(PWRITE)begin

if((state_c==SETUP)||(state_c==ENABLE))begin

PWDATA<=HWDATA_Reg;

end

else begin

PWDATA<=0;

end

end

else if(!PWRITE)begin

PRDATA<=PRDATAin;

end

else begin

PRDATA<=0;

end

end

//APB bridge状态机

wire  idle2setup_start  ;

wire  setup2enable_start;

wire  enable2idle_start ;

always@(posedge HCLK or negedge HRESETn)begin

if(!HRESETn)begin

PSELx<=0;

end

else if(state_c!=IDLE)begin

PSELx<=HSEL_Reg;

end

end

always @(posedge PCLK or negedge PRESETn) begin 

if (!PRESETn) begin

state_c <= IDLE ;

end

else begin

state_c <= state_n;

end

end

always @(*) begin 

case(state_c)  

IDLE :begin

if(idle2setup_start) 

state_n = SETUP ;

else 

state_n = state_c ;

end

SETUP :begin

if(setup2enable_start) 

state_n = ENABLE ;

else 

state_n = state_c ;

end

ENABLE :begin

if(enable2idle_start) 

state_n = IDLE ;

else 

state_n = state_c ;

end

default : state_n = IDLE ;

endcase

end

always@(posedge PCLK or negedge PRESETn)begin

if(PRESETn==1'b0)begin

PENABLE<=0;

PSEL<=0;

end

else if(state_c==SETUP)begin

PSEL<=1;

PENABLE<=0;

end

else if(state_c==ENABLE)begin

PSEL<=1;

PENABLE<=1;

end

else begin

PSEL<=0;

PENABLE<=0;

end

end

assign idle2setup_start = (state_c==IDLE)&&(HADDR!=32'b0) ;

assign setup2enable_start = state_c==SETUP ;

assign enable2idle_start = state_c==ENABLE ;

//桥寄存

always @ (negedge HRESETn or posedge HCLK) begin

if (!HRESETn)

begin 

HADDR_Reg  <= {32{1'b0}};

HWRITE_Reg <= 1'b0;

end

else

if (HREADY)begin

HADDR_Reg  <= HADDR;

HWRITE_Reg <= HWRITE;

end  

end

always  @(posedge HCLK or negedge HRESETn)begin

if(HRESETn==1'b0)begin

HSEL_Reg<=0;

end

else if(HREADY)begin

HSEL_Reg<=HSEL;

end

end

always  @(posedge HCLK or negedge HRESETn)begin

if(HRESETn==1'b0)begin

HWDATA_Reg<=0;

PRDATA_Reg<=0;

end

else if(HWRITE==1)begin

HWDATA_Reg<=HWDATA;

end

else begin

PRDATA_Reg<=PRDATA;

end

end

//master

//HREADY控制

always  @(posedge PCLK or negedge PRESETn)begin

if(!PRESETn)begin

HREADY<=0;

end

else if((state_c==IDLE)&&(HWDATA==0))begin

HREADY<=1;

end

else if(state_c==SETUP)begin

HREADY<=0;

end

end

always  @(posedge HCLK or negedge HRESETn)begin

if(HRESETn==1'b0)begin

HWDATA<=32'b0;

HRDATA<=32'b0;

end

else if(HWRITE==0)begin

HRDATA<=PRDATA_Reg;

end

else if(HWRITE==1)begin

HWDATA<=HWDATAin;

end

end

endmodule

四、仿真测试

分别对读写时序进行两组测试:

1、写时序

a、

HADDR=32’b0000_0000_0000_0000_0000_0001_0000_0000

HWDATAin=32’b0000_0000_0000_0000_0000_0001_0000_0001

接口

PSELx=1,reg_num=0

即选中了第一个从设备中第一个寄存器

b、

HADDR=32’b0000_0000_0000_0000_0000_0011_0000_1000;

HWDATAin=32’b0000_0000_0000_0000_0000_1111_0000_1111;

接口

PSELx=3,reg_num=2

即选中了第三个从设备中第三个寄存器

2、读时序

a、

HADDR=32’b0000_0000_0000_0000_0000_0011_0000_1000

PRDATAin=32’b00000_0000_0000_0000_0000_1111_0000_1111

接口

PSELx=3 reg_num=2

即第三个从设备第三个寄存器

b、

HADDR=32’b0000_0000_0000_0000_0000_0100_0000_1100

PRDATAin=32’b00000_0000_0000_0000_0000_1110_0000_1110

接口

PSELx=4 reg_num=3

即第四个从设备第四个寄存器

原文链接:

https://blog.csdn.net/yueqiu693/article/details/119849052

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分