加载中...

Xilinxddr3 mig ip核:基于AXI接口的ddr3读写控制

  本文完全参考野火的DDR3读写控制设计,原文十分详细,需要的可以去看看。


一、AXI4接口详解

  AXI接口由5个独立的通道构成,分别是读地址、读数据、写地址、写数据、写响应。
  如下是读传输过程示意图,使用读地址与读数据通道。主机首先在读地址通道给出读地址和控制信号,然后从机由读数据通道返回读出的数据。且可以看到,主机只给出了一个地址,从该地址连续突发读出4个数据。

  写传输过程如下图所示。使用写地址、写数据和写响应三个通道。主机在写地址通道给出写地址和控制信号,然后在写数据通道连续突发写四个数据。从机在接收数据之后,在写响应通道给出响应信号。

  如下图是AXI4的接口描述,左侧是IP核生成的接口信号,括号里的是本工程定义的信号。可以发现,接口信号中以“s_axi_aw”开头的是写地址通道信号,以“s_axi_w”开头的是写数据通道信号,以“s_axi_b”开头的是写响应通道信号,以“s_axi_ar”开头的是读地址通道信号,以“s_axi_r”开头的是读数据响应通道信号。


  这里也顺便将DDR3 IP核所有的接口描述一下。带ddr3的信号是引脚信号,与外部ddr3存储器相连,不需要管;带app的信号是本地接口维护命令信号,不用使用,输入信号给0,输出信号空接;带ui的信号是给用户侧使用的时钟信号和复位信号,注意复位信号是高电平有效;sys_clk_i是ip核系统时钟,一般设置为200M,这样参考时钟可以选择use system clk,所以这里的clk_ref_i被注释了;还要注意ip系统复位输入信号sys_rst,是低电平有效。

突发写时序

  写数据时序图如下。

  AXI4突发写可以分为7个状态,分别为:
  1.写空闲:等待突发写触发信号。
  2.写通道地址等待:准备好写地址AWADDR,然后拉高AWVALID。
  3.写通道写地址:从机接受到AWVALID,发出AWREADY。
  4.写数据等待:准备好写数据WDATA,拉高WVALID。
  5.写数据循环:从机接受WVALID,确认数据WDATA有效并且接受,发出WREADY,AXI是突发传输:循环该操作到接受到WLAST最后一个数据标志位。
  6.接受写应答:接受到从机发出的BVALID,主机发出BREADY。
  7.写结束:拉低未拉低的信号,进入写空闲。

突发读时序

  读数据时序图如下。

  AXI4突发读可以分为6个状态,分别为:
  1.读空闲:等待突发读触发信号。
  2.读通道写地址等待:准备好写地址ARADDR,然后拉高ARVALID。
  3.读通道写地址:从机接收到ARVALID,发出ARREADY。
  4.读数据等待:从机准备好读数据RDATA,并拉高RVALID。
  5.读数据循环:主机接收RVALID,确认数据RDATA有效并接收,发出RREADY给从机,AXI是突发传输:循环该操作到接收到RLAST最后一个数据标志位。
  6.读结束:拉低未拉低的信号,进入读空闲。

接口信号详解

  • VALID和READY信号:AXI接口的读写在于握手信号VALID与READY。VALID信号由源端产生,表示当前地址或数据线上的信息是有效的;READY信号由目的端产生,表示已经准备好接收地址、数据以及控制信息。VALID和READY信号提供了3种握手机制,即VALIDbeforeREADY握手,READYbeforeVALID握手,VALIDwithREADY握手。
  • AWID与ARID:对于只有一个主从设备,该值可设置为任意值。
  • AWADDR与ARADDR:主机只给出突发传输第一个字节的地址,从机必须计算突发传输后续的地址。突发传输不能跨4KB边界。这是因为每一个从机分配的是4KB空间。以32位地址为例,[31:12]相等的地址都是同一个page,没有跨4K边界。即[11:0]可以为0~0xFFF。 例如0x1000和0x2000就是在不同的page,跨了4K边界。0x1000和0x1FFF则是在同一个page,没有跨4K边界。同理,0x1FFF和0x2000,虽然他们是相邻的byte,但也跨了4K边界。所以,这是为了防止一次突发跨越两个从机的边界。
  • AWLEN与ARLEN:读写传输的突发长度。突发长度==AxLEN[7:0]+1。
  • ARSIZE与AWSIZE:读写突发传输大小。突发大小==2^(AxSIZE[2:0])字节。
  • AWBURST与ARBURST:突发类型。2'b00:FIXED,2'b01:INCR,2'b10:WRAP,2'b11:Reserved。FIXED:突发传输过程中地址固定;INCR:增量突发,传输过程中,地址递增,增加量取决于AxSIZE的值。WRAP:回环突发,和增量突发类似,但会在特定高地址的边界处回到低地址处。
  • WSTRB:有效字节,WSTRB[n:0]对应于对应的写字节,WSTRB[n]对应WDATA[8n+7:8n],也就是对于的数据宽度的字节数是否有效。对于一般应用,将WSTRB全部置1即可,保证全部数据有效。读通道无该信号。
  • WLAST与RLAST:拉高表示传输最后一个数据,意味着传输结束。

IP核配置

  选择AXI4 Interface。

  Data Width根据开发板板载DDR3数据位宽设置即可,在我们的程序设计中没有体现,关注点还应该是AXI。

  接下来是AXI接口的参数配置界面,本工程将AXI的Data_Width设置为64。

  200M的IP核系统时钟。

  参考时钟选择系统时钟。

  这里选择第二个。

  其他选项保持默认即可,生成IP核。
  这里强调一点,AXI接口的地址是一个字节一个地址的,千万不要和native接口的ddr芯片的地址混淆。


二、代码设计

  模块框图如下。具体流程为:用户将需要存储的数据存入写fifo,axi_ctrl模块根据写fifo的状态产生写突发信号控制axi_master_write模块,完成写操作;用户给出读请求,axi_ctrl模块根据读fifo的状态产生读突发信号控制axi_master_read模块,完成读操作。

axi_master_write模块

