`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/03/18 16:15:52
// Design Name: 
// Module Name: ddr_axi_rd
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module ddr_axi_rd(
    input           aresetn,        //axi复位
    input           aclk,           //axi时钟
    //axi读通道写地址
    output [3:0]  m_axi_arid   ,    //读地址ID，用来标志一组写信号
    output [32:0] m_axi_araddr ,    //读地址，给出一次写突发传输的读地址
    output [7:0]  m_axi_arlen  ,    //突发长度，给出突发传输的次数
    output [2:0]  m_axi_arsize ,    //突发大小，给出每次突发传输的字节数
    output [1:0]  m_axi_arburst,    //突发类型
    output [0: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 [32: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 [32: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[32:0] = reg_rd_adrs[32: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[32:0] <= 33'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[32:0] <= rd_adrs[32: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