基于FPGA的I2C verilog

游戏排行榜

空闲位:SCL 高电平 SDA低电平

起始位 :SCL 高电平  SDA 高电平到低电平

结束位:SCL 高电平 SDA低电平到高电平

读写状态:数据+响应位

`timescale 1ns/1ns


module IIC_WM(
Clk,
Rst_n,

IIC_SCL,   //iic时钟线
IIC_SDA     //iic数据总线
);


input Clk;//系统时钟
input Rst_n;//复位

output reg IIC_SCL;//IIC  时钟
inout IIC_SDA;//IIC数据

reg OE;
reg [15:0]cnt;
reg [15:0]IIC_cnt,IIC_cnt_r;
reg [15:0]data_cnt,data_cnt_r;//IIC_cnt 每计数到30,data_cnt加一,IIC_cnt_r计数到30,data_cnt_r加1

wire [7:0]addr;
wire [7:0]data;
reg done;//每当传输完一帧数据30位,done设置为1
reg total_done;//传输完8帧数据置1
reg [3:0]done_cnt;//每次来一个done加1
reg IIC_SDA_tmp;
reg [2:0]ACK;

assign IIC_SDA = OE?IIC_SDA_tmp:1'hz; //oe为1时SDA为输出

parameter CNT_MAX = 124;  

always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt <=#1 0;
else if(cnt == CNT_MAX)
cnt <=#1 0;
else if(total_done)
cnt <= #1 0;
else 
cnt <=#1 cnt + 1'b1;


//200k  IIC_SCL 时钟
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
IIC_SCL <=#1 0;
else if(cnt == CNT_MAX)
IIC_SCL <=#1 ~IIC_SCL;
else 
IIC_SCL <=#1 IIC_SCL;


//200k时钟高低电平各有一个计数器

//IIC_cnt 高电平计数

always@(posedge Clk)

if(!IIC_SCL)
IIC_cnt <=#1 IIC_cnt + 1'b1;
else 
IIC_cnt <=#1 0;
//IIC_cnt_r 低电平计数
always@(posedge Clk)
if(IIC_SCL)
begin
if(total_done)
IIC_cnt_r <=#1 0;
else 
IIC_cnt_r <=#1 IIC_cnt_r + 1'b1;
end 
else 
IIC_cnt_r <=#1 0;


//传完一次数据done_cnt加1
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
done_cnt <=#1 0;
else if(done)
done_cnt <=#1 done_cnt + 1'b1;
else 
done_cnt <=#1 done_cnt;
//
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
total_done <=#1 0;
else if(done_cnt == 8)
total_done <=#1 1;
else 
total_done <=#1 total_done;

//两个计数器,400K时钟高电平为data_cnt_r,低电平data_cnt
//IIC_cnt 每计数到30,data_cnt加一
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
data_cnt <=#1 0;
else if(!total_done)
begin 
if(IIC_cnt == 30)
data_cnt <=#1 data_cnt + 1'b1;
else if(done)
data_cnt <=#1 0;
else 
data_cnt <=#1 data_cnt;
end
else 
data_cnt <=#1 0;
//IIC_cnt_r计数到30,data_cnt_r加1
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
data_cnt_r <=#1 0;
else if(!total_done)
begin 
if(IIC_cnt_r == 30)
data_cnt_r <=#1 data_cnt_r + 1'b1;
else if(data_cnt_r == 30)
data_cnt_r <=#1 0;
else if(done)
data_cnt_r <=#1 0;
else 
data_cnt_r <=#1 data_cnt_r;
end
else 
data_cnt_r <=#1 0;

always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
begin 
OE <=#1 1;IIC_SDA_tmp <=#1 1;ACK <=#1 3'b111;
end 
else if(data_cnt_r == 1)//起始位
IIC_SDA_tmp <=#1 0;
else if(data_cnt_r == 29)//结束位
IIC_SDA_tmp <=#1 1;
else if(done)
ACK <=#1 3'b111;
else begin 

case(data_cnt)

//器件地址设置

// 1:IIC_SDA_tmp <=#1 0;
2:IIC_SDA_tmp <=#1 0;
3:IIC_SDA_tmp <=#1 0;
4:IIC_SDA_tmp <=#1 1;
5:IIC_SDA_tmp <=#1 1;
6:IIC_SDA_tmp <=#1 0;
7:IIC_SDA_tmp <=#1 1;
8:IIC_SDA_tmp <=#1 0;
9:IIC_SDA_tmp <=#1 0;
10:begin 
OE <=#1 0;IIC_SDA_tmp <=#1 0;
if(IIC_SDA == 0)
ACK[2] <=#1 IIC_SDA;

end

//器件寄存器地址设置

11:begin IIC_SDA_tmp <=#1 addr[7];OE<=#1 1;end 
12:IIC_SDA_tmp <=#1 addr[6];
13:IIC_SDA_tmp <=#1 addr[5];
14:IIC_SDA_tmp <=#1 addr[4];
15:IIC_SDA_tmp <=#1 addr[3];
16:IIC_SDA_tmp <=#1 addr[2];
17:IIC_SDA_tmp <=#1 addr[1];
18:IIC_SDA_tmp <=#1 addr[0];
19:begin 
OE <=#1 0;IIC_SDA_tmp <=#1 0;
if(IIC_SDA == 0)
ACK[1] <=#1 IIC_SDA;

end

//器件数据读取

20:begin IIC_SDA_tmp <=#1 data[7];OE<=#1 1;end 
21:IIC_SDA_tmp <=#1 data[6];
22:IIC_SDA_tmp <=#1 data[5];
23:IIC_SDA_tmp <=#1 data[4];
24:IIC_SDA_tmp <=#1 data[3];
25:IIC_SDA_tmp <=#1 data[2];
26:IIC_SDA_tmp <=#1 data[1];
27:IIC_SDA_tmp <=#1 data[0];
28:begin 
OE <=#1 0;IIC_SDA_tmp <=#1 0;
if(IIC_SDA == 0)
ACK[0] <=#1 IIC_SDA;
end
// 29:begin IIC_SDA_tmp <=#1 1;OE<=#1 1;end 
default: begin IIC_SDA_tmp <=#1 IIC_SDA_tmp;OE<=#1 1;ACK <=#1 ACK;end 
endcase
end 

always@(posedge Clk)
if((ACK == 3'd0)&&(data_cnt_r == 30))
done <=#1 1;
else 
done <=#1 0;


WM8731 WM8731(
.Clk(Clk),
.Rst_n(Rst_n),
.done(done),

.addr(addr),
.data(data)
);

endmodule 





  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于FPGAI2C控制器设计是一种用于实现I2C总线通信协议的方案。I2C是一种串行通信接口,用于在多个设备之间进行数据传输。FPGA作为一种可编程逻辑器件,具有高度灵活性和可重构性,非常适合用于设计I2C控制器。 在设计基于FPGAI2C控制器时,首先需要了解I2C协议的工作原理。I2C总线由一个主设备和多个从设备组成,主设备负责发起并控制通信过程,从设备负责响应主设备的指令。 设计中,我们可以利用FPGA的可编程性和并行处理能力来实现I2C控制器。首先,我们可以使用FPGA的I/O引脚作为SCL(时钟线)和SDA(数据线)来与外部的I2C总线进行连接。然后,我们可以使用FPGA内部的逻辑电路实现I2C协议的各个功能。 例如,在FPGA中可以设计一个状态机来控制I2C的起始,停止,发送和接收等操作。该状态机可以根据I2C的时钟以及外部的读写信号进行状态转换。同时,我们可以使用FPGA内部的存储器来缓存发送和接收的数据,以便实现数据的存储和传输。 此外,FPGA还可以使用硬件描述语言(如Verilog或VHDL)来描述I2C控制器的行为,方便实现和调试。通过FPGA的可编程性,我们可以根据需求对控制器进行优化和修改,以适应不同的应用场景。 总的来说,基于FPGAI2C控制器设计可以充分发挥FPGA的可编程性和并行处理能力,实现灵活、高效的I2C通信功能。该设计方案可以应用于各种需要I2C通信的电子设备中,提升系统的可扩展性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值