本节主要介绍了AHB协议的基本传输时序,并以基于简单AHB的SRAM读写实验加强理解。
AHB协议的基本介绍
Advanced High-performance Bus(先进高性能总线)是一种适用于高性能可综合设计的总线接口
最常见的AHB slaver是内部存储器设备、外部存储器接口和高带宽外设
虽然低带宽外设可以作为AHB slaver,但出于系统性能原因,它们通常在APB上,AHB和APB之间的连接是使用APB桥完成的
其分为地址阶段和数据阶段,支持2级流水线操作
AHB总线组成(以AHB5(在AHB-lite上的改进)为例):
单layer:
- 分配给每个slave的地址空间最小地址空间为1KB,故master的设计不会执行地址范围超过1KB的增量传输
多layer:
AHB协议的基本传输时序
- 传输时序建议直接看AHB官方手册,这里只能粘贴一些基本的时序,具体理解还得自己上手操作
1.基础传输
- 两个传输阶段:
- 地址阶段:一个时钟周期,用于准备好地址
- 数据阶段:一个或多个时钟周期,用于数据的读写
1.1 写操作
无等待:
有等待:
1.2 读操作
无等待:
有等待:
1.3 读写操作
2.传输类型(HTRANS)
IDLE(0b00):Master无数据传输,slave回复HRESP=0并忽略传输
BUSY(0b01):Master忙碌,在burst传输中间插入BUSY,请求传输延缓。slave回复HRESP=0并忽略传输
NONSEQ(0b10):表明是单次传输或者是burst传输(≈连续传输)的第一个传输,下一个传输的地址和控制信号与之前的无关系
SEQ(0b11):下一个传输的地址和控制信号与之前的有关系:下一个传输的地址=上一个地址+HSIZE的字节数(或者循环加上HSIZE的字节数)
3.传输大小(HSIZE)
- HSIZE对应的传输数据位宽:$2^{HSIZE}byte=8*2^{HSIZE}bit$
4.突发操作(HBURST)
循环突发(Wrapping burst)对应的地址计算方式:首先计算总传输数据大小,然后将当前位置除以总传输数据大小,若不能整除则以当前地址传输数据,否则将当前地址减去总传输数据大小,作为传输地址。
HTRANS决定传输的模式(主要还是看突发还是非突发),那么HBURST就决定怎么个突发规则,而HSIZE则决定在该突发规则下,地址递增的值
4.1 Four-beat wrapping burst, WRAP4
- 其中4代表突发成功传输的个数为4,而在这4个数未传输完成时,HSIZE不能改变
4.2 Four-beat incrementing burst, INCR4
4.3 Eight-beat wrapping burst, WRAP8
4.4 Eight-beat incrementing burst, INCR8
4.5 Undefined length bursts, INCR
基于AHB总线的简单SRAM读写实验
设计顶层框图:
sram_interface框图:
1.源代码
sram_top.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97module sram_top(
// AHB Signal
input HCLK,
input HRESETn,
input HSEL ,
input [1:0] HTRANS,
input [2:0] HBURST,
input [2:0] HSIZE ,
input HWRITE,
input [15:0] HADDR ,
input [31:0] HWDATA,
output HREADY,
output [1:0] HRESP ,
output [31:0] HRDATA
);
// Wires Between SRAM_interface and SRAM_core
wire SRAM_WEN_BANK0;
wire SRAM_WEN_BANK1;
wire [12:0] SRAM_ADDR ;
wire [3:0] SRAM_CSN_BANK0;
wire [3:0] SRAM_CSN_BANK1;
wire [31:0] SRAM_WDATA ;
wire [7:0] SRAM0_q;
wire [7:0] SRAM1_q;
wire [7:0] SRAM2_q;
wire [7:0] SRAM3_q;
wire [7:0] SRAM4_q;
wire [7:0] SRAM5_q;
wire [7:0] SRAM6_q;
wire [7:0] SRAM7_q;
/*————————————————————————————————————————————————————————————————————————*\
/ SRAM Interface Instantiation \
\*————————————————————————————————————————————————————————————————————————*/
sram_interface u_interface(
//---------------AHB SIGNAL--------------
//in
.iHCLK (HCLK ),
.iHRESETn(HRESETn),
.iHSEL (HSEL ),
.iHBURST (HBURST ),
.iHWRITE (HWRITE ),
.iHTRANS (HTRANS ),
.iHSIZE (HSIZE ),
.iHWDATA (HWDATA ),
.iHADDR (HADDR ),
//out
.oHRESP (HRESP ),
.oHREADY (HREADY ),
.oHRDATA (HRDATA ),
//--------------SRAM SIGNAL--------------
//in
.iSRAM0_q(SRAM0_q),
.iSRAM1_q(SRAM1_q),
.iSRAM2_q(SRAM2_q),
.iSRAM3_q(SRAM3_q),
.iSRAM4_q(SRAM4_q),
.iSRAM5_q(SRAM5_q),
.iSRAM6_q(SRAM6_q),
.iSRAM7_q(SRAM7_q),
//out
.oSRAM_WEN_BANK0(SRAM_WEN_BANK0),
.oSRAM_WEN_BANK1(SRAM_WEN_BANK1),
.oSRAM_CSN_BANK0(SRAM_CSN_BANK0),
.oSRAM_CSN_BANK1(SRAM_CSN_BANK1),
.oSRAM_ADDR (SRAM_ADDR),
.oSRAM_WDATA (SRAM_WDATA)
);
/*————————————————————————————————————————————————————————————————————————*\
/ SRAM Core Instantiation \
\*————————————————————————————————————————————————————————————————————————*/
sram_core u_core(
//----------- From AHB ------------
.iHCLK (HCLK ),
//--------- From Interface ---------
.iSRAM_WEN_BANK0 (SRAM_WEN_BANK0),
.iSRAM_WEN_BANK1(SRAM_WEN_BANK1),
.iSRAM_ADDR (SRAM_ADDR ),
.iSRAM_CSN_BANK0(SRAM_CSN_BANK0),
.iSRAM_CSN_BANK1(SRAM_CSN_BANK1),
.iSRAM_WDATA (SRAM_WDATA ),
//---------- To Interface ---------
.oSRAM0_q (SRAM0_q),
.oSRAM1_q (SRAM1_q),
.oSRAM2_q (SRAM2_q),
.oSRAM3_q (SRAM3_q),
.oSRAM4_q (SRAM4_q),
.oSRAM5_q (SRAM5_q),
.oSRAM6_q (SRAM6_q),
.oSRAM7_q (SRAM7_q)
);
endmodulesram_interface.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107module sram_interface(
//---------------AHB SIGNAL--------------
//in
input iHCLK ,
input iHRESETn,
input iHSEL ,
input iHWRITE ,
input [2 : 0] iHBURST ,
input [1 : 0] iHTRANS ,
input [2 : 0] iHSIZE ,
input [31 : 0] iHWDATA ,
input [15 : 0] iHADDR ,
//out
output [1 : 0] oHRESP ,
output oHREADY ,
output [31 : 0] oHRDATA ,
//--------------SRAM SIGNAL--------------
//in
input [7 : 0] iSRAM0_q,
input [7 : 0] iSRAM1_q,
input [7 : 0] iSRAM2_q,
input [7 : 0] iSRAM3_q,
input [7 : 0] iSRAM4_q,
input [7 : 0] iSRAM5_q,
input [7 : 0] iSRAM6_q,
input [7 : 0] iSRAM7_q,
//out
output oSRAM_WEN_BANK0,
output oSRAM_WEN_BANK1,
output [3 : 0] oSRAM_CSN_BANK0,
output [3 : 0] oSRAM_CSN_BANK1,
output [12 : 0] oSRAM_ADDR,
output [31 : 0] oSRAM_WDATA
);
/*————————————————————————————————————————————————————————————————————————*\
/ AHB Signal Register \
\*————————————————————————————————————————————————————————————————————————*/
reg iHSEL_r ;
reg iHWRITE_r ;
reg iHWRITE_2r;
reg [2 : 0] iHBURST_r ;
reg [1 : 0] iHTRANS_r ;
reg [2 : 0] iHSIZE_r ;
reg [31 : 0] iHWDATA_r ;
reg [15 : 0] iHADDR_r ;
reg [15 : 0] iHADDR_2r ;
always@(posedge iHCLK) begin
if(!iHRESETn) begin
iHSEL_r <= 1'b0;
iHWRITE_r <= 1'b0;
iHWRITE_2r <= 1'b0;
iHBURST_r <= 3'b0;
iHTRANS_r <= 2'b0;
iHSIZE_r <= 3'b0;
iHWDATA_r <= 32'b0;
iHADDR_r <= 16'b0;
iHADDR_2r <= 16'b0;
end
else begin
iHSEL_r <= iHSEL;
iHWRITE_r <= iHWRITE;
iHWRITE_2r <= iHWRITE_r;
iHBURST_r <= iHBURST;
iHTRANS_r <= iHTRANS;
iHSIZE_r <= iHSIZE;
iHWDATA_r <= iHWDATA;
iHADDR_r <= iHADDR;
iHADDR_2r <= iHADDR_r;
end
end
/*————————————————————————————————————————————————————————————————————————*\
/ AHB BUS → Interface → SRAM Core \
\*————————————————————————————————————————————————————————————————————————*/
// SRAM Write Enable
assign oSRAM_WEN_BANK0 = ( iHWRITE_r == 1'b1 && iHADDR_r[15] == 1'b0) ? 1'b1 : 1'b0;
assign oSRAM_WEN_BANK1 = ( iHWRITE_r == 1'b1 && iHADDR_r[15] == 1'b1) ? 1'b1 : 1'b0;
// SRAM Bank CSN select for read ↓ select for write ↓
assign oSRAM_CSN_BANK0 = ( iHADDR_r[15] == 1'b0 || (iHADDR[15] == 1'b0 && iHWRITE == 1'b0) ) ? 4'b1111 : 4'b0000;
assign oSRAM_CSN_BANK1 = ( iHADDR_r[15] == 1'b1 || (iHADDR[15] == 1'b1 && iHWRITE == 1'b0) ) ? 4'b1111 : 4'b0000;
// SRAM Addr
wire [12 : 0] SRAM_WRITE_ADDR;
wire [12 : 0] SRAM_READ_ADDR;
assign SRAM_WRITE_ADDR = iHADDR_r[14 : 2]; // WRITE:addr have to wait a T , sent together with data to SRAM_CORE
assign SRAM_READ_ADDR = iHADDR [14 : 2]; // READ :addr send to MEM at once
assign oSRAM_ADDR = (iHWRITE_r == 1'b1) ? SRAM_WRITE_ADDR : SRAM_READ_ADDR;
// SRAM Write Data
assign oSRAM_WDATA = iHWDATA;
/*————————————————————————————————————————————————————————————————————————*\
/ AHB BUS ← Interface ← SRAM Core \
\*————————————————————————————————————————————————————————————————————————*/
// response to AHB MASTER
assign oHREADY = (iHSEL_r == 1'b1 && (iHWRITE_r == 1'b1 || iHWRITE_2r == 1'b0)) ? 1'b1 : 1'b0 ;
assign oHRESP = (iHSEL_r == 1'b1) ? 2'b00 : 2'b01; //OKAY = 2'b00
// sram read data
assign oHRDATA = (iHSEL_r == 1'b1 && iHWRITE_r == 1'b0 && iHADDR_r[15] == 1'b0) ? {iSRAM3_q, iSRAM2_q, iSRAM1_q, iSRAM0_q}:
(iHSEL_r == 1'b1 && iHWRITE_r == 1'b0 && iHADDR_r[15] == 1'b1) ? {iSRAM7_q, iSRAM6_q, iSRAM5_q, iSRAM4_q}:
32'bz;
endmodulesram_core.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104module sram_core(
// From AHB
input iHCLK ,
// From sram_interface
input iSRAM_WEN_BANK0,
input iSRAM_WEN_BANK1,
input [12 : 0] iSRAM_ADDR ,
input [3 : 0] iSRAM_CSN_BANK0,
input [3 : 0] iSRAM_CSN_BANK1,
input [31 : 0] iSRAM_WDATA ,
// To sram_interface
output [7 : 0] oSRAM0_q,
output [7 : 0] oSRAM1_q,
output [7 : 0] oSRAM2_q,
output [7 : 0] oSRAM3_q,
output [7 : 0] oSRAM4_q,
output [7 : 0] oSRAM5_q,
output [7 : 0] oSRAM6_q,
output [7 : 0] oSRAM7_q
);
/*————————————————————————————————————————————————————————————————————————*\
/ BANK 0 Instantiation \
\*————————————————————————————————————————————————————————————————————————*/
sram_bist u_bank0_sram0 (
// Function Mode IO
.iSRAM_CLK (iHCLK ),
.iSRAM_CSN (iSRAM_CSN_BANK0[0]),
.iSRAM_WEN (iSRAM_WEN_BANK0 ),
.iSRAM_ADDR (iSRAM_ADDR ), //13 bits SRAM ADDR
.iSRAM_WDATA(iSRAM_WDATA[7:0] ),
.oSRAM_RDATA(oSRAM0_q )
);
sram_bist u_bank0_sram1 (
// Function Mode IO
.iSRAM_CLK (iHCLK ),
.iSRAM_CSN (iSRAM_CSN_BANK0[1]),
.iSRAM_WEN (iSRAM_WEN_BANK0 ),
.iSRAM_ADDR (iSRAM_ADDR ), //13 bits SRAM ADDR
.iSRAM_WDATA(iSRAM_WDATA[15:8] ),
.oSRAM_RDATA(oSRAM1_q )
);
sram_bist u_bank0_sram2 (
// Function Mode IO
.iSRAM_CLK (iHCLK ),
.iSRAM_CSN (iSRAM_CSN_BANK0[2]),
.iSRAM_WEN (iSRAM_WEN_BANK0 ),
.iSRAM_ADDR (iSRAM_ADDR ), //13 bits SRAM ADDR
.iSRAM_WDATA(iSRAM_WDATA[23:16]),
.oSRAM_RDATA(oSRAM2_q )
);
sram_bist u_bank0_sram3 (
// Function Mode IO
.iSRAM_CLK (iHCLK ),
.iSRAM_CSN (iSRAM_CSN_BANK0[3]),
.iSRAM_WEN (iSRAM_WEN_BANK0 ),
.iSRAM_ADDR (iSRAM_ADDR ), //13 bits SRAM ADDR
.iSRAM_WDATA(iSRAM_WDATA[31:24]),
.oSRAM_RDATA(oSRAM3_q )
);
/*————————————————————————————————————————————————————————————————————————*\
/ BANK 1 Instantiation \
\*————————————————————————————————————————————————————————————————————————*/
sram_bist u_bank1_sram4 (
// Function Mode IO
.iSRAM_CLK (iHCLK ),
.iSRAM_CSN (iSRAM_CSN_BANK1[0]),
.iSRAM_WEN (iSRAM_WEN_BANK1 ),
.iSRAM_ADDR (iSRAM_ADDR ), //13 bits SRAM ADDR
.iSRAM_WDATA(iSRAM_WDATA[7:0] ),
.oSRAM_RDATA(oSRAM4_q )
);
sram_bist u_bank1_sram5 (
// Function Mode IO
.iSRAM_CLK (iHCLK ),
.iSRAM_CSN (iSRAM_CSN_BANK1[1]),
.iSRAM_WEN (iSRAM_WEN_BANK1 ),
.iSRAM_ADDR (iSRAM_ADDR ), //13 bits SRAM ADDR
.iSRAM_WDATA(iSRAM_WDATA[15:8] ),
.oSRAM_RDATA(oSRAM5_q )
);
sram_bist u_bank1_sram6 (
// Function Mode IO
.iSRAM_CLK (iHCLK ),
.iSRAM_CSN (iSRAM_CSN_BANK1[2]),
.iSRAM_WEN (iSRAM_WEN_BANK1 ),
.iSRAM_ADDR (iSRAM_ADDR ), //13 bits SRAM ADDR
.iSRAM_WDATA(iSRAM_WDATA[23:16]),
.oSRAM_RDATA(oSRAM6_q )
);
sram_bist u_bank1_sram7 (
// Function Mode IO
.iSRAM_CLK (iHCLK ),
.iSRAM_CSN (iSRAM_CSN_BANK1[3]),
.iSRAM_WEN (iSRAM_WEN_BANK1 ),
.iSRAM_ADDR (iSRAM_ADDR ), //13 bits SRAM ADDR
.iSRAM_WDATA(iSRAM_WDATA[31:24]),
.oSRAM_RDATA(oSRAM7_q )
);
endmodule
2.Testbench
sram_tb.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207module sram_tb #(
//HRESP
parameter OKAY = 2'b00 ,
parameter ERROR = 2'b01 ,
parameter SPLIT = 2'b10 ,
parameter RETRY = 2'b11 ,
//HTRANS
parameter IDLE = 2'b00 ,
parameter BUSY = 2'b01 ,
parameter SEQ = 2'b10 ,
parameter NONSEQ = 2'b11 ,
//HSIZE
parameter BYTE = 3'b000 ,
parameter WORD = 3'b001 ,
parameter DWORD = 3'b010 ,
//HBURST
parameter SINGLE = 3'b000 ,
parameter INCR = 3'b001 ,
parameter WRAP4 = 3'b010 ,
parameter INCR4 = 3'b011 ,
parameter WARP8 = 3'b100 ,
parameter INCR8 = 3'b101 ,
parameter WARP16 = 3'b110 ,
parameter INCR16 = 3'b111
)();
// input output declaration
reg HCLK;
reg HRESETn;
reg HSEL ;
reg [1:0] HTRANS;
reg [2:0] HBURST;
reg [2:0] HSIZE ;
reg HWRITE;
reg [15:0] HADDR ;
reg [31:0] HWDATA;
wire HREADY;
wire [1:0] HRESP ;
wire [31:0] HRDATA;
// top module instantion
sram_top u_test(
.HCLK (HCLK ),
.HRESETn(HRESETn),
.HSEL (HSEL ),
.HTRANS (HTRANS ),
.HBURST (HBURST ),
.HSIZE (HSIZE ),
.HWRITE (HWRITE ),
.HADDR (HADDR ),
.HWDATA (HWDATA ),
.HREADY (HREADY ),
.HRESP (HRESP ),
.HRDATA (HRDATA )
);
// Excitation Vector Generation
initial begin
forever #10 HCLK = ~HCLK; //50Mhz
end
initial begin
HCLK = 0;
HRESETn = 0;
/*————————————————————————————————————————————————————————————————————————*\
/ Testbench for FUNC Mode \
\*————————————————————————————————————————————————————————————————————————*/
HRESETn = 0;
HSEL <= 0;
HTRANS <= 3'b111;
HBURST <= 2'b11;
HSIZE <= 3'b111;
HWRITE <= 1'b0;
HADDR <= 16'h0000; //HADDR[1:0] have to be 2'b00 ( 4n )
HWDATA <= 32'h0;
#51 HRESETn = 1;
//-------------------------WRITE MEM---------------
@(posedge HCLK);
// write control0
HSEL <= 1;
HTRANS <= NONSEQ;
HBURST <= SINGLE;
HSIZE <= WORD;
HWRITE <= 1'b1;
HADDR <= 16'h0000;
@(posedge HCLK);
// data0 → mem(0x0000)
HWDATA <= 32'h11223344;
// write control 1
HWRITE <= 1'b1;
HADDR <= 16'h0004;
@(posedge HCLK);
// data1 → mem(0x0004)
HWDATA <= 32'h55667788;
// write control 2
HWRITE <= 1'b1;
HADDR <= 16'h0008;
@(posedge HCLK);
// data2 → mem(0x0008)
HWDATA <= 32'h99AABBCC;
//// write control 3
//HWRITE = 1'b1;
//HADDR = 16'h000C;
@(posedge HCLK);
// data3 → mem(0x000C)
HWDATA <= 32'hAAAAAAAA;
// write control 4
HWRITE <= 1'b1;
HADDR <= 16'h0010;
@(posedge HCLK);
// data4 → mem(0x0010)
HWDATA <= 32'hBBBBBBBB;
// write control 5
HWRITE <= 1'b1;
HADDR <= 16'h0014;
@(posedge HCLK);
// data5 → mem(0x0014)
HWDATA <= 32'hCCCCCCCC;
// write control 6
HWRITE <= 1'b1;
HADDR <= 16'h8000;
@(posedge HCLK);
// data6 → mem(0x8000)
HWDATA <= 32'hDDDDDDDD;
// write control 7
HWRITE <= 1'b1;
HADDR <= 16'h8004;
@(posedge HCLK);
// data7 → mem(0x8004)
HWDATA <= 32'hEEEEEEEE;
// write control 8
HWRITE <= 1'b1;
HADDR <= 16'h8008;
@(posedge HCLK);
// data8 → mem(0x8008)
HWDATA <= 32'hFFFFFFFF;
// read control 0
HWRITE <= 1'b0;
HADDR <= 16'h0000;
//--------------READ MEM----------------
@(posedge HCLK);
// MASTER FINDS HREADY=0, SO MASTER WAITS
@(posedge HCLK);
// read control 1
HWRITE <= 1'b0;
HADDR <= 16'h0004;
HWDATA <= 32'h00000000; // to test if hwdata will work when HWRTIE = 0
@(posedge HCLK);
// read control 2
HWRITE <= 1'b0;
HADDR <= 16'h0008;
@(posedge HCLK);
// read control 3
HWRITE <= 1'b0;
HADDR <= 16'h000C;
@(posedge HCLK);
// read control 4
HWRITE <= 1'b0;
HADDR <= 16'h0010;
@(posedge HCLK);
// read control 5
HWRITE <= 1'b0;
HADDR <= 16'h0014;
@(posedge HCLK);
// read control 6
HWRITE <= 1'b0;
HADDR <= 16'h8000;
@(posedge HCLK);
// read control 7
HWRITE <= 1'b0;
HADDR <= 16'h8004;
@(posedge HCLK);
// read control 8
HWRITE <= 1'b0;
HADDR <= 16'h8008;
#100
$finish();
end
endmodule
3.仿真结果
AHB interface相关
sram_interface中的控制信号与sram_core interface的对应关系,即AHB接口如何对应到sram_core的接口
- HREADY信号之所以要拉低一拍的原因是:由于读数据用的是HADDR地址,而写数据用的是HADDR_r地址,地址其实时在连续输入的,但当由写切换到读状态时,此时虽然读写都使能(读bank0,写bank1),但只有一根地址线,其中bank1 HADDR_r以及对应的HWDATA被写入,而bank0读到的是HADDR_r的数据,并且它此时真正要读的地址HADDR并没有被打1拍缓存(这是由于在设计模块时,设计的就是直接读HADDR而不是HADDR_r),所以在读写切换的时刻到下一个clk这段时间的读地址丢失了,因为此时真正的读HADDR和写HADDR_r同时存在了,但sram_core地址线上选择的是写HADDR_r,这就导致在这一拍的读HADDR没有被采集到,所以才要拉低HREADY告诉master再拉高一次刚刚丢失的读HADDR
其次,在HADDR映射到SRAM_ADDR时,只取了HADDR的$[14:2]$,这样做的原因是:当总线地址HADDR的值在0x0000—0x7FFF之间时代表地址指向BANK0,而在0x8000—0xFFFF之间时代表地址指向BANK1,故HADDR[15]只是用来指示是bank0还是bank1的,又因为每次传输的HSIZE都是32bit(4Byte),故地址只会出现0x0000、0x0004、0x0008、0x000c、0x0010等情况,然后仔细观察一下就会发现,0(0b0000)、4(0b0100)、8(0b1000)、c(0b1100)的低2bit都为0,它们代表的是每4byte的起始地址。可以认为$HADDR[1:0]$代表的是每4byte为一组,这组数据每个字节的索引,而真正每4byte去索引的实际是$HADDR[14:2]$,可以看到前述加粗部分正好是0、1、2、3这样子的index,正好对应SRAM的address。
1
2
3
4
5
6// SRAM Addr
wire [12 : 0] SRAM_WRITE_ADDR;
wire [12 : 0] SRAM_READ_ADDR;
assign SRAM_WRITE_ADDR = iHADDR_r[14 : 2]; // WRITE:addr have to wait a T , sent together with data to SRAM_CORE
assign SRAM_READ_ADDR = iHADDR [14 : 2]; // READ :addr send to MEM at once
assign oSRAM_ADDR = (iHWRITE_r == 1'b1) ? SRAM_WRITE_ADDR : SRAM_READ_ADDR;
Reference
- 「数字IC设计项目」 —— AHB SRAM控制器设计 & March C-算法内建自测试的实现 - NorthCNuo - 博客园(实验主要参考的博客)
- 基于AHB总线的sram控制器设计_ahb sram-CSDN博客(这里面有不同HSIZE下的实现方式,有时间可以再看看)
- AHB总线协议 + AHB_SRAM代码实现(2)_哔哩哔哩_bilibili
- AMBA总线(2)—— AHB协议 - 咸鱼IC - 博客园
- AHB总线—wrap burst的理解_incrementing bursts-CSDN博客
- AHB中Hready_in和Hready_out深入理解_hreadyin hreadyout-CSDN博客