SPI通信协议2

143 阅读2分钟

扇区擦除:

和全擦除类似

32个扇区

一个扇区 = 512kb

每256页构成一个扇区。

扇区擦除在写入指令后要加入三个字节的地址。 与全擦除的区别。

选择扇区0 00_04_25 000000000, 0000 0100 ,0010 0101

00代表扇区 04 代表页地址 25代表字节地址 WREN SE_IN 和三个地址

      WREN_IN = 8'B0000_0010;
      SE_IN = 8'B1100_1000;
      S_ADDR = 8'B0000_0000;
      P_ADDR = 8'B0000_0100;
      B_ADDR = 8'B0010_0101;
module flash_se_ctrl( input wire sys_clk,input wire sys_rst_n,input wire key_flag,output  cs_n,output sck,output  mosi);

parameter IDLE = 4’b0001, WREN = 4'b0010,DELAY = 4'b0100,SE = 4'b1000;

//mosi 的指令 SE_IN为全擦除指令
parameter WREN_IN = 8'B0000_0010;
          SE_IN = 8'B1100_1000;
          S_ADDR = 8'B0000_0000;
          P_ADDR = 8'B0000_0100;
          B_ADDR = 8'B0010_0101;




reg mosi;
reg sck;
reg cs_n;

reg [3:0] state;

reg [5:0] cnt_clk;   //时钟计数器 计数0-31
reg [3:0] cnt_byte;  //字节计数器  时钟计数器一个周期后加一  0 -6   刚好七个周期
reg [10] cnt_sck;  // 比特计数器为1时候为1,每个时钟周期加一,实现四分频,0123,0123. 
reg [2:0] cnt_bit;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        state <= IDLE;
     else
         case(state)
             IDLE: if(flag == 1'b1)
                 state <= WREN;
             WREN: if(cnt_byte == 4'b2 && cnt_clk == 6'd31)
                 state <= DELAY;
             
             DELAY:  if(cnt_byte == 4'd3 && cnt_clk == 6'd31)
                 state <= SE;
             
             SE:    if(cnt_byte == 4'd9 && cnt_clk == 6'd31)
                 state <= IDLE;

            default: state <= IDLE;
                   
        endcase
always@(posedge sys_clk or negedge sys_rst_n)
      if(sys_rst_n == 1'b0)
            cnt_clk <= 5'd0;   // 5位宽会自动清零
       else if(state != IDLE)
           cnt_clk <= cnt_clk + 1'b1;
        
 always@(posedge sys_clk or negedge sys_rst_n)
      if(sys_rst_n == 1'b0)          
            cnt_byte <= 4'd0;
       
       else if(cnt_byte == 4'd9 && cnt_clk == 6'd31)
           cnt_byte  <= 4'd0;
       else if(cnt_clk == 5'd31)
           cnt_byte <= cnt_byte + 1'b1;
        
always@(posedge sys_clk or negedge sys_rst_n)
      if(sys_rst_n == 1'b0) 
            cnt_sck <= 2'd0;   //计满自动清零了
      else if(state ==WREN && cnt_byte == 4'd1)
          cnt_sck <= cnt_sck + 1'b1;
      else if(state ==SE& cnt_byte >= 4'd5 &&cnt_byte <= 4'd8)
          cnt_sck <= cnt_sck + 1'b1;


always@(posedge sys_clk or negedge sys_rst_n)
      if(sys_rst_n == 1'b0) 
            cnt_bit <= 3'd0;
       else if(cnt_sck == 2'd2)
           cnt_bit <= cnt_bit + 1'b1;
     
     
     
  // 输出信号的赋值
  always@(posedge sys_clk or negedge sys_rst_n)
      if(sys_rst_n == 1'b0) 
          cs_n <= 1'b1;
      else if(key_flag == 1'b1)
          cs_n <= 1'b0;
        
       else if(cnt_byte ==4 'd2 && cnt_clk == 5'd31 && state == WREN)
             cs_n <= 1'b1;
       else if(cnt_byte ==4 'd3&& cnt_clk == 5'd31 && state == DELAY)
             cs_n <= 1'b0
       else if(cnt_byte ==4 'd9 && cnt_clk == 5'd31 && state == SE)
             cs_n <= 1'b1;

  always@(posedge sys_clk or negedge sys_rst_n)
      if(sys_rst_n == 1'b0) 
            mosi <= 1'b0;
       else if(state == WREN && cnt_byte == 4'd2)
           mosi <= 1'b0;
         else if(state == SE&& cnt_byte == 4'd9 )
              mosi <= 1'b0;
         else if(state == WREN && cnt_byte == 4'd1 && cnt_sck == 2'd0)
              mosi <= WREN_IN[7-cnt_byte];   //先写入高位方法
            else if(state == SE&& cnt_byte == 4'd5&& cnt_sck == 2'd0)
              mosi <= SE_IN[7-cnt_byte];   
              
                else if(state == SE&& cnt_byte == 4'd6&& cnt_sck == 2'd0)
              mosi <= S_ADDR[7-cnt_byte];   
               else if(state == SE&& cnt_byte == 4'd7&& cnt_sck == 2'd0)
              mosi <= P_ADDR[7-cnt_byte];  
              
               else if(state == SE&& cnt_byte == 4'd8&& cnt_sck == 2'd0)
              mosi <= B_ADDR[7-cnt_byte];  
        
     always@(posedge sys_clk or negedge sys_rst_n)
      if(sys_rst_n == 1'b0) 
          sck <= 1'b0;
      
      else if(cnt_sck == 1'b0)
          sck <= 1'b0;
      else if(cnt_sck == 2'd2)
          sck <= 1'b1;
      
 
endmodule