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

📄 sd_cmd_serial_host.v

📁 SD卡控制器IP. 兼容SD卡协议2.0。与wishbone bus 接口
💻 V
字号:
`include "SD_defines.v"
//-------------------------
//-------------------------
module CMD_SERIAL_HOST ( SD_CLK_IN, RST_IN, SETTING_IN,GO_IDLE ,CMD_IN, REQ_IN, ACK_OUT, REQ_OUT,ACK_IN, CMD_OUT, STATUS, cmd_dat_i, cmd_out_o, cmd_oe_o, st_dat_t);
//---------------Input ports---------------
input SD_CLK_IN;
input  RST_IN;
input [15:0] SETTING_IN;   
input GO_IDLE;                         
input [39:0] CMD_IN;
input   REQ_IN;
input ACK_IN;
input cmd_dat_i;

//---------------Output ports---------------
output [39:0] CMD_OUT;
output ACK_OUT;
output REQ_OUT;
output [15:0] STATUS;
output reg cmd_oe_o; 
output reg cmd_out_o;
output reg [1:0] st_dat_t;
//---------------Input ports Data Type------  
wire SD_CLK_IN;
wire RST_IN;
wire [15:0] SETTING_IN;
wire [39:0] CMD_IN;
wire REQ_IN;
wire ACK_IN;
wire GO_IDLE;
//---------------Output ports Data Type------  
reg  [39:0] CMD_OUT;
wire ACK_OUT  ;
reg  [15:0] STATUS;
reg  REQ_OUT;

//-------------Internal Constant-------------

`ifdef SIM
 `define INIT_DELAY 2
`else
  `define INIT_DELAY 64
 `endif
  
`define NCR 2 
parameter SEND_SIZE = 48;
parameter SIZE = 10;
parameter CONTENT_SIZE = 40;
parameter 
    INIT   =  10'b0000_0000_01,
    IDLE   =  10'b0000_0000_10,
    WRITE_WR	    =  10'b0000_0001_00,
    DLY_WR       =  10'b0000_0010_00,
    READ_WR      =  10'b0000_0100_00,
	  DLY_READ    	=  10'b0000_1000_00, 
 	  ACK_WR		     =  10'b0001_0000_00, 
	  WRITE_WO	    =  10'b0010_0000_00, 
	  DLY_WO	      =  10'b0100_0000_00, 
	  ACK_WO	      =  10'b1000_0000_00;
parameter Read_Delay = 7;	
parameter EIGHT_PAD = 8;
//---------------Internal variable----------- 
//-Internal settings/buffers
reg [6:0] Response_Size;
reg [2:0] Delay_Cycler;
reg [CONTENT_SIZE-1:0] In_Buff; 
reg [39:0] Out_Buff;
//-Internal State input
reg Write_Read;
reg Write_Only; 

//-CRC
reg [4:0] word_select_counter;
reg CRC_RST;
reg [6:0]CRC_IN;
wire [6:0] CRC_VAL; 
reg CRC_Enable;
reg CRC_OUT;
reg CRC_Check_On;
reg Crc_Buffering;
reg CRC_Valid;
//-Internal Counterns
  //6 bit sent counter
reg [7:0]Cmd_Cnt; //8 bit recive counter
reg [2:0]Delay_Cnt; //3 bit Delay counter
//-State Variable
reg [SIZE-1:0] state;
reg [SIZE-1:0] next_state;
//Misc
`define Vector_Index  (CONTENT_SIZE-1-Cmd_Cnt) 
`define Bit_Nr (SEND_SIZE-Cmd_Cnt)
	
//TRI-STATE
reg block_write;
reg block_read;


//
reg [1:0]word_select;
reg FSM_ACK;
reg DECODER_ACK;

reg q;
reg Req_internal_in;
reg q1;
reg Ack_internal_in;
//------------------------------------------   
CRC_7 CRC_7( 
CRC_OUT,
CRC_Enable,
SD_CLK_IN,
CRC_RST,
CRC_VAL);
//------------------------------------------  
always @ (state or Delay_Cnt or Write_Read or Cmd_Cnt or Write_Only or Ack_internal_in or  cmd_dat_i or Response_Size or Delay_Cycler)
begin : FSM_COMBO
 next_state  = 0;   
case(state)  
INIT: begin
  if (Cmd_Cnt >= `INIT_DELAY )begin
     next_state = IDLE;
  end
 
  else begin
     
      next_state = INIT;
  end
  
