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

  tb:

  

 `timescale  ps/ 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 = ; always #(T/) clk = ~clk; initial
begin
clk = ;
rst =; #(*T) $stop; #(*T) rst =; end endmodule

对于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

  
  

// `define SIM   //if run modelsim, enable 

 module  eeprom_data(
input clk,
input rst_n, output wr_en,
output reg [:] wr_addr,
output reg [:] wr_data,
output reg wr_flag, output rd_en,
output reg [:] rd_addr,
input [:] rd_data,
output reg rd_flag, input rd_wrdata_en, //only one clk cycle high time
input wr_rddata_en ); reg [:] wr_cnt;
reg [:] rd_cnt; reg [:] cnt; reg [:] rd_wrdata_en_flag;
always @(posedge clk or negedge rst_n)
begin
if(rst_n == ) rd_wrdata_en_flag <= 'd0;
else rd_wrdata_en_flag <= {rd_wrdata_en_flag[:],rd_wrdata_en};
end `ifdef SIM
always @(posedge clk or negedge rst_n)
begin
if(rst_n == ) cnt <= ;
else if(cnt == 'd100_000) cnt <= 0;
else cnt <= cnt + ;
end assign wr_en = (cnt == 'd20_000);
assign rd_en = (cnt == 'd70_000); `else always @(posedge clk or negedge rst_n)
begin
if(rst_n == ) cnt <= ;
else if(cnt == 'd500_000_000) cnt <= 0;
else cnt <= cnt + ;
end assign wr_en = (cnt == 'd200_000_000);
assign rd_en = (cnt == 'd400_000_000); `endif parameter data_num = 'd16; //the data number of need to be write or read
//=========================================
//write
always @(posedge clk or negedge rst_n)
begin
if(rst_n == ) wr_addr <= ;
else if(rd_wrdata_en_flag[]) begin
if(wr_addr == data_num) wr_addr <= ;
else wr_addr <= wr_addr + ;
end
else wr_addr <= wr_addr;
end always @(posedge clk or negedge rst_n)
begin
if(rst_n == ) wr_data <= ;
else if(rd_wrdata_en_flag[]) begin
if(wr_data == data_num) wr_data <= ;
else wr_data <= wr_data + ;
end
else wr_data <= wr_data;
end always @(posedge clk or negedge rst_n)
begin
if(rst_n == ) wr_cnt <= ;
else if(rd_wrdata_en_flag[]) begin
if(wr_cnt == data_num) wr_cnt <= ;
else wr_cnt <= wr_cnt + ;
end
else wr_cnt <= wr_cnt;
end always @(posedge clk or negedge rst_n)
begin
if(rst_n == ) wr_flag <= ;
else if(wr_en) wr_flag <= ;
else if(rd_wrdata_en_flag[]) begin
if(wr_cnt == data_num) wr_flag <= ;
else wr_flag <= ;
end
else wr_flag <= wr_flag;
end //====================================
//read always @(posedge clk or negedge rst_n)
begin
if(rst_n == ) rd_addr <= ;
else if(wr_rddata_en) begin
if(rd_addr == data_num) rd_addr <= ;
else rd_addr <= rd_addr + ;
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 == ) rd_cnt <= ;
else if(wr_rddata_en) begin
if(rd_cnt == data_num) rd_cnt <= ;
else rd_cnt <= rd_cnt + ;
end
else rd_cnt <= rd_cnt;
end always @(posedge clk or negedge rst_n)
begin
if(rst_n == ) rd_flag <= ;
else if(rd_en) rd_flag <= ;
else if(wr_rddata_en) begin
if(data_num == ) rd_flag <= ;
else if(rd_cnt == (data_num-)) rd_flag <= ;
else rd_flag <= ;
end
else rd_flag <= rd_flag;
end wire fifo_empty;
wire [:] cnt_fifo;
wire clr_fifo; assign clr_fifo = wr_rddata_en&&(rd_cnt == (data_num-)); RD_DATA_BUF u_rd_data_buf(
.aclr(clr_fifo),
.clock(clk),
.data(rd_data),
.rdreq('b0),
.wrreq(wr_rddata_en),
.empty(fifo_empty),
.full(),
.q(),
.usedw(cnt_fifo)
); endmodule
 //======================================
// I2C.v
//
//==========================
// `define SIM //if run modelsim, enable module I2C( input clk, //sysclk = 50Mhz
input rst_n, input [:] 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 [:] wr_addr,
input [:] wr_data,
input [:] rd_addr, output [:] 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 [:] wr_rd_en_reg1,wr_rd_en_reg2; reg [:] state; parameter IDLE = 'd0;
parameter START_1 = 'd1;
parameter START_2 = 'd2;
parameter START_3 = 'd3;
parameter WR_CTL_1 = 'd4;
parameter WR_CTL_2 = 'd5;
parameter WR_CTL_ACK1 = 'd6;
parameter WR_CTL_ACK2 = 'd7;
parameter WR_ADDR_1 = 'd8;
parameter WR_ADDR_2 = 'd9;
parameter WR_ADDR_ACK1 = 'd10;
parameter WR_ADDR_ACK2 = 'd11; parameter WR_DATA_1 = 'd12;
parameter WR_DATA_2 = 'd13;
parameter WR_DATA_3 = 'd14;
parameter WR_DATA_ACK1 = 'd15;
parameter WR_DATA_ACK2 = 'd16; parameter RD_DATA_1 = 'd17;
parameter RD_DATA_2 = 'd18;
parameter RD_DATA_ACK1 = 'd19;
parameter RD_DATA_ACK2 = 'd20; parameter STOP_1 = 'd21;
parameter STOP_2 = 'd22;
parameter STOP_3 = 'd23;
parameter WRITE_TIME = 'd24; //delay 10ms parameter CMD_control = 'b1010000; //eeprom addr = 3'b000; `ifdef SIM
parameter delay = 'd100;
parameter delay_10ms = 'd500;
`else
parameter delay = 'd300;
parameter delay_10ms = 'd500000;
`endif always @(posedge clk or negedge rst_n)
begin
if(rst_n == ) begin
wr_rd_en_reg2 <= 'd0;
wr_rd_en_reg1 <= 'd0 ;
end
else begin
wr_rd_en_reg2 <= wr_rd_en_reg1;
wr_rd_en_reg1 <= wr_rd_en ;
end
end reg [:] num; //data = 8bit
reg [:] delay_cnt;
reg [:] addr_reg; //reg addr
reg [:] 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 [:] rd_data_reg;
reg ee_sclk_reg;
reg ee_data_reg; always @(posedge clk or negedge rst_n)
begin
if(rst_n == ) begin
state <= IDLE;
num <= ;
delay_cnt <= ;
addr_reg <= ;
data_reg <= ;
wr_flag <= ;
dir_sda_flag <= ;
rd_flag <= ;
rd_restart_flag <= ;
rd_wrdata_flag <= ;
wr_rddata_flag <= ;
rd_data_reg <= ; ee_sclk_reg <= ;
ee_data_reg <= ; end
else begin
case(state)
IDLE: begin
num <= ;
delay_cnt <= ;
data_reg <= ;
addr_reg <= ;
wr_flag <= ;
dir_sda_flag <= ;
rd_flag <= ;
rd_restart_flag <= ;
rd_wrdata_flag <= ;
wr_rddata_flag <= ;
rd_data_reg <= ; ee_sclk_reg <= ;
ee_data_reg <= ; if(wr_rd_en_reg2 == 'b01) begin //write
addr_reg <= wr_addr ;
wr_flag <= ;
rd_flag <= ;
state <= START_1;
dir_sda_flag <= ;
end
else if(wr_rd_en_reg2 == 'b10) begin //read
addr_reg <= rd_addr ;
wr_flag <= ;
rd_flag <= ;
state <= START_1;
dir_sda_flag <= ;
rd_data_reg <= ;
end
else begin
state <= state; end
end START_1: begin //reg
ee_sclk_reg <= ;
ee_data_reg <= ;
if(delay_cnt == delay<< ) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
START_2: begin //pull down DATA
ee_sclk_reg <= ;
ee_data_reg <= ;
if(delay_cnt == delay ) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
START_3: begin //pull down SCL
ee_sclk_reg <= ;
ee_data_reg <= ;
num <= ;
if(delay_cnt == delay ) begin
delay_cnt <= ; if(rd_restart_flag) begin
data_reg <= {CMD_control,'b1};
state <= WR_CTL_1; end
else if((wr_flag ==)&&(rd_flag == )) begin
data_reg <= {CMD_control,'b0};
state <= WR_CTL_1;
end
else if((wr_flag == )&&(rd_flag == )) begin
data_reg <= {CMD_control,'b0};
state <= WR_CTL_1;
end
else begin
data_reg <= ;
state <= IDLE;
end
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
WR_CTL_1 : begin //write CMD,change data at middle of SCL low time
ee_sclk_reg <= ; if(delay_cnt == delay>>) ee_data_reg <= data_reg[num];
else ee_data_reg <= ee_data_reg; if(delay_cnt == delay) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
WR_CTL_2: begin //write CMD,write data
ee_sclk_reg <= ;
ee_data_reg <= ee_data_reg;
if(delay_cnt == delay) begin
if(num == ) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= WR_CTL_1;
delay_cnt <= ;
num <= num -;
end
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end WR_CTL_ACK1 : begin //ack
ee_sclk_reg <= ;
ee_data_reg <= ; if(delay_cnt == ) dir_sda_flag <= ; //delay, make sure SDA change in the SCK Low
else dir_sda_flag <= dir_sda_flag; if(delay_cnt == delay) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
WR_CTL_ACK2 : begin ee_sclk_reg <= ;
if(delay_cnt == delay) begin
delay_cnt <= ;
if(rd_restart_flag) begin
state <= RD_DATA_1;
delay_cnt <= ;
num <= ;
rd_restart_flag <= ;
end
else begin
state <= WR_ADDR_1;
num <= ;
end
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end end WR_ADDR_1: begin //write addr,change data
ee_sclk_reg <= ; if(delay_cnt == ) dir_sda_flag <= ;
else dir_sda_flag <= dir_sda_flag; if(delay_cnt == delay>>) ee_data_reg <= addr_reg[num];
else ee_data_reg <= ee_data_reg; if(delay_cnt == delay) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
WR_ADDR_2: begin //write addr,WRITE data
ee_sclk_reg <= ;
ee_data_reg <= ee_data_reg;
if(delay_cnt == delay) begin
if(num == ) begin
state <= WR_ADDR_ACK1;
delay_cnt <= ;
end
else begin
state <= WR_ADDR_1;
delay_cnt <= ;
num <= num -;
end
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end WR_ADDR_ACK1 : begin
ee_sclk_reg <= ;
ee_data_reg <= ; if(delay_cnt == ) dir_sda_flag <= ;
else dir_sda_flag <= dir_sda_flag; if(delay_cnt == delay) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
WR_ADDR_ACK2: begin
ee_sclk_reg <= ;
if(delay_cnt == delay) begin
delay_cnt <= ;
if((wr_flag ==)&&(rd_flag == )) begin
state <= WR_DATA_1 ;
num <= ;
end
else if((wr_flag ==)&&(rd_flag == )) begin
state <= START_1 ;
rd_restart_flag <= ;
dir_sda_flag <= ;
end
else begin
state <= IDLE ;
end
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end WR_DATA_1 : begin
ee_sclk_reg <= ;
num <= ; if(delay_cnt == ) dir_sda_flag <= ;
else dir_sda_flag <= dir_sda_flag; if(delay_cnt == ) rd_wrdata_flag <= ;
else rd_wrdata_flag <= ; if(delay_cnt == ) begin
delay_cnt <= ;
state <= state + ;
data_reg <= wr_data; end
else begin
delay_cnt <= delay_cnt + ;
state <= state;
end
end
WR_DATA_2 : begin
ee_sclk_reg <= ;
if(delay_cnt == delay>>) ee_data_reg <= data_reg[num];
else ee_data_reg <= ee_data_reg; if(delay_cnt == delay) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end WR_DATA_3: begin
ee_sclk_reg <= ;
ee_data_reg <= ee_data_reg;
if(delay_cnt == delay) begin
if(num == ) begin
state <= WR_DATA_ACK1;
delay_cnt <= ;
end
else begin
state <= WR_DATA_2;
delay_cnt <= ;
num <= num -;
end
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end WR_DATA_ACK1: begin
ee_sclk_reg <= ;
ee_data_reg <= ; if(delay_cnt == ) dir_sda_flag <= ;
else dir_sda_flag <= dir_sda_flag; if(delay_cnt == delay) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
WR_DATA_ACK2: begin
ee_sclk_reg <= ;
if(delay_cnt == delay) begin
delay_cnt <= ;
dir_sda_flag <= ; if(wr_data_flag) state <= WR_DATA_1 ;
else state <= STOP_1 ; end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end RD_DATA_1: begin //read
ee_sclk_reg <= ; if(delay_cnt == ) dir_sda_flag <= ;
else dir_sda_flag <= dir_sda_flag; if(delay_cnt == delay>>) rd_data_reg[num] <= ee_I2C_SDA;
else data_reg <= data_reg; if(delay_cnt == delay) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
RD_DATA_2: begin
ee_sclk_reg <= ; if(delay_cnt == delay) begin
if(num == ) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= RD_DATA_1;
delay_cnt <= ;
num <= num - ;
end
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
RD_DATA_ACK1: begin //read data from slave, Notice: the ACK send from Master.
ee_sclk_reg <= ; if(delay_cnt == ) dir_sda_flag <= ;
else dir_sda_flag <= dir_sda_flag; if(rd_data_flag) ee_data_reg <= ; //if have data need to read, Master must PULL DOWN the SDA
else ee_data_reg <= ; if(delay_cnt == delay) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end end
RD_DATA_ACK2 : begin ee_sclk_reg <= ;
if(delay_cnt == ) wr_rddata_flag <= ;
else wr_rddata_flag <= ; if(delay_cnt == delay) begin
delay_cnt <= ; if(rd_data_flag) begin
state <= RD_DATA_1 ;
num <= ;
end
else begin
state <= STOP_1 ;
num <= ;
end
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end STOP_1: begin
ee_sclk_reg <= ;
ee_data_reg <= ;
if(delay_cnt == delay) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
STOP_2: begin
ee_sclk_reg <= ;
ee_data_reg <= ;
if(delay_cnt == delay) begin
state <= state + ;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
STOP_3: begin
ee_sclk_reg <= ;
ee_data_reg <= ;
if(delay_cnt == delay) begin
if(wr_flag == ) begin
state <= state + ;
delay_cnt <= ;
end
else begin //read,not need wait.
rd_flag <= ;
state <= IDLE;
delay_cnt <= ;
end
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
end
end
WRITE_TIME: begin //if write, need wait a lot time to re-satrt.if read, not need wait.
wr_flag <= ;
if(delay_cnt == delay_10ms) begin
state <= IDLE;
delay_cnt <= ;
end
else begin
state <= state ;
delay_cnt <= delay_cnt + ;
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: 'bz; assign rd_wrdata_en = rd_wrdata_flag;
assign wr_rddata_en = wr_rddata_flag; assign rd_data = rd_data_reg; endmodule
// 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 ps / ps
// synopsys translate_on
module RD_DATA_BUF (
aclr,
clock,
data,
rdreq,
wrreq,
empty,
full,
q,
usedw); input aclr;
input clock;
input [:] data;
input rdreq;
input wrreq;
output empty;
output full;
output [:] q;
output [:] usedw; wire sub_wire0;
wire sub_wire1;
wire [:] sub_wire2;
wire [:] sub_wire3;
wire empty = sub_wire0;
wire full = sub_wire1;
wire [:] q = sub_wire2[:];
wire [:] usedw = sub_wire3[:]; 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 = ,
scfifo_component.lpm_showahead = "OFF",
scfifo_component.lpm_type = "scfifo",
scfifo_component.lpm_width = ,
scfifo_component.lpm_widthu = ,
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
TB:
`timescale  ps/ 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 = ; always #(T/) clk = ~clk; initial
begin
clk = ;
rst_n = ; $stop; #(*T) rst_n = ;
end endmodule

EEPROM的操作---SPI接口和I2C接口的更多相关文章

  1. (6)s3c2440用I2C接口访问EEPROM

    在前面阅读理解了I2C的官方协议文档后,就拿s3c2440和EEPROM来验证一下. 本来是想用s3c2440的SDA和SCL管脚复用为GPIO来模拟的,但在没有示波器的情况下搞了一周,怎么都出不来, ...

  2. 为 MaixPy 加入软 I2C 接口(移植 MicroPython 的 I2C)

    起因 本文的重心为讲解如何为一款芯片移植和实现 micropython 的通用组件,但会顺带解释不同芯片的工作方式和特性. 国际惯例,先有起因,再谈问题的解决,所以记得上次总结的 关于 K210 Ma ...

  3. JZ2440 裸机驱动 第12章 I2C接口

    本章目标: 了解I2C总线协议: 掌握S3C2410/S3C2440中I2C接口的使用方法: 12.1 I2C总线协议及硬件介绍 12.1.1 I2C总线协议 1 I2C总线的概念 2 I2C总线的信 ...

  4. linux 标准i2c接口(一)

    一:I2C设备操作方式: 1.  应用程序操作法:i2c的设备的驱动可以直接利用linux内核提供的i2c-dev.c文件提供的ioctl函数接口在应用层实现对i2c设备的读写,但是在应用层使用ioc ...

  5. 解决STM32 I2C接口死锁在BUSY状态的方法讨论

    关于STM32的I2C接口死锁在BUSY状态无法恢复的现象,网上已有很多讨论,看早几年比较老的贴子,有人提到复位MCU也无法恢复.只有断电才行的状况,那可是相当严重的问题.类似复位也无法恢复的情况是存 ...

  6. 树莓派配置RTC时钟(DS3231,I2C接口)

    1.购买基于DS3231的RTC时钟模块,并且支持3.3V的那种 2.配置树莓派 a.打开树莓派的i2c接口 sudo raspi-config -->Interfacing Options - ...

  7. ESP8266开发之旅 基础篇⑤ ESP8266 SPI通信和I2C通信

        设备与设备之间的通信往往都伴随着总线的使用,而用得比较多的就当属于SPI总线和I2C总线,而恰巧NodeMcu也支持这两种总线通信,所以本章的主要内容就是讲解ESP8266 SPI和I2C总线 ...

  8. JDBC的使用(二):PreparedStatement接口;ResultSet接口(获取结果集);例题:SQL注入

    ResultSet接口:类似于一个临时表,用来暂时存放数据库查询操作所获得的结果集. getInt(), getFloat(), getDate(), getBoolean(), getString( ...

  9. 比较器:Compare接口与Comparator接口区别与理解

    一.实现Compare接口与Comparator接口的类,都是为了对象实例数组排序的方便,因为可以直接调用 java.util.Arrays.sort(对象数组名称),可以自定义排序规则. 不同之处: ...

随机推荐

  1. InnoDB On-Disk Structures(四)--Doublewrite Buffer (转载)

    转载.节选于 https://dev.mysql.com/doc/refman/8.0/en/innodb-doublewrite-buffer.html The doublewrite buffer ...

  2. November 10th, Week 45th, Sunday, 2019

    Perfection has no place in love. 爱从不完美. Perfection has no place in love, and we should always try to ...

  3. JVM基础回顾记录(一):JVM的内存模型

    JVM的内存模型&垃圾收集算法 JVM内存模型 JAVA程序执行的基本流程(基于HotSpot): 图1 1.程序计数器 程序计数器是一块较小的内存空间,是当前线程执行字节码的行号指示器,字节 ...

  4. 1(1).有监督 VS 无监督

    对比一 : 有标签 vs 无标签 有监督机器学习又被称为“有老师的学习”,所谓的老师就是标签.有监督的过程为先通过已知的训练样本(如已知输入和对应的输出)来训练,从而得到一个最优模型,再将这个模型应用 ...

  5. JS数组去掉某一个元素

    /**数组去掉某一个元素**/ Array.prototype.remove = function(val) { var index = this.indexOf(val); if (index &g ...

  6. 2019-2020-1 20199305《Linux内核原理与分析》第八周作业

    可执行程序的工作原理 (一)ELF目标文件 (1)什么是ELF? 这里先提一个常见的名词"目标文件",是指编译器生成的文件.ELF(Executable and Linkable ...

  7. 什么是java变量,java变量是什么

    什么是变量,变量是什么 1.1. 什么是变量 在日常生活中,人们会用到大量数据,像去ATM机取款,首先,需要插入银行卡,这个过程其实就是ATM机的系统在获取银行卡号这个数据,而后,输入密码,这个过程也 ...

  8. 集合系列 Set(七):LinkedHashSet

    LinkedHashSet 继承了 HashSet,在此基础上维护了元素的插入顺序. public class LinkedHashSet<E> extends HashSet<E& ...

  9. IT兄弟连 HTML5教程 HTML5表单 HTML表单中的get和post方法

    指引 表单在网页应用中十分重要,基本上任何一个网站都必须使用到表单元素,所以表单的美观和易于交互对于网站设计就变得十分重要.HTML5对目前Web表单进行了全面提升,使得我们使用表单更加智能.它在保持 ...

  10. Rsync常见问题汇总

    rsync服务端开启的iptables防火墙 客户端的错误现象  No route to host 错误演示过程 [root@nfs01 tmp]# rsync -avz /etc/hosts rsy ...