i2c_wr.v
上传用户:lcztgy
上传日期:2007-03-17
资源大小:70k
文件大小:10k
源码类别:

并行计算

开发平台:

VHDL

  1. ////////////////////////////////////////////////////////////////////////////////
  2. //                                                                            //
  3. //   本设计参考 夏宇闻 编著的《Verilog 数字系统设计教程》I2C总线接口模块的设计//
  4. //   详细的介绍请参考《Verilog 数字系统设计教程》。                           // 
  5. //                                                                            //                                                                 
  6. ////////////////////////////////////////////////////////////////////////////////
  7. `timescale 1ns/1ns
  8. module i2c_wr (clk,rst_n,wr,rd,addr,data_w,data_r,ack,scl,sda);
  9. input  clk;          //clock
  10. input  rst_n;        //reset
  11. input  wr,rd;        //write,read command
  12. input  [10:0] addr;  //write,read eeprom address
  13. input  [7:0] data_w; //write data to eeprom
  14. output [7:0] data_r; //read data from eeprom
  15. // output rd_ack;
  16. output ack;          //write,read complete
  17. output scl;          //i2c scl signal
  18. inout  sda;          //i2c sda signal
  19. reg ack;
  20. reg scl;
  21. reg wf,rf;
  22. reg ff;
  23. reg [1:0] head_buf;
  24. reg [1:0] stop_buf;
  25. reg [7:0] sh8out_buf;
  26. reg [8:0] sh8out_state;
  27. reg [9:0] sh8in_state;
  28. reg [2:0] head_state;
  29. reg [2:0] stop_state;
  30. reg [10:0] main_state;
  31. reg [7:0] data_r;
  32. reg link_sda;
  33. // reg rd_ack;
  34. reg link_head;
  35. reg link_write;
  36. reg link_stop;
  37. wire sda1,sda2,sda3,sda4;
  38. //---------------串行数据在开关控制下有次序的输出-------------------------
  39. assign sda1 = (link_head) ? head_buf[1]:1'b0;
  40. assign sda2 = (link_write)? sh8out_buf[7]:1'b0;
  41. assign sda3 = (link_stop) ? stop_buf[1]:1'b0;
  42. assign sda4 = (sda1|sda2|sda3);
  43. assign sda  = (link_sda) ? sda4:1'bz;
  44. //assign data = (rd_ack) ? data_from_rm:8'hzz;
  45. //---------------主状态机状态定义-----------------------------------------
  46. parameter
  47. Idle     =11'b00000000001,
  48. Ready     =11'b00000000010,
  49. Write_start =11'b00000000100,
  50. Ctrl_write =11'b00000001000,
  51. Addr_write =11'b00000010000,
  52. Data_write =11'b00000100000,
  53. Read_start =11'b00001000000,
  54. Ctrl_read   =11'b00010000000,
  55. Data_read   =11'b00100000000,
  56. Stop     =11'b01000000000,
  57. Ackn     =11'b10000000000,
  58. //--------------并行数据串行输出状态--------------------------------------
  59. sh8out_bit7 =9'b000000001,
  60. sh8out_bit6 =9'b000000010,
  61. sh8out_bit5 =9'b000000100,
  62. sh8out_bit4 =9'b000001000,
  63. sh8out_bit3 =9'b000010000,
  64. sh8out_bit2 =9'b000100000,
  65. sh8out_bit1 =9'b001000000,
  66. sh8out_bit0 =9'b010000000,
  67. sh8out_end =9'b100000000;
  68. //---------------串行数据并行输出状态------------------------------------
  69. parameter
  70. sh8in_begin =10'b0000000001,
  71. sh8in_bit7 =10'b0000000010,
  72. sh8in_bit6 =10'b0000000100,
  73. sh8in_bit5 =10'b0000001000,
  74. sh8in_bit4 =10'b0000010000,
  75. sh8in_bit3 =10'b0000100000,
  76. sh8in_bit2 =10'b0001000000,
  77. sh8in_bit1 =10'b0010000000,
  78. sh8in_bit0 =10'b0100000000,
  79. sh8in_end   =10'b1000000000,
  80. //--------------启动状态-------------------------------------------------
  81. head_begin =3'b001,
  82. head_bit   =3'b010,
  83. head_end   =3'b100,
  84. //-------------停止状态-------------------------------------------------
  85. stop_begin =3'b001,
  86. stop_bit   =3'b010,
  87. stop_end   =3'b100;
  88. parameter
  89.  YES =1,
  90.  NO   =0;
  91. //-------------产生串行时钟SCL,为输入时钟的二分频------------------------
  92. always @(negedge clk or negedge rst_n)
  93. if(!rst_n)
  94. scl<=0;
  95. else
  96. scl<=~scl;
  97. //-----------主状态机程序-------------------------------------------------
  98. always @(posedge clk or negedge rst_n)
  99. if(!rst_n)
  100. begin
  101. // rd_ack   <=NO;
  102. link_write  <=NO;
  103. link_head   <=NO;
  104. link_stop   <=NO;
  105. link_sda   <=NO;
  106. ack       <=0;
  107. rf       <=0;
  108. wf       <=0;
  109. ff       <=0;
  110. head_buf[1:0] <=2'b00;
  111. main_state <=Idle;
  112. end
  113. else 
  114. begin
  115. casex(main_state)
  116. Idle:
  117. begin
  118. // rd_ack  <=NO;
  119. link_write <=NO;
  120. link_head  <=NO;
  121. link_stop  <=NO;
  122. link_sda  <=NO;
  123. if(wr)
  124.   begin
  125. wf <=1;
  126. main_state<=Ready;
  127.   end
  128. else if(rd)
  129.   begin
  130. rf<=1;
  131. main_state<=Ready;
  132.   end
  133. else
  134.   begin
  135. wf<=0;
  136. rf<=0;
  137. main_state<=Idle;
  138.   end
  139. end
  140. Ready:
  141. begin
  142. // rd_ack <=NO;
  143. link_write <=NO;
  144. link_stop <=NO;
  145. link_head <=YES;
  146. link_sda <=YES;
  147. head_buf[1:0] <=2'b10;
  148. stop_buf[1:0] <=2'b01;
  149. head_state <=head_begin;
  150. ff <=0;
  151. ack <=0;
  152. main_state <=Write_start;
  153. end
  154. Write_start:
  155. if(ff==0)
  156. shift_head;
  157. else
  158. begin
  159. sh8out_buf[7:0] <={1'b1,1'b0,1'b1,1'b0,addr[10:8],1'b0};
  160. link_head <=NO;
  161. link_write <=YES;
  162. ff <=0;
  163. sh8out_state <=sh8out_bit6;
  164. main_state <=Ctrl_write;
  165. end
  166. Ctrl_write:
  167. if(ff==0)
  168. shift8_out;
  169. else
  170. begin
  171. sh8out_state <=sh8out_bit7;
  172. sh8out_buf[7:0] <=addr[7:0];
  173. ff <=0;
  174. main_state <=Addr_write;
  175. end
  176. Addr_write:
  177. if(ff==0)
  178. shift8_out;
  179. else
  180. begin
  181. ff <=0;
  182. if(wf)
  183. begin
  184. sh8out_state <=sh8out_bit7;
  185. sh8out_buf[7:0] <=data_w;
  186. main_state <=Data_write;
  187. end
  188. if(rf)
  189. begin
  190. head_buf <=2'b10;
  191. head_state <=head_begin;
  192. main_state <=Read_start;
  193. end
  194. end
  195. Data_write:
  196. if(ff==0)
  197. shift8_out;
  198. else
  199. begin
  200. stop_state <=stop_begin;
  201. main_state <=Stop;
  202. link_write <=NO;
  203. ff <=0;
  204. // ack <=1;
  205. end
  206. Read_start:
  207. if(ff==0)
  208. shift_head;
  209. else
  210. begin
  211. sh8out_buf <={1'b1,1'b0,1'b1,1'b0,addr[10:8],1'b1};
  212. link_head <=NO;
  213. link_sda <=YES;
  214. link_write <=YES;
  215. ff <=0;
  216. sh8out_state <=sh8out_bit6;
  217. main_state <=Ctrl_read;
  218. end
  219. Ctrl_read:
  220. if(ff==0)
  221. shift8_out;
  222. else
  223. begin
  224. link_sda <=NO;
  225. link_write <=NO;
  226. ff <=0;
  227. sh8in_state <=sh8in_begin;
  228. main_state <=Data_read;
  229. end
  230. Data_read:
  231. if(ff==0)
  232. shift8in;
  233. else
  234. begin
  235. //   rd_ack <=NO;
  236. link_stop <=YES;
  237. link_sda <=YES;
  238. stop_state <=stop_bit;
  239. ff <=0;
  240. main_state <=Stop;
  241. end
  242. Stop:
  243. if(ff==0)
  244. shift_stop;
  245. else
  246. begin
  247. ack <=1;
  248. ff <=0;
  249. main_state <=Ackn;
  250. end
  251. Ackn:
  252. begin
  253. ack <=0;
  254. wf <=0;
  255. rf <=0;
  256. main_state <=Idle;
  257. end
  258. default: main_state <=Idle;
  259. endcase
  260. end
  261. //------------串行数据转换为并行数据任务-----------------------------------
  262. task shift8in;
  263. begin
  264. casex(sh8in_state)
  265. sh8in_begin:
  266. sh8in_state <=sh8in_bit7;
  267. sh8in_bit7: if(scl)
  268. begin
  269. data_r[7] <=sda;
  270. sh8in_state <=sh8in_bit6;
  271. end
  272.     else
  273. sh8in_state <=sh8in_bit7;
  274. sh8in_bit6: if(scl)
  275. begin
  276. data_r[6] <=sda;
  277. sh8in_state <=sh8in_bit5;
  278. end
  279.     else
  280. sh8in_state <=sh8in_bit6;
  281. sh8in_bit5: if(scl)
  282. begin
  283. data_r[5] <=sda;
  284. sh8in_state <=sh8in_bit4;
  285. end
  286.     else
  287. sh8in_state <=sh8in_bit5;
  288. sh8in_bit4: if(scl)
  289. begin
  290. data_r[4] <=sda;
  291. sh8in_state <=sh8in_bit3;
  292. end
  293.     else
  294. sh8in_state <=sh8in_bit4;
  295. sh8in_bit3: if(scl)
  296. begin
  297. data_r[3] <=sda;
  298. sh8in_state <=sh8in_bit2;
  299. end
  300.     else
  301. sh8in_state <=sh8in_bit3;
  302. sh8in_bit2: if(scl)
  303. begin
  304. data_r[2] <=sda;
  305. sh8in_state <=sh8in_bit1;
  306. end
  307.     else
  308. sh8in_state <=sh8in_bit2;
  309. sh8in_bit1: if(scl)
  310. begin
  311. data_r[1] <=sda;
  312. sh8in_state <=sh8in_bit0;
  313. end
  314.     else
  315. sh8in_state <=sh8in_bit1;
  316. sh8in_bit0: if(scl)
  317. begin
  318. data_r[0] <=sda;
  319. sh8in_state <=sh8in_end;
  320. end
  321.     else
  322. sh8in_state <=sh8in_bit0;
  323. sh8in_end: if(scl)
  324. begin
  325. // rd_ack <=YES;
  326. ff <=1;
  327. sh8in_state <=sh8in_bit7;
  328. end
  329.     else
  330. sh8in_state <=sh8in_end;
  331. default:
  332. begin
  333. // rd_ack <=NO;
  334. sh8in_state <=sh8in_bit7;
  335. end
  336. endcase
  337. end
  338. endtask
  339. //-------------------并行数据转换为串行数据任务---------------------------
  340. task shift8_out;
  341. begin
  342. casex(sh8out_state)
  343. sh8out_bit7:
  344. if(!scl)
  345. begin
  346. link_sda <=YES;
  347. link_write <=YES;
  348. sh8out_state <=sh8out_bit6;
  349. end
  350. else
  351. sh8out_state <=sh8out_bit7;
  352. sh8out_bit6:
  353. if(!scl)
  354. begin
  355. link_sda <=YES;
  356. link_write <=YES;
  357. sh8out_state <=sh8out_bit5;
  358. sh8out_buf <=sh8out_buf<<1;
  359. end
  360. else
  361. sh8out_state <=sh8out_bit6;
  362. sh8out_bit5:
  363. if(!scl)
  364. begin
  365. sh8out_state <=sh8out_bit4;
  366. sh8out_buf <=sh8out_buf<<1;
  367. end
  368. else
  369. sh8out_state <=sh8out_bit5;
  370. sh8out_bit4:
  371. if(!scl)
  372. begin
  373. sh8out_state <=sh8out_bit3;
  374. sh8out_buf <=sh8out_buf<<1;
  375. end
  376. else
  377. sh8out_state <=sh8out_bit4;
  378. sh8out_bit3:
  379. if(!scl)
  380. begin
  381. sh8out_state <=sh8out_bit2;
  382. sh8out_buf <=sh8out_buf<<1;
  383. end
  384. else
  385. sh8out_state <=sh8out_bit3;
  386. sh8out_bit2:
  387. if(!scl)
  388. begin
  389. sh8out_state <=sh8out_bit1;
  390. sh8out_buf <=sh8out_buf<<1;
  391. end
  392. else
  393. sh8out_state <=sh8out_bit2;
  394. sh8out_bit1:
  395. if(!scl)
  396. begin
  397. sh8out_state <=sh8out_bit0;
  398. sh8out_buf <=sh8out_buf<<1;
  399. end
  400. else
  401. sh8out_state <=sh8out_bit1;
  402. sh8out_bit0:
  403. if(!scl)
  404. begin
  405. sh8out_state <=sh8out_end;
  406. sh8out_buf <=sh8out_buf<<1;
  407. end
  408. else
  409. sh8out_state <=sh8out_bit0;
  410. sh8out_end:
  411. if(!scl)
  412. begin
  413. link_sda <=NO;
  414. link_write <=NO;
  415. ff <=1;
  416. end
  417. else
  418. sh8out_state <=sh8out_end;
  419. endcase
  420. end
  421. endtask
  422. //-------------输出启动信号任务-------------------------------------------------
  423. task shift_head;
  424. begin
  425. casex(head_state)
  426. head_begin:
  427. if(!scl)
  428. begin
  429. link_write <=NO;
  430. link_sda <=YES;
  431. link_head <=YES;
  432. head_state <=head_bit;
  433. end
  434. else
  435. head_state <=head_begin;
  436. head_bit:
  437. if(scl)
  438. begin
  439. ff <=1;
  440. head_buf <=head_buf<<1;
  441. head_state <=head_end;
  442. end
  443. else
  444. head_state <=head_bit;
  445. head_end:
  446. if(!scl)
  447. begin
  448. link_head <=NO;
  449. link_write <=YES;
  450. end
  451. else
  452. head_state <=head_end;
  453. endcase
  454. end
  455. endtask
  456. //--------------输出----------------------------------------------------
  457. task shift_stop;
  458. begin
  459. casex(stop_state)
  460. stop_begin: if(!scl)
  461. begin
  462. link_sda <=YES;
  463. link_write <=NO;
  464. link_stop <=YES;
  465. stop_state <=stop_bit;
  466. end
  467.     else
  468. stop_state <=stop_begin;
  469. stop_bit:  if(scl)
  470. begin
  471. stop_buf <=stop_buf<<1;
  472. stop_state <=stop_end;
  473. end
  474.    else
  475. stop_state <=stop_bit;
  476. stop_end:  if(!scl)
  477. begin
  478. link_head <=NO;
  479. link_stop <=NO;
  480. link_sda <=NO;
  481. ff <=1;
  482. end
  483.    else
  484. stop_state <=stop_end;
  485. endcase
  486. end
  487. endtask
  488. endmodule
  489. //------------------i2c_wr.v文件结束--------------------------------------------