ZYNQ-AXI4_LITE

本文详细描述了一个基于AXI-Lite协议的Master模块的设计,涉及数据接口的三个通道、地址和数据FIFO的使用、以及写入和读取操作的同步控制,包括从地址FIFO读取数据的延迟处理和从机应答的处理机制。
摘要由CSDN通过智能技术生成

数据接口

在这里插入图片描述
分为三个通道,写地址通道,写数据通道,应答通道。其中AWPROT,WSTRB用的比较少。

在这里插入图片描述WSTRB为写的数据的掩码,写的数据为32bit,4个Byte,所以WSTRB为4bit位宽,WSTRB为4位对应4Byte的数据。
在这里插入图片描述
AWPROT保护信号,3bit全设置0即可。
在这里插入图片描述
写操作时序
在这里插入图片描述
读操作
在这里插入图片描述

程序设计

上面波形画的有BUG,这里以写入地址与数据对齐的方式写入。

程序思路

用户端:写数据,读数据。将用户写的数据转化位AXI协议写入到AXI从机,并且可以从丛机读出数据到用户端。写入优先级大于读出优先级。

module AXI_LITE_Master # (
    parameter                       P_ADDR_WIDTH = 32   ,    
    parameter                       P_DATA_WIDTH = 32    
)(     
    input                           M_AXI_ACLK          ,
    input                           M_AXI_ARESETN       ,
    output                          M_AXI_AWVALID       ,
    input                           M_AXI_AWREADY       ,
    output  [P_ADDR_WIDTH-1:0]      M_AXI_AWADDR        ,
    output  [3:0]                   M_AXI_AWPROT        ,

    output                          M_AXI_WVALID        ,
    input                           M_AXI_WREADY        ,
    output  [P_DATA_WIDTH-1:0]      M_AXI_WDATA         ,
    output  [P_DATA_WIDTH/8-1:0]    M_AXI_WSTRB         ,

    input                           M_AXI_BVALID        ,
    output                          M_AXI_BREADY        ,
    input   [3:0]                   M_AXI_BRESP         ,

    output                          M_AXI_ARVALID       ,
    input                           M_AXI_ARREADY       ,
    output   [P_ADDR_WIDTH-1:0]     M_AXI_ARADDR        ,
    output   [3:0]                  M_AXI_ARPROT        ,
    input                           M_AXI_RVALID        ,
    output                          M_AXI_RREADY        ,
    input   [P_DATA_WIDTH-1:0]      M_AXI_RDATA         ,
    input  [3:0]                    M_AXI_RRESP         ,

    input   [P_DATA_WIDTH-1:0]      USER_WDATA_I        ,
    input   [P_ADDR_WIDTH-1:0]      USER_WADDR_I        ,
    input                           USER_WVALID_I       ,

    input   [P_ADDR_WIDTH-1:0]      USER_RADDR_I        ,
    input                           USER_RVALID_I       ,
    output                          USER_RVALID_O       ,
    output  [P_DATA_WIDTH-1:0]      USER_RDATA_O        
);
//???????????reg???????
reg                          ro_M_AXI_AWVALID   ;   
reg  [P_ADDR_WIDTH-1:0]      ro_M_AXI_AWADDR    ;   
reg  [3:0]                   ro_M_AXI_AWPROT    ;   
reg                          ro_M_AXI_WVALID    ;   
reg  [P_DATA_WIDTH-1:0]      ro_M_AXI_WDATA     ;   
reg  [P_DATA_WIDTH/8-1:0]    ro_M_AXI_WSTRB     ;   
reg                          ro_M_AXI_BREADY    ;   
reg                          ro_M_AXI_ARVALID   ;   
reg   [P_ADDR_WIDTH-1:0]     ro_M_AXI_ARADDR    ;   
reg   [3:0]                  ro_M_AXI_ARPROT    ;   
reg                          ro_M_AXI_RREADY    ;   
reg                          ro_USER_RVALID_O   ;
reg   [P_DATA_WIDTH-1:0]     ro_USER_RDATA_O    ; 

reg                          write_run          ;
reg                          read_run           ;
reg                          waddr_fifo_rd_en_d1;
reg                          raddr_fifo_rd_en_d1;

//§Õ????fifo???
wire  [P_DATA_WIDTH-1:0]     wdata_fifo_din     ;
wire                         wdata_fifo_wr_en   ;
wire  [P_DATA_WIDTH-1:0]     wdata_fifo_out     ;
wire                         wdata_fifo_empty   ;
wire                         wdata_fifo_full    ;

//§Õ???fifo???
wire  [P_ADDR_WIDTH-1:0]     waddr_fifo_din     ;
wire                         waddr_fifo_wr_en   ;
reg                          waddr_fifo_rd_en   ;
wire  [P_ADDR_WIDTH-1:0]     waddr_fifo_out     ;
wire                         waddr_fifo_empty   ;

//?????fifo???
wire  [P_ADDR_WIDTH-1:0]     raddr_fifo_din     ;
wire                         raddr_fifo_wr_en   ;
reg                          raddr_fifo_rd_en   ;
wire                         raddr_fifo_empty   ;
wire  [P_ADDR_WIDTH-1:0]     raddr_fifo_out     ;

//?????????
wire                         AW_active          ;
wire                         W_active           ;
wire                         WB_active          ;
wire                         AR_active          ;
wire                         R_active           ;

//????????????????????
assign  M_AXI_AWVALID  =     ro_M_AXI_AWVALID   ;
assign  M_AXI_AWADDR   =     ro_M_AXI_AWADDR    ;
assign  M_AXI_AWPROT   =     ro_M_AXI_AWPROT    ;
assign  M_AXI_WVALID   =     ro_M_AXI_WVALID    ;
assign  M_AXI_WDATA    =     ro_M_AXI_WDATA     ;
assign  M_AXI_WSTRB    =     ro_M_AXI_WSTRB     ;
assign  M_AXI_BREADY   =     ro_M_AXI_BREADY    ;
assign  M_AXI_ARVALID  =     ro_M_AXI_ARVALID   ;
assign  M_AXI_ARADDR   =     ro_M_AXI_ARADDR    ;
assign  M_AXI_ARPROT   =     ro_M_AXI_ARPROT    ;
assign  M_AXI_RREADY   =     ro_M_AXI_RREADY    ;
assign  USER_RVALID_O  =     ro_USER_RVALID_O   ;
assign  USER_RDATA_O   =     ro_USER_RDATA_O    ;
//??????????
assign  AW_active      =     M_AXI_AWREADY  &  M_AXI_AWVALID;
assign  W_active       =     M_AXI_WREADY   &  M_AXI_WVALID ;  
assign  WB_active      =     M_AXI_BREADY   &  M_AXI_BVALID ; 
assign  AR_active      =     M_AXI_ARREADY  &  M_AXI_ARVALID;
assign  R_active       =     M_AXI_RREADY   &  M_AXI_RVALID ;
//????fifo§Õ??
assign  wdata_fifo_din      = USER_WDATA_I  ;
assign  wdata_fifo_wr_en    = USER_WVALID_I ;
assign  waddr_fifo_din      = USER_WADDR_I  ;
assign  waddr_fifo_wr_en    = USER_WVALID_I ;
assign  raddr_fifo_wr_en    = USER_RVALID_I ;
assign  raddr_fifo_din      = USER_RADDR_I  ;


fifo_32x32 user_wdata_fifo (
  .clk      (   M_AXI_ACLK          ),     // input wire clk
  .srst     (  ~M_AXI_ARESETN       ),     // input wire srst
  .din      (   wdata_fifo_din      ),     // input wire [31 : 0] din
  .wr_en    (   waddr_fifo_wr_en    ),     // input wire wr_en
  .rd_en    (   waddr_fifo_rd_en    ),     // input wire rd_en
  .dout     (   wdata_fifo_out      ),     // output wire [31 : 0] dout
  .full     (   wdata_fifo_full     ),     // output wire full
  .empty    (   wdata_fifo_empty    )      // output wire empty
);

fifo_32x32 user_waddr_fifo (
  .clk      (   M_AXI_ACLK          ),      // input wire clk
  .srst     (  ~M_AXI_ARESETN       ),      // input wire srst
  .din      (   waddr_fifo_din      ),      // input wire [31 : 0] din
  .wr_en    (   waddr_fifo_wr_en    ),      // input wire wr_en
  .rd_en    (   waddr_fifo_rd_en    ),      // input wire rd_en
  .dout     (   waddr_fifo_out      ),      // output wire [31 : 0] dout
  .empty    (   waddr_fifo_empty    )       // output wire empty
);


fifo_32x32 user_raddr_fifo (
  .clk      (   M_AXI_ACLK          ),      // input wire clk
  .srst     (  ~M_AXI_ARESETN       ),      // input wire srst
  .din      (   raddr_fifo_din      ),      // input wire [31 : 0] din
  .wr_en    (   raddr_fifo_wr_en    ),      // input wire wr_en
  .rd_en    (   raddr_fifo_rd_en    ),      // input wire rd_en
  .dout     (   raddr_fifo_out      ),      // output wire [31 : 0] dout
  .empty    (   raddr_fifo_empty    )       // output wire empty
);

//??§Õ?????????????§Õ????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN)
        write_run <= 'd0;
    else if(WB_active)
        write_run <= 'd0;
    else if(!waddr_fifo_empty)
        write_run <= 'd1;
    else
        write_run <= write_run;
end

//???????§Õ????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN)
        waddr_fifo_rd_en <= 'd0;
    else if(!waddr_fifo_empty && !write_run)
        waddr_fifo_rd_en <= 'd1;
    else
        waddr_fifo_rd_en <= 'd0;
end

//??????????????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN)
        waddr_fifo_rd_en_d1 <= 'd0;
    else
        waddr_fifo_rd_en_d1 <= waddr_fifo_rd_en;
end

