当前位置:   article > 正文

i2c协议简介,用FPGA实现I2c总线协议,i2c读写EEPROM工程示例。_fpga nois ii 实现i2c

fpga nois ii 实现i2c

本实验采用Xilinx artix 7芯片,型号为xc7a35t_2fgg484。

任务目标:设计一个可进行读写操作的 I2C 控制器,实现 FPGA对 EEPROM 存储器的数据写入和数据读取操作。

1 、I2c简介

I2C(Inter-Integrated Circuit)总线协议是一种用于在集成电路(IC)之间进行通信的串行通信协议。它由飞利浦(Philips)公司于上世纪80年代开发,并成为一种广泛应用于各种电子设备中的通信协议。

1.1 基本原理

I2C总线协议使用两根线(SDA和SCL)进行通信。SDA(Serial Data Line)是数据线,用于传输数据,而SCL(Serial Clock Line)是时钟线,用于同步数据传输。这种双线制的结构使得多个IC可以在同一总线上进行通信。

1、主从结构:I2C总线协议采用主从结构。主设备(Master)负责发起通信并控制总线上的时序,而从设备(Slave)则被动地响应主设备的请求。主设备可以与多个从设备进行通信,每个从设备都有一个唯一的地址。

2、数据传输:数据传输通过起始位(2)、地址/数据(3)和停止位(4)来完成。空闲时(1),主设备发起通信时,发送一个起始位(Start)信号,然后发送从设备的地址和读/写指令位。接下来,主设备发送读/写地址并等待从设备响应,接着发送或接收数据,并等待从设备的确认信号。通信结束时,主设备发送停止位(Stop)信号,如图1所示。具体来说,它有4种传输模式:单字节写、多字节写、单字节读、多字节读。值得注意的是,每种读写模式里面须根据从设备存储空间大小来确定WORD ADDRESS的长度,对于一些大容量设备,这里的长度可以为双字节(16bit),每字节地址都需要一个ACK信号。地址和数据都是高位在前、低位在后。

图1  i2c总线协议
图2 单字节写 时序图
图3 多字节写(顺序写) 时序图(两字节地址)

 注意,读操作与写操作的不同点在于,主机写完存储地址之后,再次给个start信号,其后再给一次设备地址+读指令位,响应后开始接收读数据。

图4 单字节读 时序图
图5 多字节读(顺序读)时序图

 3、速度和可靠性:I2C总线协议支持多种传输速率,通常有标准模式(100 kbps)和快速模式(400 kbps)。此外,还有高速模式(3.4 Mbps)和超高速模式(5 Mbps)等。总线上的设备可以根据自身的能力选择适当的速率。

1.2 常用场景

I2C总线协议在许多电子设备中得到广泛应用。一些常见的场景包括:

  • 传感器和微控制器之间的通信:I2C总线协议可用于传感器与微控制器之间的数据传输,例如温度传感器、湿度传感器等。
  • 存储器和微控制器之间的通信:I2C总线协议可用于存储器(如EEPROM)与微控制器之间的数据读写操作。
  • 外围设备控制:I2C总线协议可用于控制外围设备,如LCD显示屏、触摸屏、电子芯片等。
  • 数字信号处理器(DSP)和外设之间的通信:I2C总线协议可用于DSP与外设(如音频编解码器、ADC、DAC等)之间的数据传输。

2、 工程示例

2.1 模块设计

工程主要由3个子模块构成,包括按键消抖模块(通过按键控制读/写)、读写数据模块、i2c驱动模块。整个工程的模块划分如下图所示:

图6 模块划分

按下数据写操作按键,写触发信号传入按键消抖模块(key_filter),经消抖处理后的写触发信号传入数据收发模块(i2c_rw_data),模块接收到有效的写触发信号后,生成写使能信号、待写入数据、数据地址传入 I2C 驱动模块(i2c_ctrl), I2C 驱动模块按照 I2C 协议将数据写入 EEPROM 存储芯片;
数据写入完成后,按下数据读操作按键,读触发信号传入按键消抖模块(key_filter),经消抖处理后的读触发信号传入数据收发模块(i2c_rw_data),模块接收到有效的读触发信号后,生成读使能信号、数据地址传入 I2C 驱动模块(i2c_ctrl), I2C 驱动模块自 EEPROM存储芯片读取数据,将读取到的数据回传给数据收发模块(i2c_rw_data),数据收发模块将数据暂存,待所有数据均读取完成后,将数据输出。


2.2 i2c驱动模块

I2C 驱动模块的主要功能是按照 I2C 协议对 EERPROM 存储芯片执行数据读写操作。