end

                                                
IDLE: begin        
	 if (Write_Read ) begin 
        next_state = WRITE_WR;
      end   
      else if (Write_Only  ) begin
        next_state = WRITE_WO;
      end
      else begin
         next_state = IDLE;
      end
end
WRITE_WR: 
      if (Cmd_Cnt >=SEND_SIZE-1) begin
        next_state = DLY_WR;
      end      
      else begin
        next_state = WRITE_WR; 
      end 
WRITE_WO: 
      if (Cmd_Cnt >= SEND_SIZE-1) begin
        next_state = DLY_WO;
      end      
      else begin
        next_state = WRITE_WO; 
      end 	  
DLY_WR : 
      if ( (Delay_Cnt >= `NCR) && ( !cmd_dat_i)) begin
        next_state = READ_WR;
      end      
      else begin
        next_state = DLY_WR; 
      end 	  
DLY_WO :
       if (Delay_Cnt >= Delay_Cycler) begin
        next_state = ACK_WO;
      end      
      else begin
        next_state = DLY_WO; 
      end 
READ_WR : 
      if (Cmd_Cnt >= (Response_Size+EIGHT_PAD)) begin
        next_state = DLY_READ;
      end      
      else begin
        next_state = READ_WR; 
      end 
		
ACK_WO : 
      next_state = IDLE; 
             
DLY_READ :
     if (Ack_internal_in ) begin
        next_state = ACK_WR;
      end      
      else begin
        next_state = DLY_READ; 
      end 	  
      
ACK_WR  :
        next_state = IDLE; 


default : next_state  = INIT;
 
 endcase     
end 
  //----
    	 
always @ (posedge SD_CLK_IN or posedge RST_IN or posedge GO_IDLE)
begin
	if  (RST_IN || GO_IDLE) begin
		Req_internal_in <=1'b0;
		q <=1'b0;
	end
	else begin  
		q<=REQ_IN;
		Req_internal_in<=q;
	end


end

always @ (posedge SD_CLK_IN or posedge RST_IN or posedge GO_IDLE)
begin
	if  (RST_IN || GO_IDLE) begin
		Ack_internal_in <=1'b0;
		q1 <=1'b0;
	end
	else begin  
		q1<=ACK_IN;
		Ack_internal_in<=q1;
	end


end





		 
		 
always @ (posedge SD_CLK_IN or posedge RST_IN or posedge GO_IDLE )
  begin:COMMAND_DECODER
  if (RST_IN || GO_IDLE ) begin
		  Delay_Cycler <=3'b0;
		  Response_Size <=7'b0; 
		  DECODER_ACK <= 1;
		  Write_Read<=1'b0;
	    Write_Only<=1'b0;
	    CRC_Check_On <=0;
	    In_Buff <=0;
	    block_write<=0;
	    block_read <=0;
	    word_select<=0;
   end
   else begin
			if (Req_internal_in == 1) begin
				Response_Size[6:0] <=  SETTING_IN [6:0];
				CRC_Check_On <= SETTING_IN [7];
				Delay_Cycler[2:0] <= SETTING_IN [10:8];
				block_write <= SETTING_IN [11];
				block_read <= SETTING_IN [12];
				word_select <=SETTING_IN [14:13];
				In_Buff <= CMD_IN;
				DECODER_ACK<=0;	
				if (SETTING_IN [6:0]>0) begin
				   Write_Read<=1'b1;
				   Write_Only<=1'b0;
				end
				else begin
					Write_Read<=1'b0;
				  Write_Only<=1'b1;
				end
			end
			else begin
				Write_Read<=1'b0;
				Write_Only<=1'b0;
				DECODER_ACK <= 1;			
			end	
    end
 end
//End block COMMAND_DECODER  

//-------Function for Combo logic-----------------



assign ACK_OUT = FSM_ACK & DECODER_ACK;

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

//-------------OUTPUT_LOGIC-------
always @ (posedge SD_CLK_IN or posedge RST_IN or posedge GO_IDLE   )
begin : OUTPUT_LOGIC
 if (RST_IN || GO_IDLE ) begin    
    CRC_Enable=0;
    word_select_counter<=0;
    Delay_Cnt =0;
   	cmd_oe_o=1; 		
    cmd_out_o = 1;  
  	 Out_Buff =0;
   	FSM_ACK=1;
	  REQ_OUT =0;
	  CRC_RST =1;
	  CRC_OUT =0;
	  CRC_IN =0;
	  CMD_OUT =0;	
   	Crc_Buffering =0; 
   	STATUS = 0;
   	CRC_Valid=0;
   	Cmd_Cnt=0;
   	st_dat_t<=0;
   	if(GO_IDLE) begin
   	   	cmd_oe_o=0; 		
    	cmd_out_o = 0; 
   	end
 end 
 else begin
  case(state)
      INIT : begin
        Cmd_Cnt=Cmd_Cnt+1;
          cmd_oe_o=1; 		
          cmd_out_o = 1;  
      end
    
      IDLE : begin
		  cmd_oe_o=0;      //Put CMD to Z  
      Delay_Cnt =0;
      Cmd_Cnt =0;
		  CRC_RST =1;
		  CRC_Enable=0; 
		  CMD_OUT=0;
		  st_dat_t<=0;
		   word_select_counter<=0;
	  end  
	
	WRITE_WR:   begin 
	   FSM_ACK=0;
       CRC_RST =0;
	   CRC_Enable=1;  
     
   
    
     if (Cmd_Cnt==0) begin
       STATUS = 16'b0000_0000_0000_0001;
       REQ_OUT=1;
     end 
     else if (Ack_internal_in) begin
       REQ_OUT=0;
     end 
         
        //Wait one cycle before sending, for setting up the CRC unit.
     if (Crc_Buffering==1)  begin
        cmd_oe_o =1;
        if (`Bit_Nr > 8 ) begin  // 1->40 CMD, (41 >= CNT && CNT <=47) CRC, 48 stop_bit
				   cmd_out_o = In_Buff[`Vector_Index]; 
				   if (`Bit_Nr > 9 ) begin //1 step ahead
			       CRC_OUT = In_Buff[`Vector_Index-1];
			     end else begin
			       CRC_Enable=0;  
				   end    
			  end
			  else if ( (`Bit_Nr <=8) && (`Bit_Nr >=2) ) begin			 	
				  CRC_Enable=0; 
				  cmd_out_o = CRC_VAL[(`Bit_Nr)-2];	
				  
		    	  if (block_read & block_write)
		    	    st_dat_t<=2'b11;
		    	  else  if  (block_read)
		    	    st_dat_t<=2'b10;    				
			  end
			  else begin        
				  cmd_out_o =1'b1;
			  end		
			  Cmd_Cnt = Cmd_Cnt+1 ;
		end		
	  else begin //Pre load CRC
		    Crc_Buffering=1;
	   	  CRC_OUT = In_Buff[`Vector_Index];
	  end	  
 	end 	

	WRITE_WO:  begin 
	   FSM_ACK=0;
     CRC_RST =0;
	   CRC_Enable=1;  
         
    
     if (Cmd_Cnt==0) begin
       STATUS[3:0] = 16'b0000_0000_0000_0010;
       REQ_OUT=1;
     end 
     else if (Ack_internal_in) begin
       REQ_OUT=0;
     end 
       
    
        
        //Wait one cycle before sending, for setting up the CRC unit.
     if (Crc_Buffering==1)  begin
        cmd_oe_o =1;  
        if (`Bit_Nr > 8 ) begin  // 1->40 CMD, (41 >= CNT && CNT <=47) CRC, 48 stop_bit
			     cmd_out_o = In_Buff[`Vector_Index]; 
			     if (`Bit_Nr > 9 ) begin //1 step ahead
			        CRC_OUT = In_Buff[`Vector_Index-1];
			     end 
           else begin
			        CRC_Enable=0;  
			     end    
		    end
		    else if( (`Bit_Nr <=8) && (`Bit_Nr >=2) ) begin			 	
			     CRC_Enable=0; 
		       cmd_out_o = CRC_VAL[(`Bit_Nr)-2];	
		       if  (block_read)
		    	    st_dat_t<=2'b10;			
		    end		 
	  	   else begin        
		  	    cmd_out_o =1'b1;
		    end		
			  Cmd_Cnt = Cmd_Cnt+1;	
		end		
		else begin //Pre load CRC
		   Crc_Buffering=1;
	   	 CRC_OUT = In_Buff[`Vector_Index];
	  end	  
 	end 	
	
	DLY_WR :  begin 
	   if (Delay_Cnt==0) begin
         STATUS[3:0] = 4'b0011;
         REQ_OUT=1;
      end  
      else if (Ack_internal_in) begin
       REQ_OUT=0;
     end      
		  CRC_Enable=0;
		  CRC_RST =1;
		  Cmd_Cnt = 1; 
		  cmd_oe_o=0; 	
		  if (Delay_Cnt<3'b111)
		    Delay_Cnt =Delay_Cnt+1;  
		  Crc_Buffering=0;
    end
	
    DLY_WO :  begin  
      if (Delay_Cnt==0) begin
         STATUS[3:0] = 4'b0100;
         STATUS[5] = 0;
         STATUS[6] = 1;
         REQ_OUT=1;
      end  
      else if (Ack_internal_in) begin
       REQ_OUT=0;
     end   
		  CRC_Enable=0;
		  CRC_RST =1;
		  Cmd_Cnt = 0; 
		  cmd_oe_o=0;
	    Delay_Cnt =Delay_Cnt+1;  
	    Crc_Buffering=0;     
    end	
    
    READ_WR :  begin
      Delay_Cnt =0;
      CRC_RST =0;
	    CRC_Enable=1;        
      cmd_oe_o =0;
      
	   if (Cmd_Cnt==1) begin
       STATUS[3:0] = 16'b0000_0000_0000_0101;
       REQ_OUT=1;
       Out_Buff[39]=0; //startbit (0)
     end 
     else if (Ack_internal_in) begin
       REQ_OUT=0;
     end  
	     
	     
	     
      if (Cmd_Cnt < (Response_Size))begin
        
        if (Cmd_Cnt<8 ) //1+1+6 (S,T,Index)          
          Out_Buff[39-Cmd_Cnt] = cmd_dat_i; 
        else begin
          
          if (word_select == 2'b00) begin
            if(Cmd_Cnt<40) begin
		          word_select_counter<= word_select_counter+1;
		          Out_Buff[31-word_select_counter] = cmd_dat_i;
		         end 
		      end    
          else if (word_select == 2'b01) begin
            if ( (Cmd_Cnt>=40) && (Cmd_Cnt<72) )begin
		          word_select_counter<= word_select_counter+1;
		          Out_Buff[31-word_select_counter] = cmd_dat_i;
		         end 
		      
		      end 
          else if  (word_select == 2'b10) begin
           if ( (Cmd_Cnt>72) && (Cmd_Cnt<104) )begin
		          word_select_counter<= word_select_counter+1;
		          Out_Buff[31-word_select_counter] = cmd_dat_i;
		         end 
		      end	     
          else if  (word_select == 2'b11) begin
           if ( (Cmd_Cnt>104) && (Cmd_Cnt<126) )begin
		          word_select_counter<= word_select_counter+1;
		          Out_Buff[31-word_select_counter] = cmd_dat_i;
		         end 
		      end	  
          
          
		    end
		    CRC_OUT = cmd_dat_i;  
		        
      end       
      else if ( Cmd_Cnt - Response_Size <=6 ) begin
			  CRC_IN [(Response_Size+6)-(Cmd_Cnt)] = cmd_dat_i;
			  CRC_Enable=0;  
      end
      else begin
			   if ((CRC_IN != CRC_VAL) && ( CRC_Check_On == 1)) begin
				   CRC_Valid=0;	
				   CRC_Enable=0;			  			
		    	end  
		    	else begin
		    	CRC_Valid=1;
		    	CRC_Enable=0;
		    	end 
		    	if (block_read & block_write)
		    	    st_dat_t<=2'b11;
		    	else if (block_write)
		    	  st_dat_t<=2'b01;
		    	 
      end        
       Cmd_Cnt = Cmd_Cnt+1;
   end
    
   DLY_READ:  begin
     
     if (Delay_Cnt==0) begin
       STATUS[3:0] = 4'b0110;
       STATUS[5] = CRC_Valid;
       STATUS[6] = 1;
       REQ_OUT=1;
     end 
     else if (Ack_internal_in) begin
       REQ_OUT=0;
     end  
        
		  CRC_Enable=0;
		  CRC_RST =1;
		  Cmd_Cnt = 0; 		 
		  cmd_oe_o=0; 
      
      CMD_OUT[39:0]=Out_Buff;
		  Delay_Cnt =Delay_Cnt+1;       
    end	
    
	ACK_WO:  begin    
		  FSM_ACK=1;
    end	
	
	ACK_WR:  begin    
		  FSM_ACK=1;
		  REQ_OUT =0;	
		
    end	
	
   endcase
  end
end
  
  
endmodule


⌨️ 快捷键说明

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