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_fifo/] [verilog/] [sd_controller_fifo_actel.v] - Rev 35

Go to most recent revision | Compare with Previous | Blame | View Log

module sd_controller_fifo_wba
( 
  wb_clk_i, wb_rst_i, wb_dat_i, wb_dat_o, 
  wb_adr_i, wb_sel_i, wb_we_i, wb_cyc_i, wb_stb_i, wb_ack_o, 
  sd_cmd_dat_i,sd_cmd_out_o,  sd_cmd_oe_o, 
  sd_dat_dat_i, sd_dat_out_o , sd_dat_oe_o, sd_clk_o_pad
);
input           wb_clk_i;     
input           wb_rst_i;     
input   [7:0]  wb_dat_i;     
output  [7:0]  wb_dat_o;     
input   [2:0]  wb_adr_i;     
input    [3:0]  wb_sel_i;     
input           wb_we_i;      
input           wb_cyc_i;     
input           wb_stb_i;     
output reg          wb_ack_o;     
input wire [3:0] sd_dat_dat_i;
output wire [3:0] sd_dat_out_o;
output wire sd_dat_oe_o;
input wire sd_cmd_dat_i;
output wire sd_cmd_out_o;
output wire sd_cmd_oe_o;
output sd_clk_o_pad;
wire sd_clk_i;
input sd_clk_i_pad;
reg [7:0] controll_reg;
reg [7:0] status_reg;
reg [7:0] command_timeout_reg;
  assign sd_clk_i = wb_clk_i;
assign sd_clk_o=sd_clk_i;
reg [1:0] wb_fifo_adr_i_writer;
reg [1:0] wb_fifo_adr_i_reader;
wire [1:0] wb_fifo_adr_i;
reg add_token_read;
wire [7:0] wb_fifo_dat_i;
wire [7:0] wb_fifo_dat_o;
reg [7:0]  wb_dat_i_storage;
reg [7:0] wb_dat_o_i;
reg time_enable;
assign sd_clk_o_pad  = sd_clk_i ;
assign wb_fifo_adr_i = add_token_read ? wb_fifo_adr_i_reader : wb_fifo_adr_i_writer;
assign wb_fifo_dat_i =wb_dat_i_storage;
assign wb_dat_o = wb_adr_i[0] ? wb_fifo_dat_o :   wb_dat_o_i ;
wire [1:4]fifo_full ;
wire [1:4]fifo_empty;
reg wb_fifo_we_i;
reg wb_fifo_re_i;
wire [1:0] sd_adr_o;
wire [7:0] sd_dat_o;
wire [7:0] sd_dat_i;
sd_fifo sd_fifo_0
( 
   .wb_adr_i  (wb_fifo_adr_i ),
   .wb_dat_i  (wb_fifo_dat_i),
   .wb_dat_o  (wb_fifo_dat_o ),
   .wb_we_i   (wb_fifo_we_i),
   .wb_re_i   (wb_fifo_re_i),
   .wb_clk  (wb_clk_i),
   .sd_adr_i (sd_adr_o ),
   .sd_dat_i (sd_dat_o),
   .sd_dat_o (sd_dat_i ),
   .sd_we_i (sd_we_o),
   .sd_re_i (sd_re_o),
   .sd_clk (sd_clk_o),
   .fifo_full ( fifo_full ),
   .fifo_empty (fifo_empty    ),
   .rst (wb_rst_i) 
  ) ; 