点击查看代码
module axi_master_write
(
  input           ARESETN    , //axi复位
  input           ACLK       , //axi总时钟
//axi4写通道地址通道
  output [3:0]  M_AXI_AWID   , //写地址ID,用来标志一组写信号
  output [31:0] M_AXI_AWADDR , //写地址,给出一次写突发传输的写地址
  output [7:0]  M_AXI_AWLEN  , //突发长度,给出突发传输的次数  
  output [2:0]  M_AXI_AWSIZE , //突发大小,给出每次突发传输的字节数  
  output [1:0]  M_AXI_AWBURST, //突发类型  
  output        M_AXI_AWLOCK , //总线锁信号,可提供操作的原子性  
  output [3:0]  M_AXI_AWCACHE, //内存类型,表明一次传输是怎样通过系统的  
  output [2:0]  M_AXI_AWPROT , //保护类型,表明一次传输的特权级及安全等级  
  output [3:0]  M_AXI_AWQOS  , //质量服务QoS     
  output        M_AXI_AWVALID, //有效信号,表明此通道的地址控制信号有效
  input         M_AXI_AWREADY, //表明“从”可以接收地址和对应的控制信号
//axi4写通道数据通道
  output [63:0] M_AXI_WDATA  , //写数据
  output [7:0]  M_AXI_WSTRB  , //写数据有效的字节线
  output        M_AXI_WLAST  , //表明此次传输是最后一个突发传输
  output        M_AXI_WVALID , //写有效,表明此次写有效
  input         M_AXI_WREADY , //表明从机可以接收写数据
//axi4写通道应答通道
  input [3:0]   M_AXI_BID    , //写响应ID TAG
  input [1:0]   M_AXI_BRESP  , //写响应,表明写传输的状态
  input         M_AXI_BVALID , //写响应有效
  output        M_AXI_BREADY , //表明主机能够接收写响应
  //用户端信号
  input         WR_START     , //写突发触发信号
  input [31:0]  WR_ADRS      , //地址  
  input [9:0]   WR_LEN       , //长度
  output        WR_READY     , //写空闲
  output        WR_FIFO_RE   , //连接到写fifo的读使能
  input [63:0]  WR_FIFO_DATA , //连接到fifo的读数据
  output        WR_DONE        //完成一次突发
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//

localparam S_WR_IDLE  = 3'd0;//写空闲
localparam S_WA_WAIT  = 3'd1;//写地址等待
localparam S_WA_START = 3'd2;//写地址
localparam S_WD_WAIT  = 3'd3;//写数据等待
localparam S_WD_PROC  = 3'd4;//写数据循环
localparam S_WR_WAIT  = 3'd5;//接受写应答
localparam S_WR_DONE  = 3'd6;//写结束
//reg define  
reg [2:0]   wr_state   ; //状态寄存器
reg [31:0]  reg_wr_adrs; //地址寄存器
reg         reg_awvalid; //地址有效握手信号
reg         reg_wvalid ; //数据有效握手信号
reg         reg_w_last ; //传输最后一个数据
reg [7:0]   reg_w_len  ; //突发长度最大256,实测128最佳

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

//写完成信号的写状态完成
assign WR_DONE = (wr_state == S_WR_DONE);
//写fifo的读使能为axi数据握手成功
assign WR_FIFO_RE         = ((reg_wvalid & M_AXI_WREADY ));
//只有一个主机,可随意设置
assign M_AXI_AWID         = 4'b1111;
//把地址赋予总线
assign M_AXI_AWADDR[31:0] = reg_wr_adrs[31:0];
//一次突发传输1长度
assign M_AXI_AWLEN[7:0]   = WR_LEN-'d1;
//表示AXI总线每个数据宽度是8字节,64位
assign M_AXI_AWSIZE[2:0]  = 3'b011;
//01代表地址递增,10代表递减
assign M_AXI_AWBURST[1:0] = 2'b01; 
assign M_AXI_AWLOCK       = 1'b0;
assign M_AXI_AWCACHE[3:0] = 4'b0000;
assign M_AXI_AWPROT[2:0]  = 3'b000;
assign M_AXI_AWQOS[3:0]   = 4'b0000;
//地址握手信号AWVALID
assign M_AXI_AWVALID      = reg_awvalid;
//fifo数据赋予总线
assign M_AXI_WDATA[63:0]  = WR_FIFO_DATA[63:0];
assign M_AXI_WSTRB[7:0]   = 8'hFF;
//写到最后一个数据
assign M_AXI_WLAST        =(reg_w_len[7:0] == 8'd0)?'b1:'b0;
//数据握手信号WVALID
assign M_AXI_WVALID       = reg_wvalid;
//这个信号是告诉AXI我收到你的应答
assign M_AXI_BREADY       = M_AXI_BVALID;
//axi状态机空闲信号
assign WR_READY           = (wr_state == S_WR_IDLE)?1'b1:1'b0;

//axi写过程状态机
  always @(posedge ACLK or negedge ARESETN) begin
    if(!ARESETN) begin
      wr_state            <= S_WR_IDLE;
      reg_wr_adrs[31:0]   <= 32'd0;
      reg_awvalid         <= 1'b0;
      reg_wvalid          <= 1'b0;
      reg_w_last          <= 1'b0;
      reg_w_len[7:0]      <= 8'd0;
      
  end else begin
      case(wr_state)
        S_WR_IDLE: begin //写空闲
          if(WR_START) begin //触发写过程
            wr_state          <= S_WA_WAIT;
            reg_wr_adrs[31:0] <= WR_ADRS[31:0];
          end
          reg_awvalid         <= 1'b0;
          reg_wvalid          <= 1'b0;
          reg_w_len[7:0]      <= 8'd0;
        end
        S_WA_WAIT: begin//写地址等待
          wr_state        <= S_WA_START;//等待一个周期
        end
        S_WA_START: begin
          wr_state        <= S_WD_WAIT;//写数据等待
          reg_awvalid     <= 1'b1; //拉高地址有效信号 
          reg_wvalid      <= 1'b1;//拉高数据有效信号
        end
        S_WD_WAIT: begin
          if(M_AXI_AWREADY) begin//等待写地址就绪
            wr_state        <= S_WD_PROC;
            reg_w_len<=WR_LEN-'d1;//127代表128个长度,0代表1个长度
            reg_awvalid     <= 1'b0;
          end
        end
        S_WD_PROC: begin//等待AXI写数据就绪信号
          if(M_AXI_WREADY) begin//拉高了就可以输出fifo使能信号开始读
            
            if(reg_w_len[7:0] == 8'd0) begin//完成数据写过程
              wr_state        <= S_WR_WAIT;
              reg_wvalid      <= 1'b0;//此信号拉低,写fifo读使能无效
              reg_w_last<='b1;
              //读到最后一个数据,拉高这个标志信号告诉AXI总线这是最后一个
              //如果不拉高传输不会成功
            end           
            else begin
              reg_w_len[7:0]  <= reg_w_len[7:0] -8'd1;
            end
          end
        end
        S_WR_WAIT: begin//等待写的AXI应答信号
          reg_w_last<='b0;
          //M_AXI_BVALID拉高表示写成功,然后状态机完成一次突发传输
          if(M_AXI_BVALID) begin
              wr_state          <= S_WR_DONE;
          end
        end
        S_WR_DONE: begin //写完成           
            wr_state <= S_WR_IDLE;
          end
        
        default: begin
          wr_state <= S_WR_IDLE;
        end
      endcase
      end
  end

endmodule
  该模块所有的AXI接口模块都用组合逻辑赋值,根据与axi_ctrl模块交互的用户端信号来进行突发写传输。整体编写思路就是前面所说的7个状态的状态机。写数据状态,当当前写数据是最后一个时,需要即时拉低reg_wvalid信号,拉低写fifo的读使能。写fifo的读数据是直接通过组合逻辑给AXI接口的。

axi_master_read模块

点击查看代码
module axi_master_read
(
  input           ARESETN,//axi复位
  input           ACLK,  //axi时钟
//axi读通道写地址
  output [3:0]  M_AXI_ARID   , //读地址ID,用来标志一组写信号
  output [31:0] M_AXI_ARADDR , //读地址,给出一次写突发传输的读地址
  output [7:0]  M_AXI_ARLEN  , //突发长度,给出突发传输的次数
  output [2:0]  M_AXI_ARSIZE , //突发大小,给出每次突发传输的字节数
  output [1:0]  M_AXI_ARBURST, //突发类型
  output [1:0]  M_AXI_ARLOCK , //总线锁信号,可提供操作的原子性
  output [3:0]  M_AXI_ARCACHE, //内存类型,表明一次传输是怎样通过系统的
  output [2:0]  M_AXI_ARPROT , //保护类型,表明一次传输的特权级及安全等级
  output [3:0]  M_AXI_ARQOS  , //质量服务QOS
  output        M_AXI_ARVALID, //有效信号,表明此通道的地址控制信号有效
  input         M_AXI_ARREADY, //表明“从”可以接收地址和对应的控制信号
    
  //axi读通道读数据
  input [3:0]   M_AXI_RID   , //读ID tag
  input [63:0]  M_AXI_RDATA , //读数据
  input [1:0]   M_AXI_RRESP , //读响应,表明读传输的状态
  input         M_AXI_RLAST , //表明读突发的最后一次传输
  input         M_AXI_RVALID, //表明此通道信号有效
  output        M_AXI_RREADY, //表明主机能够接收读数据和响应信息
   //用户端fifo接口    
  input         RD_START    , //读突发触发信号
  input [31:0]  RD_ADRS     , //地址  
  input [9:0]   RD_LEN       , //长度
  output        RD_READY    , //读空闲
  output        RD_FIFO_WE  , //连接到读fifo的写使能
  output [63:0] RD_FIFO_DATA, //连接到读fifo的写数据
  output        RD_DONE       //完成一次突发
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//

//parameter  define
localparam S_RD_IDLE  = 3'd0; //读空闲
localparam S_RA_WAIT  = 3'd1; //读地址等待
localparam S_RA_START = 3'd2; //读地址
localparam S_RD_WAIT  = 3'd3; //读数据等待
localparam S_RD_PROC  = 3'd4; //读数据循环
localparam S_RD_DONE  = 3'd5; //写结束
//reg define                               
reg [2:0]   rd_state   ; //状态寄存器
reg [31:0]  reg_rd_adrs; //地址寄存器
reg [31:0]  reg_rd_len ; //突发长度寄存器
reg         reg_arvalid; //地址有效寄存器

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

assign RD_DONE = (rd_state == S_RD_DONE) ;
assign M_AXI_ARID         = 4'b1111;//地址id
assign M_AXI_ARADDR[31:0] = reg_rd_adrs[31:0];//地址
assign M_AXI_ARLEN[7:0]   = RD_LEN-32'd1;//突发长度
assign M_AXI_ARSIZE[2:0]  = 3'b011;//表示AXI总线每个数据宽度是8字节,64位
assign M_AXI_ARBURST[1:0] = 2'b01;//地址递增方式传输
assign M_AXI_ARLOCK       = 1'b0;
assign M_AXI_ARCACHE[3:0] = 4'b0000;
assign M_AXI_ARPROT[2:0]  = 3'b000;
assign M_AXI_ARQOS[3:0]   = 4'b0000;
assign M_AXI_ARVALID      = reg_arvalid;
assign M_AXI_RREADY       = M_AXI_RVALID;
assign RD_READY           = (rd_state == S_RD_IDLE)?1'b1:1'b0;//读空闲
assign RD_FIFO_WE         = M_AXI_RVALID;//读fifo的写使能信号
assign RD_FIFO_DATA[63:0] = M_AXI_RDATA[63:0];//读fifo的写数据信号 

  // 读状态机
  always @(posedge ACLK or negedge ARESETN) begin
    if(!ARESETN) begin
      rd_state          <= S_RD_IDLE;
      reg_rd_adrs[31:0] <= 32'd0;
      reg_rd_len[31:0]  <= 32'd0;
      reg_arvalid       <= 1'b0;
    end else begin
      case(rd_state)
        S_RD_IDLE: begin//读空闲
          if(RD_START) begin//突发触发信号
            rd_state          <= S_RA_WAIT;
            reg_rd_adrs[31:0] <= RD_ADRS[31:0];
            reg_rd_len[31:0]  <= RD_LEN[9:0] -32'd1;
          end
          reg_arvalid     <= 1'b0;
        end
        S_RA_WAIT: begin//写地址等待
            rd_state          <= S_RA_START;
        end
        S_RA_START: begin//写地址
          rd_state          <= S_RD_WAIT;
          reg_arvalid       <= 1'b1;//拉高地址有效
        end
        S_RD_WAIT: begin //读取数据等待
          if(M_AXI_ARREADY) begin
            rd_state        <= S_RD_PROC;
            reg_arvalid     <= 1'b0;//握手成功就拉低
          end
        end
        S_RD_PROC: begin //接受循环
          if(M_AXI_RVALID) begin //收到数据有效,握手成功
            if(M_AXI_RLAST) begin //收到最后一个数据
                rd_state<= S_RD_DONE;
            end
          end
        end
    S_RD_DONE:begin 
      rd_state          <= S_RD_IDLE;
    end
    endcase
    end
  end
   
endmodule
  每当AXI接口的读数据发送出来,都直接传给读fifo的写数据端了。

axi_ctrl模块

点击查看代码
module axi_ctrl
#(
parameter  DDR_WR_LEN=128,//写突发长度 128个64bit
parameter  DDR_RD_LEN=128 //读突发长度 128个64bit

)
(
   input   wire        ui_clk     , //时钟
   input   wire        ui_rst     , //复位,高电平有效
   input   wire        pingpang   ,   //乒乓操作
   //写fifo写数据端
   input   wire [31:0] wr_b_addr  ,   //写DDR首地址
   input   wire [31:0] wr_e_addr  ,   //写DDR末地址
   input   wire        user_wr_clk,   //写FIFO写时钟
   input   wire        data_wren  ,   //写FIFO写请求
   //写进fifo数据长度,可根据写fifo的写端口数据长度自行修改
   //写FIFO写数据 16位,此时用64位是为了兼容32,64位
   input   wire [63:0] data_wr    ,    
   input   wire        wr_rst     ,
   
   //读fifo读数据端
   input   wire [31:0] rd_b_addr  ,   //读DDR首地址
   input   wire [31:0] rd_e_addr  ,   //读DDR末地址    
   input   wire        user_rd_clk,   //读FIFO读时钟
   input   wire        data_rden  ,   //读FIFO读请求  
   //读出fifo数据长度,可根据读fifo的读端口数据长度自行修改
   //读FIFO读数据,16位,此时用64位是为了兼容32,64位
   output  wire [63:0] data_rd    ,   
   input   wire        rd_rst     ,
   input   wire        read_enable,//读ddr使能
   output  wire        data_rd_valid,
   //突发写模块控制信号   
   output  wire        wr_burst_req    , //写突发触发信号
   output  wire[31:0]  wr_burst_addr   , //地址  
   output  wire[9:0]   wr_burst_len    , //长度
   input   wire        wr_ready        , //写空闲
   input   wire        wr_fifo_re      , //连接到写fifo的读使能
   output  wire [63:0] wr_fifo_data    , //连接到fifo的读数据
   input   wire        wr_burst_finish , //完成一次突发
    //突发读模块控制信号                                 
   output  wire        rd_burst_req    , //读突发触发信号
   output  wire[31:0]  rd_burst_addr   , //地址  
   output  wire[9:0]   rd_burst_len    ,  //长度
   input   wire        rd_ready        , //读空闲
   input   wire        rd_fifo_we      , //连接到读fifo的写使能
   input   wire[63:0]  rd_fifo_data    , //连接到读fifo的写数据
   input   wire        rd_burst_finish   //完成一次突发
   );
 
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//reg define
reg       wr_burst_req_reg ; //写突发寄存器
reg [31:0]wr_burst_addr_reg; //写地址寄存器
reg [9:0] wr_burst_len_reg ; //写长度寄存器

reg       rd_burst_req_reg ; //读突发寄存器
reg [31:0]rd_burst_addr_reg; //读地址寄存器
reg [9:0] rd_burst_len_reg ; //读长度寄存器
//读写地址复位打拍寄存器
reg wr_rst_reg1;
reg wr_rst_reg2;
reg rd_rst_reg1;
reg rd_rst_reg2;

reg pingpang_reg;//乒乓操作指示寄存器

//wire define
//写fifo信号
wire        wr_fifo_wr_clk        ;
wire        wr_fifo_rd_clk        ;
wire [63:0] wr_fifo_din           ;
wire        wr_fifo_wr_en         ;
wire        wr_fifo_rd_en         ;
wire [63:0] wr_fifo_dout          ;
wire        wr_fifo_full          ;
wire        wr_fifo_almost_full   ;
wire        wr_fifo_empty         ;
wire        wr_fifo_almost_empty  ;
wire  [9:0] wr_fifo_rd_data_count ;
wire  [11:0] wr_fifo_wr_data_count;

//读fifo信号
wire        rd_fifo_wr_clk        ;
wire        rd_fifo_rd_clk        ;
wire [63:0] rd_fifo_din           ;
wire        rd_fifo_wr_en         ;
wire        rd_fifo_rd_en         ;
wire [63:0] rd_fifo_dout          ;
wire        rd_fifo_full          ;
wire        rd_fifo_almost_full   ;
wire        rd_fifo_empty         ;
wire        rd_fifo_almost_empty  ;
wire  [11:0]rd_fifo_rd_data_count ;
wire  [9:0] rd_fifo_wr_data_count ;

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

assign wr_burst_req  = wr_burst_req_reg;  //写突发请求
assign wr_burst_addr = wr_burst_addr_reg; //写地址
assign wr_burst_len  = DDR_WR_LEN;        //写长度

assign rd_burst_req  = rd_burst_req_reg;  //读突发请求
assign rd_burst_addr = rd_burst_addr_reg; //读地址
assign rd_burst_len  = DDR_RD_LEN;        //读长度

//写fifo写时钟位用户端时钟
assign wr_fifo_wr_clk = user_wr_clk;
//写fifo读时钟位axi总时钟
assign wr_fifo_rd_clk = ui_clk;     //axi接口时钟是ui_clk
//写fifo非满为用户输入数据        
assign wr_fifo_din    = data_wr;   
//写fifo非满为用户输入数据使能
assign wr_fifo_wr_en  = data_wren;
//写fifo非空为axi写主机读取使能
assign wr_fifo_rd_en  = wr_fifo_re;
//写fifo非空为axi写主机读取数据
assign wr_fifo_data   = wr_fifo_dout;
//读fifo写时钟位axi读主机时钟
assign rd_fifo_wr_clk=ui_clk;   //axi接口时钟是ui_clk
//读fifo读时钟位用户时钟
assign rd_fifo_rd_clk=user_rd_clk;
//读fifo读使能为用户使能
assign rd_fifo_rd_en =data_rden;
//读fifo读数据为用户使能
assign data_rd       =rd_fifo_dout;
//读fifo写使能为axi读主机写使能
assign rd_fifo_wr_en =rd_fifo_we;
//读fifo写使能为axi读主机写数据
assign rd_fifo_din   =rd_fifo_data;

assign data_rd_valid=~rd_fifo_empty;

//对写复位信号的跨时钟域打2拍
always@(posedge ui_clk or posedge ui_rst) begin
    if(ui_rst==1'b1)begin
        wr_rst_reg1<=1'b0;
        wr_rst_reg2<=1'b0;
    end
    else begin
        wr_rst_reg1<=wr_rst;
        wr_rst_reg2<=wr_rst_reg1;
    end

end

//对读复位信号的跨时钟域打2拍
always@(posedge ui_clk or posedge ui_rst) begin
    if(ui_rst==1'b1)begin
        rd_rst_reg1<=1'b0;
        rd_rst_reg2<=1'b0;
    end
    else begin
        rd_rst_reg1<=rd_rst;
        rd_rst_reg2<=rd_rst_reg1;
    end

end


//写burst请求产生
always@(posedge ui_clk or posedge ui_rst) begin
    if(ui_rst==1'b1)begin
        wr_burst_req_reg<=1'b0;    
    end
    //fifo数据长度大于一次突发长度并且axi写空闲
    else if((wr_fifo_rd_data_count+9'd2)>=DDR_WR_LEN && wr_ready==1'b1 ) begin 
        wr_burst_req_reg<=1'b1;      
    end
    else begin
        wr_burst_req_reg<=1'b0;
    end
end

//完成一次突发对地址进行相加
//相加地址长度=突发长度x8,64位等于8字节
//128*8=1024
always@(posedge ui_clk or posedge ui_rst) begin
    if(ui_rst==1'b1)begin
        wr_burst_addr_reg<=wr_b_addr;
        pingpang_reg<=1'b0;  
    end
    //写复位信号上升沿
    else if(wr_rst_reg1&(~wr_rst_reg2)) begin
        wr_burst_addr_reg<=wr_b_addr;
    end 
    else if(wr_burst_finish==1'b1)begin
        wr_burst_addr_reg<=wr_burst_addr_reg+DDR_WR_LEN*8;
        //判断是否是乒乓操作
        if(pingpang==1'b1) begin
        //结束地址为2倍的接受地址,有两块区域
            if(wr_burst_addr_reg>=(
            (wr_e_addr-wr_b_addr)*2+wr_b_addr-DDR_WR_LEN*8)) 
            begin
                wr_burst_addr_reg<=wr_b_addr;
            end
            //根据地址,pingpang_reg为0或者1
            //用于指示读操作与写操作地址不冲突
            if(wr_burst_addr_reg<wr_e_addr) begin
                pingpang_reg<=1'b0;
            end
            else begin
                pingpang_reg<=1'b1;
            end
        end
        //非乒乓操作
        else begin
            if(wr_burst_addr_reg>=(wr_e_addr-DDR_WR_LEN*8)) 
            begin
                wr_burst_addr_reg<=wr_b_addr;
            end
        end
    end
    else begin
        wr_burst_addr_reg<=wr_burst_addr_reg;
    end

end

//读burst请求产生
always@(posedge ui_clk or posedge ui_rst) begin
    if(ui_rst==1'b1)begin
        rd_burst_req_reg<=1'b0;
    end
    //fifo可写长度大于一次突发长度并且axi读空闲,fifo总长度1024
    else if(rd_fifo_wr_data_count<=(10'd1000-DDR_RD_LEN) 
            && rd_ready==1'b1 &&read_enable==1'b1) 
    begin
        rd_burst_req_reg<=1'b1;
    end
    else begin
        rd_burst_req_reg<=1'b0;
    end
end

//完成一次突发对地址进行相加
//相加地址长度=突发长度x8,64位等于8字节
//128*8=1024
always@(posedge ui_clk or posedge ui_rst) begin
    if(ui_rst==1'b1)begin
        if(pingpang==1'b1) rd_burst_addr_reg<=rd_e_addr;
        else rd_burst_addr_reg<=rd_b_addr;
    end
    else if(rd_rst_reg1&(~rd_rst_reg2)) begin
        rd_burst_addr_reg<=rd_b_addr;
    end 
    else if(rd_burst_finish==1'b1)begin
          rd_burst_addr_reg<=rd_burst_addr_reg+DDR_RD_LEN*8;//地址累加
        //乒乓操作
         if(pingpang==1'b1) begin
           //到达结束地址 
           if((rd_burst_addr_reg==(rd_e_addr-DDR_RD_LEN*8))||
    (rd_burst_addr_reg==((rd_e_addr-rd_b_addr)*2+rd_b_addr-DDR_RD_LEN*8))) 
           begin
                //根据写指示地址信号,对读信号进行复位
               if(pingpang_reg==1'b1) rd_burst_addr_reg<=rd_b_addr;
               else rd_burst_addr_reg<=rd_e_addr;
           end
                    
        end
        else begin  //非乒乓操作
            if(rd_burst_addr_reg>=(rd_e_addr-DDR_RD_LEN*8)) 
            begin
            rd_burst_addr_reg<=rd_b_addr;
            end
        end
    end
    else begin
        rd_burst_addr_reg<=rd_burst_addr_reg;
    end

end

//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//

//------------- wr_fifo_inst -------------
//写fifo
wr_fifo wr_fifo_inst (
  .wr_rst(wr_rst||ui_rst), // 写复位
  .rd_rst(wr_rst||ui_rst), //读复位
  .wr_clk(wr_fifo_wr_clk), // 写时钟
  .rd_clk(wr_fifo_rd_clk), // 读时钟
  .din   (wr_fifo_din   ), // 外部写进fifo的数据 16位
  .wr_en (wr_fifo_wr_en ), // 写使能
  .rd_en (wr_fifo_rd_en ), // 读使能
  .dout  (wr_fifo_dout  ), // 输出给ddr的axi写数据,写进ddr 64位
  .full  (wr_fifo_full  ), // fifo满信号
  .almost_full  (wr_fifo_almost_full  ), //fifo几乎满信号
  .empty (wr_fifo_empty ), //fifo空信号 
  .almost_empty (wr_fifo_almost_empty ),
  .rd_data_count(wr_fifo_rd_data_count), // 可读数据个数
  .wr_data_count(wr_fifo_wr_data_count)  // 可写数据个数
);

//------------- rd_fifo_inst -------------
//读fifo
rd_fifo rd_fifo_inst (
  .wr_rst(rd_rst||ui_rst), // 写复位
  .rd_rst(rd_rst||ui_rst), //读复位
  .wr_clk(rd_fifo_wr_clk), // 写时钟
  .rd_clk(rd_fifo_rd_clk), // 读时钟
  .din   (rd_fifo_din   ), // ddr读出的数据,写进fifo 64位
  .wr_en (rd_fifo_wr_en ), // 写使能
  .rd_en (rd_fifo_rd_en ), // 读使能
  .dout  (rd_fifo_dout  ), // 最终我们读出的数据 64位
  .full  (rd_fifo_full  ), // fifo满信号
  .almost_full  (rd_fifo_almost_full  ),//fifo几乎满信号
  .empty (rd_fifo_empty ), //空信号
  .almost_empty (rd_fifo_almost_empty ),
  .rd_data_count(rd_fifo_rd_data_count), // 可读数据个数
  .wr_data_count(rd_fifo_wr_data_count)  // 可写数据个数
);

endmodule
  对于突发写请求的产生,当写fifo中的读数据长度大于一次突发长度且此时axi写空闲,产生写突发请求信号。因为rd_data_count和wr_data_count永远不会报告比实际数据量更小的数字,所以这里不加2也可以,因为生成IP核时没有点more accurate count,所以报告的数据量比实际的数据量少2个。产生第一次写突发后,将突发长度、突发地址(第一次即为首地址)传输给突发写模块,接下来写突发模块会产生读写fifo使能信号,然后产生突发完成信号,axi_ctrl模块检测到突发完成信号,需要进行突发地址的更新,即在上次突发地址的基础上加上突发长度 * AXI数据位宽 / 8,因为AXI地址是一个字节一个地址。更新地址完成,还需判断是否超过用户设置的结束地址,若超过,则需将突发地址设置为起始地址。然后等待下一次的写突发请求信号。这里野火的代码加了一个乒乓操作时的地址更新,不用管他,将pingpang设置为零即可。  

  对于读突发请求的产生,也是一样的道理,当读fifo中的可写数据长度大于一次突发长度并且axi读空闲,且用户侧给ddr3读使能read_enable有效,就拉高突发读请求。代码中fifo总长度设置的是1024,所以用了一个1000,这个数据要求并不严格,只要能保证我再进行一次突发。不会将读fifo存满即可。突发读模块检测到有效信号开始突发读,读出的数据直接存进读fifo中,当检测到突发读完成信号,就需要更新突发地址。

axi_ddr_top模块

  该模块将各个模块以及IP核集成,封装成一个类FIFO的结构。

点击查看代码
module axi_ddr_top #
(
parameter  DDR_WR_LEN=128,//写突发长度 最大128个64bit
parameter  DDR_RD_LEN=128//读突发长度 最大128个64bit
)

(
    //50m的时钟与复位信号
    input wire ddr3_clk          , //ddr3 ip核时钟200M
    input wire sys_rst_n         , //外部复位
       
    inout  [31:0] ddr3_dq        , //数据线
    inout  [3:0]  ddr3_dqs_n     , //数据选取脉冲差分信号
    inout  [3:0]  ddr3_dqs_p     , //数据选取脉冲差分信号
    output [14:0] ddr3_addr      , //地址线
    output [2:0]  ddr3_ba        , //bank线
    output        ddr3_ras_n     , //行使能信号,低电平有效
    output        ddr3_cas_n     , //列使能信号,低电平有效
    output        ddr3_we_n      , //写使能信号,低电平有效
    output        ddr3_reset_n   , //ddr3复位
    output [0:0]  ddr3_ck_p      , //ddr3差分时钟
    output [0:0]  ddr3_ck_n      , //ddr3差分时钟
    output [0:0]  ddr3_cke       , //ddr3时钟使能信号
    output [0:0]  ddr3_cs_n      , //ddr3片选信号
    output [3:0]  ddr3_dm        , //ddr3掩码
    output [0:0]  ddr3_odt       , //odt阻抗
    
    input   wire      pingpang   , //乒乓操作,1使能,0不使能
    
    input   wire[31:0]wr_b_addr  , //写DDR首地址
    input   wire[31:0]wr_e_addr  , //写DDR末地址
    input   wire      user_wr_clk, //写FIFO写时钟
    input   wire      data_wren  , //写FIFO写请求
//写进fifo数据长度,可根据写fifo的写端口数据长度自行修改
//写FIFO写数据 16位,此时用64位是为了兼容32,64位
    input   wire[63:0]data_wr    , //写数据 低16有效    
    input   wire      wr_rst     , //写地址复位
     
    input   wire[31:0]rd_b_addr  , //读DDR首地址
    input   wire[31:0]rd_e_addr  , //读DDR末地址    
    input   wire      user_rd_clk, //读FIFO读时钟
    input   wire      data_rden  , //读FIFO读请求  
//读出fifo数据长度,可根据读fifo的读端口数据长度自行修改
//读FIFO读数据,16位,此时用64位是为了兼容32,64位
    output  wire[63:0]data_rd    , //读数据 低16有效   
    input   wire      rd_rst     , //读地址复位
    input   wire      read_enable, //读使能
    output  wire      data_rd_valid,
    
    output  wire      ui_clk     , //输出时钟125m
    output  wire      ui_rst     , //输出复位,高有效
    output  wire      calib_done   //ddr初始化完成
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//

//wire  define
 //axi写通道写地址
wire [3:0] M_AXI_WR_awid;   //写地址ID,用来标志一组写信号
wire [31:0]M_AXI_WR_awaddr; //写地址,给出一次写突发传输的写地址
wire [7:0] M_AXI_WR_awlen;  //突发长度,给出突发传输的次数
wire [2:0] M_AXI_WR_awsize; //突发大小,给出每次突发传输的字节数
wire [1:0] M_AXI_WR_awburst;//突发类型
wire [0:0] M_AXI_WR_awlock; //总线锁信号,可提供操作的原子性
wire [3:0] M_AXI_WR_awcache;//内存类型,表明一次传输是怎样通过系统的
wire [2:0] M_AXI_WR_awprot; //保护类型,表明一次传输的特权级及安全等级
wire [3:0] M_AXI_WR_awqos;  //质量服务QoS
wire       M_AXI_WR_awvalid;//有效信号,表明此通道的地址控制信号有效
wire       M_AXI_WR_awready;//表明“从”可以接收地址和对应的控制信号                           
//axi写通道读数据           
wire [63:0]M_AXI_WR_wdata;  //写数据
wire [7:0] M_AXI_WR_wstrb;  //写数据有效的字节线
                            //用来表明哪8bits数据是有效的
wire       M_AXI_WR_wlast;  //表明此次传输是最后一个突发传输
wire       M_AXI_WR_wvalid; //写有效,表明此次写有效
wire       M_AXI_WR_wready; //表明从机可以接收写数据
//axi写通道读应答           
wire [3:0] M_AXI_WR_bid;    //写响应ID TAG
wire [1:0] M_AXI_WR_bresp;  //写响应,表明写传输的状态
wire       M_AXI_WR_bvalid; //写响应有效
wire       M_AXI_WR_bready; //表明主机能够接收写响应
 //axi读通道写地址          
wire [3:0] M_AXI_RD_arid;   //读地址ID,用来标志一组写信号
wire [31:0]M_AXI_RD_araddr; //读地址,给出一次写突发传输的读地址
wire [7:0] M_AXI_RD_arlen;  //突发长度,给出突发传输的次数
wire [2:0] M_AXI_RD_arsize; //突发大小,给出每次突发传输的字节数
wire [1:0] M_AXI_RD_arburst;//突发类型
wire [1:0] M_AXI_RD_arlock; //总线锁信号,可提供操作的原子性
wire [3:0] M_AXI_RD_arcache;//内存类型,表明一次传输是怎样通过系统的
wire [2:0] M_AXI_RD_arprot; //保护类型,表明一次传输的特权级及安全等级
wire [3:0] M_AXI_RD_arqos;  //质量服务QOS
wire       M_AXI_RD_arvalid;//有效信号,表明此通道的地址控制信号有效
wire       M_AXI_RD_arready;//表明“从”可以接收地址和对应的控制信号
//axi读通道读数据
wire [3:0] M_AXI_RD_rid;    //读ID tag
wire [63:0]M_AXI_RD_rdata;  //读数据
wire [1:0] M_AXI_RD_rresp;  //读响应,表明读传输的状态
wire       M_AXI_RD_rlast;  //表明读突发的最后一次传输
wire       M_AXI_RD_rvalid; //表明此通道信号有效
wire       M_AXI_RD_rready; //表明主机能够接收读数据和响应信息

//axi主机用户写控制信号
wire        wr_burst_req   ;
wire [31:0] wr_burst_addr  ;
wire [9:0]  wr_burst_len   ; 
wire        wr_ready       ;
//axi写数据与使能fifo接口
wire        wr_fifo_re     ;
wire [63:0] wr_fifo_data   ;
wire        wr_burst_finish;
//axi主机用户读控制信号
wire        rd_burst_req   ;
wire [31:0] rd_burst_addr  ;
wire [9:0]  rd_burst_len   ; 
wire        rd_ready       ;
//axi读数据与使能fifo接口
wire        rd_fifo_we     ;
wire [63:0] rd_fifo_data   ;
wire        rd_burst_finish;

//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//

//------------- axi_ctrl_inst -------------
axi_ctrl
#(
.DDR_WR_LEN(DDR_WR_LEN),//写突发长度 128个64bit
.DDR_RD_LEN(DDR_RD_LEN)//读突发长度 128个64bit

)
axi_ctrl_inst
(
  .ui_clk     (ui_clk     ),
  .ui_rst     (ui_rst     ),
  .pingpang   (pingpang   ),//乒乓操作
              
  .wr_b_addr  (wr_b_addr  ), //写DDR首地址
  .wr_e_addr  (wr_e_addr  ), //写DDR末地址
  .user_wr_clk(user_wr_clk), //写FIFO写时钟
  .data_wren  (data_wren  ), //写FIFO写请求            
  .data_wr    (data_wr    ), //写FIFO写数据 16位
                             //此时用64位是为了兼容32,64位
  .wr_rst     (wr_rst     ), //写地址复位
                             
  .rd_b_addr  (rd_b_addr  ), //读DDR首地址
  .rd_e_addr  (rd_e_addr  ), //读DDR末地址    
  .user_rd_clk(user_rd_clk), //读FIFO读时钟
  .data_rden  (data_rden  ), //读FIFO读请求             
  .data_rd    (data_rd    ), //读FIFO读数据,16位,此时用64位是为了兼容32位
                             //64位,增强复用性,只需修改fifo即可
  .rd_rst     (rd_rst     ),
  .read_enable(read_enable),
  .data_rd_valid(data_rd_valid),
  //连接到axi写主机
  .wr_burst_req     (wr_burst_req   ),
  .wr_burst_addr    (wr_burst_addr  ),
  .wr_burst_len     (wr_burst_len   ),
  .wr_ready         (wr_ready       ),
  .wr_fifo_re       (wr_fifo_re     ),
  .wr_fifo_data     (wr_fifo_data   ),
  .wr_burst_finish  (wr_burst_finish),
  //连接到axi读主机                 
  .rd_burst_req     (rd_burst_req   ),
  .rd_burst_addr    (rd_burst_addr  ),
  .rd_burst_len     (rd_burst_len   ),
  .rd_ready         (rd_ready       ),
  .rd_fifo_we       (rd_fifo_we     ),
  .rd_fifo_data     (rd_fifo_data   ),
  .rd_burst_finish  (rd_burst_finish)
);

//------------- axi_master_write_inst -------------
axi_master_write axi_master_write_inst
(
  .ARESETN      (~ui_rst         ), //axi复位
  .ACLK         (ui_clk          ), //axi总时钟
  .M_AXI_AWID   (M_AXI_WR_awid   ), //写地址ID
  .M_AXI_AWADDR (M_AXI_WR_awaddr ), //写地址
  .M_AXI_AWLEN  (M_AXI_WR_awlen  ), //突发长度 
  .M_AXI_AWSIZE (M_AXI_WR_awsize ), //突发大小  
  .M_AXI_AWBURST(M_AXI_WR_awburst), //突发类型  
  .M_AXI_AWLOCK (M_AXI_WR_awlock ), //总线锁信号 
  .M_AXI_AWCACHE(M_AXI_WR_awcache), //内存类型
  .M_AXI_AWPROT (M_AXI_WR_awprot ), //保护类型
  .M_AXI_AWQOS  (M_AXI_WR_awqos  ), //质量服务QoS     
  .M_AXI_AWVALID(M_AXI_WR_awvalid), //有效信号
  .M_AXI_AWREADY(M_AXI_WR_awready), //握手信号awready
 
  .M_AXI_WDATA (M_AXI_WR_wdata   ), //写数据
  .M_AXI_WSTRB (M_AXI_WR_wstrb   ), //写数据有效的字节线
  .M_AXI_WLAST (M_AXI_WR_wlast   ), //表明此次传输是最后一个突发传输
  .M_AXI_WVALID(M_AXI_WR_wvalid  ), //写有效
  .M_AXI_WREADY(M_AXI_WR_wready  ), //表明从机可以接收写数据                         
  
  .M_AXI_BID   (M_AXI_WR_bid     ), //写响应ID TAG
  .M_AXI_BRESP (M_AXI_WR_bresp   ), //写响应
  .M_AXI_BVALID(M_AXI_WR_bvalid  ), //写响应有效
  .M_AXI_BREADY(M_AXI_WR_bready  ), //表明主机能够接收写响应  
  
  .WR_START    (wr_burst_req     ), //写突发触发信号
  .WR_ADRS     (wr_burst_addr    ), //地址  
  .WR_LEN      (wr_burst_len     ), //长度
  .WR_READY    (wr_ready         ), //写空闲
  .WR_FIFO_RE  (wr_fifo_re       ), //连接到写fifo的读使能
  .WR_FIFO_DATA(wr_fifo_data     ), //连接到fifo的读数据
  .WR_DONE     (wr_burst_finish  )  //完成一次突发              
);
 
//------------- axi_master_read_inst -------------    
axi_master_read axi_master_read_inst
(
  . ARESETN      (~ui_rst),
  . ACLK         (ui_clk),
  . M_AXI_ARID   (M_AXI_RD_arid   ), //读地址ID
  . M_AXI_ARADDR (M_AXI_RD_araddr ), //读地址
  . M_AXI_ARLEN  (M_AXI_RD_arlen  ), //突发长度
  . M_AXI_ARSIZE (M_AXI_RD_arsize ), //突发大小
  . M_AXI_ARBURST(M_AXI_RD_arburst), //突发类型
  . M_AXI_ARLOCK (M_AXI_RD_arlock ), //总线锁信号
  . M_AXI_ARCACHE(M_AXI_RD_arcache), //内存类型
  . M_AXI_ARPROT (M_AXI_RD_arprot ), //保护类型
  . M_AXI_ARQOS  (M_AXI_RD_arqos  ), //质量服务QOS
  . M_AXI_ARVALID(M_AXI_RD_arvalid), //有效信号
  . M_AXI_ARREADY(M_AXI_RD_arready), //握手信号arready
  
  . M_AXI_RID   (M_AXI_RD_rid   ), //读ID tag
  . M_AXI_RDATA (M_AXI_RD_rdata ), //读数据
  . M_AXI_RRESP (M_AXI_RD_rresp ), //读响应,表明读传输的状态
  . M_AXI_RLAST (M_AXI_RD_rlast ), //表明读突发的最后一次传输
  . M_AXI_RVALID(M_AXI_RD_rvalid), //表明此通道信号有效
  . M_AXI_RREADY(M_AXI_RD_rready), //表明主机能够接收读数据和响应信息

  . RD_START    (rd_burst_req   ), //读突发触发信号
  . RD_ADRS     (rd_burst_addr  ), //地址  
  . RD_LEN      (rd_burst_len   ), //长度
  . RD_READY    (rd_ready       ), //读空闲
  . RD_FIFO_WE  (rd_fifo_we     ), //连接到读fifo的写使能
  . RD_FIFO_DATA(rd_fifo_data   ), //连接到读fifo的写数据
  . RD_DONE     (rd_burst_finish)  //完成一次突发
);

//------------- u_axi_ddr -------------
//xilinx提供的mig ip核,开启axi4接口

axi_ddr  u_axi_ddr
(
  .ddr3_dq   (ddr3_dq   ),     //数据线
  .ddr3_dqs_n(ddr3_dqs_n),     //数据选取脉冲差分信号
  .ddr3_dqs_p(ddr3_dqs_p),     //数据选取脉冲差分信号
  .ddr3_addr (ddr3_addr ),     //地址线
  .ddr3_ba   (ddr3_ba   ),     //bank线
  .ddr3_ras_n(ddr3_ras_n),     //行使能信号,低电平有效
  .ddr3_cas_n(ddr3_cas_n),     //列使能信号,低电平有效
  .ddr3_we_n (ddr3_we_n ),     //写使能信号,低电平有效
  .ddr3_reset_n(ddr3_reset_n), //ddr3复位
  .ddr3_ck_p (ddr3_ck_p ),     //ddr3差分时钟
  .ddr3_ck_n (ddr3_ck_n ),     //ddr3差分时钟
  .ddr3_cke  (ddr3_cke  ),     //ddr3时钟使能信号
  .ddr3_cs_n (ddr3_cs_n ),     //ddr3片选信号
  .ddr3_dm   (ddr3_dm   ),     //ddr3掩码
  .ddr3_odt  (ddr3_odt  ),     //odt阻抗
  
  .sys_clk_i(ddr3_clk),        //ip核时钟
//  .clk_ref_i(ddr3_clk),        //ip核参考时钟
  .ui_clk   (ui_clk),          //用户端口时钟
  .ui_clk_sync_rst(ui_rst),    //复位
  .mmcm_locked(),
  .aresetn    (sys_rst_n),    //异步复位
  .app_sr_req ('b0),
  .app_ref_req('b0),
  .app_zq_req ('b0),
  .app_sr_active(),
  .app_ref_ack(),
  .app_zq_ack(),
  //axi写通道地址与控制信号
  .s_axi_awid    (M_AXI_WR_awid   ), //写地址ID                        输入[3:0]
  .s_axi_awaddr  (M_AXI_WR_awaddr ), //写地址                          输入[29:0]
  .s_axi_awlen   (M_AXI_WR_awlen  ), //突发长度                        输入[7:0]
  .s_axi_awsize  (M_AXI_WR_awsize ), //突发大小                        输入[2:0]
  .s_axi_awburst (M_AXI_WR_awburst), //突发类型                        输入[1:0]
  .s_axi_awlock  (M_AXI_WR_awlock ), //总线锁信号                      输入[0:0]
  .s_axi_awcache (M_AXI_WR_awcache), //内存类型                        输入[3:0]
  .s_axi_awprot  (M_AXI_WR_awprot ), //保护类型                        输入[2:0]
  .s_axi_awqos   (M_AXI_WR_awqos  ), //质量服务QoS                     输入[3:0]
  .s_axi_awvalid (M_AXI_WR_awvalid), //有效信号                        输入[0:0]
  .s_axi_awready (M_AXI_WR_awready), //握手信号awready                 输出[0:0]
  //axi写通道数据
  .s_axi_wdata   (M_AXI_WR_wdata  ), //写数据                          输入[63:0]
  .s_axi_wstrb   (M_AXI_WR_wstrb  ), //写数据有效的字节线              输入[7:0]
  .s_axi_wlast   (M_AXI_WR_wlast  ), //表明此次传输是最后一个突发传输  输入[0:0]
  .s_axi_wvalid  (M_AXI_WR_wvalid ), //写有效,表明此次写有效          输入[0:0]
  .s_axi_wready  (M_AXI_WR_wready ), //表明从机可以接收写数据          输出[0:0]
  //axi写通道应答                    
  .s_axi_bid     (M_AXI_WR_bid    ), //写响应ID TAG                    输出[3:0]
  .s_axi_bresp   (M_AXI_WR_bresp  ), //写响应,表明写传输的状态        输出[1:0]
  .s_axi_bvalid  (M_AXI_WR_bvalid ), //写响应有效                      输出[0:0]
  .s_axi_bready  (M_AXI_WR_bready ), //表明主机能够接收写响应          输入[0:0]
  //axi读通道地址与控制信号                                            
  .s_axi_arid    (M_AXI_RD_arid   ), //读地址ID                        输入[3:0]
  .s_axi_araddr  (M_AXI_RD_araddr ), //读地址                          输入[29:0]
  .s_axi_arlen   (M_AXI_RD_arlen  ), //突发长度                        输入[7:0]
  .s_axi_arsize  (M_AXI_RD_arsize ), //突发大小                        输入[2:0]
  .s_axi_arburst (M_AXI_RD_arburst), //突发类型                        输入[1:0]
  .s_axi_arlock  (M_AXI_RD_arlock ), //总线锁信号                      输入[0:0]
  .s_axi_arcache (M_AXI_RD_arcache), //内存类型                        输入[3:0]
  .s_axi_arprot  (M_AXI_RD_arprot ), //保护类型                        输入[2:0]
  .s_axi_arqos   (M_AXI_RD_arqos  ), //质量服务QOS                     输入[3:0]
  .s_axi_arvalid (M_AXI_RD_arvalid), //有效信号                        输入[0:0]
  .s_axi_arready (M_AXI_RD_arready), //握手信号arready                 输出[0:0]
  //axi读通道数据,包括应答          
  .s_axi_rid     (M_AXI_RD_rid    ), //读ID tag                        输出[3:0]  
  .s_axi_rdata   (M_AXI_RD_rdata  ), //读数据                          输出[63:0]
  .s_axi_rresp   (M_AXI_RD_rresp  ), //读响应,表明读传输的状态        输出[1:0]
  .s_axi_rlast   (M_AXI_RD_rlast  ), //表明读突发的最后一次传输        输出[0:0]
  .s_axi_rvalid  (M_AXI_RD_rvalid ), //表明此通道信号有效              输出[0:0]
  .s_axi_rready  (M_AXI_RD_rready ), //表明主机能够接收读数据          输入[0:0]
                                     
  .init_calib_complete(calib_done) , //ip核初始化完成
  .sys_rst(sys_rst_n)                //ip核复位
);

endmodule

posted @ 2024-06-19 20:14  言知木  阅读(973)  评论(0编辑  收藏  举报