用Verilog写AXI4_lite从机协议
作者:互联网
用过Xilinx Z7系列的过来人应该都很熟悉AXI4_lite协议,Z7的优点就在于有了soc,而如何将PL,PS端的信号互联,Xilinx就用到了AMBA协议的AXI部分。现在就AXI4_lite协议来分析下,AXI4_lite属于AXI4协议的轻量级形式,是简化版的 AXI4 接口, 用于较少数据量的存储映射通信。
AXI4是一种READY,VALID握手机制的通信协议,就是在信息传输中有一个握手的过程。传输源发出VALID信号来表示当前哪些数据为有效,目的源则产生READY信号来表明当前已做好接受数据的准备。信息的有效传输发生在VALID与READY同为高的时候。此时会出现以下三种情况。
1.VALID和READY信号同时变高:
2.VALID先变高READY后变高:
3.READY先变高VALID后变高:
根据时序图,我们可以初步了解握手的有效情况。然后我们可以看看官方软件Vivado生成的AXI4_lite代码,以下是Vivado2017.4生成AXI4_lite slave 的步骤:
1.打开Vivado软件,新建工程后,单击菜单栏Tools->Create and Package New IP,开始创建一个AXI4-Lite接口总线IP
选择使用vivado自带的AXI总线模板创建一个AXI4-Lite接口IP
名称改为axi4_lite
点击next之后
继续next
然后就跳出编辑IP的界面
代码如下:
axi4_lite_v1_0
1 `timescale 1 ns / 1 ps 2 3 module axi4_lite_v1_0 # 4 ( 5 // Users to add parameters here 6 7 // User parameters ends 8 // Do not modify the parameters beyond this line 9 10 11 // Parameters of Axi Slave Bus Interface S00_AXI 12 parameter integer C_S00_AXI_DATA_WIDTH = 32, 13 parameter integer C_S00_AXI_ADDR_WIDTH = 4 14 ) 15 ( 16 // Users to add ports here 17 18 // User ports ends 19 // Do not modify the ports beyond this line 20 21 22 // Ports of Axi Slave Bus Interface S00_AXI 23 input wire s00_axi_aclk, 24 input wire s00_axi_aresetn, 25 input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_awaddr, 26 input wire [2 : 0] s00_axi_awprot, 27 input wire s00_axi_awvalid, 28 output wire s00_axi_awready, 29 input wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_wdata, 30 input wire [(C_S00_AXI_DATA_WIDTH/8)-1 : 0] s00_axi_wstrb, 31 input wire s00_axi_wvalid, 32 output wire s00_axi_wready, 33 output wire [1 : 0] s00_axi_bresp, 34 output wire s00_axi_bvalid, 35 input wire s00_axi_bready, 36 input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_araddr, 37 input wire [2 : 0] s00_axi_arprot, 38 input wire s00_axi_arvalid, 39 output wire s00_axi_arready, 40 output wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_rdata, 41 output wire [1 : 0] s00_axi_rresp, 42 output wire s00_axi_rvalid, 43 input wire s00_axi_rready 44 ); 45 // Instantiation of Axi Bus Interface S00_AXI 46 axi4_lite_v1_0_S00_AXI # ( 47 .C_S_AXI_DATA_WIDTH(C_S00_AXI_DATA_WIDTH), 48 .C_S_AXI_ADDR_WIDTH(C_S00_AXI_ADDR_WIDTH) 49 ) axi4_lite_v1_0_S00_AXI_inst ( 50 .S_AXI_ACLK(s00_axi_aclk), 51 .S_AXI_ARESETN(s00_axi_aresetn), 52 .S_AXI_AWADDR(s00_axi_awaddr), 53 .S_AXI_AWPROT(s00_axi_awprot), 54 .S_AXI_AWVALID(s00_axi_awvalid), 55 .S_AXI_AWREADY(s00_axi_awready), 56 .S_AXI_WDATA(s00_axi_wdata), 57 .S_AXI_WSTRB(s00_axi_wstrb), 58 .S_AXI_WVALID(s00_axi_wvalid), 59 .S_AXI_WREADY(s00_axi_wready), 60 .S_AXI_BRESP(s00_axi_bresp), 61 .S_AXI_BVALID(s00_axi_bvalid), 62 .S_AXI_BREADY(s00_axi_bready), 63 .S_AXI_ARADDR(s00_axi_araddr), 64 .S_AXI_ARPROT(s00_axi_arprot), 65 .S_AXI_ARVALID(s00_axi_arvalid), 66 .S_AXI_ARREADY(s00_axi_arready), 67 .S_AXI_RDATA(s00_axi_rdata), 68 .S_AXI_RRESP(s00_axi_rresp), 69 .S_AXI_RVALID(s00_axi_rvalid), 70 .S_AXI_RREADY(s00_axi_rready) 71 ); 72 73 // Add user logic here 74 75 // User logic ends 76 77 endmodule
axi4_lite_v1_0_S00_AXI
1 `timescale 1 ns / 1 ps 2 3 module axi4_lite_v1_0_S00_AXI # 4 ( 5 // Users to add parameters here 6 7 // User parameters ends 8 // Do not modify the parameters beyond this line 9 10 // Width of S_AXI data bus 11 parameter integer C_S_AXI_DATA_WIDTH = 32, 12 // Width of S_AXI address bus 13 parameter integer C_S_AXI_ADDR_WIDTH = 4 14 ) 15 ( 16 // Users to add ports here 17 18 // User ports ends 19 // Do not modify the ports beyond this line 20 21 // Global Clock Signal 22 input wire S_AXI_ACLK, 23 // Global Reset Signal. This Signal is Active LOW 24 input wire S_AXI_ARESETN, 25 // Write address (issued by master, acceped by Slave) 26 input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, 27 // Write channel Protection type. This signal indicates the 28 // privilege and security level of the transaction, and whether 29 // the transaction is a data access or an instruction access. 30 input wire [2 : 0] S_AXI_AWPROT, 31 // Write address valid. This signal indicates that the master signaling 32 // valid write address and control information. 33 input wire S_AXI_AWVALID, 34 // Write address ready. This signal indicates that the slave is ready 35 // to accept an address and associated control signals. 36 output wire S_AXI_AWREADY, 37 // Write data (issued by master, acceped by Slave) 38 input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, 39 // Write strobes. This signal indicates which byte lanes hold 40 // valid data. There is one write strobe bit for each eight 41 // bits of the write data bus. 42 input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB, 43 // Write valid. This signal indicates that valid write 44 // data and strobes are available. 45 input wire S_AXI_WVALID, 46 // Write ready. This signal indicates that the slave 47 // can accept the write data. 48 output wire S_AXI_WREADY, 49 // Write response. This signal indicates the status 50 // of the write transaction. 51 output wire [1 : 0] S_AXI_BRESP, 52 // Write response valid. This signal indicates that the channel 53 // is signaling a valid write response. 54 output wire S_AXI_BVALID, 55 // Response ready. This signal indicates that the master 56 // can accept a write response. 57 input wire S_AXI_BREADY, 58 // Read address (issued by master, acceped by Slave) 59 input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, 60 // Protection type. This signal indicates the privilege 61 // and security level of the transaction, and whether the 62 // transaction is a data access or an instruction access. 63 input wire [2 : 0] S_AXI_ARPROT, 64 // Read address valid. This signal indicates that the channel 65 // is signaling valid read address and control information. 66 input wire S_AXI_ARVALID, 67 // Read address ready. This signal indicates that the slave is 68 // ready to accept an address and associated control signals. 69 output wire S_AXI_ARREADY, 70 // Read data (issued by slave) 71 output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, 72 // Read response. This signal indicates the status of the 73 // read transfer. 74 output wire [1 : 0] S_AXI_RRESP, 75 // Read valid. This signal indicates that the channel is 76 // signaling the required read data. 77 output wire S_AXI_RVALID, 78 // Read ready. This signal indicates that the master can 79 // accept the read data and response information. 80 input wire S_AXI_RREADY 81 ); 82 83 // AXI4LITE signals 84 reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; 85 reg axi_awready; 86 reg axi_wready; 87 reg [1 : 0] axi_bresp; 88 reg axi_bvalid; 89 reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr; 90 reg axi_arready; 91 reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata; 92 reg [1 : 0] axi_rresp; 93 reg axi_rvalid; 94 95 // Example-specific design signals 96 // local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH 97 // ADDR_LSB is used for addressing 32/64 bit registers/memories 98 // ADDR_LSB = 2 for 32 bits (n downto 2) 99 // ADDR_LSB = 3 for 64 bits (n downto 3) 100 localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1; 101 localparam integer OPT_MEM_ADDR_BITS = 1; 102 //---------------------------------------------- 103 //-- Signals for user logic register space example 104 //------------------------------------------------ 105 //-- Number of Slave Registers 4 106 reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg0; 107 reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg1; 108 reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg2; 109 reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg3; 110 wire slv_reg_rden; 111 wire slv_reg_wren; 112 reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out; 113 integer byte_index; 114 reg aw_en; 115 116 // I/O Connections assignments 117 118 assign S_AXI_AWREADY = axi_awready; 119 assign S_AXI_WREADY = axi_wready; 120 assign S_AXI_BRESP = axi_bresp; 121 assign S_AXI_BVALID = axi_bvalid; 122 assign S_AXI_ARREADY = axi_arready; 123 assign S_AXI_RDATA = axi_rdata; 124 assign S_AXI_RRESP = axi_rresp; 125 assign S_AXI_RVALID = axi_rvalid; 126 // Implement axi_awready generation 127 // axi_awready is asserted for one S_AXI_ACLK clock cycle when both 128 // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is 129 // de-asserted when reset is low. 130 131 always @( posedge S_AXI_ACLK ) 132 begin 133 if ( S_AXI_ARESETN == 1'b0 ) 134 begin 135 axi_awready <= 1'b0; 136 aw_en <= 1'b1; 137 end 138 else 139 begin 140 if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) 141 begin 142 // slave is ready to accept write address when 143 // there is a valid write address and write data 144 // on the write address and data bus. This design 145 // expects no outstanding transactions. 146 axi_awready <= 1'b1; 147 aw_en <= 1'b0; 148 end 149 else if (S_AXI_BREADY && axi_bvalid) 150 begin 151 aw_en <= 1'b1; 152 axi_awready <= 1'b0; 153 end 154 else 155 begin 156 axi_awready <= 1'b0; 157 end 158 end 159 end 160 161 // Implement axi_awaddr latching 162 // This process is used to latch the address when both 163 // S_AXI_AWVALID and S_AXI_WVALID are valid. 164 165 always @( posedge S_AXI_ACLK ) 166 begin 167 if ( S_AXI_ARESETN == 1'b0 ) 168 begin 169 axi_awaddr <= 0; 170 end 171 else 172 begin 173 if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) 174 begin 175 // Write Address latching 176 axi_awaddr <= S_AXI_AWADDR; 177 end 178 end 179 end 180 181 // Implement axi_wready generation 182 // axi_wready is asserted for one S_AXI_ACLK clock cycle when both 183 // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is 184 // de-asserted when reset is low. 185 186 always @( posedge S_AXI_ACLK ) 187 begin 188 if ( S_AXI_ARESETN == 1'b0 ) 189 begin 190 axi_wready <= 1'b0; 191 end 192 else 193 begin 194 if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en ) 195 begin 196 // slave is ready to accept write data when 197 // there is a valid write address and write data 198 // on the write address and data bus. This design 199 // expects no outstanding transactions. 200 axi_wready <= 1'b1; 201 end 202 else 203 begin 204 axi_wready <= 1'b0; 205 end 206 end 207 end 208 209 // Implement memory mapped register select and write logic generation 210 // The write data is accepted and written to memory mapped registers when 211 // axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to 212 // select byte enables of slave registers while writing. 213 // These registers are cleared when reset (active low) is applied. 214 // Slave register write enable is asserted when valid address and data are available 215 // and the slave is ready to accept the write address and write data. 216 assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID; 217 218 always @( posedge S_AXI_ACLK ) 219 begin 220 if ( S_AXI_ARESETN == 1'b0 ) 221 begin 222 slv_reg0 <= 0; 223 slv_reg1 <= 0; 224 slv_reg2 <= 0; 225 slv_reg3 <= 0; 226 end 227 else begin 228 if (slv_reg_wren) 229 begin 230 case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ) 231 2'h0: 232 for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) 233 if ( S_AXI_WSTRB[byte_index] == 1 ) begin 234 // Respective byte enables are asserted as per write strobes 235 // Slave register 0 236 slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; 237 end 238 2'h1: 239 for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) 240 if ( S_AXI_WSTRB[byte_index] == 1 ) begin 241 // Respective byte enables are asserted as per write strobes 242 // Slave register 1 243 slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; 244 end 245 2'h2: 246 for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) 247 if ( S_AXI_WSTRB[byte_index] == 1 ) begin 248 // Respective byte enables are asserted as per write strobes 249 // Slave register 2 250 slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; 251 end 252 2'h3: 253 for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) 254 if ( S_AXI_WSTRB[byte_index] == 1 ) begin 255 // Respective byte enables are asserted as per write strobes 256 // Slave register 3 257 slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; 258 end 259 default : begin 260 slv_reg0 <= slv_reg0; 261 slv_reg1 <= slv_reg1; 262 slv_reg2 <= slv_reg2; 263 slv_reg3 <= slv_reg3; 264 end 265 endcase 266 end 267 end 268 end 269 270 // Implement write response logic generation 271 // The write response and response valid signals are asserted by the slave 272 // when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. 273 // This marks the acceptance of address and indicates the status of 274 // write transaction. 275 276 always @( posedge S_AXI_ACLK ) 277 begin 278 if ( S_AXI_ARESETN == 1'b0 ) 279 begin 280 axi_bvalid <= 0; 281 axi_bresp <= 2'b0; 282 end 283 else 284 begin 285 if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) 286 begin 287 // indicates a valid write response is available 288 axi_bvalid <= 1'b1; 289 axi_bresp <= 2'b0; // 'OKAY' response 290 end // work error responses in future 291 else 292 begin 293 if (S_AXI_BREADY && axi_bvalid) 294 //check if bready is asserted while bvalid is high) 295 //(there is a possibility that bready is always asserted high) 296 begin 297 axi_bvalid <= 1'b0; 298 end 299 end 300 end 301 end 302 303 // Implement axi_arready generation 304 // axi_arready is asserted for one S_AXI_ACLK clock cycle when 305 // S_AXI_ARVALID is asserted. axi_awready is 306 // de-asserted when reset (active low) is asserted. 307 // The read address is also latched when S_AXI_ARVALID is 308 // asserted. axi_araddr is reset to zero on reset assertion. 309 310 always @( posedge S_AXI_ACLK ) 311 begin 312 if ( S_AXI_ARESETN == 1'b0 ) 313 begin 314 axi_arready <= 1'b0; 315 axi_araddr <= 32'b0; 316 end 317 else 318 begin 319 if (~axi_arready && S_AXI_ARVALID) 320 begin 321 // indicates that the slave has acceped the valid read address 322 axi_arready <= 1'b1; 323 // Read address latching 324 axi_araddr <= S_AXI_ARADDR; 325 end 326 else 327 begin 328 axi_arready <= 1'b0; 329 end 330 end 331 end 332 333 // Implement axi_arvalid generation 334 // axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both 335 // S_AXI_ARVALID and axi_arready are asserted. The slave registers 336 // data are available on the axi_rdata bus at this instance. The 337 // assertion of axi_rvalid marks the validity of read data on the 338 // bus and axi_rresp indicates the status of read transaction.axi_rvalid 339 // is deasserted on reset (active low). axi_rresp and axi_rdata are 340 // cleared to zero on reset (active low). 341 always @( posedge S_AXI_ACLK ) 342 begin 343 if ( S_AXI_ARESETN == 1'b0 ) 344 begin 345 axi_rvalid <= 0; 346 axi_rresp <= 0; 347 end 348 else 349 begin 350 if (axi_arready && S_AXI_ARVALID && ~axi_rvalid) 351 begin 352 // Valid read data is available at the read data bus 353 axi_rvalid <= 1'b1; 354 axi_rresp <= 2'b0; // 'OKAY' response 355 end 356 else if (axi_rvalid && S_AXI_RREADY) 357 begin 358 // Read data is accepted by the master 359 axi_rvalid <= 1'b0; 360 end 361 end 362 end 363 364 // Implement memory mapped register select and read logic generation 365 // Slave register read enable is asserted when valid address is available 366 // and the slave is ready to accept the read address. 367 assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid; 368 always @(*) 369 begin 370 // Address decoding for reading registers 371 case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ) 372 2'h0 : reg_data_out <= slv_reg0; 373 2'h1 : reg_data_out <= slv_reg1; 374 2'h2 : reg_data_out <= slv_reg2; 375 2'h3 : reg_data_out <= slv_reg3; 376 default : reg_data_out <= 0; 377 endcase 378 end 379 380 // Output register or memory read data 381 always @( posedge S_AXI_ACLK ) 382 begin 383 if ( S_AXI_ARESETN == 1'b0 ) 384 begin 385 axi_rdata <= 0; 386 end 387 else 388 begin 389 // When there is a valid read address (S_AXI_ARVALID) with 390 // acceptance of read address by the slave (axi_arready), 391 // output the read dada 392 if (slv_reg_rden) 393 begin 394 axi_rdata <= reg_data_out; // register read data 395 end 396 end 397 end 398 399 // Add user logic here 400 401 // User logic ends 402 403 endmodule
以上便是通过官方生成的AXI4_lite接口的代码,看得挺烦,可拓展性差,因此明白了其中时序原理后,自己便可以动手写下该模块取代官方这些冗余的代码。
1 //************************************************************************** 2 // *** file name : Axi4_lite_slave.v 3 // *** version : 1.0 4 // *** Description : AXI4-Lite slave interface 5 // *** Blogs : https://www.cnblogs.com/WenGalois123/ 6 // *** Author : Galois_V 7 // *** Date : 2022.3.29 8 // *** Changes : 9 //************************************************************************** 10 `timescale 1ns/1ps 11 module Axi4_lite_slave 12 ( 13 input wire i_s_axi_aclk , 14 input wire i_s_axi_aresetn , 15 input wire [31:0] i_s_axi_awaddr , 16 input wire [2:0] i_s_axi_awprot , 17 input wire i_s_axi_awvalid , 18 output reg o_s_axi_awready , 19 input wire [31:0] i_s_axi_wdata , 20 input wire [3:0] i_s_axi_wstrb , 21 input wire i_s_axi_wvalid , 22 output reg o_s_axi_wready , 23 output wire [1:0] o_s_axi_bresp , 24 output reg o_s_axi_bvalid , 25 input wire i_s_axi_bready , 26 input wire [31:0] i_s_axi_araddr , 27 input wire [2:0] i_s_axi_arprot , 28 input wire i_s_axi_arvalid , 29 output reg o_s_axi_arready , 30 output reg [31:0] o_s_axi_rdata , 31 output wire [1:0] o_s_axi_rresp , 32 output reg o_s_axi_rvalid , 33 input wire i_s_axi_rready , 34 output reg [31:0] o_ctrl_wr_addr , 35 output wire o_ctrl_wr_en , 36 output wire [31:0] o_ctrl_wr_data , 37 output wire [3:0] o_ctrl_wr_mask , 38 output reg [31:0] o_ctrl_rd_addr , 39 input wire [31:0] i_ctrl_rd_data 40 ); 41 42 reg r_wr_en; 43 reg r_rd_en; 44 wire w_raddr_en; 45 /******************************************************************************\ 46 Write Address operation 47 \******************************************************************************/ 48 always@(posedge i_s_axi_aclk) 49 begin 50 if(~i_s_axi_aresetn) 51 begin 52 r_wr_en <= 1'b1; 53 end 54 else if(o_ctrl_wr_en) 55 begin 56 r_wr_en <= 1'b0; 57 end 58 else if(o_s_axi_bvalid & i_s_axi_bready) 59 begin 60 r_wr_en <= 1'b1; 61 end 62 end 63 64 always@(posedge i_s_axi_aclk) 65 begin 66 if(~i_s_axi_aresetn) 67 begin 68 o_s_axi_awready <= 'd0; 69 end 70 else if(~o_s_axi_awready & i_s_axi_wvalid & i_s_axi_awvalid & r_wr_en) 71 begin 72 o_s_axi_awready <= 1'b1; 73 end 74 else 75 begin 76 o_s_axi_awready <= 'd0; 77 end 78 end 79 80 always@(posedge i_s_axi_aclk) 81 begin 82 if(~i_s_axi_aresetn) 83 begin 84 o_ctrl_wr_addr <= 'd0; 85 end 86 else if(~o_s_axi_awready & i_s_axi_awvalid & i_s_axi_wvalid) 87 begin 88 o_ctrl_wr_addr <= i_s_axi_awaddr; 89 end 90 end 91 /******************************************************************************\ 92 Write data operation 93 \******************************************************************************/ 94 always@(posedge i_s_axi_aclk) 95 begin 96 if(~i_s_axi_aresetn) 97 begin 98 o_s_axi_wready <= 'd0; 99 end 100 else if(~o_s_axi_wready & i_s_axi_wvalid & i_s_axi_awvalid & r_wr_en) 101 begin 102 o_s_axi_wready <= 1'b1; 103 end 104 else 105 begin 106 o_s_axi_wready <= 'd0; 107 end 108 end 109 110 assign o_ctrl_wr_data = i_s_axi_wdata; 111 assign o_ctrl_wr_mask = i_s_axi_wstrb; 112 assign o_ctrl_wr_en = o_s_axi_awready & i_s_axi_awvalid & i_s_axi_wvalid & o_s_axi_wready; 113 114 /******************************************************************************\ 115 write response and response 116 \******************************************************************************/ 117 always@(posedge i_s_axi_aclk) 118 begin 119 if(~i_s_axi_aresetn) 120 begin 121 o_s_axi_bvalid <= 'd0; 122 end 123 else if(~o_s_axi_bvalid & o_ctrl_wr_en) 124 begin 125 o_s_axi_bvalid <= 1'b1; 126 end 127 else if(o_s_axi_bvalid & i_s_axi_bready) 128 begin 129 o_s_axi_bvalid <= 'd0; 130 end 131 end 132 133 /******************************************************************************\ 134 Read Address operation 135 \******************************************************************************/ 136 always@(posedge i_s_axi_aclk) 137 begin 138 if(~i_s_axi_aresetn) 139 begin 140 r_rd_en <= 1'b1; 141 end 142 else if(w_raddr_en) 143 begin 144 r_rd_en <= 1'b0; 145 end 146 else if(o_s_axi_rvalid & i_s_axi_rready) 147 begin 148 r_rd_en <= 1'b1; 149 end 150 end 151 152 always@(posedge i_s_axi_aclk) 153 begin 154 if(~i_s_axi_aresetn) 155 begin 156 o_s_axi_arready <= 'd0; 157 end 158 else if(~o_s_axi_arready & i_s_axi_arvalid & r_rd_en) 159 begin 160 o_s_axi_arready <= 1'b1; 161 end 162 else 163 begin 164 o_s_axi_arready <= 'd0; 165 end 166 end 167 168 always@(posedge i_s_axi_aclk) 169 begin 170 if(~i_s_axi_aresetn) 171 begin 172 o_ctrl_rd_addr <= 'd0; 173 end 174 else if(~o_s_axi_arready & i_s_axi_arvalid) 175 begin 176 o_ctrl_rd_addr <= i_s_axi_araddr; 177 end 178 end 179 180 assign w_raddr_en = o_s_axi_arready & i_s_axi_arvalid & (~o_s_axi_rvalid); 181 /******************************************************************************\ 182 Read data operation 183 \******************************************************************************/ 184 always@(posedge i_s_axi_aclk) 185 begin 186 if(~i_s_axi_aresetn) 187 begin 188 o_s_axi_rvalid <= 'd0; 189 end 190 else if(w_raddr_en) 191 begin 192 o_s_axi_rvalid <= 1'b1; 193 end 194 else if(o_s_axi_rvalid & i_s_axi_rready) 195 begin 196 o_s_axi_rvalid <= 'd0; 197 end 198 end 199 200 always@(posedge i_s_axi_aclk) 201 begin 202 if(~i_s_axi_aresetn) 203 begin 204 o_s_axi_rdata <= 'd0; 205 end 206 else if(w_raddr_en) 207 begin 208 o_s_axi_rdata <= i_ctrl_rd_data; 209 end 210 end 211 212 213 assign o_s_axi_rresp = 2'b00; 214 assign o_s_axi_bresp = 2'b00; 215 216 endmodule
下图为仿真后的axi4_lite从机的时序,暂时没发现什么问题。
后续将使用该模块的代码进行IP核的编写。
标签:wire,s00,axi,lite,从机,AXI4,input,AXI,reg 来源: https://www.cnblogs.com/WenGalois123/p/16071850.html