通过状态机来对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