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