1.实现的功能:向相应的地址写一个字节;随机读取某一地址的数据;
2.语言:Verilog;
3.基本知识:
IIC协议:关于IIC协议的接收文档网上很多,推荐网址:https://wenku.baidu.com/view/838dc456ad02de80d4d840c8.html添加链接描述
特别注意的地方:
EEPROM AT24LC04:
4.设计思路:
IIC读写有多个过程状态,可以使用状态机的思想来实现;
我的设计中涉及到三个时钟:系统时钟50mhz;IIC时钟也就是scl为250khz;用于驱动iic时钟为:4250khz=1mhz;
从上到下:系统时钟;驱动IIC时钟;SCL;SDA;
之所以产生一个1mhz的时钟是为了保证每次scl=0时sda数据改变,acl=1时sda数据稳定不变;这也就是为什么是4250khz了,这个4倍关系这么来的,当scl时钟为100khz,则需要4100khz时钟来驱动。
start信号:
stop信号:
5.设计中遇到的问题及感悟:
a)起始信号和停止信号sda满足的时间条件很重要,否则通信很容易不成功;
b)随机读数据的时候:切记切记切记要**发送两次起始信号和器件地址***,笔者由于看手册不仔细把第二个起始信号忘了发送,导致读取数据错误、通信不成功;
c)调试过程:先用modelsim仿真,符合时序要求时再上板,quartus ii可以使用虚拟逻辑分析来观察读出的数据;同时可以使用示波器一路看时钟,一路看数据线;
在这//IIC驱动模块
module I2C_Driver(
input sys_clk_50m ,
input sys_rst_n ,
input iic_en , //IIC使能
input wr_control , //IIC读写控制信号,0:写 1:读
input addr_control, //地址字节控制,0:1字节地址,1:2字节地址
input[15:0] iic_addr , //IIC字部地址输入
input[ 7:0] write_data , //写入IIC器件的数据
output reg[7:0] read_data , //读取IIC器件的数据
output reg iic_done , //一次IIC操作完成信号
output reg ACK , //应答信号
output reg iic_scl , //IIC时钟输出
inout iic_sda //IIC数据线(双向)
);
parameter SLAVE_ADDR = 7'b1010000 ;//IIC器件地址
parameter Write = 1'b0 ;//写
parameter Read = 1'b1 ;//读
parameter CLK_FREQ = 26'd50_000_000 ;//IIC模块的驱动时钟频率(CLK_FREQ),即系统时钟50MHz
parameter I2C_FREQ = 20'd250_000 ;//IIC的SCL时钟频率为250kHz
parameter CLK_Devide = (CLK_FREQ / I2C_FREQ) >> 2'd3 ;//分频系数
parameter WRITE_FLAG = 1'b0 ;//写标志位
parameter READ_FLAG = 1'b1 ;//读标志位
//localparam define
localparam iic_idle = 8'b0000_0001; //空闲状态
localparam iic_sladdr = 8'b0000_0010; //器件地址
localparam iic_addr16 = 8'b0000_0100; //发送16位字地址
localparam iic_addr8 = 8'b0000_1000; //发送8位字地址
localparam iic_data_wr = 8'b0001_0000; //写数据(8 bit)
localparam iic_addr_rd = 8'b0010_0000; //器件地址读
localparam iic_data_rd = 8'b0100_0000; //读数据(8 bit)
localparam iic_stop = 8'b1000_0000; //结束I2C操作
reg sda_dir ; //I2C数据(SDA)方向控制,1:out,0:高阻,可以输出
reg iic_sda_out ; //SDA输出
wire iic_sda_in ; //SDA输入
reg[7:0] current_state;
reg[7:0] next_state;
reg state_done1; //状态结束
reg state_done2; //状态结束
reg state_done3; //状态结束
reg state_done4; //状态结束
reg state_done5; //状态结束
reg state_done6; //状态结束
reg state_done7; //状态结束
reg wr_flag ; //读写标志
reg[15:0] addr_buff ; //写地址地址缓存
reg[ 7:0] wdata_buff ; //写数据缓存
reg[ 7:0] rdata_buff ; //读取数据缓存
reg[11:0] sys_clk_cnt ; //系统时钟计数器
reg[ 5:0] dri_clk_cnt ;
reg dri_clk ; //驱动iic时钟
assign iic_sda = sda_dir ? iic_sda_out : 1'bz; //SDA数据输出或高阻,高阻状态时数据线的状态不定这是就可以由从机来控制数据线的状态,主机负责读取状态
assign iic_sda_in = iic_sda ; //SDA数据输入
//对系统时钟计数
always @ ( posedge sys_clk_50m or negedge sys_rst_n ) begin
if( !sys_rst_n )
sys_clk_cnt <= 12'd0;
else if( sys_clk_cnt == CLK_Devide - 1 )
sys_clk_cnt <= 12'd0;
else
sys_clk_cnt <= sys_clk_cnt + 1'b1;
end
//获得驱动IIC时钟,IIC时钟250khz,驱动IIC时钟为4*250khz=1Mhz
always @ ( posedge sys_clk_50m or negedge sys_rst_n ) begin
if( !sys_rst_n )
dri_clk <= 1'b1;
else if( sys_clk_cnt == CLK_Devide - 1 )
dri_clk <= ~dri_clk;
else
dri_clk <= dri_clk;
end
//(三段式状态机)同步时序描述状态转移
always @ ( posedge sys_clk_50m or negedge sys_rst_n ) begin
if( !sys_rst_n )
current_state <= iic_idle;
else
current_state <= next_state;
end
//组合逻辑判断状态转移
always @ ( * ) begin
case( current_state )
iic_idle : if( iic_en )//1 //iic使能之后
next_state <= iic_sladdr; //进入器件地址状态
else
next_state <= iic_idle;
iic_sladdr : if( state_done1 ) begin//2
if( addr_control == 0) //进入字地址为1字节状态,直接发一个字节的地址
next_state <= iic_addr8;
else //进入字地址为2字节状态,先发高字节地址
next_state <= iic_addr16;
end
else
next_state <= iic_sladdr;
iic_addr16 : if( state_done2 ) //4
next_state <= iic_addr8; //进入地址低字节
else
next_state <= iic_addr16;
iic_addr8 : if( state_done3 ) begin //8
if( wr_flag == 1'b1 ) //进入读数据
next_state <= iic_addr_rd;
else //进入写数据
next_state <= iic_data_wr;
end
else
next_state <= iic_addr8;
iic_data_wr : if( state_done4 ) //写数据,16
next_state <= iic_stop;
else
next_state <= iic_data_wr;
iic_addr_rd : if( state_done5 )
next_state <= iic_data_rd; //写地址读取数据,32
else
next_state <= iic_addr_rd;
iic_data_rd : if( state_done6 ) //读取数据,64
next_state <= iic_stop;
else
next_state <= iic_data_rd;
iic_stop : if( state_done7 ) //停止信号,128
next_state <= iic_idle;
else
next_state <= iic_stop;
default : next_state <= iic_idle; //空闲状态
endcase
end
//时序电路描述状态输出
always @ ( posedge dri_clk or negedge sys_rst_n ) begin
if( !sys_rst_n ) begin
iic_scl <= 1'b1; //时钟线拉高
sda_dir <= 1'b1; //数据线输出
iic_sda_out <= 1'b1; //数据线拉高
addr_buff <= 16'd0; //字地址缓存
wdata_buff <= 8'd0; //写数据缓存
read_data <= 8'd0; //读数据寄存器
rdata_buff <= 8'd0; //读数据缓存
wr_flag <= 1'b0; //读写标志位
dri_clk_cnt <= 6'd0; //IIC驱动时钟计数器
state_done1 <= 1'b0; //各个状态结束标志位
state_done2 <= 1'b0;
state_done3 <= 1'b0;
state_done4 <= 1'b0;
state_done5 <= 1'b0;
state_done6 <= 1'b0;
state_done7 <= 1'b0;
ACK <= 1'b0; //应答标志位
iic_done <= 1'b0; //IIC计数操作
end
else begin
dri_clk_cnt <= dri_clk_cnt + 1'b1;
state_done1 <= 1'b0;
state_done2 <= 1'b0;
state_done3 <= 1'b0;
state_done4 <= 1'b0;
state_done5 <= 1'b0;
state_done6 <= 1'b0;
state_done7 <= 1'b0;
addr_buff <= iic_addr ; //将字地址缓存
wdata_buff <= write_data ; //将待写进从机的数据缓存
wr_flag <= wr_control ; //获得读写信号
ACK <= 1'b0; //应答标志位
iic_done <= 1'b0; //IIC结束标志信号为低电平
case( current_state )
iic_idle : begin
iic_scl <= 1'b1; //空闲时:时钟线和数据线拉高
sda_dir <= 1'b1; //输出
iic_sda_out <= 1'b1; //拉高
dri_clk_cnt <= 6'd0; //IIC驱动时钟计数器
if( iic_en ) begin
wr_flag <= wr_control; //获得读写信号
end
end
iic_sladdr : begin
case( dri_clk_cnt )
6'd0 : iic_scl <= 1'b1; //拉低数据线准备
6'd1 : begin
sda_dir <= 1'b1; //输出
iic_sda_out <= 1'b0; //数据线拉低,发送起始信号
end
6'd2 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd3 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd4 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd5 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd6 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd7 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd8 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd9 : iic_scl <= 1'b0; //拉低数据线准备
6'd10 : iic_sda_out <= SLAVE_ADDR[6];//器件地址
6'd11 : iic_scl <= 1'b1; //拉高锁存数据
6'd12 : iic_scl <= 1'b1;//拉高锁存数据
6'd13 : iic_scl <= 1'b0;//拉低数据线准备
6'd14 : iic_sda_out <= SLAVE_ADDR[5];//器件地址
6'd15 : iic_scl <= 1'b1;//拉高锁存数据
6'd16 : iic_scl <= 1'b1;//拉高锁存数据
6'd17 : iic_scl <= 1'b0;//拉低数据线准备
6'd18 : iic_sda_out <= SLAVE_ADDR[4];//器件地址
6'd19 : iic_scl <= 1'b1;//拉高锁存数据
6'd20 : iic_scl <= 1'b1;//拉高锁存数据
6'd21 : iic_scl <= 1'b0;//拉低数据线准备
6'd22 : iic_sda_out <= SLAVE_ADDR[3];//器件地址
6'd23 : iic_scl <= 1'b1;//拉高锁存数据
6'd24 : iic_scl <= 1'b1;//拉高锁存数据
6'd25 : iic_scl <= 1'b0;//拉低数据线准备
6'd26 : iic_sda_out <= SLAVE_ADDR[2];//器件地址
6'd27 : iic_scl <= 1'b1;//拉高锁存数据
6'd28 : iic_scl <= 1'b1;//拉高锁存数据
6'd29 : iic_scl <= 1'b0;//拉低数据线准备
6'd30 : iic_sda_out <= SLAVE_ADDR[1];//器件地址
6'd31 : iic_scl <= 1'b1;//拉高锁存数据
6'd32 : iic_scl <= 1'b1;//拉高锁存数据
6'd33 : iic_scl <= 1'b0;//拉低数据线准备
6'd34 : iic_sda_out <= SLAVE_ADDR[0];//器件地址
6'd35 : iic_scl <= 1'b1;//拉高锁存数据
6'd36 : iic_scl <= 1'b1;//拉高锁存数据
6'd37 : iic_scl <= 1'b0;//拉低数据线准备
6'd38 : iic_sda_out <= WRITE_FLAG;//写
6'd39 : iic_scl <= 1'b1;//拉高锁存数据
6'd40 : iic_scl <= 1'b1;//拉高锁存数据
6'd41 : iic_scl <= 1'b0;//拉低数据线准备
6'd42 : begin//从机应答
sda_dir <= 1'b0;//让数据线变为高阻态,主机读取数据线的电平,低电平为有效应答
end
6'd43 : iic_scl <= 1'b1;//拉高锁存数据
6'd44 : begin
iic_scl <= 1'b1;//拉高锁存数据
ACK <= iic_sda_in;
end
6'd45 : begin
iic_scl <= 1'b0;//拉低数据线准备
dri_clk_cnt <= 6'd0;//
state_done1 <= 1'b1;
end
default : ;
endcase
end
iic_addr16 : begin
case( dri_clk_cnt )
6'd0 : begin
iic_scl <= 1'b0;
sda_dir <= 1'b1;
iic_sda_out <= addr_buff[15];
end
6'd1 : iic_scl <= 1'b1;
6'd2 : iic_scl <= 1'b1;
6'd3 : iic_scl <= 1'b0;
6'd4 : iic_sda_out <= addr_buff[14];
6'd5 : iic_scl <= 1'b1;
6'd6 : iic_scl <= 1'b1;
6'd7 : iic_scl <= 1'b0;
6'd8 : iic_sda_out <= addr_buff[13];
6'd9 : iic_scl <= 1'b1;
6'd10 : iic_scl <= 1'b1;
6'd11 : iic_scl <= 1'b0;
6'd12 : iic_sda_out <= addr_buff[12];
6'd13 : iic_scl <= 1'b1;
6'd14 : iic_scl <= 1'b1;
6'd15 : iic_scl <= 1'b0;
6'd16 : iic_sda_out <= addr_buff[11];
6'd17 : iic_scl <= 1'b1;
6'd18 : iic_scl <= 1'b1;
6'd19 : iic_scl <= 1'b0;
6'd20 : iic_sda_out <= addr_buff[10];
6'd21 : iic_scl <= 1'b1;
6'd22 : iic_scl <= 1'b1;
6'd23 : iic_scl <= 1'b0;
6'd24 : iic_sda_out <= addr_buff[9];
6'd25 : iic_scl <= 1'b1;
6'd26 : iic_scl <= 1'b1;
6'd27 : iic_scl <= 1'b0;
6'd28 : iic_sda_out <= addr_buff[8];
6'd29 : iic_scl <= 1'b1;
6'd30 : iic_scl <= 1'b1;
6'd31 : iic_scl <= 1'b0;
6'd32 : begin //从机应答
sda_dir <= 1'b0;
end
6'd33 : iic_scl <= 1'b1;
6'd34 : begin
iic_scl <= 1'b1;
ACK <= iic_sda_in;
end
6'd35 : begin
iic_scl <= 1'b0;
state_done2 <= 1'b1;//4
dri_clk_cnt <= 6'd0;//
end
default : ;
endcase
end
iic_addr8 : begin
case( dri_clk_cnt )
6'd0 : begin
iic_scl <= 1'b0;
sda_dir <= 1'b1;
iic_sda_out <= addr_buff[7];
end
6'd1 : iic_scl <= 1'b1;
6'd2 : iic_scl <= 1'b1;
6'd3 : iic_scl <= 1'b0;
6'd4 : iic_sda_out <= addr_buff[6];
6'd5 : iic_scl <= 1'b1;
6'd6 : iic_scl <= 1'b1;
6'd7 : iic_scl <= 1'b0;
6'd8 : iic_sda_out <= addr_buff[5];
6'd9 : iic_scl <= 1'b1;
6'd10 : iic_scl <= 1'b1;
6'd11 : iic_scl <= 1'b0;
6'd12 : iic_sda_out <= addr_buff[4];
6'd13 : iic_scl <= 1'b1;
6'd14 : iic_scl <= 1'b1;
6'd15 : iic_scl <= 1'b0;
6'd16 : iic_sda_out <= addr_buff[3];
6'd17 : iic_scl <= 1'b1;
6'd18 : iic_scl <= 1'b1;
6'd19 : iic_scl <= 1'b0;
6'd20 : iic_sda_out <= addr_buff[2];
6'd21 : iic_scl <= 1'b1;
6'd22 : iic_scl <= 1'b1;
6'd23 : iic_scl <= 1'b0;
6'd24 : iic_sda_out <= addr_buff[1];
6'd25 : iic_scl <= 1'b1;
6'd26 : iic_scl <= 1'b1;
6'd27 : iic_scl <= 1'b0;
6'd28 : iic_sda_out <= addr_buff[0];
6'd29 : iic_scl <= 1'b1;
6'd30 : iic_scl <= 1'b1;
6'd31 : iic_scl <= 1'b0;
6'd32 : begin //从机应答
sda_dir <= 1'b0;
end
6'd33 : iic_scl <= 1'b1;
6'd34 : begin
iic_scl <= 1'b1;
ACK <= iic_sda_in;
end
6'd35 : begin
iic_scl <= 1'b0;
state_done3 <= 1'b1;//8
dri_clk_cnt <= 6'd0;//
end
default : ;
endcase
end
iic_data_wr : begin
case( dri_clk_cnt )
6'd0 : begin
iic_scl <= 1'b0;
sda_dir <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= wdata_buff[7];
end
6'd1 : iic_scl <= 1'b1;
6'd2 : iic_scl <= 1'b1;
6'd3 : iic_scl <= 1'b0;
6'd4 : iic_sda_out <= wdata_buff[6];
6'd5 : iic_scl <= 1'b1;
6'd6 : iic_scl <= 1'b1;
6'd7 : iic_scl <= 1'b0;
6'd8 : iic_sda_out <= wdata_buff[5];
6'd9 : iic_scl <= 1'b1;
6'd10 : iic_scl <= 1'b1;
6'd11 : iic_scl <= 1'b0;
6'd12 : iic_sda_out <= wdata_buff[4];
6'd13 : iic_scl <= 1'b1;
6'd14 : iic_scl <= 1'b1;
6'd15 : iic_scl <= 1'b0;
6'd16 : iic_sda_out <= wdata_buff[3];
6'd17 : iic_scl <= 1'b1;
6'd18 : iic_scl <= 1'b1;
6'd19 : iic_scl <= 1'b0;
6'd20 : iic_sda_out <= wdata_buff[2];
6'd21 : iic_scl <= 1'b1;
6'd22 : iic_scl <= 1'b1;
6'd23 : iic_scl <= 1'b0;
6'd24 : iic_sda_out <= wdata_buff[1];
6'd25 : iic_scl <= 1'b1;
6'd26 : iic_scl <= 1'b1;
6'd27 : iic_scl <= 1'b0;
6'd28 : iic_sda_out <= wdata_buff[0];
6'd29 : iic_scl <= 1'b1;
6'd30 : iic_scl <= 1'b1;
6'd31 : iic_scl <= 1'b0;
6'd32 : begin //从机应答
sda_dir <= 1'b0;
end
6'd33 : begin
iic_scl <= 1'b1;
ACK <= iic_sda_in;
end
6'd34 : iic_scl <= 1'b1;
6'd35 : begin
iic_scl <= 1'b0;
state_done4 <= 1'b1;//16
dri_clk_cnt <= 6'd0;//
end
default : ;
endcase
end
iic_addr_rd : begin
case( dri_clk_cnt )
6'd0 : begin
iic_scl <= 1'b0; //拉低数据线准备
sda_dir <= 1'b1; //输出
iic_sda_out <= 1'b1; //数据线拉低,发送起始信号
end
6'd1 : begin
iic_scl <= 1'b1; //拉低数据线准备
sda_dir <= 1'b1; //输出
iic_sda_out <= 1'b1; //数据线拉低,发送起始信号
end
6'd2 : iic_sda_out <= 1'b1; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd3 : iic_sda_out <= 1'b1; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd4 : iic_sda_out <= 1'b1; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd5 : iic_sda_out <= 1'b1; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd6 : iic_sda_out <= 1'b1; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd7 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd8 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd9 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd10 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd11 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd12 : iic_sda_out <= 1'b0; //SDA低电平时间持续要大于4us时SCL才能拉低
6'd13 : iic_scl <= 1'b0; //拉低数据线准备
6'd14 : iic_sda_out <= SLAVE_ADDR[6];//器件地址
6'd15 : iic_scl <= 1'b1; //拉高锁存数据
6'd16 : iic_scl <= 1'b1;//拉高锁存数据
6'd17 : iic_scl <= 1'b0;//拉低数据线准备
6'd18 : iic_sda_out <= SLAVE_ADDR[5];//器件地址
6'd19 : iic_scl <= 1'b1;//拉高锁存数据
6'd20 : iic_scl <= 1'b1;//拉高锁存数据
6'd21 : iic_scl <= 1'b0;//拉低数据线准备
6'd22 : iic_sda_out <= SLAVE_ADDR[4];//器件地址
6'd23 : iic_scl <= 1'b1;//拉高锁存数据
6'd24 : iic_scl <= 1'b1;//拉高锁存数据
6'd25 : iic_scl <= 1'b0;//拉低数据线准备
6'd26 : iic_sda_out <= SLAVE_ADDR[3];//器件地址
6'd27 : iic_scl <= 1'b1;//拉高锁存数据
6'd28 : iic_scl <= 1'b1;//拉高锁存数据
6'd29 : iic_scl <= 1'b0;//拉低数据线准备
6'd30 : iic_sda_out <= SLAVE_ADDR[2];//器件地址
6'd31 : iic_scl <= 1'b1;//拉高锁存数据
6'd32 : iic_scl <= 1'b1;//拉高锁存数据
6'd33 : iic_scl <= 1'b0;//拉低数据线准备
6'd34 : iic_sda_out <= SLAVE_ADDR[1];//器件地址
6'd35 : iic_scl <= 1'b1;//拉高锁存数据
6'd36 : iic_scl <= 1'b1;//拉高锁存数据
6'd37 : iic_scl <= 1'b0;//拉低数据线准备
6'd38 : iic_sda_out <= SLAVE_ADDR[0];//器件地址
6'd39 : iic_scl <= 1'b1;//拉高锁存数据
6'd40 : iic_scl <= 1'b1;//拉高锁存数据
6'd41 : iic_scl <= 1'b0;//拉低数据线准备
6'd42 : iic_sda_out <= READ_FLAG;//写
6'd43 : iic_scl <= 1'b1;//拉高锁存数据
6'd44 : iic_scl <= 1'b1;//拉高锁存数据
6'd45 : iic_scl <= 1'b0;//拉低数据线准备
6'd46 : begin//从机应答
sda_dir <= 1'b0;//让数据线变为高阻态,主机读取数据线的电平,低电平为有效应答
end
6'd47 : iic_scl <= 1'b1;//拉高锁存数据
6'd48 : begin
iic_scl <= 1'b1;//拉高锁存数据
ACK <= iic_sda_in;
end
6'd49 : begin
iic_scl <= 1'b0;//拉低数据线准备
dri_clk_cnt <= 6'd0;//
state_done5 <= 1'b1;
end
default : ;
endcase
end
iic_data_rd : begin
case( dri_clk_cnt )
6'd0 : begin
iic_scl <= 1'b0;
sda_dir <= 1'b0;
end
6'd1 : iic_scl <= 1'b1;
6'd2 : rdata_buff[7] <= iic_sda_in;
6'd3 : iic_scl <= 1'b0;
6'd4 : iic_scl <= 1'b0;
6'd5 : iic_scl <= 1'b1;
6'd6 : rdata_buff[6] <= iic_sda_in;
6'd7 : iic_scl <= 1'b0;
6'd8 : iic_scl <= 1'b0;
6'd9 : iic_scl <= 1'b1;
6'd10 : rdata_buff[5] <= iic_sda_in;
6'd11 : iic_scl <= 1'b0;
6'd12 : iic_scl <= 1'b0;
6'd13 : iic_scl <= 1'b1;
6'd14 : rdata_buff[4] <= iic_sda_in;
6'd15 : iic_scl <= 1'b0;
6'd16 : iic_scl <= 1'b0;
6'd17 : iic_scl <= 1'b1;
6'd18 : rdata_buff[3] <= iic_sda_in;
6'd19 : iic_scl <= 1'b0;
6'd20 : iic_scl <= 1'b0;
6'd21 : iic_scl <= 1'b1;
6'd22 : rdata_buff[2] <= iic_sda_in;
6'd23 : iic_scl <= 1'b0;
6'd24 : iic_scl <= 1'b0;
6'd25 : iic_scl <= 1'b1;
6'd26 : rdata_buff[1] <= iic_sda_in;
6'd27 : iic_scl <= 1'b0;
6'd28 : iic_scl <= 1'b0;
6'd29 : iic_scl <= 1'b1;
6'd30 : rdata_buff[0] <= iic_sda_in;
6'd31 : iic_scl <= 1'b0;
6'd32 : begin
sda_dir <= 1'b1;//非应答
iic_sda_out <= 1'b1;
end
6'd33 : iic_scl <= 1'b1;
6'd34 : iic_scl <= 1'b1;
6'd35 : begin
iic_scl <= 1'b0;
state_done6 <= 1'b1;//64
dri_clk_cnt <= 6'd0;//
read_data <= rdata_buff;
end
default : ;
endcase
end
iic_stop : begin //结束IIC操作
sda_dir <= 1'b1;
case( dri_clk_cnt )
6'd0 : begin //从机应答
sda_dir <= 1'b1;
iic_sda_out <= 1'b0;
end
6'd1 : iic_scl <= 1'b1;
6'd2 : iic_sda_out <= 1'b0;
6'd3 : iic_sda_out <= 1'b0;
6'd4 : iic_sda_out <= 1'b0;
6'd5 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b0;
end
6'd6 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b0;
end
6'd7 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b0;
end
6'd8 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b0;
end
6'd9 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b0;
end
6'd10 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b0;
end
6'd11 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd12 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd13 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd14 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd15 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd16 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd17 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd18 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd19 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd20 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd21 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd22 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd23 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd24 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd25 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd26 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd27 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd28 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd29 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd30 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd31 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd32 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd33 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd34 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
end
6'd35 : begin
iic_scl <= 1'b1;
sda_dir <= 1'b1;
iic_sda_out <= 1'b1;
dri_clk_cnt <= 6'd0;//
iic_done <= 1'b1;
state_done7 <= 1'b1;//128
end
default : ;
endcase
end
endcase
end
end
endmodule里插入代码片