目录
一、协议概述
1.1 多主设备,多从设备
i. 单主设备、单从设备
ii.单主设备、多从设备
iii.多主机、多从机
二、I2C的信号线
三、I2C的状态传输格式
3.1 空闲状态
3.2 起始状态
3.3 读/写状态
3.4 停止状态
四、I2C数据传输格式
4.1 器件地址数据
4.2 字节地址数据
4.3 有效数据
4.3.1 写数据 编辑
4.3.2 读数据
五、协议传输规范小结
5.1 单字节
5.1.1 写数据传输
5.1.2 读数据传输
实例:为正点原子达芬奇开发板所提供
I2C驱动模块
EEPROM_AT24C64模块
仿真TB模块
I2C是一种两线式串行总线,用于连接微控制器以及其外围设备,具有接口线少、控制简单、器件封装形式小和通信速率较高等优点。I2C只要求两条双向线路:串行数据线(Serial Data,SDA)和串行时钟线(Serial Clock,SCL),两条线都是双向传输的。I2C协议属于半双工协议(同一时刻,数据单向流动)。
I2C是可以多主设备,多从设备的总线协议,主机通过地址索引,驱动所需的从机设备。
SCL:串行时钟总线,主设备向从设备传输;
SDA:串行数据总线,可双向传输数据信号。
I2C传输时有空闲状态、起始状态、读/写状态以及停止状态。
SCL和SDA都为高电平,此时I2C的设备都处于空闲状态。
当SCL为高电平时,SDA从1跳转到0,则为起始位,等待数据开始传输。
当SCL为低电平时,SDA可以进行数据传输;当SCL为高电平时,SDA则保持不变。
当SCL为高电平时,SDA信号从0到1,则为停止位,I2C则进入空闲状态。
接收到起始信号后,主设备从高到低的顺序依次发送器件地址给从设备,器件地址一般为7bit,器件地址后面紧接着1bit读写控制位,读操作则为高电平,写操作为低电平;最后紧跟1bit的应答位ACK,由从机发送给主机;若接收正确,则应答位为低电平0;接收错误,则为高电平。
接收到字节地址的低电平应答位,则开始字节地址传输,同样是按照从高到底的顺序依次发送字节地址给从设备,字节地址可以是16bit,也可以是8bit。若是16位则分成高八位和低八位分别传输。字节地址传输完成后则从机向主机发送1bit的应答信号。
主机向从机每次发送一个字节的数据,按照从高位到低位的顺序发送。发送完8bit的数据后,从机会给主机发送一个bit的应答信号,若应答信号为低位,则表示从机接收完成;若应答信号为高,则表示接收失败。这里只发送了一个字节的数据,如果发送多个字节数据,只需要在接收到应答信号后继续发送后续的字节。
从机向主机从高位到低位发送前面写入的数据,每完成一个字节的传输,主机向从机发送一个bit的应答位,此时应答位为高位表示数据有效。
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/08/01 15:46:06
// Design Name:
// Module Name: i2c_dri
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module i2c_dri(
input clk, //系统时钟,50MHz
input rst_n, //系统复位信号
input i2c_exec, //i2c开始执行传输信号
input bit_ctrl, //地址字节控制信号
input [15:0] i2c_addr, //读写字节地址信号
input i2c_rh_wl, //i2c读写控制信号
input [7:0] i2c_data_w, //i2c写入数据的信号
output reg scl, //i2c的scl时钟信号
output sda, //i2c的sda数据信号
output reg[7:0] i2c_data_r, //i2c读出数据的信号
output reg i2c_done, //i2c信号传输完成信号
output reg i2c_ack, //i2c的应答信号
output reg clk_dri //i2c的驱动时钟
);
parameter ST_IDLE = 8'b0000_0001, //
ST_ADDR = 8'b0000_0010,
ADDR16 = 8'b0000_0100,
ADDR8 = 8'b0000_1000,
DATA_WR = 8'b0001_0000,
ADDR_RD = 8'b0010_0000,
DATA_RD = 8'b0100_0000,
STOP = 8'b1000_0000;
reg [7:0] current_state,next_state;
reg st_done; //状态结束信号
reg sda_dir; //I2C数据方向控制
wire sda_in; //SDA输入信号
reg sda_out; //SDA输出信号
reg [6:0] cnt; //i2c计数
reg wr_flag; //读写标志信号
reg [15:0] addr_t; //地址寄存器
reg [7:0] data_wr_t; //写入数据的临时寄存器
reg [7:0] data_r; //读取的数据
parameter SLAVE_ADDR = 7'b1010000; //从机地址
parameter CLK_FREQ = 26'd50_000_000;
parameter I2C_FREQ = 18'd250_000;
wire [8:0] clk_divide; //模块驱动时钟的分频系数
reg [7:0] clk_cnt;
assign clk_divide = (CLK_FREQ/I2C_FREQ)>>2'd2; //模块驱动时钟的分频系数
//生成I2C的SCL的四倍频率的驱动时钟用于驱动i2c的操作
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
clk_dri <= 1'b0;
clk_cnt <= 8'b0;
end
else if(clk_cnt == (clk_divide[8:1]-1'b1))begin
clk_dri <= ~clk_dri;
clk_cnt <= 8'b0;
end
else begin
clk_dri <= clk_dri;
clk_cnt <= clk_cnt + 1'b1;
end
end
//同步时序描述状态转移
always @(posedge clk_dri or negedge rst_n)begin
if(!rst_n)
current_state <= ST_IDLE;
else
current_state <= next_state ;
end
//组合逻辑判断状态转移条件
always @(*)begin
next_state = ST_IDLE;
case(current_state)
ST_IDLE :begin
if(i2c_exec)begin
next_state <= ST_ADDR;
end
else
next_state <= ST_IDLE;
end
ST_ADDR :begin
if(st_done)begin
if(bit_ctrl)
next_state <= ADDR16;
else
next_state <= ADDR8;
end
else
next_state <= ST_ADDR;
end
ADDR16 : begin
if(st_done)
next_state <= ADDR8;
else
next_state <= ADDR16;
end
ADDR8 : begin
if(st_done)begin
if(i2c_rh_wl)
next_state <= ADDR_RD;
else
next_state <= DATA_WR;
end
else
next_state <= ADDR8;
end
ADDR_RD : begin
if(st_done)
next_state <= DATA_RD;
else
next_state <= ADDR_RD;
end
DATA_RD : begin
if(st_done)
next_state <= STOP;
else
next_state <= DATA_RD;
end
DATA_WR : begin
if(st_done)
next_state <= STOP;
else
next_state <= DATA_WR;
end
STOP : begin
if(st_done)
next_state <= ST_IDLE;
else
next_state <= STOP;
end
default : next_state <= ST_IDLE;
endcase
end
assign sda = sda_dir ? sda_out : 1'bz; //sda数据输出或高阻
assign sda_in = sda; //sda数据输入
//时序电路描述状态输出
always @(posedge clk_dri or negedge rst_n)begin
if(!rst_n)begin
scl <= 1'b1;
sda_out <= 1'b1;
sda_dir <= 1'b1;
i2c_done <= 1'b0;
i2c_ack <= 1'b0;
cnt <= 7'b0;
st_done <= 1'b0;
i2c_data_r <= 8'b0;
wr_flag <= 1'b0;
addr_t <= 16'b0;
data_wr_t <= 1'b0;
data_r <= 8'b0;
end
st_done <= 1'b0;
cnt <= cnt + 1'b1;
case(current_state)
ST_IDLE : begin
scl <= 1'b1;
sda_out <= 1'b1;
i2c_done <= 1'b0;
cnt <= 7'b0;
if(i2c_exec)begin
wr_flag <= i2c_rh_wl;
addr_t <= i2c_addr;
data_wr_t <= i2c_data_w;
i2c_ack <= 1'b0;
end
end
ST_ADDR : begin
case(cnt)
7'd1: sda_out <= 1'b0; //开始I2C传输
7'd3: scl <= 1'b0;
7'd4: sda_out <= SLAVE_ADDR[6];
7'd5: scl <= 1'b1;
7'd7: scl <= 1'b0;
7'd8: sda_out <= SLAVE_ADDR[5];
7'd9: scl <= 1'b1;
7'd11: scl <= 1'b0;
7'd12: sda_out <= SLAVE_ADDR[4];
7'd13: scl <= 1'b1;
7'd15: scl <= 1'b0;
7'd16: sda_out <= SLAVE_ADDR[3];
7'd17: scl <= 1'b1;
7'd19: scl <= 1'b0;
7'd20: sda_out <= SLAVE_ADDR[2];
7'd21: scl <= 1'b1;
7'd23: scl <= 1'b0;
7'd24: sda_out <= SLAVE_ADDR[1];
7'd25: scl <= 1'b1;
7'd27: scl <= 1'b0;
7'd28: sda_out <= SLAVE_ADDR[0];
7'd29: scl <= 1'b1;
7'd31: scl <= 1'b0;
7'd32: sda_out <= 1'b0; //写操作
7'd33: scl <= 1'b1;
7'd35: scl <= 1'b0;
7'd36: begin
sda_dir <= 1'b0;
sda_out <= 1'b1;
end
7'd37: scl <= 1'b1;
7'd38: begin //从机应答
st_done <= 1'b1;
if(sda_in) //高电平表示未应答
i2c_ack <= 1'b1;
end
7'd39: begin
scl <= 1'b0;
cnt <= 7'b0;
end
default: ;
endcase
end
ADDR16 : begin
case(cnt)
7'd0:begin
sda_dir <= 1'b1;
sda_out <= addr_t[15];
end
7'd1 :scl <= 1'b1;
7'd3 :scl <= 1'b0;
7'd4 :sda_out <= addr_t[14];
7'd5 :scl <= 1'b1;
7'd7 :scl <= 1'b0;
7'd8 :sda_out <= addr_t[13];
7'd9 :scl <= 1'b1;
7'd11 :scl <= 1'b0;
7'd12 :sda_out <= addr_t[12];
7'd13 :scl <= 1'b1;
7'd15 :scl <= 1'b0;
7'd16 :sda_out <= addr_t[11];
7'd17 :scl <= 1'b1;
7'd19 :scl <= 1'b0;
7'd20 :sda_out <= addr_t[10];
7'd21 :scl <= 1'b1;
7'd23 :scl <= 1'b0;
7'd24 :sda_out <= addr_t[9];
7'd25 :scl <= 1'b1;
7'd27 :scl <= 1'b0;
7'd28 :sda_out <= addr_t[8];
7'd29 :scl <= 1'b1;
7'd31 :scl <= 1'b0;
7'd32 :begin
sda_dir <= 1'b0;
sda_out <= 1'b1;
end
7'd33 :scl <= 1'b1;
7'd34 :begin
st_done <= 1'b1;
if(sda_in)
i2c_ack <= 1'b1;
end
7'd35 :begin
scl <= 1'b0;
cnt <= 1'b0;
end
default : ;
endcase
end
ADDR8 : begin
case(cnt)
7'd0:begin
sda_dir <= 1'b1;
sda_out <= addr_t[7];
end
7'd1 :scl <= 1'b1;
7'd3 :scl <= 1'b0;
7'd4 :sda_out <= addr_t[6];
7'd5 :scl <= 1'b1;
7'd7 :scl <= 1'b0;
7'd8 :sda_out <= addr_t[5];
7'd9 :scl <= 1'b1;
7'd11 :scl <= 1'b0;
7'd12 :sda_out <= addr_t[4];
7'd13 :scl <= 1'b1;
7'd15 :scl <= 1'b0;
7'd16 :sda_out <= addr_t[3];
7'd17 :scl <= 1'b1;
7'd19 :scl <= 1'b0;
7'd20 :sda_out <= addr_t[2];
7'd21 :scl <= 1'b1;
7'd23 :scl <= 1'b0;
7'd24 :sda_out <= addr_t[1];
7'd25 :scl <= 1'b1;
7'd27 :scl <= 1'b0;
7'd28 :sda_out <= addr_t[0];
7'd29 :scl <= 1'b1;
7'd31 :scl <= 1'b0;
7'd32 :begin
sda_dir <= 1'b0;
sda_out <= 1'b1;
end
7'd33 :scl <= 1'b1;
7'd34 :begin
st_done <= 1'b1;
if(sda_in)
i2c_ack <= 1'b1;
end
7'd35 :begin
scl <= 1'b0;
cnt <= 1'b0;
end
default : ;
endcase
end
DATA_WR : begin
case(cnt)
7'd0 :begin
sda_out <= data_wr_t[7];
sda_dir <= 1'b1;
end
7'd1 :scl <= 1'b1;
7'd3 :scl <= 1'b0;
7'd4 :sda_out <= data_wr_t[6];
7'd5 :scl <= 1'b1;
7'd7 :scl <= 1'b0;
7'd8 :sda_out <= data_wr_t[5];
7'd9 :scl <= 1'b1;
7'd11 :scl <= 1'b0;
7'd12 :sda_out <= data_wr_t[4];
7'd13 :scl <= 1'b1;
7'd15 :scl <= 1'b0;
7'd16 :sda_out <= data_wr_t[3];
7'd17 :scl <= 1'b1;
7'd19 :scl <= 1'b0;
7'd20 :sda_out <= data_wr_t[2];
7'd21 :scl <= 1'b1;
7'd23 :scl <= 1'b0;
7'd24 :sda_out <= data_wr_t[1];
7'd25 :scl <= 1'b1;
7'd27 :scl <= 1'b0;
7'd28 :sda_out <= data_wr_t[0];
7'd29 :scl <= 1'b1;
7'd31 :scl <= 1'b0;
7'd32 :begin
sda_dir <= 1'b0;
sda_out <= 1'b1;
end
7'd33 :scl <= 1'b1;
7'd34 :begin
st_done <= 1'b1;
if(sda_in)
i2c_ack <= 1'b1;
end
7'd35 :begin
scl <= 1'b0;
cnt <= 1'b0;
end
default : ;
endcase
end
ADDR_RD :begin
case(cnt)
7'd0 :begin
sda_dir <= 1'b1;
sda_out <= 1'b1;
end
7'd1 :scl <= 1'b1;
7'd2 :sda_out <= 1'b0;
7'd3 :scl <= 1'b0;
7'd4 :sda_out <= SLAVE_ADDR[6];
7'd5 :scl <= 1'b1;
7'd7 :scl <= 1'b0;
7'd8 :sda_out <= SLAVE_ADDR[5];
7'd9 :scl <= 1'b1;
7'd11 :scl <= 1'b0;
7'd12 :sda_out <= SLAVE_ADDR[4];
7'd13 :scl <= 1'b1;
7'd15 :scl <= 1'b0;
7'd16 :sda_out <= SLAVE_ADDR[3];
7'd17 :scl <= 1'b1;
7'd19 :scl <= 1'b0;
7'd20 :sda_out <= SLAVE_ADDR[2];
7'd21 :scl <= 1'b1;
7'd23 :scl <= 1'b0;
7'd24 :sda_out <= SLAVE_ADDR[1];
7'd25 :scl <= 1'b1;
7'd27 :scl <= 1'b0;
7'd28 :sda_out <= SLAVE_ADDR[0];
7'd29 :scl <= 1'b1;
7'd31 :scl <= 1'b0;
7'd32 :sda_out <= 1'd1; //读操作
7'd33 :scl <= 1'b1;
7'd35 :scl <= 1'b0;
7'd36 :begin
sda_dir <= 1'b0;
sda_out <= 1'b1;
end
7'd37 :scl <= 1'b1;
7'd38 :begin
st_done <= 1'd1;
if(sda_in)
i2c_ack <= 1'b1;
end
7'd39 :begin
scl <= 1'b0;
cnt <= 1'b0;
end
default : ;
endcase
end
DATA_RD : begin
case(cnt)
7'b0 :sda_dir <= 1'b0;
7'd1 :begin
data_r[7] <= sda_in;
scl <= 1'b1;
end
7'd3 :scl <= 1'b0;
7'd5 :begin
data_r[6] <= sda_in;
scl <= 1'b1;
end
7'd7 :scl <= 1'b0;
7'd9 :begin
data_r[5] <= sda_in;
scl <= 1'b1;
end
7'd11 :scl <= 1'b0;
7'd13 :begin
data_r[4] <= sda_in;
scl <= 1'b1;
end
7'd15 :scl <= 1'b0;
7'd17 :begin
data_r[3] <= sda_in;
scl <= 1'b1;
end
7'd19 :scl <= 1'b0;
7'd21 :begin
data_r[2] <= sda_in;
scl <= 1'b1;
end
7'd23 :scl <= 1'b0;
7'd25 :begin
data_r[1] <= sda_in;
scl <= 1'b1;
end
7'd27 :scl <= 1'b0;
7'd29 :begin
data_r[0] <= sda_in;
scl <= 1'b1;
end
7'd31 :scl <= 1'b0;
7'd32 :begin
sda_dir <= 1'b1;
sda_out <= 1'b1;
end
7'd33 :scl <= 1'b1;
7'd34 :st_done <= 1'b1; //非应答
7'd35 :begin
scl <= 1'b0;
cnt <= 7'd0;
i2c_data_r <= data_r;
end
default : ;
endcase
end
STOP : begin
case(cnt)
7'd0 : begin
sda_dir <= 1'b1;
sda_out <= 1'b0;
end
7'd1 : scl <= 1'b1;
7'd3 : sda_out <= 1'b1;
7'd15 : st_done <= 1'b1;
7'd16 : begin
cnt <= 7'd0;
i2c_done <= 1'b1;
end
default : ;
endcase
end
endcase
end
endmodule
`timescale 1ns/1ns
`define timeslice 1250
module EEPROM_AT24C64(
scl,
sda
);
input scl;
inout sda;
reg out_flag;
reg[7:0] memory[8191:0];
reg[12:0]address;
reg[7:0]memory_buf;
reg[7:0]sda_buf;
reg[7:0]shift;
reg[7:0]addr_byte_h;
reg[7:0]addr_byte_l;
reg[7:0]ctrl_byte;
reg[1:0]State;
integer i;
//---------------------------
parameter
r7 = 8'b1010_1111, w7 = 8'b1010_1110, //main7
r6 = 8'b1010_1101, w6 = 8'b1010_1100, //main6
r5 = 8'b1010_1011, w5 = 8'b1010_1010, //main5
r4 = 8'b1010_1001, w4 = 8'b1010_1000, //main4
r3 = 8'b1010_0111, w3 = 8'b1010_0110, //main3
r2 = 8'b1010_0101, w2 = 8'b1010_0100, //main2
r1 = 8'b1010_0011, w1 = 8'b1010_0010, //main1
r0 = 8'b1010_0001, w0 = 8'b1010_0000; //main0
assign sda = (out_flag == 1) ? sda_buf[7] : 1'bz;
initial
begin
addr_byte_h = 0;
addr_byte_l = 0;
ctrl_byte = 0;
out_flag = 0;
sda_buf = 0;
State = 2'b00;
memory_buf = 0;
address = 0;
shift = 0;
for(i=0;i<=8191;i=i+1)
memory[i] = 0;
end
always@(negedge sda)
begin
if(scl == 1)
begin
State = State + 1;
if(State == 2'b11)
disable write_to_eeprom;
end
end
always@(posedge sda)
begin
if(scl == 1)
stop_W_R;
else
begin
casex(State)
2'b01:begin
read_in;
if(ctrl_byte == w7 || ctrl_byte == w6
|| ctrl_byte == w5 || ctrl_byte == w4
|| ctrl_byte == w3 || ctrl_byte == w2
|| ctrl_byte == w1 || ctrl_byte == w0)
begin
State = 2'b10;
write_to_eeprom;
end
else
State = 2'b00;
end
2'b11:
read_from_eeprom;
default:
State = 2'b00;
endcase
end
end
task stop_W_R;
begin
State = 2'b00;
addr_byte_h = 0;
addr_byte_l = 0;
ctrl_byte = 0;
out_flag = 0;
sda_buf = 0;
end
endtask
task read_in;
begin
shift_in(ctrl_byte);
shift_in(addr_byte_h);
shift_in(addr_byte_l);
end
endtask
task write_to_eeprom;
begin
shift_in(memory_buf);
address = {addr_byte_h[4:0], addr_byte_l};
memory[address] = memory_buf;
State = 2'b00;
end
endtask
task read_from_eeprom;
begin
shift_in(ctrl_byte);
if(ctrl_byte == r7 || ctrl_byte == w6
|| ctrl_byte == r5 || ctrl_byte == r4
|| ctrl_byte == r3 || ctrl_byte == r2
|| ctrl_byte == r1 || ctrl_byte == r0)
begin
address = {addr_byte_h[4:0], addr_byte_l};
sda_buf = memory[address];
shift_out;
State = 2'b00;
end
end
endtask
task shift_in;
output[7:0]shift;
begin
@(posedge scl) shift[7] = sda;
@(posedge scl) shift[6] = sda;
@(posedge scl) shift[5] = sda;
@(posedge scl) shift[4] = sda;
@(posedge scl) shift[3] = sda;
@(posedge scl) shift[2] = sda;
@(posedge scl) shift[1] = sda;
@(posedge scl) shift[0] = sda;
@(negedge scl)
begin
#(`timeslice);
out_flag = 1;
sda_buf = 0;
end
@(negedge scl)
begin
#(`timeslice-250);
out_flag = 0;
end
end
endtask
task shift_out;
begin
out_flag = 1;
for(i=6; i>=0; i=i-1)
begin
@(negedge scl);
#`timeslice;
sda_buf = sda_buf << 1;
end
@(negedge scl) #`timeslice sda_buf[7] = 1;
@(negedge scl) #`timeslice out_flag = 0;
end
endtask
endmodule
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/08/01 17:35:16
// Design Name:
// Module Name: i2c_dri_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
`timescale 1ns/1ps
module i2c_dri_tb();
parameter T = 20; //时钟周期为20ns
parameter IIC_WR_CYCYLE = 100;
parameter SLAVE_ADDR = 7'b1010000 ; //EEPROM从机地址
parameter CLK_FREQ = 26'd50_000_000; //模块输入的时钟频率
parameter I2C_FREQ = 18'd250_000; //IIC_SCL的时钟频率
reg clk;
reg rst_n;
reg i2c_exec;
reg bit_ctrl;
reg i2c_rh_wl;
reg [15:0]i2c_addr;
reg [7:0]i2c_data_w;
reg [13:0]delay_cnt;
reg [3:0]flow_cnt;
wire [7:0]i2c_data_r;
wire i2c_done;
wire scl;
wire sda;
wire clk_dri;
initial begin
clk = 1'b0;
rst_n = 1'b0;
#(T+1)rst_n = 1'b1;
end
always #(T/2)clk = ~clk;
always @(posedge clk_dri or negedge rst_n)begin
if(!rst_n)begin
i2c_exec <= 1'b0;
bit_ctrl <= 1'b0;
i2c_rh_wl <= 1'b0;
i2c_addr <= 16'h0;
i2c_data_w <= 8'h0;
flow_cnt <= 3'b0;
delay_cnt <= 1'b0;
end
else begin
case(flow_cnt)
'd0 : flow_cnt <= flow_cnt + 1'b1;
'd1 : begin
i2c_exec <= 1'b1;
bit_ctrl <= 1'b1;
i2c_rh_wl <= 1'b0;
i2c_addr <= 16'h0555;
i2c_data_w <= 8'hAA;
flow_cnt <= flow_cnt + 1'b1;
end
'd2 : begin
i2c_exec <= 1'b0;
flow_cnt <= flow_cnt + 1'b1;
end
'd3 : begin
if(i2c_done)
flow_cnt <= flow_cnt + 1'b1;
end
'd4 : begin
delay_cnt <= delay_cnt + 1'b1;
if(delay_cnt == IIC_WR_CYCYLE - 1'b1)
flow_cnt <= flow_cnt + 1'b1;
end
'd5 : begin
i2c_exec <= 1'b1;
bit_ctrl <= 1'b1;
i2c_rh_wl <= 1'b1; //读操作
i2c_addr <= 16'h0555;
i2c_data_w <= 8'hAA;
flow_cnt <= flow_cnt + 1'b1;
end
'd6 : begin
i2c_exec <= 1'b0;
flow_cnt <= flow_cnt + 1'b1;
end
'd7 : begin
if(i2c_done)
flow_cnt <= flow_cnt + 1'b1;
end
default:;
endcase
end
end
pullup(sda);
i2c_dri #(
.SLAVE_ADDR (SLAVE_ADDR), //EEPROM从机地址
.CLK_FREQ (CLK_FREQ ), //模块输入的时钟频率
.I2C_FREQ (I2C_FREQ ) //IIC_SCL的时钟频率
) u1(
.clk(clk), //系统时钟,50MHz
.rst_n(rst_n), //系统复位信号
.i2c_exec(i2c_exec), //i2c开始执行传输信号
.bit_ctrl(bit_ctrl), //地址字节控制信号
.i2c_addr(i2c_addr), //读写字节地址信号
.i2c_rh_wl(i2c_rh_wl), //i2c读写控制信号
.i2c_data_w(i2c_data_w), //i2c写入数据的信号
.scl(scl), //i2c的scl时钟信号
.sda(sda), //i2c的sda数据信号
.i2c_data_r(i2c_data_r), //i2c读出数据的信号
.i2c_done(i2c_done), //i2c信号传输完成信号
.i2c_ack(i2c_ack), //i2c的应答信号
.clk_dri(clk_dri) //i2c的驱动时钟
);
EEPROM_AT24C64 u_EEPROM_AT24C64(
.scl (scl),
.sda (sda)
);
endmodule