wire [1:0] sd_adr_o_cmd;
wire [7:0] sd_dat_i_cmd;
wire [7:0] sd_dat_o_cmd;
wire [1:0] sd_adr_o_dat;
wire [7:0] sd_dat_i_dat;
wire [7:0] sd_dat_o_dat;
wire [1:0] st_dat_t;
sd_cmd_phy sdc_cmd_phy_0
(
  .sd_clk (sd_clk_o),
  .rst (wb_rst_i ),
  .cmd_dat_i ( sd_cmd_dat_i  ),
  .cmd_dat_o (sd_cmd_out_o   ),
  .cmd_oe_o (sd_cmd_oe_o   ),  
  .sd_adr_o (sd_adr_o_cmd),
  .sd_dat_i (sd_dat_i_cmd),
  .sd_dat_o (sd_dat_o_cmd),
  .sd_we_o (sd_we_o_cmd),
  .sd_re_o (sd_re_o_cmd),
  .fifo_full ( fifo_full[1:2] ),
  .fifo_empty ( fifo_empty [1:2]),
  .start_dat_t (st_dat_t),
  .fifo_acces_token (fifo_acces_token)
  ); 
  sd_data_phy sd_data_phy_0 (
  .sd_clk (sd_clk_o),
  .rst (wb_rst_i | controll_reg[0]),
  .DAT_oe_o ( sd_dat_oe_o  ),
  .DAT_dat_o (sd_dat_out_o),
  .DAT_dat_i  (sd_dat_dat_i ),
  .sd_adr_o (sd_adr_o_dat   ),
  .sd_dat_i (sd_dat_i_dat  ),
  .sd_dat_o (sd_dat_o_dat  ),
  .sd_we_o  (sd_we_o_dat),
  .sd_re_o (sd_re_o_dat),
  .fifo_full ( fifo_full[3:4] ),
  .fifo_empty ( fifo_empty [3:4]),
  .start_dat (st_dat_t),
  .fifo_acces (~fifo_acces_token)  
  ); 
  assign sd_adr_o =  fifo_acces_token ? sd_adr_o_cmd : sd_adr_o_dat; 
  assign sd_dat_o =  fifo_acces_token ? sd_dat_o_cmd : sd_dat_o_dat;
  assign sd_we_o  = fifo_acces_token ? sd_we_o_cmd : sd_we_o_dat;
  assign sd_re_o  =  fifo_acces_token ? sd_re_o_cmd : sd_re_o_dat;
 assign sd_dat_i_dat = sd_dat_i;
 assign sd_dat_i_cmd = sd_dat_i;
  always @(posedge wb_clk_i or posedge wb_rst_i)
	begin
	if (wb_rst_i)
	    status_reg<=0;
	  else begin	
      status_reg[0] <= fifo_full[1];
      status_reg[1] <= fifo_empty[2];
      status_reg[2] <=  fifo_full[3];
      status_reg[3] <=  fifo_empty[4];
    end
  end
  reg delayed_ack;
  always @(posedge wb_clk_i or posedge wb_rst_i)
	begin	
	  if (wb_rst_i) 
	    wb_ack_o <=0; 
	   else 
	     wb_ack_o <=wb_stb_i & wb_cyc_i &  ~wb_ack_o & delayed_ack;
	end
  always @(posedge wb_clk_i or posedge wb_rst_i)
	begin	
    if ( wb_rst_i )begin
	    command_timeout_reg<=255;
	    wb_dat_i_storage<=0;
	    controll_reg<=0;
	    wb_fifo_we_i<=0;
	    wb_fifo_adr_i_writer<=0;
	    time_enable<=0;
	  end
	  else if (wb_stb_i  & wb_cyc_i & (~wb_ack_o))begin 
	    if (wb_we_i) begin
	      case (wb_adr_i) 
	      4'h0 : begin
	        wb_fifo_adr_i_writer<=0;
	        wb_fifo_we_i<=1&!delayed_ack;
	        wb_dat_i_storage<=wb_dat_i;	       
	        command_timeout_reg<=255;
	        time_enable<=1;
	      end       
        4'h2 : begin
	        wb_fifo_adr_i_writer<=2;
	        wb_fifo_we_i<=1&!delayed_ack;
	        wb_dat_i_storage<=wb_dat_i;
	        command_timeout_reg<=255;
	        time_enable<=0;
	      end        
        4'h5 : controll_reg <= wb_dat_i;
  	      endcase
	    end  	  
	   end
	   else begin
	      wb_fifo_we_i<=0;
	     if (!status_reg[1])
	       time_enable<=0; 
	     if ((command_timeout_reg!=0) && (time_enable))
	         command_timeout_reg<=command_timeout_reg-1;   
	   end   
