⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd_data_master.v

📁 SD卡控制器IP. 兼容SD卡协议2.0。与wishbone bus 接口
💻 V
字号:
`include "SD_defines.v"

module SD_DATA_MASTER (
  input clk,
  input rst,
  //Tx Bd
  input new_tx_bd,
  input [`RAM_MEM_WIDTH-1:0] dat_in_tx,
  input [`BD_WIDTH-1:0] free_tx_bd,
  input ack_i_s_tx,
  output reg re_s_tx,
  output reg a_cmp_tx,
  //Rx Bd
  input new_rx_bd,
  input [`RAM_MEM_WIDTH-1:0] dat_in_rx,
  input [`BD_WIDTH-1:0] free_rx_bd,
  input ack_i_s_rx,
  output reg re_s_rx,
  output reg a_cmp_rx,
  //Input from SD-Host Reg
  input  cmd_busy, //STATUS_REG[0] and mux  
  //Output to SD-Host Reg
  output reg we_req,
  input we_ack,
  output reg d_write,
  output reg d_read,
  output reg [31:0] cmd_arg,
  output reg [15:0] cmd_set,
  input cmd_tsf_err,
  input [4:0] card_status,
  //To fifo filler
  output reg start_tx_fifo,
  output reg start_rx_fifo,
  output reg [31:0] sys_adr,
  input tx_empt,
  input rx_full,
  //SD-DATA_Host
  input busy_n     ,
  input transm_complete ,
  input crc_ok,
  output reg ack_transfer, 
  //status output
  output reg  [7:0] bd_int_st ,
  input bd_int_st_rst,
  output reg  CIDAT
  
    
  );
`define BD_EMPTY (`BD_SIZE  /4) 
`ifdef RAM_MEM_WIDTH_32
      `define READ_CYCLE 2
       reg bd_cnt  ;
`else `ifdef  RAM_MEM_WIDTH_16
      `define READ_CYCLE 4
       reg [1:0] bd_cnt;
   `endif
`endif 

reg send_done;
reg rec_done;
reg rec_failed;
reg tx_cycle;
reg rx_cycle;
reg [2:0] resend_try_cnt;
`ifdef SIM
parameter CMD24 = 16'h181A ; //11000 0001 1010
parameter CMD17 = 16'h111A; //10001 0001 1010
parameter CMD12 = 16'hC1A ; //01100 0001 1010
`else
parameter CMD24 = 16'h181A;
parameter CMD17 = 16'h111A;
parameter CMD12 = 16'hC1A ;
`endif 
parameter SIZE = 9;
reg [SIZE-1:0] state;
reg [SIZE-1:0] next_state;  
parameter IDLE             =  9'b000000001;
parameter GET_TX_BD        =  9'b000000010;
parameter GET_RX_BD        =  9'b000000100;
parameter SEND_CMD         =  9'b000001000;
parameter RECIVE_CMD       =  9'b000010000;
parameter DATA_TRANSFER    =  9'b000100000;
parameter STOP             =  9'b001000000;
parameter STOP_SEND        =  9'b010000000;
parameter STOP_RECIVE_CMD  =  9'b100000000;

reg trans_done;
reg trans_failed;


always @ (state or free_tx_bd or free_rx_bd or bd_cnt or send_done or rec_done or rec_failed or trans_done or trans_failed)
begin : FSM_COMBO
 next_state  = 0;   
case(state)  
  
  IDLE: begin
   if (free_tx_bd !=`BD_EMPTY)begin
      next_state = GET_TX_BD;
   end
   else if (free_rx_bd !=`BD_EMPTY) begin
      next_state = GET_RX_BD;
   end  
   else begin
      next_state = IDLE;
   end
  end
  GET_TX_BD: begin
    if (bd_cnt>= (`READ_CYCLE-1))begin
     next_state = SEND_CMD;
    end   
    else begin
     next_state = GET_TX_BD;
    end
  end   
  
  GET_RX_BD: begin  
    if (bd_cnt >= (`READ_CYCLE-1))begin
     next_state = SEND_CMD;
    end   
    else begin
     next_state = GET_RX_BD;
    end
  end
  
  SEND_CMD: begin 
   if (send_done)begin
     next_state = RECIVE_CMD;
    end   
    else begin
     next_state = SEND_CMD;
    end 
  end
    
  
 RECIVE_CMD: begin 
    if (rec_done)
      next_state = DATA_TRANSFER;       
    else if (rec_failed)
      next_state =  SEND_CMD;
    else 
      next_state = RECIVE_CMD;    
   end 

  DATA_TRANSFER: begin
    if (trans_done)
      next_state = IDLE;
   else if (trans_failed)
      next_state = STOP;
   else
      next_state = DATA_TRANSFER;
   end
  
  STOP: begin 
     next_state = STOP_SEND;     
   end
   
   STOP_SEND: begin
    if (send_done)begin
     next_state = STOP_RECIVE_CMD;
    end   
    else begin
     next_state = STOP_SEND;
    end  
   end
   
   STOP_RECIVE_CMD : begin
    if (rec_done)
      next_state = SEND_CMD;       
    else if (rec_failed)
      next_state =  STOP;
    else if (resend_try_cnt>=`RESEND_MAX_CNT)
      next_state = IDLE;
    else 
      next_state = STOP_RECIVE_CMD;    
   end 
 
   
 
 default : next_state  = IDLE; 
 endcase

end

//----------------Seq logic------------
always @ (posedge clk or posedge rst   )
begin : FSM_SEQ
  if (rst ) begin
    state <= #1 IDLE;
 end 
 else begin
    state <= #1 next_state;
 end
end



//Output logic-----------------


always @ (posedge clk or posedge rst   )
begin  
 if (rst) begin
      send_done<=0;
      bd_cnt<=0;
      sys_adr<=0;
      cmd_arg<=0;
      rec_done<=0;
      start_tx_fifo<=0;
      start_rx_fifo<=0;
      send_done<=0;
      rec_failed<=0;
      d_write <=0;  
      d_read <=0;  
      trans_failed<=0;
      trans_done<=0;
      tx_cycle <=0;
      rx_cycle <=0;
      ack_transfer<=0;
      a_cmp_tx<=0;           
      a_cmp_rx<=0;
      CIDAT<=0;
      bd_int_st<=0;
      we_req<=0;
      re_s_tx<=0;
      re_s_rx<=0;
      cmd_set<=0;
      resend_try_cnt=0;
 end
 else begin
  case(state)
     IDLE: begin
      send_done<=0;
      bd_cnt<=0;
      sys_adr<=0;
      cmd_arg<=0;
      rec_done<=0;
      rec_failed<=0;
      start_tx_fifo<=0;
      start_rx_fifo<=0;
      send_done<=0;     
      d_write <=0;  
      d_read <=0; 
      trans_failed<=0;
      trans_done<=0;
      tx_cycle <=0;
      rx_cycle <=0;
      ack_transfer<=0;
      a_cmp_tx<=0;           
      a_cmp_rx<=0;
      resend_try_cnt=0;
     end
     
     GET_RX_BD: begin                 
        //0,1,2,3...
      re_s_rx <= 1;
      `ifdef  RAM_MEM_WIDTH_16
      if (ack_i_s_rx) begin        
        if( bd_cnt == 2'b00) begin
           sys_adr [15:0] <= dat_in_rx; end
        else if ( bd_cnt == 2'b01)  begin
           sys_adr [31:16] <= dat_in_rx; end
        else if ( bd_cnt == 2) begin
          cmd_arg [15:0] <= dat_in_rx;
          re_s_rx <= 0; end
        else if ( bd_cnt == 3) begin
           cmd_arg [31:16] <= dat_in_rx;
           re_s_rx <= 0;
            end
         bd_cnt <= bd_cnt+1;
           
     
      end
       `endif
     //Add Later Save last block addres for comparison with current (For multiple block cmd)
     //Add support for Pre-erased
      cmd_set <= CMD17;
      rx_cycle<=1;  
     end
          
     GET_TX_BD:  begin             
        //0,1,2,3...
      re_s_tx <= 1;
      `ifdef  RAM_MEM_WIDTH_16
      if (ack_i_s_tx) begin
        
        if( bd_cnt == 2'b00) begin
           sys_adr [15:0] <= dat_in_tx; end
        else if ( bd_cnt == 2'b01)  begin
           sys_adr [31:16] <= dat_in_tx; end
        else if ( bd_cnt == 2) begin
          cmd_arg [15:0] <= dat_in_tx;
          re_s_tx <= 0; end
        else if ( bd_cnt == 3) begin
           cmd_arg [31:16] <= dat_in_tx;
           re_s_tx <= 0;
            end
         bd_cnt <= bd_cnt+1;   
     
      end
       `endif
     //Add Later Save last block addres for comparison with current (For multiple block cmd)
     //Add support for Pre-erased
      cmd_set <= CMD24;  
      tx_cycle <=1;       
   end  
   
     SEND_CMD : begin  
       rec_done<=0;     
       if (rx_cycle)    begin     
         re_s_rx <=0; 
         d_read<=1;
       end
       else begin
         re_s_tx <=0; 
         d_write<=1;
        end
       start_rx_fifo<=0; //Reset FIFO  
       start_tx_fifo<=0;  //Reset FIFO 
       if (!cmd_busy) begin
         we_req <= 1;  
         
       end  //When send complete change state and wait for reply
       if (we_ack) begin     
           send_done<=1;
           we_req <= 1;  
          
       end       
    end   
   
   
    RECIVE_CMD : begin
         //When waiting for reply fill TX fifo
        if (tx_cycle)
         start_tx_fifo<=1; //start_fifo prebuffering
       else
         start_rx_fifo <=1;
        
         we_req <= 0;  
          
         send_done<=0;
       if (!cmd_busy) begin //Means the sending is completed,
         d_read<=0; 
         d_write<=0;  
         if (!cmd_tsf_err) begin
           if (card_status[0]) begin
               `ifdef SYN
                if ( (card_status[4:1] == 4'b0100) || (card_status[4:1] == 4'b0110) || (card_status[4:1] == 4'b0101) )
                    rec_done<=1;
                else begin
                    rec_failed<=1;
                    bd_int_st[4] <=1; 
                    
                end 
                `endif  
                 
                 `ifdef SIM
                  rec_done<=1;  
                  `endif                       
               //Check card_status[5:1] for state 4 or 6... 
               //If wrong state change interupt status reg,so software can put card in
               // transfer state and restart/cancel Data transfer
          end
         end
         else
             rec_failed<=1;  //CRC-Error, CIC-Error or timeout 
       end  
    end
    
    DATA_TRANSFER: begin
       CIDAT<=1;
     if (tx_cycle) begin 
      if (tx_empt) begin
         bd_int_st[2] <=1;
         trans_failed<=1;  
       end
     end
     else begin 
       if (rx_full) begin
         bd_int_st[2] <=1; 
         trans_failed<=1; 
      end
    end            
      //Check for fifo underflow, 
      //2 DO: if deteced stop transfer, reset data host
      if (transm_complete) begin //Transfer complete
         ack_transfer<=1;
        
         if ((!crc_ok) && (busy_n))  begin //Wrong CRC and Data line free.
            bd_int_st[5] <=1; 
            trans_failed<=1;
         end 
         else if ((crc_ok) && (busy_n)) begin //Data Line free
           trans_done <=1;           
           bd_int_st[0]<=1;
           if (tx_cycle)
            a_cmp_tx<=1;
           else
             a_cmp_rx<=1;
         end  
 
       end
   
  end
  
  STOP: begin
    cmd_set <= CMD12;
    rec_done<=0;
    rec_failed<=0;     
    send_done<=0;  
    trans_failed<=0;
    trans_done<=0;    
    d_read<=1; 
    d_write<=1; 
    start_rx_fifo <=0;
    start_tx_fifo <=0;         
     
  end
   STOP_SEND: begin
      resend_try_cnt=resend_try_cnt+1;
      if (resend_try_cnt==`RESEND_MAX_CNT)
          bd_int_st[1]<=1;
      if (!cmd_busy) 
         we_req <= 1;      
      if (we_ack)      
           send_done<=1;    
   end  
  
   STOP_RECIVE_CMD: begin
     we_req <= 0; 
     if (!cmd_busy) begin //Means the sending is completed,
         if (!cmd_tsf_err) begin
              rec_done<=1;  
              send_done<=0;
              d_read<=0;
              d_write<=0;  
              if (tx_cycle)
                 cmd_set<= CMD24;
              else
                 cmd_set <= CMD17;             
         end
         else
             rec_failed<=1;
      end         
    end 
  
  endcase  
  if (bd_int_st_rst)
    bd_int_st<=0;
 end 
  
end  
  
endmodule 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -