通過狀態機來對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.在完成一次完整的狀態后,必須對相關信號進行清除
2.初始狀態不需要數據信號,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