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

📄 sd_controller.v

📁 基于FPGA的SD控制器实现.目前实现读操作功能,可作参考.
💻 V
字号:
//Written by Vladimir Boykov//Last modification August, 2005module sd_controller (sys_clk, sd_clk, reset, cs, sd_cmd, address, sd_data, data_input, data_output, write_to_buffer,                      write, read, int_reg, clear);parameter CMD0 = 6'd0;    //Reset all cards to Idle stateparameter CMD2 = 6'd2;    //Ask CID numberparameter CMD3 = 6'd3;    //Ask to publish a new relative address RCAparameter CMD17 = 6'd17;  //Read single blockparameter CMD7 = 6'd7;    //Select/Deselect SD Cardparameter CMD13 = 6'd13;  //Send status registerparameter CMD55 = 6'd55;  //Application specific commandparameter ACMD6 = 6'd6;   //Set data line widthparameter ACMD41 = 6'd41; //Asks the accessed card to send its operating condition register (OCR) content in the response on the CMD line.                      input sys_clk;input sd_clk;input reset;input cs;inout sd_cmd;input [2:0] address;inout [3:0] sd_data;input [31:0] data_input;output [31:0] data_output;output write_to_buffer;input write;input read;output [31:0] int_reg;output clear;reg [31:0] control_reg, status_reg, serial_reg;reg [15:0] RCA;              //New published RCA of the cardreg [31:0] blocknum;         //Block number for readingwire status_req, control_req, serial_req;wire block_rdy;reg [4:0] cmd;reg [7:0] count;reg [3:0] command_count;reg rw;reg mode;reg write_to_fifo;reg clear_fifo;reg [7:0] count_resp;reg resp_start;reg ocr_rdy;reg [6:0] data_count;reg [4:0] bit_count;reg data_start;reg [31:0] word;reg block_rdy_reg;wire [47:0] command;wire [6:0] crc7;wire reset_cmd, stop_cmd;assign data_output = {word[7:0], word[15:8], word[23:16], word[31:24]};assign write_to_buffer = write_to_fifo;assign clear = clear_fifo;assign sd_data = 4'bzzzz;assign status_req =   ((address==3'b010) && cs);assign control_req =  ((address==3'b011) && cs);assign serial_req =   ((address==3'b100) && cs);assign block_rdy = (data_start && (data_count < 7'd1))? 1'b1 : 1'b0;assign int_reg = (status_req && read)? status_reg :                  ((serial_req && read)? serial_reg : 32'd0);always @ (posedge sys_clk or posedge reset) begin   if (reset) begin      block_rdy_reg <= 1'b0;   end else begin      if (block_rdy) begin         block_rdy_reg <= 1'b1;      end else if (control_reg) begin         block_rdy_reg <= 1'b0;      end   endend//CONTROL REGISTERalways @ (posedge sys_clk or posedge reset) begin   if (reset) begin      control_reg <= 32'd0;   end else begin      if (control_req && write && !data_start) control_reg <= data_input;      else if (block_rdy) control_reg <= 32'd0;   endendassign sd_cmd = (rw)? command[count] : 1'bz;assign command =  (command_count==5'd0)?  {2'b01, CMD0, 32'h0, crc7, 1'b1} :                 ((command_count==5'd1)?  {2'b01, CMD55, RCA, 16'h0, crc7, 1'b1} :                 ((command_count==5'd2)?  {2'b01, ACMD41, 32'h00FF8000, crc7, 1'b1} :                  ((command_count==5'd3)?  {2'b01, CMD2, 32'h0, crc7, 1'b1} :                  ((command_count==5'd4)?  {2'b01, CMD3, 32'h0, crc7, 1'b1} :                  ((command_count==5'd5)?  {2'b01, CMD7, RCA, 16'h0, crc7, 1'b1}  :                  ((command_count==5'd6)?  {2'b01, CMD13, RCA, 16'h0, crc7, 1'b1} :                  ((command_count==5'd7)?  {2'b01, CMD17, blocknum, crc7, 1'b1}   :                  ((command_count==5'd9)?  {2'b01, ACMD6, 30'h0, mode, 1'b0, crc7, 1'b1} :                  48'hz))))))));                                  //SD FSM MODELalways @ (posedge sd_clk or posedge reset) begin   if (reset) begin      cmd <= 5'd0;      count <= 8'd90;      mode <= 1'b0;      clear_fifo <= 1'b0;      rw <= 1'b0;      command_count <= 4'd0;      blocknum <= 32'd0;   end else begin      case (cmd)          //Waiting for 80 clocks cycle before work with SD          5'd0: begin             if (count) count <= count - 8'd1;             else cmd <= 5'd1;          end                //Prepearing to sending the command          5'd1: begin             count <= 8'd47;              rw <= 1'b1;             cmd <= 5'd2;          end          //Sending the command          5'd2: begin             if (count) count <= count - 8'd1;             else begin                rw <= 1'b0;                if (command_count) begin                   //Waiting for response                   cmd <= 5'd3;                end else begin                   //Send next command                   command_count <= command_count + 4'd1;                   count <= 8'd6;                   cmd <= 5'd0;                end             end          end          5'd3: begin             if (!count_resp) begin                if (command_count!=4'd2) begin                   if (command_count!=4'd6) begin                      command_count <= command_count + 4'd1;                      count <= 8'd31;                      cmd <= 5'd0;                   end else begin                      cmd <= 5'd31;                   end                end else begin                   if (ocr_rdy) begin                      command_count <= command_count + 4'd1;                      count <= 8'd31;                      cmd <= 5'd0;                   end else begin                      command_count <= 4'd1;                      count <= 8'd31;                      cmd <= 5'd0;                   end                 end             end          end          //Reading some block          5'd4: begin             count <= 8'd47;              clear_fifo <= 1'b0;             rw <= 1'b1;             cmd <= 5'd5;          end          5'd5: begin             if (count) count <= count - 8'd1;             else begin                rw <= 1'b0;                cmd <= 5'd6;             end          end          5'd6: begin             if (block_rdy) begin                cmd <= 5'd31;             end          end          //Getting a command from CPU          5'd31: begin             if ((control_reg[3:0]==4'b0001) && (status_reg==32'h900)) begin                 blocknum[31:9] <= control_reg[26:4];                blocknum[8:0] <= 9'd0;                command_count <= 5'd7;                clear_fifo <= 1'b1;                cmd <= 5'd4;             end else cmd <= 5'd31;          end          default: cmd <= 5'd0;      endcase   endend//Getting a response from SDalways @ (negedge sd_clk or negedge (!reset)) begin    if (reset) begin      count_resp <= 46;      resp_start <= 1'b0;      status_reg <= 0;      serial_reg <= 0;      RCA <= 16'd0;      ocr_rdy <= 1'b0;   end else begin      if (!rw) begin         if (!sd_cmd && !resp_start) begin            resp_start <= 1'b1;               end else if (resp_start) begin            if (count_resp) begin               count_resp <= count_resp - 8'd1;               //R1               if ((command_count==4'd1) || (command_count>4'd4)) begin                  if ((count_resp>7) && (count_resp<40)) begin                     status_reg[31:1] <= status_reg[30:0];                     status_reg[0] <= sd_cmd;                  end               //R3               end else if (command_count==4'd2) begin                  if ((count_resp==39) && sd_cmd)begin                     ocr_rdy <=1'b1;                       end               //R2               end else if (command_count==4'd3) begin                  if ((count_resp>23) && (count_resp<56)) begin                     serial_reg[31:1] <= serial_reg[30:0];                     serial_reg[0] <= sd_cmd;                  end               //R6               end else if (command_count==4'd4) begin                  if ((count_resp>23) && (count_resp<40)) begin                     RCA[15:1] <= RCA[14:0];                     RCA[0] <= sd_cmd;                  end               end            end else begin               resp_start <= 1'b0;            end         end      end else begin         if (command_count==4'd3) begin            count_resp <= 8'd134;         end else begin            count_resp <= 8'd46;         end      end   endend//Getting data blockalways @ (negedge sd_clk or negedge (!reset)) begin   if (reset) begin      data_count <= 7'd127;         bit_count  <= 5'd31;      data_start <= 1'b0;      write_to_fifo <= 1'b0;      word <= 32'd0;   end else begin      if (!sd_data[0] && !data_start && (cmd!=5'd31)) begin         data_start <= 1'b1;         write_to_fifo <= 1'b0;      end else if ((data_count || bit_count) && data_start) begin         if (bit_count) begin            write_to_fifo <= 1'b0;            bit_count <= bit_count - 5'd1;            word[31:1] <= word[30:0];            word[0] <= sd_data[0];         end else begin            word[31:1] <= word[30:0];            word[0] <= sd_data[0];            write_to_fifo <= 1'b1;            bit_count <= 5'd31;            data_count <= data_count - 7'd1;         end      end else if (data_start) begin         word[31:1] <= word[30:0];         word[0] <= sd_data[0];         write_to_fifo <= 1'b1;         data_count <= 7'd127;         bit_count <= 5'd31;         data_start <= 1'b0;      end else begin         write_to_fifo <= 1'b0;      end   endendassign reset_cmd = ((cmd==5'd1) || (cmd==5'd4))? 1'b1 : 1'b0;assign stop_cmd =  (count<8'd8)? 1'b1 : 1'b0;//Checksum for command tokencrc_unit_7  CRC_7 (                   .sd_clk(sd_clk),                    .reset(reset_cmd),                    .data_in(command[count]),                    .stop(stop_cmd),                    .crc(crc7)                  );endmodule

⌨️ 快捷键说明

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