OpenCores
URL https://opencores.org/ocsvn/sdcard_mass_storage_controller/sdcard_mass_storage_controller/trunk

Subversion Repositories sdcard_mass_storage_controller

[/] [sdcard_mass_storage_controller/] [trunk/] [rtl/] [sdc_dma/] [verilog/] [sd_cmd_serial_host.v] - Rev 134

Compare with Previous | Blame | View Log

`include "sd_defines.v"
//-------------------------
//-------------------------
module sd_cmd_serial_host ( SD_CLK_IN, RST_IN, SETTING_IN ,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 [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 [7: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;
 
//---------------Output ports Data Type------  
reg  [39:0] CMD_OUT;
wire ACK_OUT  ;
reg  [7: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;
//------------------------------------------   
sd_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)
begin : REQ_SYNC
	if  (RST_IN ) 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)
begin :ACK_SYNC
	if  (RST_IN ) 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 )
  begin:COMMAND_DECODER
  if (RST_IN ) 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   )
begin : FSM_SEQ
  if (RST_IN ) begin
    state <= #1 INIT;
 end 
 
 else begin
    state <= #1 next_state;
 end
end
 
//-------------OUTPUT_LOGIC-------
always @ (posedge SD_CLK_IN or posedge RST_IN   )
begin : FSM_OUT
 if (RST_IN ) 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;
 
 
 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<128) )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
 
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.