end
always @(posedge wb_clk_i or posedge wb_rst_i )begin
   if ( wb_rst_i) begin
     add_token_read<=0;
     delayed_ack<=0;
     wb_fifo_re_i<=0;
      wb_fifo_adr_i_reader<=0;
      wb_dat_o_i<=0;
  end 
 else begin  
    delayed_ack<=0;
    wb_fifo_re_i<=0;
   if (wb_stb_i  & wb_cyc_i & (~wb_ack_o)) begin 
   delayed_ack<=delayed_ack+1;
    add_token_read<=0;
    if (!wb_we_i) begin
      case (wb_adr_i)
      4'h1 : begin
         add_token_read<=1;
         wb_fifo_adr_i_reader<=1;
	      wb_fifo_re_i<=1&delayed_ack; 
      end
      4'h3 :begin
         add_token_read<=1;
         wb_fifo_adr_i_reader<=3;
	       wb_fifo_re_i<=1 & delayed_ack;
     end 
      4'h4 : wb_dat_o_i <= status_reg;
      4'h6 : wb_dat_o_i <= command_timeout_reg;
     endcase
    end
  end  
end
end
 assign m_wb_adr_o =0;
 assign m_wb_sel_o =0; 
 assign m_wb_we_o=0;
 assign m_wb_dat_o =0;
 assign m_wb_cyc_o=0;
 assign m_wb_stb_o=0;
 assign m_wb_cti_o=0;
 assign m_wb_bte_o=0;
endmodule
module sd_counter
  (
    output reg [9:1] q,
    output [9:1]    q_bin,
    input cke,
    input clk,
    input rst
   );
   reg [9:1] qi;
   wire [9:1] q_next;   
   assign q_next =
   qi + 9'd1;
   always @ (posedge clk or posedge rst)
     if (rst)
       qi <= 9'd0;
     else
   if (cke)
     qi <= q_next;
   always @ (posedge clk or posedge rst)
     if (rst)
       q <= 9'd0;
     else
       if (cke)
	 q <= (q_next>>1) ^ q_next;
   assign q_bin = qi;
endmodule
module CRC_7(BITVAL, Enable, CLK, RST, CRC);
   input        BITVAL;
   input Enable;
   input        CLK;                           
   input        RST;                             
   output [6:0] CRC;                               
   reg    [6:0] CRC;   
   wire         inv;
   assign inv = BITVAL ^ CRC[6];                   
    always @(posedge CLK or posedge RST) begin
		if (RST) begin
			CRC = 0;   
        end
		else begin
			if (Enable==1) begin
				CRC[6] = CRC[5];
				CRC[5] = CRC[4];
				CRC[4] = CRC[3];
				CRC[3] = CRC[2] ^ inv;
				CRC[2] = CRC[1];
				CRC[1] = CRC[0];
				CRC[0] = inv;
			end
		end
     end
endmodule
module CRC_16(BITVAL, Enable, CLK, RST, CRC);
 input        BITVAL;
   input Enable;
   input        CLK;                           
   input        RST;                             
   output reg [15:0] CRC;                               
   wire         inv;
   assign inv = BITVAL ^ CRC[15];                   
  always @(posedge CLK or posedge RST) begin
		if (RST) begin
			CRC = 0;   
        end
      else begin
        if (Enable==1) begin
         CRC[15] = CRC[14];
         CRC[14] = CRC[13];
         CRC[13] = CRC[12];
         CRC[12] = CRC[11] ^ inv;
         CRC[11] = CRC[10];
         CRC[10] = CRC[9];
         CRC[9] = CRC[8];
         CRC[8] = CRC[7];
         CRC[7] = CRC[6];
         CRC[6] = CRC[5];
         CRC[5] = CRC[4] ^ inv;
         CRC[4] = CRC[3];
         CRC[3] = CRC[2];
         CRC[2] = CRC[1];
         CRC[1] = CRC[0];
         CRC[0] = inv;
        end
         end
      end
