AHB总线搭建-1搭建顶层模块
学习AHB总线是数字IC设计中比较重要的一部分,本系列文章将说明如何一步步搭建AHB完整的总线。本文的源代码来自于https://github.com/adki/AMBA_AXI_AHB_APB
AHB总线简介:
AMBA AHB是用于高性能、高时钟频率的系统模块,支持处理器、片上存储器、片外存储器及低功耗外设宏单元之间的有效连接。
bfm_ahb任务与mem直接通过AHB协议进行通信的示意图:
信号介绍:
名称 | 来源 | 描述 |
---|---|---|
HCLK总线时钟 | 时钟源 | 所有信号时序都和HCLK上升沿相关 |
HRESETn复位 | 复位控制器 | 复位系统和总线,低电平有效 |
HBUSREQ总线请求 | 主机 | 主机向仲裁器请求控制总线型号 |
HGRANT总线授予 | 仲裁器 | 表示该主机目前是优先级最高的主机。当HREADY为高时传输结束,地址/控制信号的所有权发生改变。所以主机应在HREADY和HGRANT都为高时获得对总线的访问。 |
HLOCK锁定的传输 | 主机 | 信号为高时表示主机请求锁定对总线的访问,并在信号为低之前其它主机不应该被允许授予总线。 |
HTRANS[1:0]传输类型 | 主机 | 表示当前传输类型(忙、空闲、连续、不连续) |
HPORT[3:0]保护控制 | 主机 | 指示当前传输是否为预取值或数据传输,同时表示传输是保护模式访问还是用户模式访问。 |
HADDR[31:0]地址总线 | 主机 | 32位系统地址总线 |
HWRITE传输方向 | 主机 | 信号为高表示写传输,为低表示读传输 |
HSIZE[2:0]传输大小 | 主机 | 表示传输的大小(字节、半字、字) |
HBURST[2:0]突发类型 | 主机 | 表示传输是否组成的突发的一部分,支持四个、八个、十六个节拍的突发传输,并且可以是增量或者回环的 |
HWDATA[31:0]写数据总线 | 主机 | 写操作期间主机向从机传输数据 |
HRDATA[31:0]读数据总线 | 从机 | 读操作期间从机向主机传输数据 |
HRESP[1:0]传输响应 | 从机 | 提供四种不同响应(OKEY、ERROR、RETRY、SPLIT) |
HREADY传输完成 | 从机 | 信号为高表示总线上的传输已经完成 |
顶层文件建立:
第一步,建立top.v,其中包含以上信号和HCLK、HRESETn信号的初始化;
第二步,建立bfm_ahb.v及mem_ahb.v,并初始化端口。
其代码如下:
top.v
`ifndef CLK_FREQ
`define CLK_FREQ 50000000
module top ;
reg HRESETn= 1'b0;
reg HCLK = 1'b0;
wire HBUSREQ;
wire HGRANT = HBUSREQ; // no arbiter
wire [31:0] HADDR ;
wire [3:0] HPROT ;
wire HLOCK ;
wire [1:0] HTRANS ;
wire HWRITE ;
wire [2:0] HSIZE ;
wire [2:0] HBURST ;
wire [31:0] HWDATA ;
wire [31:0] HRDATA ;
wire [1:0] HRESP ;
wire HREADY ;
wire HSEL = HTRANS[1]; // no address decoder
//------------------------------------------------
bfm_ahb #(.START_ADDR(0),.DEPTH_IN_BYTES(32'h100))
u_bfm_ahb (
.HRESETn (HRESETn)
, .HCLK (HCLK )
, .HBUSREQ (HBUSREQ)
, .HGRANT (HGRANT )
, .HADDR (HADDR )
, .HPROT (HPROT )
, .HLOCK (HLOCK )
, .HTRANS (HTRANS )
, .HWRITE (HWRITE )
, .HSIZE (HSIZE )
, .HBURST (HBURST )
, .HWDATA (HWDATA )
, .HRDATA (HRDATA )
, .HRESP (HRESP )
, .HREADY (HREADY )
, .IRQ (1'b0 )
);
//----------------------------------------------------
mem_ahb #(.SIZE_IN_BYTES(SIZE_IN_BYTES),.DELAY(DELAY))
u_mem_ahb (
.HRESETn (HRESETn)
, .HCLK (HCLK )
, .HSEL (HSEL )
, .HADDR (HADDR )
, .HTRANS (HTRANS )
, .HWRITE (HWRITE )
, .HSIZE (HSIZE )
, .HBURST (HBURST )
, .HWDATA (HWDATA )
, .HRDATA (HRDATA )
, .HRESP (HRESP )
, .HREADYin (HREADY )
, .HREADYout (HREADY )
);
localparam CLK_FREQ=`CLK_FREQ;
localparam CLK_PERIOD_HALF=1000000000/(CLK_FREQ*2);
always #CLK_PERIOD_HALF HCLK <= ~HCLK;
initial begin
HRESETn <= 1'b0;
repeat (5) @ (posedge HCLK);
HRESETn <= 1'b1;
end
endmodule
由于当前只有一主一从,无需主机仲裁器,也没有从机地址解码器,所以令
HGRANT = HBUSREQ;
HSEL = HTRANS[1];
其它信号按照原理图的进行连接。
bfm_ahb.v
module bfm_ahb #(parameter START_ADDR=0
, DEPTH_IN_BYTES=32'h100
, END_ADDR=START_ADDR+DEPTH_IN_BYTES-1)
(
input wire HRESETn
, input wire HCLK
, output reg HBUSREQ
, input wire HGRANT
, output reg [31:0] HADDR
, output reg [3:0] HPROT
, output reg HLOCK
, output reg [1:0] HTRANS
, output reg HWRITE
, output reg [2:0] HSIZE
, output reg [2:0] HBURST
, output reg [31:0] HWDATA
, input wire [31:0] HRDATA
, input wire [1:0] HRESP
, input wire HREADY
, input wire IRQ
);
endmodule
mem_ahb.v
module mem_ahb #(parameter SIZE_IN_BYTES=1024
, DELAY=0
, INIT=0)
(
input wire HRESETn
, input wire HCLK
, input wire HSEL
, input wire [31:0] HADDR
, input wire [ 1:0] HTRANS
, input wire HWRITE
, input wire [ 2:0] HSIZE
, input wire [ 2:0] HBURST
, input wire [31:0] HWDATA
, output reg [31:0] HRDATA
, output wire [ 1:0] HRESP
, input wire HREADYin
, output reg HREADYout
);
endmodule
进行综合后其原理图如下: