I2C

霍北北發表於2024-05-12
  1. module I2C(clk,cmd,rst,contr_b,addr_h_b,addr_l_b,data_in,sclk,sda,data_out);  //草稿
  2. input clk,rst;
  3. input [7:0] contr_b;
  4. input [7:0] addr_h_b;
  5. input [7:0] addr_l_b;
  6. input [7:0] data_in;
  7. input cmd; // write: cmd=1, read: cmd=0
  8. output sclk;
  9. output [7:0] data_out;
  10. inout sda;
  11.  
  12. wire sda_w,sda_r;
  13.  
  14. wire sclk_w,sclk_r;
  15.  
  16. assign sda=cmd?sda_w:sda_r;
  17.  
  18. assign sclk=cmd?sclk_w:sclk_r;
  19.  
  20. I2C_w I2C_w(
  21. .clk(clk),
  22. .rst(rst),
  23. .contr_b(contr_b),
  24. .addr_h_b(addr_h_b),
  25. .addr_l_b(addr_l_b),
  26. .data(data_in),
  27. .sclk(sclk_w),
  28. .sda(sda_w)
  29. );
  30.  
  31. I2C_r I2C_r(
  32. .clk(clk),
  33. .rst(rst),
  34. .contr_b(contr_b),
  35. .addr_h_b(addr_h_b),
  36. .addr_l_b(addr_l_b),
  37. .sclk(sclk_r),
  38. .data(data_out),
  39. .sda(sda_r)
  40. );
  41.  
  42. endmodule
  43.  
  44. module I2C_r(clk,rst,sda,contr_b,addr_h_b,addr_l_b,sclk,data);
  45. input clk,rst;
  46. input [7:0] contr_b;
  47. input [7:0] addr_h_b;
  48. input [7:0] addr_l_b;
  49. output sclk;
  50. output [7:0] data;
  51. inout sda;
  52.  
  53. reg sclk;
  54. reg [6:0] cnt1;
  55. reg [3:0] cnt2;
  56. reg en;
  57. reg en2;
  58. reg sda_reg;
  59. reg [7:0] d_reg;
  60. reg [7:0] data_in;
  61. reg sda_en;
  62. reg [7:0] data;
  63. wire Q;
  64.  
  65. parameter [15:0] contr1 = 16'b0000_0000_0000_0001;
  66. parameter [15:0] start = 16'b0000_0000_0000_0010;
  67. parameter [15:0] start1 = 16'b0000_0000_0000_0100;
  68. parameter [15:0] contr = 16'b0000_0000_0000_1000;
  69. parameter [15:0] ack1 = 16'b0000_0000_0001_0000;
  70. parameter [15:0] addr_h = 16'b0000_0000_0010_0000;
  71. parameter [15:0] ack2 = 16'b0000_0000_0100_0000;
  72. parameter [15:0] addr_l = 16'b0000_0000_1000_0000;
  73. parameter [15:0] start2 = 16'b0000_0001_0000_0000;
  74. parameter [15:0] start3 = 16'b0000_0010_0000_0000;
  75. parameter [15:0] ack4 = 16'b0000_0100_0000_0000;
  76. parameter [15:0] data_t = 16'b0000_1000_0000_0000;
  77. parameter [15:0] no_ack = 16'b0001_0000_0000_0000;
  78. parameter [15:0] stop = 16'b0010_0000_0000_0000;
  79. parameter [15:0] stop1 = 16'b0100_0000_0000_0000;
  80. parameter [15:0] ack3 = 16'b1000_0000_0000_0000;
  81.  
  82. reg [15:0] present_state, next_state;
  83.  
  84. always@(posedge clk or negedge rst)
  85. begin
  86. if(!rst) present_state <= start;
  87. else present_state <= next_state;
  88. end
  89.  
  90. always@(present_state or cnt1 or cnt2)
  91. begin
  92. case(present_state)
  93. start: if(cnt1 == 7'd62)
  94. next_state = start1;
  95. else
  96. next_state = start;
  97. start1:if(cnt1 == 7'd124 && cnt2 == 4'd0)
  98. next_state = contr;
  99. else
  100. next_state = start1;
  101. contr: if(cnt1 == 7'd124 && cnt2 == 4'd8)
  102. next_state = ack1;
  103. else
  104. next_state = contr;
  105. ack1: if(cnt1 == 7'd124 && cnt2 == 4'd0)
  106. next_state = addr_h;
  107. else
  108. next_state = ack1;
  109. addr_h:if(cnt1 == 7'd124 && cnt2 == 4'd8)
  110. next_state = ack2;
  111. else
  112. next_state = addr_h;
  113. ack2: if(cnt1 == 7'd124 && cnt2 == 4'd0)
  114. next_state = addr_l;
  115. else
  116. next_state = ack2;
  117. addr_l:if(cnt1 == 7'd124 && cnt2 == 4'd8)
  118. next_state = ack3;
  119. else
  120. next_state = addr_l;
  121. ack3: if(cnt1 == 7'd124)
  122. next_state = start2;
  123. else
  124. next_state = ack3;
  125. start2:if(cnt1 == 7'd62 && cnt2 == 4'd0)
  126. next_state = start3;
  127. else
  128. next_state = start2;
  129. start3:if(cnt1 == 7'd124 && cnt2 == 4'd0)
  130. next_state = contr1;
  131. else
  132. next_state = start3;
  133. contr1:if(cnt1 == 7'd124 && cnt2 == 4'd8)
  134. next_state = ack4;
  135. else
  136. next_state = contr1;
  137. ack4: if(cnt1 == 7'd124 && cnt2 == 4'd0)
  138. next_state = data_t;
  139. else
  140. next_state = ack4;
  141. data_t:if(cnt1 == 7'd124 && cnt2 == 4'd8)
  142. next_state = no_ack;
  143. else
  144. next_state = data_t;
  145. no_ack:if(cnt1 == 7'd124 && cnt2 == 4'd0)
  146. next_state = stop;
  147. else
  148. next_state = no_ack;
  149. stop: if(cnt1 == 7'd62 && cnt2 == 4'd0)
  150. next_state = stop1;
  151. else
  152. next_state = stop;
  153. stop1: next_state = stop1;
  154. default: next_state = start;
  155. endcase
  156. end
  157.  
  158. always@(posedge clk)
  159. begin
  160. case(present_state)
  161. start : begin
  162. en<=1;
  163. en2<=0;
  164. sda_reg<=1;
  165. end
  166. start1: begin
  167. en<=1;
  168. en2<=0;
  169. sda_reg<=0;
  170. end
  171. contr : begin
  172. en<=1;
  173. en2<=1;
  174. sda_reg<=d_reg[7];
  175. data_in<=contr_b;
  176. end
  177. ack1 : begin
  178. en<=1;
  179. en2<=1;
  180. sda_reg<=0;
  181. end
  182. addr_h: begin
  183. en<=1;
  184. en2<=1;
  185. sda_reg<=d_reg[7];
  186. data_in<=addr_h_b;
  187. end
  188. ack2 : begin
  189. en<=1;
  190. en2<=1;
  191. sda_reg<=0;
  192. end
  193. addr_l: begin
  194. en<=1;
  195. en2<=1;
  196. sda_reg<=d_reg[7];
  197. data_in<=addr_l_b;
  198. end
  199. ack3 : begin
  200. en=1;
  201. en2<=0;
  202. sda_reg<=0;
  203. end
  204. start2: begin
  205. en=1;
  206. en2<=1;
  207. sda_reg<=1;
  208. end
  209. start3: begin
  210. en=1;
  211. en2<=1;
  212. sda_reg<=0;
  213. end
  214. contr1: begin
  215. en=1;
  216. en2<=1;
  217. sda_reg<=d_reg[7];
  218. data_in<=contr_b;
  219. end
  220. ack4 : begin
  221. en=1;
  222. en2<=1;
  223. sda_reg<=0;
  224. end
  225. data_t: begin
  226. en=1;
  227. en2<=1;
  228. end
  229. no_ack: begin
  230. en<=1;
  231. en2<=0;
  232. sda_reg<=1;
  233. end
  234. stop : begin
  235. en<=1;
  236. en2<=1;
  237. sda_reg<=0;
  238. end
  239. stop1 : begin
  240. en<=0;
  241. en2<=0;
  242. sda_reg<=1;
  243. end
  244. default:;
  245. endcase
  246. end
  247.  
  248. // 分頻計數器----------------------------------------------------------------
  249.  
  250. always@(posedge clk or negedge rst)
  251. begin
  252. if(!rst) cnt1 <= 7'd0;
  253. else if(en)
  254. begin
  255. if(cnt1 == 7'd124) cnt1 <= 7'd0;
  256. else cnt1 <= cnt1 + 7'd1;
  257. end
  258. else cnt1 <= cnt1;
  259. end
  260.  
  261. always@(posedge clk or negedge rst)
  262. begin
  263. if(!rst) cnt2 <= 4'd0;
  264. else if(en2)
  265. begin
  266. if(cnt1 == 7'd124)
  267. begin
  268. if(cnt2 == 4'd8) cnt2 <= 4'd0;
  269. else cnt2 <= cnt2 + 4'd1;
  270. end
  271. end
  272. else cnt2 <= cnt2;
  273. end
  274.  
  275. // 移位暫存器---------------------------------------------------------------------------
  276.  
  277. always@(posedge clk or negedge rst)
  278. begin
  279. if(!rst)
  280. d_reg <= 8'b00000000;
  281. else if(cnt2 == 4'd1)
  282. d_reg <= data_in;
  283. else if(cnt1 == 7'd1)
  284. begin
  285. d_reg[7:1] <= d_reg[6:0];
  286. d_reg[0] <= 0;
  287. end
  288. else
  289. d_reg <= d_reg;
  290. end
  291.  
  292. //-------------------------------------------------------
  293.  
  294. assign sda = sda_en ? sda_reg : 1'bz;
  295.  
  296. assign Q = sda;
  297.  
  298. always@(posedge clk or negedge rst)
  299. begin
  300. if(!rst)
  301. sda_en<=1;
  302. else if((present_state == ack1 && cnt1==7'd1) || (present_state == ack2 && cnt1==7'd1) || (present_state == ack3 && cnt1==7'd1) || (present_state == ack4 && cnt1==7'd1) || present_state == data_t)
  303. sda_en<=0;
  304. else
  305. sda_en<=1;
  306. end
  307.  
  308. // sclk-----------------------------------------------------------------------------
  309.  
  310. always@(posedge clk)
  311. begin
  312. if(present_state==start || present_state==start1 || present_state==stop || present_state==stop1 || present_state==start2 || present_state==start3)
  313. sclk<=1;
  314. else if(present_state==contr || present_state==ack1 || present_state==ack2 || present_state==ack3 || present_state==ack4 || present_state==data_t || present_state==addr_l || present_state==addr_h || present_state==contr1 || present_state==no_ack)
  315. begin
  316. if(cnt1 == 7'd0)
  317. sclk<=0;
  318. else if(cnt1 == 7'd31)
  319. sclk<=1;
  320. else if(cnt1 == 7'd93)
  321. sclk<=0;
  322. else
  323. sclk<=sclk;
  324. end
  325. else
  326. sclk<=sclk;
  327. end
  328.  
  329. //present_state==data_t--------------------------------------------------
  330.  
  331. always@(posedge clk)
  332. begin
  333. if(present_state == data_t && cnt2 == 4'd1 && cnt1==7'd1)
  334. data[7] <= Q;
  335. else if(present_state == data_t && cnt2 == 4'd2 && cnt1==7'd1)
  336. data[6] <= Q;
  337. else if(present_state == data_t && cnt2 == 4'd3 && cnt1==7'd1 )
  338. data[5] <= Q;
  339. else if(present_state == data_t && cnt2 == 4'd4 && cnt1==7'd1 )
  340. data[4] <= Q;
  341. else if(present_state == data_t && cnt2 == 4'd5 && cnt1==7'd1 )
  342. data[3] <= Q;
  343. else if(present_state == data_t && cnt2 == 4'd6 && cnt1==7'd1 )
  344. data[2] <= Q;
  345. else if(present_state == data_t && cnt2 == 4'd7 && cnt1==7'd1 )
  346. data[1] <= Q;
  347. else if(present_state == data_t && cnt2 == 4'd8 && cnt1==7'd1 )
  348. data[0] <= Q;
  349. else
  350. data <= data;
  351. end
  352.  
  353. endmodule
  354.  
  355. module I2C_w(clk,rst,contr_b,addr_h_b,addr_l_b,data,sclk,sda);
  356. input clk,rst;
  357. input [7:0] contr_b;
  358. input [7:0] addr_h_b;
  359. input [7:0] addr_l_b;
  360. input [7:0] data;
  361. output sclk;
  362. output sda;
  363.  
  364. reg sclk;
  365.  
  366. reg [6:0] cnt1;
  367.  
  368. reg [3:0] cnt2;
  369.  
  370. reg en;
  371.  
  372. reg en2;
  373.  
  374. reg sda_reg;
  375.  
  376. reg [7:0] d_reg;
  377.  
  378. reg [7:0] data_in;
  379.  
  380. reg sda_en;
  381.  
  382. // FSM狀態機-------------------------------------------------------------------------------------
  383.  
  384. parameter [11:0] start = 12'b000000000001,
  385. contr = 12'b000000000010,
  386. ack1 = 12'b000000000100,
  387. addr_h = 12'b000000001000,
  388. ack2 = 12'b000000010000,
  389. addr_l = 12'b000000100000,
  390. ack3 = 12'b000001000000,
  391. data_t = 12'b000010000000,
  392. ack4 = 12'b000100000000,
  393. stop = 12'b001000000000,
  394. start1 = 12'b010000000000,
  395. stop1 = 12'b100000000000;
  396.  
  397. reg [11:0] present_state, next_state;
  398.  
  399. always@(posedge clk or negedge rst)
  400. begin
  401. if(!rst) present_state <= start;
  402. else present_state <= next_state;
  403. end
  404.  
  405. always@(present_state or cnt1 or cnt2)
  406. begin
  407. case(present_state)
  408. start: if(cnt1 == 7'd62)
  409. next_state = start1;
  410. else
  411. next_state = start;
  412. start1: if(cnt1 == 7'd124 && cnt2 == 4'd0)
  413. next_state = contr;
  414. else
  415. next_state = start1;
  416. contr: if(cnt1 == 7'd124 && cnt2 == 4'd8)
  417. next_state = ack1;
  418. else
  419. next_state = contr;
  420. ack1: if(cnt1 == 7'd124 && cnt2 == 4'd0)
  421. next_state = addr_h;
  422. else
  423. next_state = ack1;
  424. addr_h:if(cnt1 == 7'd124 && cnt2 == 4'd8)
  425. next_state = ack2;
  426. else
  427. next_state = addr_h;
  428. ack2: if(cnt1 == 7'd124 && cnt2 == 4'd0)
  429. next_state = addr_l;
  430. else
  431. next_state = ack2;
  432. addr_l:if(cnt1 == 7'd124 && cnt2 == 4'd8)
  433. next_state = ack3;
  434. else
  435. next_state = addr_l;
  436. ack3: if(cnt1 == 7'd124 && cnt2 == 4'd0)
  437. next_state = data_t;
  438. else
  439. next_state = ack3;
  440. data_t:if(cnt1 == 7'd124 && cnt2 == 4'd8)
  441. next_state = ack4;
  442. else
  443. next_state = data_t;
  444. ack4: if(cnt1 == 7'd124 && cnt2 == 4'd0)
  445. next_state = stop;
  446. else
  447. next_state = ack4;
  448. stop: if(cnt1 == 7'd62 && cnt2 == 4'd0)
  449. next_state = stop1;
  450. else
  451. next_state = stop;
  452. stop1: next_state = stop1;
  453. default: next_state = start;
  454. endcase
  455. end
  456.  
  457. always@(posedge clk)
  458. begin
  459. case(present_state)
  460. start : begin
  461. en<=1;
  462. en2<=0;
  463. sda_reg<=1;
  464. end
  465. start1: begin
  466. en<=1;
  467. en2<=0;
  468. sda_reg<=0;
  469. end
  470. contr : begin
  471. en<=1;
  472. en2<=1;
  473. sda_reg<=d_reg[7];
  474. data_in<=contr_b;
  475. end
  476. ack1 : begin
  477. en<=1;
  478. en2<=1;
  479. sda_reg<=0;
  480. end
  481. addr_h: begin
  482. en<=1;
  483. en2<=1;
  484. sda_reg<=d_reg[7];
  485. data_in<=addr_h_b;
  486. end
  487. ack2 : begin
  488. en<=1;
  489. en2<=1;
  490. sda_reg<=0;
  491. end
  492. addr_l: begin
  493. en<=1;
  494. en2<=1;
  495. sda_reg<=d_reg[7];
  496. data_in<=addr_l_b;
  497. end
  498. ack3 : begin
  499. en=1;
  500. en2<=1;
  501. sda_reg<=0;
  502. end
  503. data_t: begin
  504. en<=1;
  505. en2<=1;
  506. sda_reg<=d_reg[7];
  507. data_in<=data;
  508. end
  509. ack4 : begin
  510. en<=1;
  511. en2<=0;
  512. sda_reg<=0;
  513. end
  514. stop : begin
  515. en<=1;
  516. en2<=1;
  517. sda_reg<=0;
  518. end
  519. stop1 : begin
  520. en<=0;
  521. en2<=0;
  522. sda_reg<=1;
  523. end
  524. default:;
  525. endcase
  526. end
  527.  
  528. // 分頻計數器----------------------------------------------------------------
  529.  
  530. always@(posedge clk or negedge rst)
  531. begin
  532. if(!rst) cnt1 <= 7'd0;
  533. else if(en)
  534. begin
  535. if(cnt1 == 7'd124) cnt1 <= 7'd0;
  536. else cnt1 <= cnt1 + 7'd1;
  537. end
  538. else cnt1 <= cnt1;
  539. end
  540.  
  541. always@(posedge clk or negedge rst)
  542. begin
  543. if(!rst) cnt2 <= 4'd0;
  544. else if(en2)
  545. begin
  546. if(cnt1 == 7'd124)
  547. begin
  548. if(cnt2 == 4'd8) cnt2 <= 4'd0;
  549. else cnt2 <= cnt2 + 4'd1;
  550. end
  551. end
  552. else cnt2 <= cnt2;
  553. end
  554.  
  555. // sclk-----------------------------------------------------------------------------
  556.  
  557. always@(posedge clk)
  558. begin
  559.      if(present_state==start || present_state==start1 || present_state==stop || present_state==stop1)
  560.        sclk<=1;
  561.      else if(present_state==contr || present_state==ack1 || present_state==ack2 || present_state==ack3 || present_state==ack4 || present_state==data_t ||                  present_state==addr_l || present_state==addr_h)
  562.      begin
  563.          if(cnt1 == 7'd0)
  564.          sclk<=0;
  565.          else if(cnt1 == 7'd31)
  566.             sclk<=1;
  567.          else if(cnt1 == 7'd93)
  568.             sclk<=0;
  569.          else
  570.             sclk<=sclk;
  571.       end
  572.        else
  573. sclk<=sclk;
  574. end
  575.  
  576. // 移位暫存器---------------------------------------------------------------------------
  577.  
  578. always@(posedge clk or negedge rst)
  579. begin
  580. if(!rst)
  581. d_reg <= 8'b00000000;
  582. else if(cnt2 == 4'd1)
  583. d_reg <= data_in;
  584. else if(cnt1 == 7'd1)
  585. begin
  586. d_reg[7:1] <= d_reg[6:0];
  587. d_reg[0] <= 0;
  588. end
  589. else
  590. d_reg <= d_reg;
  591. end
  592.  
  593. //-------------------------------------------------------------------
  594.  
  595. assign sda = sda_en ? sda_reg : 1'bz;
  596.  
  597. always@(posedge clk or negedge rst)
  598. begin
  599.     if(!rst)
  600.       sda_en<=1;
  601.       else if((present_state == ack1 && cnt1==7'd1) || (present_state == ack2 && cnt1==7'd1) || (present_state == ack3 && cnt1==7'd1) || (present_state == ack4 &&                               cnt1==7'd1))
  602.          sda_en<=0;
  603.       else
  604.          sda_en<=1;
  605. end
  606.  
  607. endmodule

 


 


相關文章