当前位置:网站首页>【FPGA】设计思路——I2C协议
【FPGA】设计思路——I2C协议
2022-08-11 03:28:00 【春风浅作序】
一、模块框图
二、状态转移图
三、端口列表
1、控制模块:
input clk ,
input rst_n ,
input rd_en ,//读请求,按键控制
input [7:0] din ,//接收串口的数据
input din_vld ,//串口数据完成标志
input [7:0] rd_data ,//接收接口端的数据
input done ,//rd_data数据完成标志
input ready ,//串口端空闲标志
output reg [7:0] dout ,//将数据读出到串口
output reg dout_vld,//串口数据完成标志
output reg [3:0] cmd ,//向接口端发送数据
output reg req ,//向接口端发送请求
output reg [7:0] wr_data ,//向接口端发送数据
2、接口模块
input clk ,
input rst_n ,
//控制模块
input req ,//接收请求
input [3:0] cmd ,//接收命令
input [7:0] wr_data ,//接收控制模块传入的数据
output done ,//一个字节传输完成标志
output reg [7:0] rd_data ,//将读取的数据传入控制模块
//output reg slave_ack ,//写入数据后EEPROM应答信号
//eeprom
input i2c_sda_i ,//EEPROM传到接口模块的串行数据
output reg i2c_scl ,//I2C时钟
output reg i2c_sda_oe ,//输出使能信号
output reg i2c_sda_o //接口模块传到EEPROM的串行数据
四、设计思路
1、控制模块
(1)状态机设计
assign idle2rd_req = state_c == IDLE && rd_en;
assign idle2wr_req = state_c == IDLE && (wfifo_usedw > WR_LEN - 2);
assign rd_req2rd_wait = state_c == RD_REQ && (1'b1);
assign rd_wait2rd_req = state_c == RD_WAIT && (done & cnt_byte < RD_LEN - 1);
assign rd_wait2done = state_c == RD_WAIT && end_cnt_byte;
assign wr_req2wr_wait = state_c == WR_REQ && (1'b1);
assign wr_wait2wr_req = state_c == WR_WAIT && (done & cnt_byte < WR_LEN - 1);
assign wr_wait2done = state_c == WR_WAIT && end_cnt_byte;
assign done2idle = state_c == DONE && (1'b1);
(2)字节计数器设计
assign add_cnt_byte = (state_c == RD_WAIT | state_c == WR_WAIT) & done ;
assign end_cnt_byte = add_cnt_byte && cnt_byte == ((state_c == WR_WAIT)?(WR_LEN-1):(RD_LEN-1)) ;
(3)设计一个task,用于发送请求,命令,数据
读状态时:
第0字节发送(请求,{开始命令,写命令},{I2C器件地址,写请求});
第1字节发送(请求,写命令,寄存器地址};
最后一个字节发送(请求,{写命令,停止命令},wfifo中的输出数据);
写状态时:
第0字节发送(请求,{开始命令,写命令},{I2C器件地址,写请求});
第1字节发送(请求,写命令,寄存器地址};
第2字节发送(请求,{开始命令,写命令},{I2C器件地址,读请求}};
最后一个字节发送(请求,{读命令,停止命令},0);
(4)寄存器地址设计
读地址:
初始为0,每当一次完整的读操作完成(即rd_wait2done),地址自增读入的数据个(即rd_addr <= rd_addr + RD_LEN - 3)
写地址:
初始为0,每当一次完整的写操作完成(即wr_wait2done),地址自增写入的数据个(即wr_addr <= wr_addr + WR_LEN - 2)
(5)输出到串口端数据设计
即dout 与 dout_vld
dout等于rfifo的输出数据
dout_vld等于rfifo的读请求
(6)FIFO设计
数据宽度为8,深度为默认256
wfifo:
数据输入为串口端输入的数据
读请求:写状态且开始有数据
wfifo_rdreq = state_c == WR_WAIT & done & cnt_byte > 1;
写请求:非满且输入有效
wfifo_wrreq = ~wfifo_full && din_vld;
rfifo:
数据输入为接口端输入的数据
读请求:非空且串口端空闲
rfifo_rdreq = ready && ~rfifo_empty;
写请求:读状态且开始有数据
rfifo_wrreq = ~rfifo_full && state_c == RD_WAIT && done && cnt_byte >2;
2、接口模块
(1)状态机设计
assign idle2start = state_c == IDLE && (req && (cmd & `CMD_START));
assign idle2write = state_c == IDLE && (req && (cmd & `CMD_WRITE));
assign idle2read = state_c == IDLE && (req && (cmd & `CMD_READ));
assign start2write= state_c == START && (end_cnt_bit && (command & `CMD_WRITE));
assign start2read = state_c == START && (end_cnt_bit && (command & `CMD_READ));
assign write2rack = state_c == WRITE && end_cnt_bit;
assign rack2stop = state_c == RACK && (end_cnt_bit && (command & `CMD_STOP));
assign rack2idle = state_c == RACK && (end_cnt_bit && (command & `CMD_STOP) == 0);
assign read2sack = state_c == READ && end_cnt_bit;
assign sack2stop = state_c == SACK && (end_cnt_bit && (command & `CMD_STOP));
assign sack2idle = state_c == SACK && (end_cnt_bit && (command & `CMD_STOP) == 0);
assign stop2idle = state_c == STOP && end_cnt_bit;
(2)计数器设计
I2C时钟
非IDLE状态开启,
每记完250个系统时钟周期结束一次。
bit时钟
每当I2C时钟结束时开启一次,
结束状态为:读/写状态记完8bit,其余状态记完1bit。
(3)I2C时钟设计
初始为1,跳出IDLE状态后拉低,记到I2C时钟一半(125)时拉高,记完一个I2C时钟后拉低。
(4)I2C输出设计
初始为1
起始状态,I2C时钟低电平中间时将信号拉高,确保能检测到起始信号,I2C时钟高电平中间时将信号拉低
写状态且I2C时钟低电平中间时,将控制模块传入的数据进行并串转换输出
发送应答信号且I2C时钟低电平中间时,如果有停止命令,则发高电平,否则发低电平。
结束状态,I2C时钟低电平中间时将信号拉低,确保能检测到停止信号,I2C时钟高电平中间时将信号拉高。
(5)I2C输出使能设计
开始状态、结束状态、写状态、发送应答状态为高电平,其余为低电平。
(6)接收EEPROM数据设计
读状态且I2C时钟高电平中间时,串并转换
(7)接收EEPROM应答设计
接收应答且I2C时钟高电平中间时,应答信号等于输入信号。
边栏推荐
- Add user error useradd: cannot open /etc/passwd
- A practice arrangement about map GIS (below) GIS practice of Redis
- "Life Is Like First Seen" is ill-fated, full of characters, and the contrast of Zhu Yawen's characters is too surprising
- 字体反扒
- Goodbye Guangzhou paper invoices!The issuance of electronic invoices for accommodation fees will completely replace the invoices of hotels, restaurants and gas stations
- The solution to the height collapse problem
- What does the sanction of the mixer Tornado mean for the DeFi market?
- CSDN 博客更换皮肤
- DOM-DOM tree, a DOM tree has three types of nodes
- 【ADI低功耗2k代码】基于ADuCM4050的ADXL363、TMP75的加速度、温度检测及串口打印、蜂鸣器播放音乐(孤勇者)
猜你喜欢
Is Redis old?Performance comparison between Redis and Dragonfly
Detailed explanation of VIT source code
多商户商城系统功能拆解26讲-平台端分销设置
索引的创建、查看、删除
【Yugong Series】August 2022 Go Teaching Course 036-Type Assertion
没想到MySQL还会问这些...
一次简单的 JVM 调优,学会拿去写到简历里
CSDN blog replacement skin
A simple JVM tuning, learn to write it on your resume
Official release丨VS Code 1.70
随机推荐
uni-app - 获取汉字拼音首字母(根据中文获取拼音首字母)
EasyCVR接入海康大华设备选择其它集群服务器时,通道ServerID错误该如何解决?
Is Redis old?Performance comparison between Redis and Dragonfly
Official release丨VS Code 1.70
(CVPR - 2017) in depth and potential body learning context awareness feature for pedestrian recognition
Rotary array problem: how to realize the array "overall reverse, internal orderly"?"Three-step conversion method" wonderful array
二叉树相关代码题【较全】C语言
【Pdf自动生成书签】
程序化交易的策略类型可以分为哪几种?
Watch to monitor
Google search skills - programmer is recommended
En-us is an invalid culture error solution when Docker links sqlserver
The problem that Merge will be lost again after code Revert has been solved
Goodbye Guangzhou paper invoices!The issuance of electronic invoices for accommodation fees will completely replace the invoices of hotels, restaurants and gas stations
C language recv() function, recvfrom() function, recvmsg() function
DNS separation resolution and intelligent resolution
CC0 vs. commercial IP: which model is better for NFTs?
UNI-APP_iphone苹果手机底部安全区域
The thirteenth day of learning programming
Add user error useradd: cannot open /etc/passwd