//???????????????????????????§¹???
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN) begin
        ro_M_AXI_AWVALID <= 'd0;
        ro_M_AXI_AWADDR  <= 'd0;
        ro_M_AXI_AWPROT  <= 'd0;
        ro_M_AXI_WVALID  <= 'd0;
    end
    else if(AW_active) begin
        ro_M_AXI_AWVALID <= 'd0;
        ro_M_AXI_AWADDR  <= 'd0;
        ro_M_AXI_AWPROT  <= 'd0;
    end
    else if(waddr_fifo_rd_en_d1) begin
        ro_M_AXI_AWVALID <= 'd1;
        ro_M_AXI_AWADDR  <= waddr_fifo_out;
        ro_M_AXI_AWPROT  <= 'd0;
    end
    else begin
        ro_M_AXI_AWVALID <= ro_M_AXI_AWVALID;
        ro_M_AXI_AWADDR  <= ro_M_AXI_AWADDR ;
        ro_M_AXI_AWPROT  <= ro_M_AXI_AWPROT ;
    end    
end

//??????????????????????????????§¹???
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN) begin
        ro_M_AXI_WVALID <= 'd0;
        ro_M_AXI_WDATA  <= 'd0;
        ro_M_AXI_WSTRB  <= 'd0;
    end
    else if(W_active || AW_active) begin
        ro_M_AXI_WVALID <= 'd0;
        ro_M_AXI_WDATA  <= 'd0;
        ro_M_AXI_WSTRB  <= 'd0;
    end
    else if(waddr_fifo_rd_en_d1) begin
        ro_M_AXI_WVALID <= 'd1;
        ro_M_AXI_WDATA  <= wdata_fifo_out;
        ro_M_AXI_WSTRB  <= 'b1111;
    end
    else begin
        ro_M_AXI_WVALID <= ro_M_AXI_WVALID;
        ro_M_AXI_WDATA  <= ro_M_AXI_WDATA ;
        ro_M_AXI_WSTRB  <= ro_M_AXI_WSTRB ; 
    end  
end

always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN)
        ro_M_AXI_BREADY <= 'd0;
    else if(WB_active)
        ro_M_AXI_BREADY <= 'd0;
    else if(W_active)
        ro_M_AXI_BREADY <= 'd1;
    else
        ro_M_AXI_BREADY <= ro_M_AXI_BREADY;
end

//????????????§Õ????????????????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN)
        read_run <= 'd0;
    else if(R_active)
        read_run <= 'd0;
    else if(!raddr_fifo_empty && waddr_fifo_empty)
        read_run <= 'd1;
    else
        read_run <= read_run;
end

//?????fifo?????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN)
        raddr_fifo_rd_en <= 'd0;
    else if(!read_run && !raddr_fifo_empty && waddr_fifo_empty)
        raddr_fifo_rd_en <= 'd1;
    else
        raddr_fifo_rd_en <= 'd0;
end

//????????????????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN)
        raddr_fifo_rd_en_d1 <= 'd0;
    else
        raddr_fifo_rd_en_d1 <= raddr_fifo_rd_en;
end

//???????§Õ??AXI??????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN) begin
        ro_M_AXI_ARVALID <= 'd0;
        ro_M_AXI_ARADDR  <= 'd0;
        ro_M_AXI_ARPROT  <= 'd0;
    end
    else if(AR_active) begin
        ro_M_AXI_ARVALID <= 'd0;
        ro_M_AXI_ARADDR  <= 'd0;   
        ro_M_AXI_ARPROT  <= 'd0; 
    end 
    else if(raddr_fifo_rd_en_d1) begin
        ro_M_AXI_ARVALID <= 'd1;
        ro_M_AXI_ARADDR  <= raddr_fifo_out;    
        ro_M_AXI_ARPROT  <= 'd0;
    end
    else begin
        ro_M_AXI_ARVALID <= ro_M_AXI_ARVALID;
        ro_M_AXI_ARADDR  <= ro_M_AXI_ARADDR ;
        ro_M_AXI_ARPROT  <= ro_M_AXI_ARPROT ;    
    end   
end

//???????§Õ?????????????????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN)
        ro_M_AXI_RREADY <= 'd0;
    else if(R_active)
        ro_M_AXI_RREADY <= 'd0;
    else if(AR_active)
        ro_M_AXI_RREADY <= 'd1;
    else
        ro_M_AXI_RREADY <= ro_M_AXI_RREADY;
end

//??AXI?????????????????????????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
    if(!M_AXI_ARESETN) begin
        ro_USER_RVALID_O  <= 'd0;
        ro_USER_RDATA_O   <= 'd0;  
    end
    else begin
        ro_USER_RVALID_O  <= M_AXI_RVALID;
        ro_USER_RDATA_O   <= M_AXI_RDATA ;
    end
end



endmodule

仿真波形分析

写入地址、数据FIFO

在这里插入图片描述

从地址、数据FIFO将数据读出

在这里插入图片描述
当FIFO读使能拉高,数据会延时一个周期

数据被送到AXI总线上的握手

在这里插入图片描述

从机的应答

在这里插入图片描述

写入读地址fifo

在这里插入图片描述

FIFO读出都地址

在这里插入图片描述

数据从AXI接口读出

在这里插入图片描述

读出数据送到用户接口

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值