endmodule
module sd_data_phy(
input sd_clk,
input rst,
output reg DAT_oe_o,
output reg[3:0] DAT_dat_o,
input  [3:0] DAT_dat_i,
output  [1:0] sd_adr_o,
input [7:0] sd_dat_i,
output reg [7:0] sd_dat_o,
output reg sd_we_o,
output reg sd_re_o,
input  [3:4] fifo_full,
input [3:4] fifo_empty,
input  [1:0] start_dat,
input fifo_acces
);
 reg [5:0] in_buff_ptr_read;
 reg [5:0] out_buff_ptr_read;
 reg crc_ok;
 reg [3:0] last_din_read;
reg [7:0] tmp_crc_token ;  
reg[2:0] crc_read_count;
reg [3:0] crc_in_write;
reg crc_en_write;
reg crc_rst_write;
wire [15:0] crc_out_write [3:0];
reg [3:0] crc_in_read;
reg crc_en_read;
reg crc_rst_read;
wire [15:0] crc_out_read [3:0];  
  reg[7:0] next_out;
    reg data_read_index;  
reg [10:0] transf_cnt_write;
reg [10:0] transf_cnt_read;
parameter SIZE = 6;
reg [SIZE-1:0] state;
reg [SIZE-1:0] next_state;
parameter IDLE        = 6'b000001;
parameter WRITE_DAT   = 6'b000010;
parameter READ_CRC   = 6'b000100;
parameter WRITE_CRC  = 6'b001000;   
parameter  READ_WAIT = 6'b010000;
parameter  READ_DAT  = 6'b100000;
reg in_dat_buffer_empty;
reg [2:0] crc_status_token; 
reg busy_int;
reg add_token;   
genvar i;
generate
for(i=0; i<4; i=i+1) begin:CRC_16_gen_write
  CRC_16 CRC_16_i (crc_in_write[i],crc_en_write, sd_clk, crc_rst_write, crc_out_write[i]);
end
endgenerate
generate
for(i=0; i<4; i=i+1) begin:CRC_16_gen_read
  CRC_16 CRC_16_i (crc_in_read[i],crc_en_read, sd_clk, crc_rst_read, crc_out_read[i]);
end
endgenerate
reg q_start_bit;
always @ (state or start_dat or DAT_dat_i[0] or  transf_cnt_write or transf_cnt_read or busy_int or crc_read_count or sd_we_o or  in_dat_buffer_empty )
begin : FSM_COMBO
 next_state  = 0;   
case(state)
  IDLE: begin
   if (start_dat == 2'b01) 
      next_state=WRITE_DAT;
    else if  (start_dat == 2'b10)
      next_state=READ_WAIT;
    else 
      next_state=IDLE;
    end
  WRITE_DAT: begin
    if (transf_cnt_write >= 1044+2) 
       next_state= READ_CRC;
   else if (start_dat == 2'b11)
        next_state=IDLE;
    else 
       next_state=WRITE_DAT;
  end
  READ_WAIT: begin
    if (DAT_dat_i[0]== 0 ) 
       next_state= READ_DAT;
    else 
       next_state=READ_WAIT;
  end
  READ_CRC: begin
    if ( (crc_read_count == 3'b111) &&(busy_int ==1) ) 
       next_state= WRITE_CRC;
    else 
       next_state=READ_CRC;    
  end
  WRITE_CRC: begin
       next_state= IDLE;
  end
  READ_DAT: begin
    if ((transf_cnt_read >= 1044-3)  && (in_dat_buffer_empty)) 
       next_state= IDLE;
    else if (start_dat == 2'b11)
        next_state=IDLE;   
    else 
       next_state=READ_DAT;
    end  
 endcase
end 
always @ (posedge sd_clk or posedge rst   )
 begin 
  if (rst ) begin
    q_start_bit<=1;
 end 
 else begin
    q_start_bit <= DAT_dat_i[0];
 end
end
always @ (posedge sd_clk or posedge rst   )
begin : FSM_SEQ
  if (rst ) begin
    state <= #1 IDLE;
 end 
 else begin
    state <= #1 next_state;
 end
end
reg [4:0] crc_cnt_write;
reg [4:0]crc_cnt_read;
reg [3:0] last_din;
reg [2:0] crc_s ;
reg [7:0] write_buf_0,write_buf_1, sd_data_out;
reg out_buff_ptr,in_buff_ptr;
reg data_send_index;
reg [1:0] sd_adr_o_read;  
reg [1:0] sd_adr_o_write;
reg read_byte_cnt;       
assign sd_adr_o = add_token ? sd_adr_o_read : sd_adr_o_write;
assign sd_adr_o = add_token ? sd_adr_o_read : sd_adr_o_write;         
reg [3:0] in_dat_buffer [63:0];
always @ (negedge sd_clk or posedge rst   )
begin
if (rst) begin
  DAT_oe_o<=0;
  crc_en_write<=0;
  crc_rst_write<=1;
  transf_cnt_write<=0;
  crc_cnt_write<=15;
  crc_status_token<=7;       
  data_send_index<=0;
  out_buff_ptr<=0;
  in_buff_ptr<=0;  
  read_byte_cnt<=0;
   write_buf_0<=0;
    write_buf_1<=0;
    sd_re_o<=0; 
    sd_data_out<=0;
    sd_adr_o_write<=0;
    crc_in_write<=0;
    DAT_dat_o<=0;
     last_din<=0;    
end  
else begin
 case(state)
   IDLE: begin
      DAT_oe_o<=0;    
      crc_en_write<=0;
      crc_rst_write<=1;     
      crc_cnt_write<=16;
      read_byte_cnt<=0;
      crc_status_token<=7;
      data_send_index<=0;
      out_buff_ptr<=0;
      in_buff_ptr<=0;  
        sd_re_o<=0;
        transf_cnt_write<=0;
   end     
   WRITE_DAT: begin     
      transf_cnt_write<=transf_cnt_write+1; 
      if ( (in_buff_ptr != out_buff_ptr) ||  (transf_cnt_write<2) ) begin
       read_byte_cnt<=read_byte_cnt+1;
       sd_re_o<=0;
        case (read_byte_cnt)
        0:begin
           sd_adr_o_write <=2;
           sd_re_o<=1; 
        end 
        1:begin
          if (!in_buff_ptr)
             write_buf_0<=sd_dat_i;         
          else
            write_buf_1 <=sd_dat_i;
          in_buff_ptr<=in_buff_ptr+1;     
        end    
     endcase
     end
      if (!out_buff_ptr)
        sd_data_out<=write_buf_0;
      else
       sd_data_out<=write_buf_1;
        if (transf_cnt_write==1+2) begin
          crc_rst_write<=0;
          crc_en_write<=1;
          last_din <=write_buf_0[3:0]; 
          DAT_oe_o<=1;  
          DAT_dat_o<=0;
          crc_in_write<= write_buf_0[3:0]; 
          data_send_index<=1;  
          out_buff_ptr<=out_buff_ptr+1;  
        end
        else if ( (transf_cnt_write>=2+2) && (transf_cnt_write<=1044-19+2 )) begin                 
          DAT_oe_o<=1;    
        case (data_send_index) 
           0:begin 
              last_din <=sd_data_out[3:0];
              crc_in_write <=sd_data_out[3:0];
               out_buff_ptr<=out_buff_ptr+1;
           end
           1:begin 
              last_din <=sd_data_out[7:4];
              crc_in_write <=sd_data_out[7:4];
           end
         endcase 
          data_send_index<=data_send_index+1;
          DAT_dat_o<= last_din; 
        if ( transf_cnt_write >=1044-19 +2) begin
             crc_en_write<=0;             
         end
       end
       else if (transf_cnt_write>1044-19 +2 & crc_cnt_write!=0) begin
         crc_en_write<=0;
         crc_cnt_write<=crc_cnt_write-1;      
         DAT_oe_o<=1; 
         DAT_dat_o[0]<=crc_out_write[0][crc_cnt_write-1];
         DAT_dat_o[1]<=crc_out_write[1][crc_cnt_write-1];
         DAT_dat_o[2]<=crc_out_write[2][crc_cnt_write-1];
         DAT_dat_o[3]<=crc_out_write[3][crc_cnt_write-1];         
       end
       else if (transf_cnt_write==1044-2+2) begin
          DAT_oe_o<=1; 
          DAT_dat_o<=4'b1111;
      end   
      else if (transf_cnt_write !=0) begin
         DAT_oe_o<=0;          
      end
   end
 endcase
end
end
always @ (posedge sd_clk or posedge rst   )
begin
  if (rst) begin
    add_token<=0;   
    sd_adr_o_read<=0;
    crc_read_count<=0;
    sd_we_o<=0; 
    tmp_crc_token<=0;
    crc_rst_read<=0;
    crc_en_read<=0;
    in_buff_ptr_read<=0;
    out_buff_ptr_read<=0;
    crc_cnt_read<=0;
    transf_cnt_read<=0;
    data_read_index<=0;
    in_dat_buffer_empty<=0;
    next_out<=0; 
    busy_int<=0;
    sd_dat_o<=0;
  end  
  else begin
   case(state)
   IDLE: begin          
     add_token<=0;
     crc_read_count<=0;
     sd_we_o<=0; 
     tmp_crc_token<=0;
      crc_rst_read<=1;
      crc_en_read<=0;
      in_buff_ptr_read<=0;
     out_buff_ptr_read<=0;
      crc_cnt_read<=15;
      transf_cnt_read<=0;
      data_read_index<=0;
      in_dat_buffer_empty<=0;
    end
    READ_DAT: begin  
     add_token<=1; 
      crc_rst_read<=0;
      crc_en_read<=1;
      if (fifo_acces) begin
        if ( (in_buff_ptr_read - out_buff_ptr_read) >=2) begin
          data_read_index<=~data_read_index;
          case(data_read_index)
            0: begin
             sd_adr_o_read<=3;
             sd_we_o<=0; 
             next_out[3:0]<=in_dat_buffer[out_buff_ptr_read ];
             next_out[7:4]<=in_dat_buffer[out_buff_ptr_read+1 ];
           end
           1: begin
              out_buff_ptr_read<=out_buff_ptr_read+2;
            sd_dat_o<=next_out; 
            sd_we_o<=1;  
            end
          endcase    
          end  
        else
           in_dat_buffer_empty<=1;
      end
     if (transf_cnt_read<1024) begin
       in_dat_buffer[in_buff_ptr_read]<=DAT_dat_i;
       crc_in_read<=DAT_dat_i;
       crc_ok<=1;
       transf_cnt_read<=transf_cnt_read+1; 
       in_buff_ptr_read<=in_buff_ptr_read+1;        
     end  
     else if  ( transf_cnt_read <= (1024 +16)) begin
       transf_cnt_read<=transf_cnt_read+1; 
       crc_en_read<=0;  
       last_din_read <=DAT_dat_i; 
       if (transf_cnt_read> 1024) begin       
         crc_cnt_read <=crc_cnt_read-1;
          if  (crc_out_read[0][crc_cnt_read] != last_din[0])
           crc_ok<=0;
          if  (crc_out_read[1][crc_cnt_read] != last_din[1])
           crc_ok<=0;
          if  (crc_out_read[2][crc_cnt_read] != last_din[2])
           crc_ok<=0;
          if  (crc_out_read[3][crc_cnt_read] != last_din[3])
           crc_ok<=0;  
         if (crc_cnt_read==0) begin
         end
      end
    end  
    end
    READ_CRC: begin
       if (crc_read_count<3'b111) begin
         crc_read_count<=crc_read_count+1;
         tmp_crc_token[crc_read_count]  <= DAT_dat_i[0];     
        end
      busy_int <=DAT_dat_i[0];  
    end
    WRITE_CRC: begin
      add_token<=1;
      sd_adr_o_read<=3;
      sd_we_o<=1; 
      sd_dat_o<=tmp_crc_token;      
    end
  endcase
end
end
endmodule
 

Go to most recent revision | 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.