图7 状态转移图
  1. module i2c_ctrl #(
  2. parameter sys_clk_freq = 50_000_000,
  3. i2c_clk_freq = 1_000_000 ,
  4. i2c_scl_freq = 250_000,
  5. parameter device_addr_w = 8'b1010_0110,
  6. device_addr_r = 8'b1010_0111
  7. )
  8. (
  9. input wire sys_clk ,
  10. input wire sys_rst_n ,
  11. input wire i2c_start ,
  12. input wire wr_en ,
  13. input wire rd_en ,
  14. input wire [15:0] address ,
  15. input wire [7:0] wr_data ,
  16. input wire addr_num ,
  17. inout wire i2c_sda ,
  18. output reg i2c_scl ,
  19. output reg i2c_clk ,
  20. output reg [7:0] rd_data ,
  21. output reg i2c_end
  22. );
  23. localparam IDLE = 5'd1 ,
  24. START = 5'd2 ,
  25. SEND_DEV_ADDR = 5'd3 ,
  26. ACK_1 = 5'd4 ,
  27. SEND_H = 5'd5 ,
  28. ACK_2 = 5'd6 ,
  29. SEND_B_L = 5'd7 ,
  30. ACK_3 = 5'd8 ,
  31. WR_DAT = 5'd9 ,
  32. ACK_4 = 5'd10,
  33. STOP = 5'd11;
  34. localparam START_2 = 5'd12,
  35. SEND_RD_A = 5'd13,
  36. ACK_5 = 5'd14,
  37. RD_DAT = 5'd15,
  38. NO_ACK = 5'd16;
  39. localparam cnt_sys_clk_max = 5'd24;
  40. reg [4:0] cnt_sys_clk ;
  41. reg cnt_i2c_clk_en ;
  42. reg [1:0] cnt_i2c_clk ;
  43. (*mark_debug="true"*)reg [4:0] state ;
  44. (*mark_debug="true"*)reg [2:0] cnt_bit ;
  45. reg ack ;
  46. reg i2c_sda_out ;
  47. (*mark_debug="true"*)wire i2c_sda_in ;
  48. (*mark_debug="true"*)wire sda_en ;
  49. reg [7:0] rd_data_reg ;
  50. wire ack_flag;
  51. always @(posedge sys_clk or negedge sys_rst_n) //生成i2c_clk时钟
  52. if (sys_rst_n == 1'b0) begin
  53. cnt_sys_clk <= 5'b0;
  54. i2c_clk <= 1'b0;
  55. end
  56. else if (cnt_sys_clk == cnt_sys_clk_max) begin
  57. cnt_sys_clk <= 5'd0;
  58. i2c_clk <= ~i2c_clk ;
  59. end
  60. else
  61. cnt_sys_clk <= cnt_sys_clk + 5'd1;
  62. always @(posedge i2c_clk or negedge sys_rst_n) //i2c_clk时钟计数起始信号
  63. if (sys_rst_n == 1'b0)
  64. cnt_i2c_clk_en <= 1'b0;
  65. else if (state == STOP && cnt_bit == 3'd3 && cnt_i2c_clk == 2'd3)
  66. cnt_i2c_clk_en <= 1'b0;
  67. else if (i2c_start == 1'b1)
  68. cnt_i2c_clk_en <= 1'b1;
  69. else
  70. cnt_i2c_clk_en <= cnt_i2c_clk_en;
  71. always @(posedge i2c_clk or negedge sys_rst_n) //i2c_clk计数生成cnt_bit控制信号
  72. if (sys_rst_n == 1'b0)
  73. cnt_i2c_clk <= 2'd0;
  74. else if (cnt_i2c_clk_en == 1'b1) begin
  75. if (cnt_i2c_clk == 2'd3)
  76. cnt_i2c_clk <= 2'd0;
  77. else
  78. cnt_i2c_clk <= cnt_i2c_clk + 2'd1;
  79. end
  80. else
  81. cnt_i2c_clk <= 2'd0;
  82. always@(*) //i2c_scl ?
  83. case (state)
  84. IDLE:
  85. i2c_scl <= 1'b1;
  86. START:if(cnt_i2c_clk == 2'd3)
  87. i2c_scl <= 1'b0;
  88. else
  89. i2c_scl <= 1'b1;
  90. SEND_DEV_ADDR,ACK_1,SEND_H,ACK_2,SEND_B_L,
  91. ACK_3,WR_DAT,ACK_4,START_2,SEND_RD_A,ACK_5,RD_DAT,NO_ACK:
  92. if((cnt_i2c_clk == 2'd1) || (cnt_i2c_clk == 2'd2))
  93. i2c_scl <= 1'b1;
  94. else
  95. i2c_scl <= 1'b0;
  96. STOP:
  97. if((cnt_bit == 3'd0) &&(cnt_i2c_clk == 2'd0))
  98. i2c_scl <= 1'b0;
  99. else
  100. i2c_scl <= 1'b1;
  101. default: i2c_scl <= 1'b1;
  102. endcase
  103. always @(posedge i2c_clk or negedge sys_rst_n) //收发字节的计 ?
  104. if (sys_rst_n == 1'b0)
  105. cnt_bit <= 3'b0;
  106. else if ((cnt_bit == 3'd7&&cnt_i2c_clk == 2'd3) || (state == ACK_1 || state == ACK_2 || state == ACK_3
  107. || state == ACK_4 ||state == ACK_5||state == IDLE||state == NO_ACK||state == START_2||state == START)
  108. ||(state == STOP && cnt_bit == 3'd3&&cnt_i2c_clk == 2'd3))
  109. cnt_bit <= 3'b0;
  110. else if ((cnt_i2c_clk == 2'd3) && (state != IDLE))
  111. cnt_bit <= cnt_bit + 1'd1;
  112. else
  113. cnt_bit <= cnt_bit;
  114. always @(posedge i2c_clk or negedge sys_rst_n) //状 ? 机的跳 ?
  115. if(sys_rst_n == 1'b0)
  116. state <= IDLE;
  117. else case(state)
  118. IDLE:
  119. if (i2c_start == 1'b1)
  120. state <= START;
  121. else
  122. state <= IDLE;
  123. START: if (cnt_i2c_clk == 2'd3)
  124. state <= SEND_DEV_ADDR;
  125. else
  126. state <= START;
  127. SEND_DEV_ADDR: if(cnt_bit == 3'd7 && cnt_i2c_clk==2'd3)
  128. state <= ACK_1;
  129. else
  130. ;
  131. ACK_1: if(ack == 1'b0 && cnt_i2c_clk==2'd3)begin
  132. if(addr_num == 1'b0)
  133. state <= SEND_B_L;
  134. else
  135. state <= SEND_H;
  136. end
  137. else
  138. ;
  139. SEND_H: if(cnt_bit == 3'd7 && cnt_i2c_clk==2'd3)
  140. state <= ACK_2;
  141. else
  142. ;
  143. ACK_2: if(ack == 1'b0 && cnt_i2c_clk==2'd3)
  144. state <= SEND_B_L;
  145. else
  146. ;
  147. SEND_B_L: if(cnt_bit == 3'd7 && cnt_i2c_clk==2'd3)
  148. state <= ACK_3;
  149. else
  150. ;
  151. ACK_3: if(ack == 1'b0 && cnt_i2c_clk==2'd3)begin
  152. if(rd_en == 1'b1)
  153. state <= START_2;
  154. else if(wr_en == 1'b1)
  155. state <= WR_DAT;
  156. else
  157. ;
  158. end
  159. else
  160. ;
  161. WR_DAT: if(cnt_bit == 3'd7 && cnt_i2c_clk==2'd3)
  162. state <= ACK_4;
  163. else
  164. ;
  165. ACK_4: if(ack == 1'b0 && cnt_i2c_clk==2'd3)
  166. state <= STOP;
  167. else
  168. ;
  169. STOP: if(cnt_bit == 3'd3 && cnt_i2c_clk == 2'd3)
  170. state <= IDLE;
  171. else
  172. ;
  173. START_2: if(cnt_i2c_clk == 2'd3)
  174. state <= SEND_RD_A;
  175. else
  176. ;
  177. SEND_RD_A: if(cnt_bit == 3'd7 && cnt_i2c_clk == 2'd3)
  178. state <= ACK_5;
  179. else
  180. ;
  181. ACK_5: if(ack == 1'b0 && cnt_i2c_clk == 2'd3)
  182. state <= RD_DAT;
  183. else
  184. ;
  185. RD_DAT: if(cnt_bit == 3'd7 && cnt_i2c_clk == 2'd3)
  186. state <= NO_ACK;
  187. else
  188. ;
  189. NO_ACK: if(i2c_sda_out == 1'b1 && cnt_i2c_clk == 2'd3)
  190. state <= STOP;
  191. else
  192. ;
  193. default: state <= IDLE;
  194. endcase
  195. always @(posedge i2c_clk or negedge sys_rst_n) //i2c的结束信 ?
  196. if(sys_rst_n == 1'b0)
  197. i2c_end <= 1'b0;
  198. else if(state == STOP && cnt_bit == 3'd3 && cnt_i2c_clk ==2'd3)
  199. i2c_end <= 1'b1;
  200. else
  201. i2c_end <= 1'b0;
  202. /*always @(posedge i2c_clk or negedge sys_rst_n) //使用时序逻辑给sda线输出时的数据赋 ?
  203. if(sys_rst_n == 1'b0)
  204. i2c_sda_out = 1'b1;
  205. else if(state == START)
  206. i2c_sda_out = 1'b0;
  207. else if(state == START && cnt_i2c_clk == 2'd3)
  208. i2c_sda_out <= device_addr_w[7];
  209. else if(state == SEND_DEV_ADDR) begin
  210. if (cnt_i2c_clk == 2'd3) begin
  211. case(cnt_bit)
  212. 0: i2c_sda_out <= device_addr_w[6];
  213. 1: i2c_sda_out <= device_addr_w[5];
  214. 2: i2c_sda_out <= device_addr_w[4];
  215. 3: i2c_sda_out <= device_addr_w[3];
  216. 4: i2c_sda_out <= device_addr_w[2];
  217. 5: i2c_sda_out <= device_addr_w[1];
  218. 6: i2c_sda_out <= device_addr_w[0];
  219. default: i2c_sda_out <= 1'b1;
  220. endcase
  221. end
  222. else
  223. ;
  224. end
  225. else if(state == ACK_1 && cnt_i2c_clk == 2'd3)
  226. i2c_sda_out <= address[15];
  227. else if(state == SEND_H) begin
  228. if (cnt_i2c_clk == 2'd3) begin
  229. case(cnt_bit)
  230. 0: i2c_sda_out <= address[14];
  231. 1: i2c_sda_out <= address[13];
  232. 2: i2c_sda_out <= address[12];
  233. 3: i2c_sda_out <= address[11];
  234. 4: i2c_sda_out <= address[10];
  235. 5: i2c_sda_out <= address[9];
  236. 6: i2c_sda_out <= address[8];
  237. default: i2c_sda_out <= 1'b1;
  238. endcase
  239. end
  240. else
  241. ;
  242. end
  243. else if(state == ACK_2 && cnt_i2c_clk == 2'd3)
  244. i2c_sda_out <= address[7];
  245. else if(state == SEND_B_L) begin
  246. if (cnt_i2c_clk == 2'd3) begin
  247. case(cnt_bit)
  248. 0: i2c_sda_out <= address[6];
  249. 1: i2c_sda_out <= address[5];
  250. 2: i2c_sda_out <= address[4];
  251. 3: i2c_sda_out <= address[3];
  252. 4: i2c_sda_out <= address[2];
  253. 5: i2c_sda_out <= address[1];
  254. 6: i2c_sda_out <= address[0];
  255. default: i2c_sda_out <= 1'b1 ;
  256. endcase
  257. end
  258. else
  259. ;
  260. end
  261. else if(state == ACK_3 && cnt_i2c_clk == 2'd3)
  262. i2c_sda_out <= wr_data[7];
  263. else if(state == WR_DAT) begin
  264. if (cnt_i2c_clk == 2'd3) begin
  265. case(cnt_bit)
  266. 0: i2c_sda_out <= wr_data[6];
  267. 1: i2c_sda_out <= wr_data[5];
  268. 2: i2c_sda_out <= wr_data[4];
  269. 3: i2c_sda_out <= wr_data[3];
  270. 4: i2c_sda_out <= wr_data[2];
  271. 5: i2c_sda_out <= wr_data[1];
  272. 6: i2c_sda_out <= wr_data[0];
  273. default: i2c_sda_out <= 1'b1 ;
  274. endcase
  275. end
  276. else
  277. ;
  278. end
  279. else if(state == ACK_4 && cnt_i2c_clk == 2'd3)
  280. i2c_sda_out <= 1'b0;
  281. else if(state == START_2 && cnt_i2c_clk == 2'd1) //随机写操作的 ? ?
  282. i2c_sda_out <= 1'b0;
  283. else if(state == START_2 && cnt_i2c_clk == 2'd3)
  284. i2c_sda_out <= device_addr_r[7];
  285. else if(state == SEND_RD_A) begin
  286. if (cnt_i2c_clk == 2'd3) begin
  287. case(cnt_bit)
  288. 0: i2c_sda_out <= device_addr_r[6];
  289. 1: i2c_sda_out <= device_addr_r[5];
  290. 2: i2c_sda_out <= device_addr_r[4];
  291. 3: i2c_sda_out <= device_addr_r[3];
  292. 4: i2c_sda_out <= device_addr_r[2];
  293. 5: i2c_sda_out <= device_addr_r[1];
  294. 6: i2c_sda_out <= device_addr_r[0];
  295. default: i2c_sda_out <= 1'b1 ;
  296. endcase
  297. end
  298. else
  299. ;
  300. end
  301. else if(state == NO_ACK && cnt_i2c_clk == 2'd3)
  302. i2c_sda_out <= 1'b0;
  303. else if(state == STOP && cnt_i2c_clk == 2'd2)
  304. i2c_sda_out <= 1'b1;
  305. else if(state == IDLE)
  306. i2c_sda_out <= 1'b1;
  307. else
  308. i2c_sda_out <= i2c_sda_out;
  309. always @(posedge i2c_scl or negedge sys_rst_n) //sda作为输入时,接收到的数据串转 ?
  310. if(sys_rst_n == 1'b0)
  311. rd_data <= 8'b0;
  312. else if(state == RD_DAT && cnt_i2c_clk == 2'd2) begin
  313. rd_data= {rd_data[6:0],i2c_sda_in};
  314. end
  315. else if(state == IDLE)
  316. rd_data <= 8'b0;
  317. else
  318. ;
  319. */
  320. always @(*)
  321. case(state)
  322. IDLE,START,SEND_DEV_ADDR,SEND_H,SEND_B_L,WR_DAT,STOP,START_2,SEND_RD_A,RD_DAT,NO_ACK:
  323. ack <= 1'b1;
  324. ACK_1,ACK_2,ACK_3,ACK_4,ACK_5:
  325. if(cnt_i2c_clk == 2'd0)
  326. ack <= i2c_sda;
  327. else
  328. ack <= ack;
  329. default : ack <= 1'b1;
  330. endcase
  331. always @(*) //使用组合逻辑对sda线的输出和读取寄存器赋 ??,更方 ?
  332. case(state)
  333. IDLE:
  334. begin
  335. i2c_sda_out <= 1'b1;
  336. rd_data_reg <= 8'd0;
  337. end
  338. START:
  339. i2c_sda_out <= 1'b0;
  340. SEND_DEV_ADDR:
  341. if(cnt_bit <= 3'd7)
  342. i2c_sda_out <= device_addr_w[7 - cnt_bit];
  343. else
  344. ;
  345. ACK_1:
  346. i2c_sda_out <= 1'b1;
  347. SEND_H:
  348. i2c_sda_out <= address[15-cnt_bit];
  349. ACK_2:
  350. i2c_sda_out <= 1'b1;
  351. SEND_B_L:
  352. i2c_sda_out <= address[7-cnt_bit];
  353. ACK_3:
  354. i2c_sda_out <= 1'b1;
  355. WR_DAT:
  356. i2c_sda_out <= wr_data[7-cnt_bit];
  357. ACK_4:
  358. i2c_sda_out <= 1'b1;
  359. STOP:
  360. if(cnt_bit == 3'd0 && cnt_i2c_clk < 2'd3)
  361. i2c_sda_out <= 1'b0;
  362. else
  363. i2c_sda_out <= 1'b1;
  364. START_2:
  365. if(cnt_i2c_clk == 2'd0)
  366. i2c_sda_out <= 1'b1;
  367. else if(cnt_i2c_clk == 2'd2)
  368. i2c_sda_out <= 1'b0;
  369. else
  370. ;
  371. SEND_RD_A:
  372. i2c_sda_out <= device_addr_r[7-cnt_bit];
  373. ACK_5:
  374. i2c_sda_out <= 1'b1;
  375. RD_DAT:
  376. if(cnt_i2c_clk == 2'd2)
  377. rd_data_reg[7-cnt_bit] <= i2c_sda_in;
  378. else
  379. rd_data_reg <= rd_data_reg;
  380. default: begin
  381. i2c_sda_out <= 1'b1;
  382. rd_data_reg <= rd_data_reg;
  383. end
  384. endcase
  385. always @(posedge i2c_clk or negedge sys_rst_n) //读数据输出赋 ?
  386. if(sys_rst_n == 1'b0)
  387. rd_data <= 8'd0;
  388. else if(state == RD_DAT && cnt_bit == 3'd7 && cnt_i2c_clk == 2'd3)
  389. rd_data <= rd_data_reg; //在读数据寄存器收集数据完成后赋 ??
  390. else
  391. ;
  392. //assign ack = ((state == ACK_1) || (state == ACK_2) ||(state == ACK_3) || (state == ACK_4) || (state == ACK_5)) ? i2c_sda_in: 1'b1;
  393. assign i2c_sda_in = i2c_sda; //sda作为输入时,接收到的数据
  394. assign sda_en = ( (state == ACK_1) || (state == ACK_2) ||(state == ACK_3) || (state == ACK_4) || (state == ACK_5)|| (state == RD_DAT)) ? 1'b0 : 1'b1;
  395. assign i2c_sda = (sda_en == 1'b1) ? i2c_sda_out : 1'bz; //数据使能时作为输出,否则输出为高阻 ??
  396. //IOBUF #(
  397. // .DRIVE(12), // Specify the output drive strength
  398. // .IBUF_LOW_PWR("FALSE"), // Low Power - "TRUE", High Performance = "FALSE"
  399. // .IOSTANDARD("DEFAULT"), // Specify the I/O standard
  400. // .SLEW("SLOW") // Specify the output slew rate
  401. // ) IOBUF_i2c(
  402. // .O(i2c_sda_in), // Buffer output
  403. // .IO(i2c_sda), // Buffer inout port (connect directly to top-level port)
  404. // .I(i2c_sda_out), // Buffer input
  405. // .T(~sda_en) // 3-state enable input, high=input, low=output
  406. // );
  407. endmodule

2.3 数据收发模块

数据收发模块的主要功能是:为 I2C 驱动模块提供读/写数据存储地址、待写入数据以及作为 EEPROM 读出数据缓存。

  1. module i2c_rw_data(
  2. input wire sys_clk ,
  3. input wire sys_rst_n ,
  4. input wire write ,
  5. input wire read ,
  6. input wire i2c_clk ,
  7. input wire [7:0] rd_data ,
  8. input wire i2c_end ,
  9. output reg i2c_start ,
  10. output reg wr_en ,
  11. output reg rd_en ,
  12. output reg [15:0] byte_addr ,
  13. output reg [7:0] wr_data ,
  14. output wire[7:0] fifo_rd_data
  15. );
  16. parameter cnt_sys_clk_m = 8'd200, cnt_wr_m = 4'd10,
  17. cnt_start_m = 32'd4999,cnt_fifo_wait_m=28'd499999;
  18. reg [7:0] cnt_wr_valid;
  19. reg [7:0] cnt_rd_valid;
  20. reg wr_valid ;
  21. reg rd_valid ;
  22. reg [31:0] cnt_i2c_start; //每次“开始 ? 信号的间隔时间
  23. reg [3:0] cnt_wr ; //发 ? 数据个数计 ?
  24. reg [3:0] cnt_rd ; //读取数据个数计数
  25. reg fifo_rd_valid; //fifo读取有效信号
  26. reg [27:0] cnt_fifo_wait; //每次从FIFO读出数据的时间间隔,方便观察
  27. reg fifo_rd_en ; //从fifo读数据的使能信号
  28. reg [3:0] rd_fifo_num ; //从fifo读出数据的个 ?
  29. wire [7:0] fifo_num ; //fifo中的数据个数
  30. wire full ;
  31. wire empty ;
  32. always @(posedge sys_clk or negedge sys_rst_n) //信号从高频到低频跨时钟域,延 ?
  33. if(sys_rst_n == 1'b0) begin
  34. cnt_wr_valid <= 8'd0;
  35. wr_valid <= 1'b0;
  36. cnt_rd_valid <= 8'd0;
  37. rd_valid <= 1'b0;
  38. end
  39. else if (cnt_wr_valid == cnt_sys_clk_m) begin
  40. cnt_wr_valid <= 8'd0;
  41. wr_valid <= 1'b0;
  42. end
  43. else if (write == 1'b1)
  44. wr_valid <= 1'b1;
  45. else if (wr_valid == 1'b1)
  46. cnt_wr_valid <= cnt_wr_valid + 8'd1;
  47. else if (cnt_rd_valid == cnt_sys_clk_m)begin
  48. cnt_rd_valid <= 8'd0;
  49. rd_valid <= 1'b0;
  50. end
  51. else if(read == 1'b1)
  52. rd_valid <= 1'b1;
  53. else if(rd_valid == 1'b1)
  54. cnt_rd_valid <= cnt_rd_valid + 8'd1;
  55. else begin
  56. wr_valid <= wr_valid;
  57. rd_valid <= rd_valid;
  58. end
  59. always @(posedge i2c_clk or negedge sys_rst_n) //i2c的读写使能信 ?
  60. if(sys_rst_n == 1'b0) begin
  61. wr_en <= 1'b0;
  62. rd_en <= 1'b0;
  63. end
  64. else if(wr_valid == 1'b1)
  65. wr_en <= 1'b1;
  66. else if (rd_valid == 1'b1)
  67. rd_en <= 1'b1;
  68. else if (cnt_wr == cnt_wr_m - 1 && i2c_end == 1'b1)
  69. wr_en <= 1'b0;
  70. else if (cnt_rd == cnt_wr_m - 1 && i2c_end == 1'b1)
  71. rd_en <= 1'b0;
  72. else
  73. ;
  74. always @(posedge i2c_clk or negedge sys_rst_n) //i2c的开始信 ?
  75. if(sys_rst_n == 1'b0)
  76. cnt_i2c_start <= 32'd0;
  77. else if(cnt_i2c_start == cnt_start_m)
  78. cnt_i2c_start <= 32'd0;
  79. else if(wr_en == 1'b0 && rd_en == 1'b0)
  80. cnt_i2c_start <= 32'd0;
  81. else if(wr_en == 1'b1 || rd_en == 1'b1)
  82. cnt_i2c_start <= cnt_i2c_start + 32'd1;
  83. else
  84. ;
  85. always @(posedge i2c_clk or negedge sys_rst_n) //i2c的开始信 ?
  86. if(sys_rst_n == 1'b0)
  87. i2c_start <= 1'b0;
  88. else if(cnt_i2c_start == cnt_start_m)
  89. i2c_start <= 1'b1;
  90. else
  91. i2c_start <= 1'b0;
  92. always @(posedge i2c_clk or negedge sys_rst_n) //i2c写 ? 读的次数计 ?
  93. if(sys_rst_n == 1'b0)
  94. cnt_wr <= 4'd0;
  95. else if(wr_en == 1'b0)
  96. cnt_wr <= 4'd0;
  97. else if((i2c_end == 1'b1) && (wr_en == 1'b1))
  98. cnt_wr <= cnt_wr + 4'd1;
  99. else
  100. ;
  101. always @(posedge i2c_clk or negedge sys_rst_n) //i2c写 ? 读的次数计 ?
  102. if(sys_rst_n == 1'b0)
  103. cnt_rd <= 4'd0;
  104. else if(rd_en == 1'b0)
  105. cnt_rd <= 4'd0;
  106. else if((i2c_end == 1'b1) && (rd_en == 1'b1))
  107. cnt_rd <= cnt_rd + 4'd1;
  108. else
  109. ;
  110. always @(posedge i2c_clk or negedge sys_rst_n) //fifo读有效信 ?
  111. if(sys_rst_n == 1'b0)
  112. fifo_rd_valid <= 1'b0;
  113. else if (cnt_rd == 4'd10)
  114. fifo_rd_valid <= 1'b1;
  115. else if(rd_fifo_num == 8'd10 && cnt_fifo_wait == cnt_fifo_wait_m)
  116. fifo_rd_valid <= 1'b0;
  117. else
  118. ;
  119. always @(posedge i2c_clk or negedge sys_rst_n) //每次从fifo读数据的等待时间
  120. if(sys_rst_n == 1'b0)
  121. cnt_fifo_wait <= 28'b0;
  122. else if(cnt_fifo_wait == cnt_fifo_wait_m)
  123. cnt_fifo_wait <= 28'd0;
  124. else if(fifo_rd_valid == 1'b1)
  125. cnt_fifo_wait <= cnt_fifo_wait + 28'd1;
  126. else if(fifo_rd_valid == 1'b0)
  127. cnt_fifo_wait <= 28'd0;
  128. else
  129. ;
  130. always @(posedge i2c_clk or negedge sys_rst_n) //fifo读使能信 ?
  131. if(sys_rst_n == 1'b0)
  132. fifo_rd_en <= 1'b0;
  133. else if(fifo_rd_valid == 1'b1 && (cnt_fifo_wait==cnt_fifo_wait_m))
  134. fifo_rd_en <= 1'b1;
  135. else
  136. fifo_rd_en <= 1'b0;
  137. always @(posedge i2c_clk or negedge sys_rst_n) //从FIFO中读取的次数
  138. if(sys_rst_n == 1'b0)
  139. rd_fifo_num <= 4'd0;
  140. else if(fifo_rd_en == 1'b1)
  141. rd_fifo_num <= rd_fifo_num + 4'd1;
  142. else if(fifo_rd_valid == 1'b0)
  143. rd_fifo_num <= 4'd0;
  144. else
  145. ;
  146. always @(posedge i2c_clk or negedge sys_rst_n) //i2c写入的eeprom存储地址和数 ?
  147. if(sys_rst_n == 1'b0 ) begin
  148. byte_addr <= 16'h005a;
  149. wr_data <= 8'h01;
  150. end
  151. else if(((cnt_wr == 4'd9)||(cnt_rd == 4'd9)) && i2c_end == 1'b1)begin
  152. byte_addr <= 16'h005a;
  153. wr_data <= 8'h01;
  154. end
  155. else if((rd_en == 1'b1) && (i2c_end == 1'b1)&&(wr_en == 1'b0))
  156. byte_addr <= byte_addr + 16'h1;
  157. else if((wr_en == 1'b1) && (i2c_end == 1'b1)) begin
  158. wr_data <= wr_data + 8'h1;
  159. byte_addr <= byte_addr + 16'h1;
  160. end
  161. else
  162. ;
  163. fifo_i2c_read fifo_i2c_read_i2c(
  164. .clk(i2c_clk ), // input wire clk
  165. .din(rd_data ), // input wire [7 : 0] din
  166. .wr_en(rd_en && i2c_end ), // input wire wr_en
  167. .rd_en(fifo_rd_en ), // input wire rd_en
  168. .dout(fifo_rd_data ), // output wire [7 : 0] dout
  169. .full(full ), // output wire full
  170. .empty(empty ), // output wire empty
  171. .data_count(fifo_num ) // output wire [7 : 0] data_count
  172. );
  173. endmodule

2.4 按键消抖模块

  1. module key_filter
  2. #(
  3. parameter cnt_max=20'd999_999
  4. )
  5. (
  6. input clk,
  7. input rst_n,
  8. input key_n,
  9. output key_flag
  10. );
  11. reg [19:0] cnt_20ms;
  12. reg key_flag1;
  13. always @(posedge clk or negedge rst_n)
  14. if(rst_n == 1'b0)
  15. cnt_20ms <= 20'd0;
  16. else if(cnt_20ms == cnt_max)
  17. cnt_20ms <= cnt_max;
  18. else if(key_n == 1'b1)
  19. cnt_20ms <= 20'd0;
  20. else
  21. cnt_20ms <= cnt_20ms+1'd1;
  22. always @(posedge clk or negedge rst_n)
  23. if(rst_n == 1'b0)
  24. key_flag1 <= 1'b0;
  25. else if (cnt_20ms == cnt_max - 20'd1)
  26. key_flag1 <= 1'b1;
  27. else
  28. key_flag1 <= 1'b0;
  29. assign key_flag = key_flag1;
  30. endmodule

2.5 顶层模块

  1. module i2c_eeprom(
  2. input sys_clk ,
  3. input sys_rst_n ,
  4. input [1:0] key ,
  5. output reg [2:0] led ,
  6. output i2c_scl ,
  7. output i2c_sda
  8. );
  9. wire write;
  10. wire read ;
  11. wire i2c_clk;
  12. wire i2c_end;
  13. wire [7:0] i2c_rd_data;
  14. wire i2c_start ;
  15. wire wr_en ;
  16. wire rd_en ;
  17. wire [15:0] byte_addr ;
  18. wire [7:0] wr_data ;
  19. wire [7:0] fifo_rd_data;
  20. always @(*)
  21. if(sys_rst_n == 1'b0)
  22. led <= 3'b000;
  23. else if(wr_data == 8'h0a)
  24. led <= 3'b001;
  25. else if (i2c_rd_data == 8'h0a)
  26. led <= 3'b011;
  27. else if (fifo_rd_data == 8'h0a)
  28. led <= 3'b111;
  29. else
  30. ;
  31. key_filter
  32. #(
  33. .cnt_max (20'd999_999)
  34. )key_filter_a
  35. (
  36. .clk ( sys_clk ),
  37. .rst_n ( sys_rst_n ),
  38. .key_n ( key[0] ),
  39. .key_flag ( write )
  40. );
  41. key_filter
  42. #(
  43. .cnt_max (20'd999_999)
  44. )key_filter_b
  45. (
  46. .clk ( sys_clk ),
  47. .rst_n ( sys_rst_n ),
  48. .key_n ( key[1] ),
  49. .key_flag ( read )
  50. );
  51. i2c_rw_data i2c_rw_data_inst(
  52. .sys_clk ( sys_clk ),
  53. .sys_rst_n ( sys_rst_n ),
  54. .write ( write ),
  55. .read ( read ),
  56. .i2c_clk ( i2c_clk ),
  57. .rd_data ( i2c_rd_data ),
  58. .i2c_end ( i2c_end ),
  59. .i2c_start ( i2c_start ),
  60. .wr_en ( wr_en ),
  61. .rd_en ( rd_en ),
  62. .byte_addr ( byte_addr ),
  63. .wr_data ( wr_data ),
  64. .fifo_rd_data ( fifo_rd_data )
  65. );
  66. i2c_ctrl #(
  67. .sys_clk_freq (50_000_000),
  68. .i2c_clk_freq (1_000_000 ),
  69. .i2c_scl_freq (250_000 ),
  70. .device_addr_w (8'b1010_0110),
  71. .device_addr_r (8'b1010_0111)
  72. )i2c_ctrl_top
  73. (
  74. .sys_clk ( sys_clk ),
  75. .sys_rst_n ( sys_rst_n ),
  76. .i2c_start ( i2c_start ),
  77. .wr_en ( wr_en ),
  78. .rd_en ( rd_en ),
  79. .address ( byte_addr ),
  80. .wr_data ( wr_data ),
  81. .addr_num ( 1'b1 ), // i2c ַ ֽ
  82. .i2c_sda ( i2c_sda ),
  83. .i2c_scl ( i2c_scl ),
  84. .i2c_clk ( i2c_clk ),
  85. .rd_data ( i2c_rd_data ),
  86. .i2c_end ( i2c_end )
  87. );
  88. ila_i2c_eeprom ila_i2c_eeprom_inst(
  89. .clk(sys_clk), // input wire clk
  90. .probe0(sys_rst_n), // input wire [0:0] probe0
  91. .probe1(key), // input wire [1:0] probe1
  92. .probe2(i2c_clk), // input wire [0:0] probe2
  93. .probe3(i2c_rd_data), // input wire [7:0] probe3
  94. .probe4(wr_data), // input wire [7:0] probe4
  95. .probe5(i2c_end), // input wire [0:0] probe5
  96. .probe6(i2c_scl), // input wire [0:0] probe6
  97. .probe7(i2c_sda), // input wire [0:0] probe7
  98. .probe8(rd_en) // input wire [0:0] probe8
  99. );
  100. endmodule

3、 testbench仿真文件

  1. module i2c_eeprom_tb( );
  2. reg sys_clk ;
  3. reg sys_rst_n ;
  4. reg [1:0] key ;
  5. wire [2:0] led ;
  6. wire i2c_scl ;
  7. wire i2c_sda ;
  8. initial
  9. begin
  10. sys_clk <= 1'b1;
  11. sys_rst_n <= 1'b0;
  12. key <= 2'b11;
  13. #200
  14. sys_rst_n <= 1'b1;
  15. #2000
  16. key <= 2'b10;
  17. #400
  18. key <= 2'b11;
  19. #51_000_000
  20. key <= 2'b01;
  21. #400
  22. key <= 2'b11;
  23. end
  24. always #10 sys_clk = ~sys_clk;
  25. defparam i2c_eeprom_testbench.key_filter_a.cnt_max = 5;
  26. defparam i2c_eeprom_testbench.key_filter_b.cnt_max = 5;
  27. defparam i2c_eeprom_testbench.i2c_rw_data_inst.cnt_fifo_wait_m = 28'd1000;
  28. defparam i2c_eeprom_testbench.i2c_ctrl_top.device_addr_w = 8'b1010_0000;
  29. defparam i2c_eeprom_testbench.i2c_ctrl_top.device_addr_r = 8'b1010_0001;
  30. i2c_eeprom i2c_eeprom_testbench(
  31. .sys_clk (sys_clk ),
  32. .sys_rst_n (sys_rst_n ),
  33. .key (key ),
  34. .led ( led ),
  35. .i2c_scl (i2c_scl ),
  36. .i2c_sda (i2c_sda )
  37. );
  38. M24LC64 M24LC64_inst(
  39. .A0 ( 1'b0 ), // ַ
  40. .A1 ( 1'b0 ), // ַ
  41. .A2 ( 1'b0 ), // ַ
  42. .WP ( 1'b0 ), //д źţ ߵ ƽ Ч
  43. .SDA ( i2c_sda ),
  44. .SCL ( i2c_scl ),
  45. .RESET ( ~sys_rst_n )
  46. );
  47. endmodule

其中,M24LC64为EEPROM器件的fpga实现,相关v文件在网上查得,供参考。

  1. `timescale 1ns/10ps
  2. module M24LC64 (A0, A1, A2, WP, SDA, SCL, RESET);
  3. input A0; // chip select bit
  4. input A1; // chip select bit
  5. input A2; // chip select bit
  6. input WP; // write protect pin
  7. inout SDA; // serial data I/O
  8. input SCL; // serial data clock
  9. input RESET; // system reset
  10. // *******************************************************************************************************
  11. // ** DECLARATIONS **
  12. // *******************************************************************************************************
  13. reg SDA_DO; // serial data - output
  14. reg SDA_OE; // serial data - output enable
  15. wire SDA_DriveEnable; // serial data output enable
  16. reg SDA_DriveEnableDlyd; // serial data output enable - delayed
  17. wire [02:00] ChipAddress; // hardwired chip address
  18. reg [03:00] BitCounter; // serial bit counter
  19. reg START_Rcvd; // START bit received flag
  20. reg STOP_Rcvd; // ACK_4 bit received flag
  21. reg CTRL_Rcvd; // control byte received flag
  22. reg ADHI_Rcvd; // byte address hi received flag
  23. reg ADLO_Rcvd; // byte address lo received flag
  24. reg MACK_Rcvd; // master acknowledge received flag
  25. reg WrCycle; // memory write cycle
  26. reg RdCycle; // memory read cycle
  27. reg [07:00] ShiftRegister; // input data shift register
  28. reg [07:00] ControlByte; // control byte register
  29. wire RdWrBit; // read/write control bit
  30. reg [12:00] StartAddress; // memory access starting address
  31. reg [04:00] PageAddress; // memory page address
  32. reg [07:00] WrDataByte [0:31]; // memory write data buffer
  33. wire [07:00] RdDataByte; // memory read data
  34. reg [15:00] WrCounter; // write buffer counter
  35. reg [04:00] WrPointer; // write buffer pointer
  36. reg [12:00] RdPointer; // read address pointer
  37. reg WriteActive; // memory write cycle active
  38. reg [07:00] MemoryBlock [0:8191]; // EEPROM data memory array
  39. integer LoopIndex; // iterative loop index
  40. integer tAA; // timing parameter
  41. integer tWC; // timing parameter
  42. // *******************************************************************************************************
  43. // ** INITIALIZATION **
  44. // *******************************************************************************************************
  45. //----------------------------
  46. //------写数据间隔改 ?----------
  47. initial tAA = 900; // SCL to SDA output delay
  48. initial tWC = 500; // memory write cycle time
  49. // initial tAA = 900; // SCL to SDA output delay
  50. // initial tWC = 5000000; // memory write cycle time
  51. initial begin
  52. SDA_DO = 0;
  53. SDA_OE = 0;
  54. end
  55. initial begin
  56. START_Rcvd = 0;
  57. STOP_Rcvd = 0;
  58. CTRL_Rcvd = 0;
  59. ADHI_Rcvd = 0;
  60. ADLO_Rcvd = 0;
  61. MACK_Rcvd = 0;
  62. end
  63. initial begin
  64. BitCounter = 0;
  65. ControlByte = 0;
  66. end
  67. initial begin
  68. WrCycle = 0;
  69. RdCycle = 0;
  70. WriteActive = 0;
  71. end
  72. assign ChipAddress = {A2,A1,A0};
  73. // *******************************************************************************************************
  74. // ** CORE LOGIC **
  75. // *******************************************************************************************************
  76. // -------------------------------------------------------------------------------------------------------
  77. // 1.01: START Bit Detection
  78. // -------------------------------------------------------------------------------------------------------
  79. always @(negedge SDA) begin
  80. if (SCL == 1) begin
  81. START_Rcvd <= 1;
  82. STOP_Rcvd <= 0;
  83. CTRL_Rcvd <= 0;
  84. ADHI_Rcvd <= 0;
  85. ADLO_Rcvd <= 0;
  86. MACK_Rcvd <= 0;
  87. WrCycle <= #1 0;
  88. RdCycle <= #1 0;
  89. BitCounter <= 0;
  90. end
  91. end
  92. // -------------------------------------------------------------------------------------------------------
  93. // 1.02: ACK_4 Bit Detection
  94. // -------------------------------------------------------------------------------------------------------
  95. always @(posedge SDA) begin
  96. if (SCL == 1) begin
  97. START_Rcvd <= 0;
  98. STOP_Rcvd <= 1;
  99. CTRL_Rcvd <= 0;
  100. ADHI_Rcvd <= 0;
  101. ADLO_Rcvd <= 0;
  102. MACK_Rcvd <= 0;
  103. WrCycle <= #1 0;
  104. RdCycle <= #1 0;
  105. BitCounter <= 10;
  106. end
  107. end
  108. // -------------------------------------------------------------------------------------------------------
  109. // 1.03: Input Shift Register
  110. // -------------------------------------------------------------------------------------------------------
  111. always @(posedge SCL) begin
  112. ShiftRegister[00] <= SDA;
  113. ShiftRegister[01] <= ShiftRegister[00];
  114. ShiftRegister[02] <= ShiftRegister[01];
  115. ShiftRegister[03] <= ShiftRegister[02];
  116. ShiftRegister[04] <= ShiftRegister[03];
  117. ShiftRegister[05] <= ShiftRegister[04];
  118. ShiftRegister[06] <= ShiftRegister[05];
  119. ShiftRegister[07] <= ShiftRegister[06];
  120. end
  121. // -------------------------------------------------------------------------------------------------------
  122. // 1.04: Input Bit Counter
  123. // -------------------------------------------------------------------------------------------------------
  124. always @(posedge SCL) begin
  125. if (BitCounter < 10) BitCounter <= BitCounter + 1;
  126. end
  127. // -------------------------------------------------------------------------------------------------------
  128. // 1.05: Control Byte Register
  129. // -------------------------------------------------------------------------------------------------------
  130. always @(negedge SCL) begin
  131. if (START_Rcvd & (BitCounter == 8)) begin
  132. if (!WriteActive & (ShiftRegister[07:01] == {4'b1010,ChipAddress[02:00]})) begin
  133. if (ShiftRegister[00] == 0) WrCycle <= 1;
  134. if (ShiftRegister[00] == 1) RdCycle <= 1;
  135. ControlByte <= ShiftRegister[07:00];
  136. CTRL_Rcvd <= 1;
  137. end
  138. START_Rcvd <= 0;
  139. end
  140. end
  141. assign RdWrBit = ControlByte[00];
  142. // -------------------------------------------------------------------------------------------------------
  143. // 1.06: Byte Address Register
  144. // -------------------------------------------------------------------------------------------------------
  145. always @(negedge SCL) begin
  146. if (CTRL_Rcvd & (BitCounter == 8)) begin
  147. if (RdWrBit == 0) begin
  148. StartAddress[12:08] <= ShiftRegister[04:00];
  149. RdPointer[12:08] <= ShiftRegister[04:00];
  150. ADHI_Rcvd <= 1;
  151. end
  152. WrCounter <= 0;
  153. WrPointer <= 0;
  154. CTRL_Rcvd <= 0;
  155. end
  156. end
  157. always @(negedge SCL) begin
  158. if (ADHI_Rcvd & (BitCounter == 8)) begin
  159. if (RdWrBit == 0) begin
  160. StartAddress[07:00] <= ShiftRegister[07:00];
  161. RdPointer[07:00] <= ShiftRegister[07:00];
  162. ADLO_Rcvd <= 1;
  163. end
  164. WrCounter <= 0;
  165. WrPointer <= 0;
  166. ADHI_Rcvd <= 0;
  167. end
  168. end
  169. // -------------------------------------------------------------------------------------------------------
  170. // 1.07: Write Data Buffer
  171. // -------------------------------------------------------------------------------------------------------
  172. always @(negedge SCL) begin
  173. if (ADLO_Rcvd & (BitCounter == 8)) begin
  174. if (RdWrBit == 0) begin
  175. WrDataByte[WrPointer] <= ShiftRegister[07:00];
  176. WrCounter <= WrCounter + 1;
  177. WrPointer <= WrPointer + 1;
  178. end
  179. end
  180. end
  181. // -------------------------------------------------------------------------------------------------------
  182. // 1.08: Acknowledge Generator
  183. // -------------------------------------------------------------------------------------------------------
  184. always @(negedge SCL) begin
  185. if (!WriteActive) begin
  186. if (BitCounter == 8) begin
  187. if (WrCycle | (START_Rcvd & (ShiftRegister[07:01] == {4'b1010,ChipAddress[02:00]}))) begin
  188. SDA_DO <= 0;
  189. SDA_OE <= 1;
  190. end
  191. end
  192. if (BitCounter == 9) begin
  193. BitCounter <= 0;
  194. if (!RdCycle) begin
  195. SDA_DO <= 0;
  196. SDA_OE <= 0;
  197. end
  198. end
  199. end
  200. end
  201. // -------------------------------------------------------------------------------------------------------
  202. // 1.09: Acknowledge Detect
  203. // -------------------------------------------------------------------------------------------------------
  204. always @(posedge SCL) begin
  205. if (RdCycle & (BitCounter == 8)) begin
  206. if ((SDA == 0) & (SDA_OE == 0)) MACK_Rcvd <= 1;
  207. end
  208. end
  209. always @(negedge SCL) MACK_Rcvd <= 0;
  210. // -------------------------------------------------------------------------------------------------------
  211. // 1.10: Write Cycle Timer
  212. // -------------------------------------------------------------------------------------------------------
  213. always @(posedge STOP_Rcvd) begin
  214. if (WrCycle & (WP == 0) & (WrCounter > 0)) begin
  215. WriteActive = 1;
  216. #(tWC);
  217. WriteActive = 0;
  218. end
  219. end
  220. always @(posedge STOP_Rcvd) begin
  221. #(1.0);
  222. STOP_Rcvd = 0;
  223. end
  224. // -------------------------------------------------------------------------------------------------------
  225. // 1.11: Write Cycle Processor
  226. // -------------------------------------------------------------------------------------------------------
  227. always @(negedge WriteActive) begin
  228. for (LoopIndex = 0; LoopIndex < WrCounter; LoopIndex = LoopIndex + 1) begin
  229. PageAddress = StartAddress[04:00] + LoopIndex;
  230. MemoryBlock[{StartAddress[12:05],PageAddress[04:00]}] = WrDataByte[LoopIndex[04:00]];
  231. end
  232. end
  233. // -------------------------------------------------------------------------------------------------------
  234. // 1.12: Read Data Multiplexor
  235. // -------------------------------------------------------------------------------------------------------
  236. always @(negedge SCL) begin
  237. if (BitCounter == 8) begin
  238. if (WrCycle & ADLO_Rcvd) begin
  239. RdPointer <= StartAddress + WrPointer + 1;
  240. end
  241. if (RdCycle) begin
  242. RdPointer <= RdPointer + 1;
  243. end
  244. end
  245. end
  246. assign RdDataByte = MemoryBlock[RdPointer[12:00]];
  247. // -------------------------------------------------------------------------------------------------------
  248. // 1.13: Read Data Processor
  249. // -------------------------------------------------------------------------------------------------------
  250. always @(negedge SCL) begin
  251. if (RdCycle) begin
  252. if (BitCounter == 8) begin
  253. SDA_DO <= 0;
  254. SDA_OE <= 0;
  255. end
  256. else if (BitCounter == 9) begin
  257. SDA_DO <= RdDataByte[07];
  258. if (MACK_Rcvd) SDA_OE <= 1;
  259. end
  260. else begin
  261. SDA_DO <= RdDataByte[7-BitCounter];
  262. end
  263. end
  264. end
  265. // -------------------------------------------------------------------------------------------------------
  266. // 1.14: SDA Data I/O Buffer
  267. // -------------------------------------------------------------------------------------------------------
  268. bufif1 (SDA, 1'b0, SDA_DriveEnableDlyd);
  269. assign SDA_DriveEnable = !SDA_DO & SDA_OE;
  270. always @(SDA_DriveEnable) SDA_DriveEnableDlyd <= #(tAA) SDA_DriveEnable;
  271. // *******************************************************************************************************
  272. // ** DEBUG LOGIC **
  273. // *******************************************************************************************************
  274. // -------------------------------------------------------------------------------------------------------
  275. // 2.01: Memory Data Bytes
  276. // -------------------------------------------------------------------------------------------------------
  277. wire [07:00] MemoryByte_000 = MemoryBlock[00];
  278. wire [07:00] MemoryByte_001 = MemoryBlock[01];
  279. wire [07:00] MemoryByte_002 = MemoryBlock[02];
  280. wire [07:00] MemoryByte_003 = MemoryBlock[03];
  281. wire [07:00] MemoryByte_004 = MemoryBlock[04];
  282. wire [07:00] MemoryByte_005 = MemoryBlock[05];
  283. wire [07:00] MemoryByte_006 = MemoryBlock[06];
  284. wire [07:00] MemoryByte_007 = MemoryBlock[07];
  285. wire [07:00] MemoryByte_008 = MemoryBlock[08];
  286. wire [07:00] MemoryByte_009 = MemoryBlock[09];
  287. wire [07:00] MemoryByte_00A = MemoryBlock[10];
  288. wire [07:00] MemoryByte_00B = MemoryBlock[11];
  289. wire [07:00] MemoryByte_00C = MemoryBlock[12];
  290. wire [07:00] MemoryByte_00D = MemoryBlock[13];
  291. wire [07:00] MemoryByte_00E = MemoryBlock[14];
  292. wire [07:00] MemoryByte_00F = MemoryBlock[15];
  293. // -------------------------------------------------------------------------------------------------------
  294. // 2.02: Write Data Buffer
  295. // -------------------------------------------------------------------------------------------------------
  296. wire [07:00] WriteData_00 = WrDataByte[00];
  297. wire [07:00] WriteData_01 = WrDataByte[01];
  298. wire [07:00] WriteData_02 = WrDataByte[02];
  299. wire [07:00] WriteData_03 = WrDataByte[03];
  300. wire [07:00] WriteData_04 = WrDataByte[04];
  301. wire [07:00] WriteData_05 = WrDataByte[05];
  302. wire [07:00] WriteData_06 = WrDataByte[06];
  303. wire [07:00] WriteData_07 = WrDataByte[07];
  304. wire [07:00] WriteData_08 = WrDataByte[08];
  305. wire [07:00] WriteData_09 = WrDataByte[09];
  306. wire [07:00] WriteData_0A = WrDataByte[10];
  307. wire [07:00] WriteData_0B = WrDataByte[11];
  308. wire [07:00] WriteData_0C = WrDataByte[12];
  309. wire [07:00] WriteData_0D = WrDataByte[13];
  310. wire [07:00] WriteData_0E = WrDataByte[14];
  311. wire [07:00] WriteData_0F = WrDataByte[15];
  312. wire [07:00] WriteData_10 = WrDataByte[16];
  313. wire [07:00] WriteData_11 = WrDataByte[17];
  314. wire [07:00] WriteData_12 = WrDataByte[18];
  315. wire [07:00] WriteData_13 = WrDataByte[19];
  316. wire [07:00] WriteData_14 = WrDataByte[20];
  317. wire [07:00] WriteData_15 = WrDataByte[21];
  318. wire [07:00] WriteData_16 = WrDataByte[22];
  319. wire [07:00] WriteData_17 = WrDataByte[23];
  320. wire [07:00] WriteData_18 = WrDataByte[24];
  321. wire [07:00] WriteData_19 = WrDataByte[25];
  322. wire [07:00] WriteData_1A = WrDataByte[26];
  323. wire [07:00] WriteData_1B = WrDataByte[27];
  324. wire [07:00] WriteData_1C = WrDataByte[28];
  325. wire [07:00] WriteData_1D = WrDataByte[29];
  326. wire [07:00] WriteData_1E = WrDataByte[30];
  327. wire [07:00] WriteData_1F = WrDataByte[31];
  328. // *******************************************************************************************************
  329. // ** TIMING CHECKS **
  330. // *******************************************************************************************************
  331. wire TimingCheckEnable = (RESET == 0) & (SDA_OE == 0);
  332. wire StopTimingCheckEnable = TimingCheckEnable && SCL;
  333. //--------------------------------
  334. //-------仿真时时序约束需改动--------
  335. //--------------------------------
  336. specify
  337. specparam
  338. tHI = 600, // SCL pulse width - high
  339. // tLO = 1300, // SCL pulse width - low
  340. tLO = 600,
  341. tSU_STA = 600, // SCL to SDA setup time
  342. tHD_STA = 600, // SCL to SDA hold time
  343. tSU_DAT = 100, // SDA to SCL setup time
  344. tSU_STO = 600, // SCL to SDA setup time
  345. tSU_WP = 600, // WP to SDA setup time
  346. tHD_WP = 1300, // WP to SDA hold time
  347. // tBUF = 1300; // Bus free time
  348. tBUF = 600;
  349. $width (posedge SCL, tHI);
  350. $width (negedge SCL, tLO);
  351. $width (posedge SDA &&& SCL, tBUF);
  352. $setup (posedge SCL, negedge SDA &&& TimingCheckEnable, tSU_STA);
  353. $setup (SDA, posedge SCL &&& TimingCheckEnable, tSU_DAT);
  354. $setup (posedge SCL, posedge SDA &&& TimingCheckEnable, tSU_STO);
  355. $setup (WP, posedge SDA &&& StopTimingCheckEnable, tSU_WP);
  356. $hold (negedge SDA &&& TimingCheckEnable, negedge SCL, tHD_STA);
  357. $hold (posedge SDA &&& StopTimingCheckEnable, WP, tHD_WP);
  358. endspecify
  359. endmodule

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/599808
推荐阅读
相关标签
  

闽ICP备14008679号