博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EEPROM的操作---SPI接口和I2C接口
阅读量:5066 次
发布时间:2019-06-12

本文共 43110 字,大约阅读时间需要 143 分钟。

 

参考:http://blog.csdn.net/yuanlulu/article/details/6163106

 ROM最初不能编程,出厂什么内容就永远什么内容,不灵活。后来出现了PROM,可以自己写入一次,要是写错了,只能换一片,自认倒霉。人类文明不断进步,终于出现了可多次擦除写入的EPROM,每次擦除要把芯片拿到紫外线上照一下,想一下你往单片机上下了一个程序之后发现有个地方需要加一句话,为此你要把单片机放紫外灯下照半小时,然后才能再下一次,这么折腾一天也改不了几次。历史的车轮不断前进,伟大的EEPROM出现了,拯救了一大批程序员,终于可以随意的修改rom中的内容了

  EEPROM的全称是“电可擦除可编程只读存储器”,即Electrically Erasable Programmable Read-Only Memory。是相对于紫外擦除的rom来讲的。但是今天已经存在多种EEPROM的变种,变成了一类存储器的统称.这种rom的特点是可以随机访问和修改任何一个字节,可以往每个bit中写入0或者1。这是最传统的一种EEPROM,掉电后数据不丢失,可以保存100年,可以擦写100w次。具有较高的可靠性,但是电路复杂/成本也高。因此目前的EEPROM都是几十千字节到几百千字节的,绝少有超过512K的。

  EEPROM的接口分为两种:SPI和I2C。

      SPI接口为四线,型号如AT25XXX。 

    

 

      I2C接口为2线,型号如24CL02/04/XX.

        

    这两种EEPROM的操作主要按SPI 和I2C的协议操作就可以了,不过也有一些需要注意的地方。在这里记录下来,不涉及细节的处理。

      对于SPI接口的EEPROM:

    1、在写数据的时候需要先写WR_EN的命令,然后在按SPI写写操作。读的时候不需要先写WR_EN.

                 

    2、WR_EN 和WR_DATA 的操作之间要隔一段时间,如10us,不能写完WR_EN就写WR_DATA,否则数据将不能被写入。

         3、WR_DATA操作送入EEPROM之后,要等待一段时间,等EEPROM将数据写入内部,时间长短可以参考datasheet中的一个参数 write_cycle。

       

    4、RD_DATA操作到下一次的WR_EN/WR_DATA命令之间也要间隔一段时间,如400us.

    5、SPI协议的最后一个SPI_CLK也要保证完整,有低有高,不能只有一半,如将SPI_CLK拉高之后不拉低就将SPI_CS信号拉低。

      

     example: verilog 

    EEPROM--SPI interface     

  
module EE_WR(//------------outputs-----------output   EE_SI, output   EE_CSb,output   EE_SCK, input    EE_SO,//------------inputs------------input clk,//50MHZinput rst)/*synthesis noprune*/; parameter  cmd_wr_en =8'h06         /* synthesis keep */; parameter  cmd_wr_sr =16'h0180      /* synthesis keep */; //16'h018C all block are protected parameter  cmd_rd_sr =8'h05         /* synthesis keep */; parameter  cmd_wr_op =536'h020000_63555560595857565554535251504948474645444342414039383736353433323130292827262524232221201918171615141312111009080706050403020100  /* synthesis keep */; //parameter  cmd_wr_op =32'h020000_f5 /* synthesis keep */; parameter  cmd_rd_op =24'h030000    /* synthesis keep */;     parameter  tck_delay = 4'd6; parameter  num_data_bit = 12'd512; parameter  IDLE = 5'd0; parameter  WR_EN_1 = 5'd1; parameter  WR_EN_2 = 5'd2; parameter  WR_EN_3 = 5'd3; parameter  WR_EN_4 = 5'd4; parameter  WR_EN_5 = 5'd5; parameter  WR_SR_1 = 5'd6; parameter  WR_SR_2 = 5'd7; parameter  WR_SR_3 = 5'd8; parameter  WR_SR_4 = 5'd9; parameter  WR_SR_5 = 5'd10;   parameter  RD_SR_1 = 5'd11; parameter  RD_SR_2 = 5'd12; parameter  RD_SR_3 = 5'd13; parameter  RD_SR_4 = 5'd14; parameter  RD_SR_5 = 5'd15; parameter  RD_SR_6 = 5'd16; parameter  RD_SR_7 = 5'd17;   parameter  WR_DATA_1 = 5'd18; parameter  WR_DATA_2 = 5'd19; parameter  WR_DATA_3 = 5'd20; parameter  WR_DATA_4 = 5'd21; parameter  WR_DATA_5 = 5'd22;   parameter  RD_DATA_1 = 5'd23; parameter  RD_DATA_2 = 5'd24; parameter  RD_DATA_3 = 5'd25; parameter  RD_DATA_4 = 5'd26; parameter  RD_DATA_5 = 5'd27; parameter  RD_DATA_6 = 5'd28; parameter  RD_DATA_7 = 5'd29;    reg   [31:0]   cnt;always @(posedge clk or negedge rst )  begin  if(rst == 0 )  cnt <= 0;  else if(cnt == 32'd500_000_000)   cnt <= 32'd500_000_000;    else cnt <= cnt + 1; end  wire    wr_en /* synthesis keep */; wire    wr_op /* synthesis keep */; wire    rd_op /* synthesis keep */; wire    rd_sr /* synthesis keep */; wire    wr_sr /* synthesis keep */;   assign  wr_en = (cnt == 32'd000_000_500);    assign  rd_sr = (cnt == 32'd000_000_000);   assign  wr_sr = (cnt == 32'd000_000_000);   assign  wr_op = (cnt == 32'd000_001_000);   assign  rd_op = (cnt == 32'd001_000_000);    reg   [4:0]   state; reg   [3:0]   delay; reg   [11:0]  num; reg   [7:0]   data_sr; reg   [7:0]   data_rd;  reg      spi_clk; reg      spi_cs; reg      spi_si;    always @(posedge clk or negedge rst )  begin  if(rst == 0 )  begin    spi_clk <= 0;     spi_cs <= 1;     spi_si <= 0;     delay <= 0;     num <= 0;     state <= IDLE;    data_sr    <= 0;      data_rd<= 0;    end else begin   case(state)      IDLE : begin         spi_clk <= 0;         spi_cs <= 1;         spi_si <= 0;         delay <= 0;         num <= 0;         data_sr    <= 0;          data_rd <= 0;                if(wr_en)  state <= WR_EN_1; //        else if(wr_sr) state <= WR_SR_1; //         else if(rd_sr) state <= RD_SR_1;          else if(wr_op) state <= WR_DATA_1;          else if(rd_op) state <= RD_DATA_1 ;               else  state <= state;     end//-------------wr_en-------------       WR_EN_1: begin    //拉低CS        spi_clk <= 0;         spi_cs <= 0;         num <= 7;        if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1; end     end          WR_EN_2: begin   //sck 下降沿        spi_clk <= 0;         spi_si <= cmd_wr_en[num];         if(delay == tck_delay)  begin  state <= state + 1;  delay <= 0; end                     else  begin  state <= state;  delay <= delay + 1;   end     end                   WR_EN_3: begin   //sck 上升沿        spi_clk <= 1;         spi_si <= spi_si;        if(delay == tck_delay) begin            if(num == 0) begin state <= state + 1; delay <= 0;  end           else begin state <= WR_EN_2; delay <= 0;  num <= num - 1; end             end        else  begin  state <= state;  delay <= delay + 1;  end     end      WR_EN_4: begin   //SCK 下降沿延时一个        spi_clk <= 0;         spi_si <= spi_si;         if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;   end     end       WR_EN_5: begin   //CS 拉高        spi_cs <= 1;        spi_clk<= 0;         spi_si <= 0;         if(delay == tck_delay)  begin state <= IDLE;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;   end     end        //-------------wr_sr-------------  WR_SR_1: begin    //拉低CS        spi_clk <= 0;         spi_cs <= 0;         num <= 15;         spi_si <= 0;        if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;  end     end  WR_SR_2: begin   //sck 下降沿        spi_clk <= 0;                  spi_si <= cmd_wr_sr[num];         if(delay == tck_delay)  begin state <= state + 1; delay <= 0; end            else  begin  state <= state;  delay <= delay + 1;   end     end               WR_SR_3: begin   //sck 上升沿        spi_clk <= 1;         spi_si <= spi_si;        if(delay == tck_delay)  begin             if(num == 0) begin  state <= state + 1;  delay <= 0;   end             else  begin  state <= WR_SR_2;  delay <= 0; num <= num -1;  end          end        else  begin  state <= state;  delay <= delay + 1;  end     end   WR_SR_4: begin   //SCK 下降沿延时一个        spi_clk <= 0;         spi_si <= spi_si;         if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;   end     end      WR_SR_5: begin   //CS 拉高        spi_cs <= 1;        spi_clk<= 0;         spi_si <= 0;         if(delay == tck_delay)  begin state <= IDLE;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;   end     end       //-----rd_sr-----------   RD_SR_1: begin    //拉低CS        spi_clk <= 0;         spi_cs <= 0;         num <= 7;         data_sr    <= 0;          spi_si <= 0;        if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <=delay + 1;  end     end    RD_SR_2: begin     //sck 下降沿        spi_clk <= 0;         spi_si <= cmd_rd_sr[num];         if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;   end     end    RD_SR_3: begin   //sck 上升沿        spi_clk <= 1;         spi_si <= spi_si;        if(delay == tck_delay)  begin             if(num == 0) begin state <= state + 1;  delay <= 0; num <= 7;  end           else  begin state <= RD_SR_2;  delay <= 0; num <= num - 1;  end          end                 else  begin  state <= state;  delay <= delay + 1;  end     end         RD_SR_4: begin    //read SCK 下降沿        spi_clk <= 0;         spi_si <= 0;                   data_sr <= data_sr;         if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;   end     end     RD_SR_5: begin    //READ sck 上升沿        spi_clk <= 1;         data_sr[num]    <= EE_SO;        if(delay == tck_delay)  begin             if(num == 0) begin state <= state + 1;  delay <= 0;  end           else  begin state <= RD_SR_4;  delay <= 0; num <= num - 1;  end          end                 else  begin  state <= state;  delay <= delay + 1;  end     end        RD_SR_6: begin  //SCK 下降沿延时一个       spi_clk <= 0;         data_sr <= data_sr;         if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;   end     end          RD_SR_7: begin  //CS拉高           spi_cs <= 1;         spi_clk<= 0;          spi_si <= 0;          if(delay == tck_delay)  begin state <= IDLE;  delay <= 0;  end         else  begin  state <= state;  delay <= delay + 1;   end      end       //---------------------wr_data------------------   WR_DATA_1: begin    //拉低CS        spi_clk <= 0;         spi_cs <= 0;        spi_si <= 0;         num <= num_data_bit + 23;        if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;  end     end    WR_DATA_2: begin  //SCK下降沿        spi_clk <= 0;         spi_si <= cmd_wr_op[num];         if(delay == tck_delay)  begin  state <= state + 1;  delay <= 0;   end        else  begin  state <= state;  delay <= delay + 1;   end     end            WR_DATA_3: begin //SCK 上升沿            spi_clk <= 1;         spi_si <= spi_si;        if(delay == tck_delay)  begin            if(num == 0)   begin   state <= state + 1; delay <= 0;  end           else  begin state <= WR_DATA_2;  delay <= 0;  num <= num - 1; end            end        else  begin  state <= state;  delay <= delay + 1;   end     end     WR_DATA_4: begin  //SCK延时下降沿        spi_clk <= 0;         spi_si <=  0;         if(delay == tck_delay)  begin  state <= state + 1;  delay <= 0;   end        else  begin  state <= state;  delay <= delay + 1;   end     end      WR_DATA_5:  begin  //CS拉高           spi_cs <= 1;         spi_clk<= 0;          spi_si <= 0;          if(delay == tck_delay)  begin state <= IDLE;  delay <= 0;  end         else  begin  state <= state;  delay <= delay + 1;   end      end           //---------------------rd_data-------------------  RD_DATA_1: begin    //拉低CS        spi_clk <= 0;         spi_cs <= 0;        spi_si <= 0;         num <= 23;        if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;  end     end    RD_DATA_2: begin  //SCK下降沿        spi_clk <= 0;         spi_si <= cmd_rd_op[num];         if(delay == tck_delay)  begin  state <= state + 1;  delay <= 0;   end        else  begin  state <= state;  delay <= delay + 1;   end     end             RD_DATA_3: begin //SCK 上升沿            spi_clk <= 1;         spi_si <= spi_si;        if(delay == tck_delay)  begin            if(num == 0)   begin   state <= state + 1; delay <= 0;   num <= num_data_bit - 1; end           else  begin state <= RD_DATA_2;  delay <= 0;  num <= num - 1; end            end        else  begin  state <= state;  delay <= delay + 1;   end     end     RD_DATA_4: begin    //read SCK 下降沿        spi_clk <= 0;         spi_si <= 0;                  data_rd <= data_rd;         if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;   end     end     RD_DATA_5: begin    //READ sck 上升沿        spi_clk <= 1;         data_rd[num]    <= EE_SO;        if(delay == tck_delay)  begin             if(num == 0) begin state <= state + 1;  delay <= 0;  end           else  begin state <= RD_DATA_4;  delay <= 0; num <= num - 1;  end          end                 else  begin  state <= state;  delay <= delay + 1;  end     end        RD_DATA_6: begin  //SCK 下降沿延时一个       spi_clk <= 0;         data_rd <= data_rd;         if(delay == tck_delay)  begin state <= state + 1;  delay <= 0;  end        else  begin  state <= state;  delay <= delay + 1;   end     end         RD_DATA_7 :begin  //CS拉高           spi_cs <= 1;         spi_clk<= 0;          spi_si <= 0;          if(delay == tck_delay)  begin state <= IDLE;  delay <= 0;  end         else  begin  state <= state;  delay <= delay + 1;   end      end           default : state <= 0;  endcase endend  assign  EE_CSb = spi_cs; assign  EE_SCK = spi_clk; assign  EE_SI  = spi_si; endmodule
View Code

   tb: 

  
`timescale 1 ps/1 ps    module EE_WR_tb ;       wire   EE_SI;     wire   EE_CSb;    wire   EE_SCK;     reg    EE_SO;//------------inputs------------   reg      clk;//50MHZ   reg      rst;        EE_WR u0_EE_WR(//------------outputs-----------    .EE_SI(EE_SI),     .EE_CSb(EE_CSb),    .EE_SCK(EE_SCK),     .EE_SO(EE_SO),    //------------inputs------------   .clk(clk),//50MHZ   .rst(rst) )/*synthesis noprune*/;  parameter T = 20000;    always #(T/2)  clk = ~clk;    initial     begin       clk = 0;        rst =0;                        #(300*T)  $stop;                #(200*T)  rst =1;            end     endmodule
View Code

 对于I2C的接口:

    1、读写之间按I2C的协议进行就可以。

    2、在读取数据时候,master在接收完8bit数据之后,需要给从机发一个ACK(输出一个SDA =0)。注意读取的时候ACK是由Master发出的,在写数据的时候ACK是由slaver发出的。

   可以参考:http://blog.csdn.net/lingfeng5/article/details/73361833

   3、写数据同样也有一定的write_cycle. 参考datasheet.

     

  example: verilog

  
View Code
  
// `define SIM   //if run modelsim, enable   module  eeprom_data(    input            clk,    input            rst_n,        output                     wr_en,    output    reg [7:0]   wr_addr,    output    reg [7:0]   wr_data,    output    reg           wr_flag,        output                     rd_en,    output    reg [7:0]    rd_addr,    input          [7:0]    rd_data,    output    reg           rd_flag,       input                rd_wrdata_en,    //only one clk cycle high time    input          wr_rddata_en      );         reg  [7:0]  wr_cnt;    reg  [7:0]  rd_cnt;       reg   [31:0]    cnt;        reg    [5:0]        rd_wrdata_en_flag;  always @(posedge clk or negedge rst_n)    begin          if(rst_n == 0) rd_wrdata_en_flag <= 6'd0;         else rd_wrdata_en_flag <= {rd_wrdata_en_flag[5:0],rd_wrdata_en};                end              `ifdef   SIM    always @(posedge clk or negedge rst_n)     begin        if(rst_n == 0) cnt <= 0;        else if(cnt == 32'd100_000)  cnt <= 0;        else cnt <= cnt + 1;     end               assign  wr_en = (cnt == 32'd20_000);     assign  rd_en = (cnt == 32'd70_000);     `else                    always @(posedge clk or negedge rst_n)     begin        if(rst_n == 0) cnt <= 0;        else if(cnt == 32'd500_000_000)  cnt <= 0;        else cnt <= cnt + 1;     end   assign  wr_en = (cnt == 32'd200_000_000); assign  rd_en = (cnt == 32'd400_000_000);      `endif   parameter data_num = 8'd16;  //the data number of need to be write or read  //========================================= //write always @(posedge clk or negedge rst_n) begin    if(rst_n == 0) wr_addr <= 0;    else if(rd_wrdata_en_flag[5])  begin        if(wr_addr == data_num) wr_addr <= 0;          else wr_addr <= wr_addr + 1;      end     else   wr_addr <= wr_addr; end   always @(posedge clk or negedge rst_n) begin    if(rst_n == 0) wr_data <= 0;    else if(rd_wrdata_en_flag[5])  begin        if(wr_data == data_num) wr_data <= 0;          else wr_data <= wr_data + 1;      end     else   wr_data <= wr_data; end       always @(posedge clk or negedge rst_n) begin    if(rst_n == 0) wr_cnt <= 0;    else if(rd_wrdata_en_flag[5])  begin        if(wr_cnt == data_num) wr_cnt <= 0;          else wr_cnt <= wr_cnt + 1;      end     else   wr_cnt <= wr_cnt; end    always @(posedge clk or negedge rst_n) begin    if(rst_n == 0) wr_flag <= 0;    else if(wr_en) wr_flag <= 1;    else if(rd_wrdata_en_flag[5])  begin        if(wr_cnt == data_num) wr_flag <= 0;          else wr_flag <= 1;      end     else   wr_flag <= wr_flag; end    //==================================== //read   always @(posedge clk or negedge rst_n) begin    if(rst_n == 0) rd_addr <= 0;    else if(wr_rddata_en)  begin        if(rd_addr == data_num) rd_addr <= 0;          else rd_addr <= rd_addr + 1;      end     else   rd_addr <= rd_addr; end  // always @(posedge clk or negedge rst_n)// begin//    if(rst_n == 0) rd_data <= 0;//    else if(wr_rddata_en)  begin//        if(rd_data == 8'D127) rd_data <= 0;  //        else rd_data <= rd_data + 1;//      end //    else   rd_data <= rd_data;// end//         always @(posedge clk or negedge rst_n) begin    if(rst_n == 0) rd_cnt <= 0;    else if(wr_rddata_en)  begin        if(rd_cnt == data_num) rd_cnt <= 0;          else rd_cnt <= rd_cnt + 1;      end     else   rd_cnt <= rd_cnt; end       always @(posedge clk or negedge rst_n) begin    if(rst_n == 0) rd_flag <= 0;    else if(rd_en) rd_flag <= 1;    else if(wr_rddata_en)  begin        if(data_num == 0)  rd_flag <= 0;        else if(rd_cnt == (data_num-1)) rd_flag <= 0;          else rd_flag <= 1;      end     else   rd_flag <= rd_flag; end  wire                fifo_empty; wire [4:0]      cnt_fifo; wire             clr_fifo;  assign  clr_fifo = wr_rddata_en&&(rd_cnt == (data_num-1));  RD_DATA_BUF u_rd_data_buf(        .aclr(clr_fifo),        .clock(clk),        .data(rd_data),        .rdreq(1'b0),        .wrreq(wr_rddata_en),        .empty(fifo_empty),        .full(),        .q(),        .usedw(cnt_fifo)        );  endmodule
View Code
//====================================== //  I2C.v //    //==========================// `define SIM         //if run modelsim, enable     module I2C(         input            clk,         //sysclk = 50Mhz      input            rst_n,            input    [1:0] wr_rd_en,   //wr_rd_en[1] = read, wr_rd_en[0] = write      input            wr_data_flag, //if still have data to write,the flag always is high      input            rd_data_flag, //if still have data to read,the flag always is high      input    [7:0]    wr_addr,      input    [7:0]    wr_data,      input    [7:0]    rd_addr,            output    [7:0]    rd_data,      output            rd_wrdata_en,  //read data from eeprom_data.v to write eeprom      output         wr_rddata_en,  //write the read data from eeprom to eeprom_data.v              output       ee_I2C_CLK,      inout        ee_I2C_SDA   );          reg    [1:0]        wr_rd_en_reg1,wr_rd_en_reg2;       reg        [4:0]   state;      parameter IDLE = 5'd0;    parameter START_1 = 5'd1;    parameter START_2 = 5'd2;    parameter START_3 = 5'd3;    parameter WR_CTL_1 = 5'd4;    parameter WR_CTL_2 = 5'd5;    parameter WR_CTL_ACK1 = 5'd6;    parameter WR_CTL_ACK2 = 5'd7;    parameter WR_ADDR_1 = 5'd8;        parameter WR_ADDR_2 = 5'd9;        parameter WR_ADDR_ACK1 = 5'd10;    parameter WR_ADDR_ACK2 = 5'd11;        parameter WR_DATA_1 = 5'd12;    parameter WR_DATA_2 = 5'd13;        parameter WR_DATA_3 = 5'd14;        parameter WR_DATA_ACK1 = 5'd15;    parameter WR_DATA_ACK2 = 5'd16;        parameter RD_DATA_1 = 5'd17;    parameter RD_DATA_2 = 5'd18;        parameter RD_DATA_ACK1 = 5'd19;        parameter RD_DATA_ACK2 = 5'd20;        parameter STOP_1 = 5'd21;    parameter STOP_2 = 5'd22;    parameter STOP_3 = 5'd23;      parameter WRITE_TIME = 5'd24;     //delay 10ms        parameter CMD_control = 7'b1010000; //eeprom addr = 3'b000;   `ifdef SIM    parameter delay = 20'd100;    parameter delay_10ms = 20'd500;`else   parameter delay = 20'd300;    parameter delay_10ms = 20'd500000;`endif          always @(posedge clk or negedge rst_n)    begin     if(rst_n == 0) begin             wr_rd_en_reg2 <= 2'd0;            wr_rd_en_reg1 <= 2'd0 ;        end     else begin            wr_rd_en_reg2 <= wr_rd_en_reg1;            wr_rd_en_reg1 <= wr_rd_en ;        end   end        reg     [4:0]   num;  //data = 8bit    reg     [19:0]  delay_cnt;     reg    [7:0]      addr_reg;  //reg addr    reg     [7:0]    data_reg;  //reg data    reg                wr_flag;   //write flag    reg                rd_flag;   //read flag    reg                rd_restart_flag; // read, the next start flag    reg                dir_sda_flag;  // dir of sda flag    reg                rd_wrdata_flag; //when write data ,need read data first    reg                wr_rddata_flag;        reg    [7:0]   rd_data_reg;    reg                ee_sclk_reg;       reg                ee_data_reg;    always @(posedge clk or negedge rst_n)    begin     if(rst_n == 0) begin        state <= IDLE;        num <= 0;        delay_cnt <= 0;        addr_reg <= 0;        data_reg <= 0;        wr_flag <= 0;        dir_sda_flag <= 0;        rd_flag <= 0;        rd_restart_flag <= 0;        rd_wrdata_flag <= 0;        wr_rddata_flag <= 0;        rd_data_reg <= 0;                ee_sclk_reg <= 1;        ee_data_reg <= 1;                end    else begin        case(state)            IDLE: begin             num <= 0;             delay_cnt <= 0;             data_reg  <= 0;             addr_reg <= 0;             wr_flag <= 0;             dir_sda_flag <= 0;             rd_flag <= 0;             rd_restart_flag <= 0;             rd_wrdata_flag <= 0;             wr_rddata_flag <= 0;             rd_data_reg <= 0;                          ee_sclk_reg <= 1;             ee_data_reg <= 1;                          if(wr_rd_en_reg2 == 2'b01) begin   //write                addr_reg <= wr_addr ;                wr_flag <= 1;                rd_flag <= 0;                state <= START_1;                    dir_sda_flag <= 1;                             end            else if(wr_rd_en_reg2 == 2'b10)  begin   //read                addr_reg <= rd_addr ;                wr_flag <= 0;                rd_flag <= 1;                state <= START_1;                dir_sda_flag <= 1;                rd_data_reg <= 0;                             end            else begin                state <= state;                             end         end        START_1: begin          //reg             ee_sclk_reg <= 1;            ee_data_reg <= 1;          if(delay_cnt == delay<<1 ) begin                state <= state + 1;                delay_cnt <= 0;             end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;             end            end     START_2: begin       //pull down DATA             ee_sclk_reg <= 1;            ee_data_reg <= 0;          if(delay_cnt == delay ) begin                state <= state + 1;                delay_cnt <= 0;             end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;             end            end    START_3: begin         //pull down SCL             ee_sclk_reg <= 0;            ee_data_reg <= 0;            num <= 7;          if(delay_cnt == delay ) begin                                            delay_cnt <= 0;                                if(rd_restart_flag) begin                         data_reg <= {CMD_control,1'b1};                        state <= WR_CTL_1;                                                             end                else if((wr_flag ==1)&&(rd_flag == 0)) begin                        data_reg <= {CMD_control,1'b0};                        state <= WR_CTL_1;                    end                else if((wr_flag == 0)&&(rd_flag == 1)) begin                        data_reg <= {CMD_control,1'b0};                        state <= WR_CTL_1;                    end                         else begin                        data_reg <= 0;                          state <= IDLE;                    end             end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;             end            end     WR_CTL_1 : begin   //write CMD,change data at middle of SCL low time            ee_sclk_reg <= 0;                            if(delay_cnt == delay>>1) ee_data_reg <= data_reg[num];            else  ee_data_reg <= ee_data_reg;                        if(delay_cnt == delay) begin                  state <= state + 1;                delay_cnt <= 0;                end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;                end            end        WR_CTL_2: begin  //write CMD,write data            ee_sclk_reg <= 1;            ee_data_reg <= ee_data_reg;            if(delay_cnt == delay) begin                  if(num == 0) begin                                         state <= state + 1;                    delay_cnt <= 0;                                           end               else begin                    state <= WR_CTL_1;                    delay_cnt <= 0;                   num <= num -1;                 end              end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;                end            end                    WR_CTL_ACK1 : begin     //ack            ee_sclk_reg <= 0;            ee_data_reg <= 0;                        if(delay_cnt == 4)  dir_sda_flag <= 0;  //delay, make sure SDA change in the SCK Low            else  dir_sda_flag <= dir_sda_flag;                        if(delay_cnt == delay) begin                    state <= state + 1;                    delay_cnt <= 0;                  end                else  begin                    state <= state ;                    delay_cnt <= delay_cnt + 1;             end         end        WR_CTL_ACK2 : begin                    ee_sclk_reg <= 1;            if(delay_cnt == delay) begin                                        delay_cnt <= 0;                    if(rd_restart_flag)  begin                         state <= RD_DATA_1;                        delay_cnt <= 0;                            num <= 7;                        rd_restart_flag <= 0;                    end                    else begin                       state <= WR_ADDR_1;                            num <= 7;                    end                  end                else  begin                    state <= state ;                    delay_cnt <= delay_cnt + 1;             end                            end                  WR_ADDR_1: begin   //write addr,change data          ee_sclk_reg <= 0;                            if(delay_cnt == 4)  dir_sda_flag <= 1;            else  dir_sda_flag <= dir_sda_flag;                if(delay_cnt == delay>>1) ee_data_reg <= addr_reg[num];            else  ee_data_reg <= ee_data_reg;                        if(delay_cnt == delay) begin                  state <= state + 1;                delay_cnt <= 0;                end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;                end                            end            WR_ADDR_2: begin   //write addr,WRITE data            ee_sclk_reg <= 1;            ee_data_reg <= ee_data_reg;            if(delay_cnt == delay) begin                  if(num == 0) begin                        state <= WR_ADDR_ACK1;                    delay_cnt <= 0;                     end               else begin                    state <= WR_ADDR_1;                    delay_cnt <= 0;                   num <= num -1;                 end              end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;                end            end             WR_ADDR_ACK1 : begin            ee_sclk_reg <= 0;            ee_data_reg <= 0;                        if(delay_cnt == 4)  dir_sda_flag <= 0;            else  dir_sda_flag <= dir_sda_flag;                        if(delay_cnt == delay) begin                    state <= state + 1;                    delay_cnt <= 0;                  end                else  begin                    state <= state ;                    delay_cnt <= delay_cnt + 1;             end            end   WR_ADDR_ACK2: begin            ee_sclk_reg <= 1;            if(delay_cnt == delay) begin                    delay_cnt <= 0;                    if((wr_flag ==1)&&(rd_flag == 0))  begin                        state <= WR_DATA_1 ;                        num <= 7;                        end                    else if((wr_flag ==0)&&(rd_flag == 1))  begin                        state <= START_1 ;                        rd_restart_flag <= 1;                        dir_sda_flag <= 1;                     end                    else begin                        state <= IDLE ;                    end                   end                else  begin                    state <= state ;                    delay_cnt <= delay_cnt + 1;             end            end            WR_DATA_1 : begin            ee_sclk_reg <= 0;                num <= 7 ;                        if(delay_cnt == 3)  dir_sda_flag <= 1;            else  dir_sda_flag <= dir_sda_flag;                        if(delay_cnt == 1) rd_wrdata_flag <= 1;            else rd_wrdata_flag <= 0;                        if(delay_cnt == 5) begin                delay_cnt <= 0 ;               state <= state + 1;                data_reg <= wr_data;                              end            else  begin                                delay_cnt <= delay_cnt + 1 ;               state <= state;             end            end        WR_DATA_2 : begin            ee_sclk_reg <= 0;            if(delay_cnt == delay>>1) ee_data_reg <= data_reg[num];            else  ee_data_reg <= ee_data_reg;                        if(delay_cnt == delay) begin                  state <= state + 1;                delay_cnt <= 0;                end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;                end                  end                  WR_DATA_3: begin             ee_sclk_reg <= 1;            ee_data_reg <= ee_data_reg;            if(delay_cnt == delay) begin                  if(num == 0) begin                        state <= WR_DATA_ACK1;                        delay_cnt <= 0;                         end                           else begin                    state <= WR_DATA_2;                    delay_cnt <= 0;                   num <= num -1;                 end              end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;             end             end                 WR_DATA_ACK1: begin           ee_sclk_reg <= 0;            ee_data_reg <= 0;                        if(delay_cnt == 4)  dir_sda_flag <= 0;            else  dir_sda_flag <= dir_sda_flag;                        if(delay_cnt == delay) begin                    state <= state + 1;                    delay_cnt <= 0;                  end                else  begin                    state <= state ;                    delay_cnt <= delay_cnt + 1;             end            end      WR_DATA_ACK2: begin           ee_sclk_reg <= 1;            if(delay_cnt == delay) begin                    delay_cnt <= 0;                    dir_sda_flag <= 1;                                        if(wr_data_flag)  state <= WR_DATA_1 ;                    else state <= STOP_1 ;                                          end                else  begin                    state <= state ;                    delay_cnt <= delay_cnt + 1;             end            end                                   RD_DATA_1: begin   //read             ee_sclk_reg <= 0;                         if(delay_cnt == 4)  dir_sda_flag <= 0;             else  dir_sda_flag <= dir_sda_flag;                         if(delay_cnt == delay>>1)     rd_data_reg[num] <= ee_I2C_SDA;            else  data_reg <= data_reg;                          if(delay_cnt == delay) begin                  state <= state + 1;                delay_cnt <= 0;                end              else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;                end         end      RD_DATA_2: begin             ee_sclk_reg <= 1;                         if(delay_cnt == delay) begin                 if(num == 0) begin                    state <= state + 1;                    delay_cnt <= 0;                  end                 else begin                   state <= RD_DATA_1;                    delay_cnt <= 0;                    num <= num - 1;                 end                end              else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;                end         end        RD_DATA_ACK1: begin    //read data  from slave, Notice: the ACK send from Master.                ee_sclk_reg <= 0;                          if(delay_cnt == 4)  dir_sda_flag <= 1;            else  dir_sda_flag <= dir_sda_flag;                            if(rd_data_flag) ee_data_reg <= 0;     //if have data need to read, Master must PULL DOWN the SDA                         else ee_data_reg <= 1;                        if(delay_cnt == delay) begin                    state <= state + 1;                    delay_cnt <= 0;                  end                else  begin                    state <= state ;                    delay_cnt <= delay_cnt + 1;             end                                end        RD_DATA_ACK2 : begin                        ee_sclk_reg <= 1;            if(delay_cnt == 2)  wr_rddata_flag <= 1;            else wr_rddata_flag <= 0;                        if(delay_cnt == delay) begin                    delay_cnt <= 0;                                                            if(rd_data_flag) begin                        state <= RD_DATA_1 ;                        num <= 7;                     end                    else begin                        state <= STOP_1 ;                            num <= 0;                     end                  end                else  begin                    state <= state ;                    delay_cnt <= delay_cnt + 1;             end                end                 STOP_1: begin             ee_sclk_reg <= 0;                ee_data_reg <= 0;           if(delay_cnt == delay) begin                  state <= state + 1;                delay_cnt <= 0;                end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;                end                            end                STOP_2: begin            ee_sclk_reg <= 1;                ee_data_reg <= 0;           if(delay_cnt == delay) begin                  state <= state + 1;                delay_cnt <= 0;                end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;                end                            end        STOP_3: begin            ee_sclk_reg <= 1;                ee_data_reg <= 1;           if(delay_cnt == delay) begin                  if(wr_flag == 1)  begin                     state <= state + 1;                    delay_cnt <= 0;                    end                else begin  //read,not need wait.                    rd_flag <= 0;                    state <= IDLE;                     delay_cnt <= 0;                 end                end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;                end                            end      WRITE_TIME:  begin  //if write, need wait a lot time to re-satrt.if read, not need wait.           wr_flag <= 0;            if(delay_cnt == delay_10ms) begin                  state <= IDLE;                delay_cnt <= 0;                end            else begin                 state <= state ;                delay_cnt <= delay_cnt + 1;                end                            end        default: state <= IDLE;         endcase     end  end     //----------------------------------  assign     ee_I2C_CLK = ee_sclk_reg;  assign     ee_I2C_SDA = dir_sda_flag ? ee_data_reg: 1'bz;      assign     rd_wrdata_en = rd_wrdata_flag;  assign     wr_rddata_en = wr_rddata_flag;    assign     rd_data = rd_data_reg;       endmodule
View Code
// megafunction wizard: %FIFO%// GENERATION: STANDARD// VERSION: WM1.0// MODULE: scfifo // ============================================================// File Name: RD_DATA_BUF.v// Megafunction Name(s)://             scfifo//// Simulation Library Files(s)://             altera_mf// ============================================================// ************************************************************// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!//// 16.0.0 Build 211 04/27/2016 SJ Standard Edition// ************************************************************//Copyright (C) 1991-2016 Altera Corporation. All rights reserved.//Your use of Altera Corporation's design tools, logic functions //and other software and tools, and its AMPP partner logic //functions, and any output files from any of the foregoing //(including device programming or simulation files), and any //associated documentation or information are expressly subject //to the terms and conditions of the Altera Program License //Subscription Agreement, the Altera Quartus Prime License Agreement,//the Altera MegaCore Function License Agreement, or other //applicable license agreement, including, without limitation, //that your use is for the sole purpose of programming logic //devices manufactured by Altera and sold by Altera or its //authorized distributors.  Please refer to the applicable //agreement for further details.// synopsys translate_off`timescale 1 ps / 1 ps// synopsys translate_onmodule RD_DATA_BUF (    aclr,    clock,    data,    rdreq,    wrreq,    empty,    full,    q,    usedw);    input      aclr;    input      clock;    input    [7:0]  data;    input      rdreq;    input      wrreq;    output      empty;    output      full;    output    [7:0]  q;    output    [4:0]  usedw;    wire  sub_wire0;    wire  sub_wire1;    wire [7:0] sub_wire2;    wire [4:0] sub_wire3;    wire  empty = sub_wire0;    wire  full = sub_wire1;    wire [7:0] q = sub_wire2[7:0];    wire [4:0] usedw = sub_wire3[4:0];    scfifo    scfifo_component (                .aclr (aclr),                .clock (clock),                .data (data),                .rdreq (rdreq),                .wrreq (wrreq),                .empty (sub_wire0),                .full (sub_wire1),                .q (sub_wire2),                .usedw (sub_wire3),                .almost_empty (),                .almost_full (),                .eccstatus (),                .sclr ());    defparam        scfifo_component.add_ram_output_register = "OFF",        scfifo_component.intended_device_family = "Cyclone IV E",        scfifo_component.lpm_numwords = 32,        scfifo_component.lpm_showahead = "OFF",        scfifo_component.lpm_type = "scfifo",        scfifo_component.lpm_width = 8,        scfifo_component.lpm_widthu = 5,        scfifo_component.overflow_checking = "ON",        scfifo_component.underflow_checking = "ON",        scfifo_component.use_eab = "ON";endmodule// ============================================================// CNX file retrieval info// ============================================================// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "1"// Retrieval info: PRIVATE: Clock NUMERIC "0"// Retrieval info: PRIVATE: Depth NUMERIC "32"// Retrieval info: PRIVATE: Empty NUMERIC "1"// Retrieval info: PRIVATE: Full NUMERIC "1"// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"// Retrieval info: PRIVATE: Optimize NUMERIC "2"// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"// Retrieval info: PRIVATE: UsedW NUMERIC "1"// Retrieval info: PRIVATE: Width NUMERIC "8"// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"// Retrieval info: PRIVATE: diff_widths NUMERIC "0"// Retrieval info: PRIVATE: msb_usedw NUMERIC "0"// Retrieval info: PRIVATE: output_width NUMERIC "8"// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"// Retrieval info: PRIVATE: rsFull NUMERIC "0"// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"// Retrieval info: PRIVATE: sc_aclr NUMERIC "1"// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"// Retrieval info: PRIVATE: wsFull NUMERIC "1"// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "32"// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8"// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "5"// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"// Retrieval info: CONSTANT: USE_EAB STRING "ON"// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL "aclr"// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty"// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL "full"// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq"// Retrieval info: USED_PORT: usedw 0 0 5 0 OUTPUT NODEFVAL "usedw[4..0]"// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq"// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0// Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 0// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0// Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0// Retrieval info: CONNECT: usedw 0 0 5 0 @usedw 0 0 5 0// Retrieval info: GEN_FILE: TYPE_NORMAL RD_DATA_BUF.v TRUE// Retrieval info: GEN_FILE: TYPE_NORMAL RD_DATA_BUF.inc FALSE// Retrieval info: GEN_FILE: TYPE_NORMAL RD_DATA_BUF.cmp FALSE// Retrieval info: GEN_FILE: TYPE_NORMAL RD_DATA_BUF.bsf FALSE// Retrieval info: GEN_FILE: TYPE_NORMAL RD_DATA_BUF_inst.v FALSE// Retrieval info: GEN_FILE: TYPE_NORMAL RD_DATA_BUF_bb.v TRUE// Retrieval info: LIB_FILE: altera_mf
View Code
TB:
`timescale 1 ps/1 ps  module  EEPROM_TB;  reg            clk;  reg            rst_n;    wire       ee_I2C_CLK;  wire       ee_I2C_SDA;        EEPROM u_EEPROM(        .clk(clk),        .rst_n(rst_n),                .EEPROM_SCK(ee_I2C_CLK),        .EEPROM_SDA(ee_I2C_SDA)          );    parameter T = 20000;        always #(T/2)  clk = ~clk;         initial      begin        clk = 0;        rst_n = 0;                $stop;        #(500*T)  rst_n = 1;     end     endmodule
View Code

 

    

 

     

 

转载于:https://www.cnblogs.com/fhyfhy/p/7878679.html

你可能感兴趣的文章
大数据学习系列(8)-- WordCount+Block+Split+Shuffle+Map+Reduce技术详解
查看>>
【AS3代码】播放FLV视频流的三步骤!
查看>>
枚举的使用
查看>>
luogu4849 寻找宝藏 (cdq分治+dp)
查看>>
日志框架--(一)基础篇
查看>>
关于源程序到可运行程序的过程
查看>>
转载:mysql数据库密码忘记找回方法
查看>>
scratch少儿编程第一季——06、人在江湖混,没有背景怎么行。
查看>>
【贪心+DFS】D. Field expansion
查看>>
C# Async与Await的使用
查看>>
Mysql性能调优
查看>>
iOS基础-UIKit框架-多控制器管理-实例:qq界面框架
查看>>
自定义tabbar(纯代码)
查看>>
小程序底部导航栏
查看>>
ibatis学习笔记
查看>>
18-ES6(1)
查看>>
poj1611 简单并查集
查看>>
Ubuntu 14.04下安装CUDA8.0
查看>>
跨平台开发 -- C# 使用 C/C++ 生成的动态链接库
查看>>
C# BS消息推送 SignalR介绍(一)
查看>>