由於上一篇已经介绍过了 SPI 的 Timing Diagram,那麽今天就直接进入 I2C Master 状态机的程序喽~~
先来定义 8 个状态(下面会解释各个状态的行为)
/*---------parameter---------*/
parameter IDLE = 3'd0;
parameter GO = 3'd1;
parameter START = 3'd2;
parameter WAIT = 3'd3;
parameter SHIFT = 3'd4;
parameter STOP = 3'd5;
parameter FINAL = 3'd6;
parameter END = 3'd7;
再来定义输入输出
输入:
输出:
module I2C_control_R_W(
clk_sys,
SCLK_100k,
tick_I2C,
rst_n,
en,
count,
countEN,
rstcount,
ACK1,
ACK2,
ACK3,
rstACK,
SCLK,
SCLK_temp,
SHEN,
LDEN,
SDO,
R_W
);
/*---------ports declaration---------*/
input clk_sys;
input rst_n;
input en;
input SCLK_100k;
input tick_I2C;
input R_W;// W---->0, R---->1
input [4:0] count;
output ACK1;
output ACK2;
output ACK3;
output SCLK_temp;
output SHEN;
output LDEN;
output SDO;
output countEN;
output rstcount;
output rstACK;
output SCLK;
reg ACK1;
reg ACK2;
reg ACK3;
reg SCLK_temp;
reg SHEN;
reg LDEN;
reg SDO;
reg countEN;
reg rstcount;
reg rstACK;
wire SCLK;
宣告跑状态的变数:
/*---------variables---------*/
reg [2:0] fstate;
状态逻辑:
/*---------fstate state---------*/
always@(posedge clk_sys or negedge rst_n)begin
if(!rst_n)begin
fstate <= IDLE;
end
else begin
case(fstate)
IDLE:begin
if(en) fstate <= GO;
else fstate <= IDLE;
end
GO:begin
if(tick_I2C)fstate <= START;
else fstate <= GO;
end
START:begin
if(tick_I2C)fstate <= WAIT;
else fstate <= START;
end
WAIT:begin
if(tick_I2C)fstate <= SHIFT;
else fstate <= WAIT;
end
SHIFT:begin
if(!R_W)begin//write-->18bit
if(count==5'd16&&tick_I2C)fstate <= STOP;
else fstate <= SHIFT;
end
else begin//read-->27bit
if(count==5'd25&&tick_I2C)fstate <= STOP;
else fstate <= SHIFT;
end
end
STOP:begin
if(tick_I2C)fstate <= FINAL;
else fstate <= STOP;
end
FINAL:begin
if(tick_I2C)fstate <= END;
else fstate <= FINAL;
end
END:begin
if(tick_I2C)fstate <= IDLE;
else fstate <= END;
end
endcase
end
end
输出逻辑:
/*---------fstate output---------*/
always@(posedge clk_sys or negedge rst_n)begin
if(!rst_n)begin
SCLK_temp <= 1'b1;
LDEN <= 1'b0;
SHEN <= 1'b0;
ACK1 <= 1'b0;
ACK2 <= 1'b0;
ACK3 <= 1'b0;
SDO <= 1'b1;//SDIN_temp control data[26]/raising/falling
countEN <= 1'b0;
rstcount <= 1'b0;
rstACK <= 1'b0;
end
else begin
if(tick_I2C)begin
case(fstate)
IDLE:begin
SCLK_temp <= 1'b1;//high
LDEN <= 1'b0;
SHEN <= 1'b0;
ACK1 <= 1'b0;
ACK2 <= 1'b0;
ACK3 <= 1'b0;
SDO <= 1'b1;//high
countEN <= 1'b0;
rstcount <= 1'b0;
rstACK <= 1'b0;
end
GO:begin
SCLK_temp <= 1'b1;//high
LDEN <= 1'b1;//load data
SHEN <= 1'b0;
ACK1 <= 1'b0;
ACK2 <= 1'b0;
ACK3 <= 1'b0;
SDO <= 1'b1;//high
countEN <= 1'b0;
rstcount <= 1'b0;
rstACK <= 1'b0;
end
START:begin
SCLK_temp <= 1'b1;//high
LDEN <= 1'b0;
SHEN <= 1'b0;
ACK1 <= 1'b0;
ACK2 <= 1'b0;
ACK3 <= 1'b0;
SDO <= 1'b0;//falling(start)
countEN <= 1'b0;
rstcount <= 1'b0;
rstACK <= 1'b0;
end
WAIT:begin
SCLK_temp <= 1'b1;//high
LDEN <= 1'b0;
SHEN <= 1'b0;
ACK1 <= 1'b0;
ACK2 <= 1'b0;
ACK3 <= 1'b0;
SDO <= 1'b0;//low
countEN <= 1'b0;
rstcount <= 1'b0;
rstACK <= 1'b0;
end
SHIFT:begin
SCLK_temp <= 1'b0;//don't care
LDEN <= 1'b0;
SHEN <= 1'b1;//shifting
//ACK1
if(count==5'd7) ACK1 <= 1'b1;
else ACK1 <= 1'b0;
//ACK2
if(count==5'd16)ACK2 <= 1'b1;
else ACK2 <= 1'b0;
//ACK3
if(count==5'd25)ACK3 <= 1'b1;
else ACK3 <= 1'b0;
SDO <= 1'b1;//don't care(data[26])
countEN <= 1'b1;//counting
//rstcount
if(!R_W)begin//write-->18bit
if(count==5'd16)rstcount <= 1'b1;
else rstcount <= 1'b0;
end
else begin//read-->27bit
if(count==5'd25)rstcount <= 1'b1;
else rstcount <= 1'b0;
end
rstACK <= 1'b0;
end
STOP:begin
SCLK_temp <= 1'b0;//stop the clock
LDEN <= 1'b0;
SHEN <= 1'b0;
ACK1 <= 1'b0;
ACK2 <= 1'b0;
ACK3 <= 1'b0;
SDO <= 1'b0;//low
countEN <= 1'b0;
rstcount <= 1'b0;
rstACK <= 1'b0;
end
FINAL:begin
SCLK_temp <= 1'b1;//high
LDEN <= 1'b0;
SHEN <= 1'b0;
ACK1 <= 1'b0;
ACK2 <= 1'b0;
ACK3 <= 1'b0;
SDO <= 1'b0;//low
countEN <= 1'b0;
rstcount <= 1'b0;
rstACK <= 1'b0;
end
END:begin
SCLK_temp <= 1'b1;//high
LDEN <= 1'b0;
SHEN <= 1'b0;
ACK1 <= 1'b0;
ACK2 <= 1'b0;
ACK3 <= 1'b0;
SDO <= 1'b1;//raising
countEN <= 1'b0;
rstcount <= 1'b0;
rstACK <= 1'b1;//reset ACK
end
endcase
end
else begin
SCLK_temp <= SCLK_temp;
LDEN <= LDEN;
SHEN <= SHEN;
ACK1 <= ACK1;
ACK2 <= ACK2;
ACK3 <= ACK3;
SDO <= SDO;
countEN <= countEN;
rstcount <= rstcount;
rstACK <= rstACK;
end
end
end
endmodule
这次的 I2C Master 看起来虽然好像复杂很多,但其实与前面几篇的 Uart 及 SPI 都有很大的相似之处欧~~
下一篇我们会继续来完成 I2C Master 的模组~!
>>: Swift纯Code之旅 Day27. 「画面最後的温柔 - 大胎头」
当疫情不止,行销活动还是要想办法办下去,而举办视讯会议已经不能像以往只在一般的会议室,各种的场地都要...
JQ-UI使用步骤-1: (1)API Documentation > (左侧) Intera...
在python中,有许多可以拿来处理影像的套件。今天就先稍微介绍一下,pillow这个影像处理套件。...
前言 前几天我们聊的是串接API,在前端功能开发里,遇到的第二个主题就是档案处理。 档案处理也是在网...
图片来源 接下来继续谈到Q2的目标是Azure Certificate, 云端相关证照, 因为我非...