通过状态机来对axi_lite总线进行操作
状态跳转:
1.初始状态
将axi_lite读写两个信道分开进行控制,在初始状态,就根据读,写信号来判断应该跳转到那一个状态。
2.写状态
在写状态中不需要跳转条件,即写状态只需要消耗一个时钟周期,然后自动跳转到下一个状态。
3.写有效状态
当接收到slave端的awready 和 wready 即地址写准备和数据写准备信号后,跳转到write_ready状态。
4.write_ready状态
在write_ready状态中,等到slave端bvalid信号的到来,然后跳转到write_bready状态。
5.write_bready状态
WRITE_BREADY 状态不需要状态跳转条件,只需要消耗一个时钟周期,同时在这个状态中,也没有相关信号需要输出。
6.write_end状态
write_end状态也不需要状态跳转条件,写完数据之后,直接回到初始状态。
7.read_start状态
类比write_start状态
8.read_valid状态
类比write_valid信号,只是读数据的过程中不需要接收数据准备信号,在read_valid状态中,当接收到slave端的读地址准备信号后,跳转到read_ready状态。
9.read_ready
当slave端传回来读数据有效信号后,状态机跳转进read_finish状态。
10.read_finish状态
类比write_finish状态
11.read_end状态
类比write_end状态
总结axi_lite读写时序:
写:首先准备好访问地址,和需要写入的数据同时给出地址有效,数据有效,bready信号,
当接收到slave端的地址ready和数据ready信号后,表示可以进行下一写操作了,同时,还需要等待slave端的bvalid信号到来,表示一次写完成了,即slave端的一个写反馈过程
读:首先准备好访问地址,和地址有效信号先拉高,当接收到slave端的地址ready信号后,表示可以进行下一次读操作了,同时,当slave端传过来valid信号的同时,才可以接受axi_lite上读取的数据。
状态机输出控制:
1.在完成一次完整的状态后,必须对相关信号进行清除
初始状态不需要数据信号,write_start信号输出结果如下:
3.write_valid状态输出结果:
4.write_ready状态输出结果:
5.write_bready状态无需输出信号,write_end状态数据结果:
6.read_start状态输出结果:
7.read_valid状态输出结果:
8.read_ready状态中不需要输出,read_finish输出结果:
9.read_end状态中输出结果:
axi_lite总线时序波形图具体分析(仿真版)
写:
观察awvalid,wvalid,bready是怎么左对齐的,awready,wready是怎么对齐的,还有awready,wready,awvalid,wvalid是怎么右对齐的,bready和bvalid是怎么右对齐的,反正你需要知道这些信号之间的关系与实际的波形图。
这次加上了地址与数据。
读:
注意arvalid,rready信号的左边是怎么对齐的,右边的rready要多一个时钟周期。
1 `timescale 1ns / 1ps
2 //////////////////////////////////////////////////////////////////////////////////
3 // Company:
4 // Engineer: chensimin
5 //
6 // Create Date: 2018/02/07 09:54:03
7 // Design Name:
8 // Module Name: ipc_axi_spi
9 // Project Name:
10 // Target Devices:
11 // Tool Versions:
12 // Description:
13 //
14 // Dependencies:
15 //
16 // Revision:
17 // Revision 0.01 - File Created
18 // Additional Comments:
19 //
20 //////////////////////////////////////////////////////////////////////////////////
21
22
23 module axi_spi(
24
25 input clk_100M,
26 inout [3:0]spi_dq,
27 inout spi_ss,
28 //-----------------------ipc_interface---------------------------
29 input wire [11:0] ipc_addr,
30 input wire [31:0] ipc_wdata,
31 output wire [31:0] ipc_rdata,
32 input wire ipc_rd,
33 input wire ipc_wr,
34 output wire ipc_ack
35
36 );
37
38
39 //--------------------------------------------------------------
40
41 ila_0 your_instance_name (
42 .clk(clk_100M), // input wire clk
43 .probe0(ipc_wr_rise), // input wire [0:0] probe0
44 .probe1(ipc_rd_rise), // input wire [0:0] probe1
45 .probe2(m_axi_awvalid), // input wire [0:0] probe2
46 .probe3(m_axi_wvalid), // input wire [0:0] probe3
47 .probe4(m_axi_arvalid), // input wire [0:0] probe4
48 .probe5(m_axi_rready), // input wire [0:0] probe5
49 .probe6(m_axi_bready), // input wire [0:0] probe6
50 .probe7(s_axi_awready), // input wire [0:0] probe7
51 .probe8(s_axi_arready), // input wire [0:0] probe8
52 .probe9(s_axi_wready), // input wire [0:0] probe9
53 .probe10(s_axi_rvalid), // input wire [0:0] probe10
54 .probe11(s_axi_bvalid), // input wire [0:0] probe11
55 .probe12(io0_i), // input wire [0:0] probe12
56 .probe13(io0_o), // input wire [0:0] probe13
57 .probe14(io0_t), // input wire [0:0] probe14
58 .probe15(io1_i), // input wire [0:0] probe15
59 .probe16(io1_o), // input wire [0:0] probe16
60 .probe17(io1_t), // input wire [0:0] probe17
61 .probe18(io2_i), // input wire [0:0] probe18
62 .probe19(io2_o), // input wire [0:0] probe19
63 .probe20(io2_t), // input wire [0:0] probe20
64 .probe21(io3_i), // input wire [0:0] probe21
65 .probe22(io3_o), // input wire [0:0] probe22
66 .probe23(io3_t), // input wire [0:0] probe23
67 .probe24(ss_i), // input wire [0:0] probe24
68 .probe25(ss_o), // input wire [0:0] probe25
69 .probe26(ss_t), // input wire [0:0] probe26
70 .probe27(m_axi_awaddr), // input wire [6:0] probe27
71 .probe28(m_axi_araddr), // input wire [6:0] probe28
72 .probe29(current_state), // input wire [6:0] probe29
73 .probe30(next_state), // input wire [6:0] probe30
74 .probe31(m_axi_wdata), // input wire [31:0] probe31
75 .probe32(m_axi_rdata), // input wire [31:0] probe32
76 .probe33(s_axi_rdata), // input wire [31:0] probe33
77 .probe34(ipc_addr), // input wire [11:0] probe34
78 .probe35(ipc_wdata), // input wire [31:0] probe35
79 .probe36(ipc_rdata), // input wire [31:0] probe36
80 .probe37(ipc_rd), // input wire [0:0] probe37
81 .probe38(ipc_wr), // input wire [0:0] probe38
82 .probe39(ipc_ack) // input wire [0:0] probe39
83 );
84
85
86
87
88
89
90
91
92
93 //--------------------------------------------------------------
94
95 reg ipc_rd_delay_1;
96 reg ipc_wr_delay_1;
97 reg ipc_rd_delay_2;
98 reg ipc_wr_delay_2;
99 wire ipc_rd_rise;
100 wire ipc_wr_rise;
101 always @(posedge clk_100M or posedge rst)
102 begin
103 if(rst)
104 begin
105 ipc_rd_delay_1 <= 1'b0;
106 ipc_wr_delay_1 <= 1'b0;
107 ipc_rd_delay_2 <= 1'b0;
108 ipc_wr_delay_2 <= 1'b0;
109 end
110 else
111 begin
112 ipc_rd_delay_1 <= ipc_rd;
113 ipc_wr_delay_1 <= ipc_wr;
114 ipc_rd_delay_2 <= ipc_rd_delay_1;
115 ipc_wr_delay_2 <= ipc_wr_delay_1;
116 end
117 end
118
119 assign ipc_rd_rise = !ipc_rd_delay_2 && ipc_rd_delay_1;
120 assign ipc_wr_rise = !ipc_wr_delay_2 && ipc_wr_delay_1;
121
122 //--------------------------------------------------------------
123 reg [6:0]current_state;
124 reg [6:0]next_state;
125 always @ (posedge clk_100M or posedge rst)
126 begin
127 if(rst)
128 current_state <= IDLE;
129 else
130 current_state <= next_state;
131 end
132
133 //--------------------------------------------------------------
134 parameter [4:0] IDLE = 5'd0 ,
135 WRITE_START = 5'd1 ,
136 WRITE_VALID = 5'd2 ,
137 WRITE_READY = 5'd3 ,
138 WRITE_BREADY = 5'd4 ,
139 WRITE_END = 5'd5 ,
140 READ_START = 5'd11 ,
141 READ_VALID = 5'd12 ,
142 READ_READY = 5'd13 ,
143 READ_FINISH = 5'd14 ,
144 READ_END = 5'd15 ;
145
146 always @ (*)
147 begin
148 next_state = IDLE;
149 case(current_state)
150 IDLE:
151 begin
152 if(ipc_wr_rise)
153 next_state = WRITE_START;
154 else if(ipc_rd_rise)
155 next_state = READ_START;
156 else
157 next_state = IDLE;
158 end
159
160 WRITE_START:
161 begin
162 next_state = WRITE_VALID;
163 end
164
165 WRITE_VALID:
166 begin
167 if(s_axi_awready && s_axi_wready)
168 next_state = WRITE_READY;
169 else
170 next_state = WRITE_VALID;
171 end
172
173 WRITE_READY:
174 begin
175 if(s_axi_bvalid)
176 next_state = WRITE_BREADY;
177 else
178 next_state = WRITE_READY;
179 end
180
181 WRITE_BREADY:
182 begin
183 next_state = WRITE_END;
184 end
185
186 WRITE_END:
187 begin
188 next_state = IDLE;
189 end
190
191 READ_START:
192 begin
193 next_state = READ_VALID;
194 end
195
196 READ_VALID:
197 begin
198 if(s_axi_arready)
199 next_state = READ_READY;
200 else
201 next_state = READ_VALID;
202 end
203
204 READ_READY:
205 begin
206 if(s_axi_rvalid)
207 next_state = READ_FINISH;
208 else
209 next_state = READ_READY;
210 end
211
212 READ_FINISH:
213 begin
214 next_state = READ_END;
215 end
216
217 READ_END:
218 begin
219 next_state = IDLE;
220 end
221
222 endcase
223 end
224
225 //-------------------------------------------------------------
226 reg m_axi_awvalid;
227 reg m_axi_wvalid;
228 reg m_axi_arvalid;
229
230 reg m_axi_rready;
231 reg m_axi_bready;
232
233 reg [6:0]m_axi_awaddr;
234 reg [6:0]m_axi_araddr;
235
236 reg [31:0]m_axi_wdata;
237 reg [31:0]m_axi_rdata;
238
239 reg ipc_ack_r;
240
241
242 always @(posedge clk_100M or posedge rst)
243 begin
244 if (rst)
245 begin
246 m_axi_awvalid <= 1'b0;
247 m_axi_wvalid <= 1'b0;
248 m_axi_arvalid <= 1'b0;
249 m_axi_rready <= 1'b0;
250 m_axi_bready <= 1'b0;
251 m_axi_awaddr <= 0;
252 m_axi_araddr <= 0;
253 m_axi_wdata <= 0;
254 m_axi_rdata <= 0;
255 ipc_ack_r <= 1'b0;
256 end
257 else
258 begin
259
260 m_axi_awvalid <= 1'b0;
261 m_axi_wvalid <= 1'b0;
262 m_axi_arvalid <= 1'b0;
263 m_axi_rready <= 1'b0;
264 m_axi_bready <= 1'b0;
265 ipc_ack_r <= 1'b0;
266
267 case(next_state)
268 //IDLE:
269
270 WRITE_START:
271 begin
272 m_axi_awaddr <= ipc_addr[6:0];
273 m_axi_wdata <= ipc_wdata;
274 m_axi_awvalid <= 1'b1;
275 m_axi_wvalid <= 1'b1;
276 m_axi_bready <= 1'b1;
277 end
278
279 WRITE_VALID:
280 begin
281 m_axi_awvalid <= 1'b1;
282 m_axi_wvalid <= 1'b1;
283 m_axi_bready <= 1'b1;
284 end
285
286 WRITE_READY:
287 begin
288 m_axi_bready <= 1'b1;
289 end
290
291 //WRITE_BREADY:
292 WRITE_END:
293 begin
294 ipc_ack_r <= 1'b1;
295 end
296
297 READ_START:
298 begin
299 m_axi_araddr <= ipc_addr[6:0];
300 m_axi_arvalid <= 1'b1;
301 end
302
303 READ_VALID:
304 begin
305 m_axi_arvalid <= 1'b1;
306 end
307
308 //READ_READY:
309
310 READ_FINISH:
311 begin
312 m_axi_rdata <= s_axi_rdata;
313 m_axi_rready <= 1'b1;
314 end
315
316 READ_END:
317 begin
318 ipc_ack_r <= 1'b1;
319 end
320
321 default:
322 begin
323 m_axi_awvalid <= 1'b0;
324 m_axi_wvalid <= 1'b0;
325 m_axi_arvalid <= 1'b0;
326 m_axi_rready <= 1'b0;
327 m_axi_bready <= 1'b0;
328 ipc_ack_r <= 1'b0;
329 end
330
331 endcase
332
333 end
334 end
335
336 assign ipc_rdata = m_axi_rdata;
337 assign ipc_ack = ipc_ack_r;
338
339 //-------------------------------------------------------------
340 wire s_axi_awready;
341 wire s_axi_arready;
342 wire s_axi_wready;
343 wire s_axi_rvalid;
344 wire s_axi_bvalid;
345 wire [31:0]s_axi_rdata;
346
347 wire io0_i;
348 wire io0_o;
349 wire io0_t;
350 wire io1_i;
351 wire io1_o;
352 wire io1_t;
353 wire io2_i;
354 wire io2_o;
355 wire io2_t;
356 wire io3_i;
357 wire io3_o;
358 wire io3_t;
359 wire ss_i;
360 wire ss_o;
361 wire ss_t;
362
363 axi_quad_spi_0 U1 (
364 .ext_spi_clk(clk_100M), // input wire ext_spi_clk
365 .s_axi_aclk(clk_100M), // input wire s_axi_aclk
366 .s_axi_aresetn(~rst), // input wire s_axi_aresetn
367 .s_axi_awaddr(m_axi_awaddr), // input wire [6 : 0] s_axi_awaddr
368 .s_axi_awvalid(m_axi_awvalid), // input wire s_axi_awvalid
369 .s_axi_awready(s_axi_awready), // output wire s_axi_awready
370 .s_axi_wdata(m_axi_wdata), // input wire [31 : 0] s_axi_wdata
371 .s_axi_wstrb(4'b1111), // input wire [3 : 0] s_axi_wstrb
372 .s_axi_wvalid(m_axi_wvalid), // input wire s_axi_wvalid
373 .s_axi_wready(s_axi_wready), // output wire s_axi_wready
374 .s_axi_bresp(), // output wire [1 : 0] s_axi_bresp
375 .s_axi_bvalid(s_axi_bvalid), // output wire s_axi_bvalid
376 .s_axi_bready(m_axi_bready), // input wire s_axi_bready
377 .s_axi_araddr(m_axi_araddr), // input wire [6 : 0] s_axi_araddr
378 .s_axi_arvalid(m_axi_arvalid), // input wire s_axi_arvalid
379 .s_axi_arready(s_axi_arready), // output wire s_axi_arready
380 .s_axi_rdata(s_axi_rdata), // output wire [31 : 0] s_axi_rdata
381 .s_axi_rresp(), // output wire [1 : 0] s_axi_rresp
382 .s_axi_rvalid(s_axi_rvalid), // output wire s_axi_rvalid
383 .s_axi_rready(m_axi_rready), // input wire s_axi_rready
384 .io0_i(io0_i), // input wire io0_i
385 .io0_o(io0_o), // output wire io0_o
386 .io0_t(io0_t), // output wire io0_t
387 .io1_i(io1_i), // input wire io1_i
388 .io1_o(io1_o), // output wire io1_o
389 .io1_t(io1_t), // output wire io1_t
390 .io2_i(io2_i), // input wire io2_i
391 .io2_o(io2_o), // output wire io2_o
392 .io2_t(io2_t), // output wire io2_t
393 .io3_i(io3_i), // input wire io3_i
394 .io3_o(io3_o), // output wire io3_o
395 .io3_t(io3_t), // output wire io3_t
396 .ss_i(ss_i), // input wire [0 : 0] ss_i
397 .ss_o(ss_o), // output wire [0 : 0] ss_o
398 .ss_t(ss_t), // output wire ss_t
399 .cfgclk(cfgclk), // output wire cfgclk
400 .cfgmclk(cfgmclk), // output wire cfgmclk
401 .eos(eos), // output wire eos
402 .preq(preq), // output wire preq
403 .ip2intc_irpt(ip2intc_irpt) // output wire ip2intc_irpt
404 );
405
406 IOBUF dq0(
407 .IO (spi_dq[0]),
408 .O (io0_i),
409 .I (io0_o),
410 .T (io0_t)
411 );
412
413 IOBUF dq1(
414 .IO (spi_dq[1]),
415 .O (io1_i),
416 .I (io1_o),
417 .T (io1_t)
418 );
419
420 IOBUF dq2(
421 .IO (spi_dq[2]),
422 .O (io2_i),
423 .I (io2_o),
424 .T (io2_t)
425 );
426
427 IOBUF dq3(
428 .IO (spi_dq[3]),
429 .O (io3_i),
430 .I (io3_o),
431 .T (io3_t)
432 );
433
434 IOBUF spiss(
435 .IO (spi_ss),
436 .O (ss_i),
437 .I (ss_o),
438 .T (ss_t)
439 );
440
441 endmodule