参考: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

最新文章

  1. How PhoneGap &amp; Titanium Works
  2. Hadoop学习-生态体系(ecosystem)概览
  3. IOS时间戳
  4. WebView点击加载的页面中的按钮时不弹出新窗口以及在加载后执行javascript
  5. Java Socket Example
  6. 安卓模拟器创建和使用SD卡的方法
  7. getgrgid()函数
  8. B/S和C/S的区别。
  9. 转:Java compiler level does not match the version of the installed Java project facet
  10. 一个小时学会Git
  11. MongoDB简单操作(java版)
  12. 【blog】MarkDown语法解析为HTML工具
  13. JCenter下载太慢, jcenter修改 https为http也许能帮助你
  14. 获取手机浏览器IP的函数
  15. 自己动手制作一个本地的yum仓库
  16. Spring Boot(七):Mybatis 多数据源最简解决方案
  17. Introduction to the visual formatting model
  18. Oracle EBS 清除并发请求和(或)管理器数据 请求
  19. erlang和ruby互相调用
  20. 寄存器CPU存储地址信息和数据信息的地方 CPU通过地址寄存器区分指令和数据

热门文章

  1. HDFS存入文件的整个流程
  2. spring boot 加入mail邮件支持
  3. Os-HackNos-Report
  4. vue定义全局date过滤器(自定义JS文件模块和Moment.js库)
  5. 通过 Filebeat 收集 ubuntu 系统日志
  6. java之子类对象实例化过程
  7. laravel5+ElasticSearch+go-mysql-elasticsearch MySQL数据实时导入(mac)
  8. ESP8266源码分析--打印的基本用法
  9. Metasploit从文件中读取目标地址
  10. Linux系统目录结构知识