完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
源码贴上来吧。感觉代码少了一部分。而且字体看着好奇怪。
大概意思就是C1在“数据写”的模式下。 每一次时钟上升沿C1+1。 当C1计算到100的时候。SDA就变为低电平。 当C1计算到200的时候。SCL就变为低电平。 当C1计算到249的时候,C1就会变为0,同时i加上1. 至于前面的C1等于0的情况应该是SDA和SCL的复位 |
|
|
|
module iic_com ( input CLK, input RSTn, input [1:0] Start_Sig, //read or write command input [7:0] Addr_Sig, //eeprom words address input [7:0] Wr Data, output [7:0] Rd Data, output Done_Sig, output SCL, inout SDA ); parameter F100K = 9'd200; reg [4:0] i; reg [4:0] Go; reg [8:0] C1; reg [7:0] r Data; reg r SCL; reg r SDA; reg is Ack; reg is Done; reg is Out; assign Done_Sig = is Done; assign Rd Data = r Data; assign SCL = r SCL; assign SDA = is Out ? r SDA : 1'bz; //****************************************// //* I2C 读写处理程序 *// //****************************************// always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin i <= 5'd0; Go <= 5'd0; C1 <= 9'd0; r Data <= 8'd0; r SCL <= 1'b1; r SDA <= 1'b1; is Ack <= 1'b1; is Done <= 1'b0; is Out <= 1'b1; end else if( Start_Sig[0] ) //I2C 数据写 case( i ) 0: // Start begin is Out <= 1; //SDA 端口输出 if( C1 == 0 ) r SCL <= 1'b1; else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低 if( C1 == 0 ) r SDA <= 1'b1; else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低 if( C1 == 250 -1) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 1: // Write Device Addr begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end 2: // Wirte Word Addr reg r SDA; reg is Ack; reg is Done; reg is Out; assign Done_Sig = is Done; assign Rd Data = r Data; assign SCL = r SCL; assign SDA = is Out ? r SDA : 1'bz; //****************************************// //* I2C 读写处理程序 *// //****************************************// always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin i <= 5'd0; Go <= 5'd0; C1 <= 9'd0; r Data <= 8'd0; r SCL <= 1'b1; r SDA <= 1'b1; is Ack <= 1'b1; is Done <= 1'b0; is Out <= 1'b1; end else if( Start_Sig[0] ) //I2C 数据写 case( i ) 0: // Start begin is Out <= 1; //SDA 端口输出 if( C1 == 0 ) r SCL <= 1'b1; else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低 if( C1 == 0 ) r SDA <= 1'b1; else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低 if( C1 == 250 -1) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 1: // Write Device Addr begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end 2: // Wirte Word Addr else if( C1 == 150 ) r SCL <= 1'b0; if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 16: if( is Ack != 0 ) i <= 5'd0; else i <= Go; endcase else if( Start_Sig[1] ) //I2C 数据读 case( i ) 0: // Start begin is Out <= 1; //SDA 端口输出 if( C1 == 0 ) r SCL <= 1'b1; else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低 if( C1 == 0 ) r SDA <= 1'b1; else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低 if( C1 == 250 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 1: // Write Device Addr begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd9; Go <= i + 1'b1; end 2: // Wirte Word Addr begin r Data <= Addr_Sig; i <= 5'd9; Go <= i + 1'b1; end 3: // Start again begin is Out <= 1'b1; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; else if( C1 == 250 ) r SCL <= 1'b0; if( C1 == 0 ) r SDA <= 1'b0; else if( C1 == 50 ) r SDA <= 1'b1; else if( C1 == 150 ) r SDA <= 1'b0; if( C1 == 300 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 4: // Write Device Addr ( Read ) begin r Data <= {4'b1010, 3'b000, 1'b1}; i <= 5'd9; Go <= i + 1'b1; end 5: // Read Data begin r Data <= 8'd0; i <= 5'd19; Go <= i + 1'b1; end 6: // Stop begin is Out <= 1'b1; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; if( C1 == 0 ) r SDA <= 1'b0; else if( C1 == 150 ) r SDA <= 1'b1; if( C1 == 250 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 7: //写 I2C 结束 begin is Done <= 1'b1; i <= i + 1'b1; end 8: begin is Done <= 1'b0; i <= 5'd0; end 9,10,11,12,13,14,15,16: //发送 Device Addr(write)/Word Addr/Device Addr(read) begin is Out <= 1'b1; r SDA <= r Data[16-i]; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; else if( C1 == 150 ) r SCL <= 1'b0; if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 17: // waiting for acknowledge begin is Out <= 1'b0; //SDA 端口改为输入 if( C1 == 100 ) is Ack <= SDA; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; else if( C1 == 150 ) r SCL <= 1'b0; if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 18: if( is Ack != 0 ) i <= 5'd0; else i <= Go; 19,20,21,22,23,24,25,26: // Read data begin is Out <= 1'b0; if( C1 == 100 ) r Data[26-i] <= SDA; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; else if( C1 == 150 ) r SCL <= 1'b0; if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 27: // no acknowledge begin is Out <= 1'b1; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; else if( C1 == 150 ) r SCL <= 1'b0; if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= Go; end else C1 <= C1 + 1'b1; end endcase endmodule 这是原码,谢谢你回答我的问题,我主要的疑问是为什么这个C1在200的时候变成电平改变,我能理解这是一个启动写的过程,但是我就有时候纠结在具体数字上。 |
|
|
|
module iic_com ( input CLK, input RSTn, input [1:0] Start_Sig, //read or write command input [7:0] Addr_Sig, //eeprom words address input [7:0] Wr Data, output [7:0] Rd Data, output Done_Sig, output SCL, inout SDA ); parameter F100K = 9'd200; reg [4:0] i; reg [4:0] Go; reg [8:0] C1; reg [7:0] r Data; reg r SCL; reg r SDA; reg is Ack; reg is Done; reg is Out; assign Done_Sig = is Done; assign Rd Data = r Data; assign SCL = r SCL; assign SDA = is Out ? r SDA : 1'bz; //****************************************// //* I2C 读写处理程序 *// //****************************************// always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin i <= 5'd0; Go <= 5'd0; C1 <= 9'd0; r Data <= 8'd0; r SCL <= 1'b1; r SDA <= 1'b1; is Ack <= 1'b1; is Done <= 1'b0; is Out <= 1'b1; end else if( Start_Sig[0] ) //I2C 数据写 case( i ) 0: // Start begin is Out <= 1; //SDA 端口输出 if( C1 == 0 ) r SCL <= 1'b1; else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低 if( C1 == 0 ) r SDA <= 1'b1; else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低 if( C1 == 250 -1) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 1: // Write Device Addr begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end 2: // Wirte Word Addr reg r SDA; reg is Ack; reg is Done; reg is Out; assign Done_Sig = is Done; assign Rd Data = r Data; assign SCL = r SCL; assign SDA = is Out ? r SDA : 1'bz; //****************************************// //* I2C 读写处理程序 *// //****************************************// always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin i <= 5'd0; Go <= 5'd0; C1 <= 9'd0; r Data <= 8'd0; r SCL <= 1'b1; r SDA <= 1'b1; is Ack <= 1'b1; is Done <= 1'b0; is Out <= 1'b1; end else if( Start_Sig[0] ) //I2C 数据写 case( i ) 0: // Start begin is Out <= 1; //SDA 端口输出 if( C1 == 0 ) r SCL <= 1'b1; else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低 if( C1 == 0 ) r SDA <= 1'b1; else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低 if( C1 == 250 -1) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 1: // Write Device Addr begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end 2: // Wirte Word Addr else if( C1 == 150 ) r SCL <= 1'b0; if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 16: if( is Ack != 0 ) i <= 5'd0; else i <= Go; endcase else if( Start_Sig[1] ) //I2C 数据读 case( i ) 0: // Start begin is Out <= 1; //SDA 端口输出 if( C1 == 0 ) r SCL <= 1'b1; else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低 if( C1 == 0 ) r SDA <= 1'b1; else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低 if( C1 == 250 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 1: // Write Device Addr begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd9; Go <= i + 1'b1; end 2: // Wirte Word Addr begin r Data <= Addr_Sig; i <= 5'd9; Go <= i + 1'b1; end 3: // Start again begin is Out <= 1'b1; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; else if( C1 == 250 ) r SCL <= 1'b0; if( C1 == 0 ) r SDA <= 1'b0; else if( C1 == 50 ) r SDA <= 1'b1; else if( C1 == 150 ) r SDA <= 1'b0; if( C1 == 300 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 4: // Write Device Addr ( Read ) begin r Data <= {4'b1010, 3'b000, 1'b1}; i <= 5'd9; Go <= i + 1'b1; end 5: // Read Data begin r Data <= 8'd0; i <= 5'd19; Go <= i + 1'b1; end 6: // Stop begin is Out <= 1'b1; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; if( C1 == 0 ) r SDA <= 1'b0; else if( C1 == 150 ) r SDA <= 1'b1; if( C1 == 250 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 7: //写 I2C 结束 begin is Done <= 1'b1; i <= i + 1'b1; end 8: begin is Done <= 1'b0; i <= 5'd0; end 9,10,11,12,13,14,15,16: //发送 Device Addr(write)/Word Addr/Device Addr(read) begin is Out <= 1'b1; r SDA <= r Data[16-i]; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; else if( C1 == 150 ) r SCL <= 1'b0; if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 17: // waiting for acknowledge begin is Out <= 1'b0; //SDA 端口改为输入 if( C1 == 100 ) is Ack <= SDA; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; else if( C1 == 150 ) r SCL <= 1'b0; if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 18: if( is Ack != 0 ) i <= 5'd0; else i <= Go; 19,20,21,22,23,24,25,26: // Read data begin is Out <= 1'b0; if( C1 == 100 ) r Data[26-i] <= SDA; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; else if( C1 == 150 ) r SCL <= 1'b0; if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end else C1 <= C1 + 1'b1; end 27: // no acknowledge begin is Out <= 1'b1; if( C1 == 0 ) r SCL <= 1'b0; else if( C1 == 50 ) r SCL <= 1'b1; else if( C1 == 150 ) r SCL <= 1'b0; if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= Go; end else C1 <= C1 + 1'b1; end endcase endmodule 这是原码,谢谢你回答我的问题,我主要的疑问是为什么这个C1在200的时候变成电平改变,我能理解这是一个启动写的过程,但是我就有时候纠结在具体数字上。 |
|
|
|
|
|
|
|
哦。明白了。你是纠结为什么这里是50.这里是100那里是200是吧? 这个其实是取决于你需要操作什么样的芯片,它用的是什么样的时序。 你随便找个使用I2C通讯协议的芯片的技术手册看看吧。 里面肯定会有讲时序图。说得很明白。 随便扯一下把 写数据的时候。这个ABC引脚,要低电平,然后才会把数据写进去。 那么,这个低电平要保持多久我才可以写数据? 我ABC引脚拉低1ns然后立刻拉高芯片识别的到吗? 那10ns呢?哦,这个是低速芯片。要拉低100ns啊。 我的FPGA用的是100M的晶振,一个周期是10ns。 那我就写C1==10 10*10=100ns。 假如芯片手册说。不。要拉低200ns 那我就写C1==20 10*20=200ns 然后我发现100M晶振用完了,现在只有50M的,一个周期是20ns 那我就只好改回去了C1==10 20*10=200ns |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1693 浏览 1 评论
1447 浏览 0 评论
矩阵4x4个按键,如何把识别结果按编号01-16(十进制)显示在两个七段数码管上?
1661 浏览 0 评论
943 浏览 0 评论
2451 浏览 0 评论
1507 浏览 38 评论
5706 浏览 113 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-30 02:07 , Processed in 0.637367 second(s), Total 51, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号