当前位置:   article > 正文

iic i2c协议介绍以及 verilog实现_i2c verilog代码

i2c verilog代码

iic介绍:

         I2C(Inter-Integrated Circuit)是一种串行通信协议,也被称为IIC(Inter-IC)。它由飞利浦(Philips)公司开发,并广泛用于连接各种集成电路(IC)之间的通信。 iic属于半双工同步传输类型总线,即允许数据在发送和接收设备之间进行双向传输,但每次只能进行一种方向的数据传输(要么发送,要么接收),而不能同时发送和接收数据。

      I2C协议有多个主设备(master)和从设备(slave)。主设备跟从设备之间使用两条线进行通信,一条是串行数据线(SDA,Serial Data Line),另一条是串行时钟线(SCL,erial Clock Line)。

iic的时钟频率:

       IIC(Inter-Integrated Circuit)协议的时钟频率是可以根据具体应用和设备支持的情况进行调节的。传统的标准模式下,IIC总线的时钟频率通常为100 kHz。此外,还有三种快速模式:快速模式(Fast Mode)和高速模式(High-Speed Mode)和超快速模式(Ultra-fast mode)。在快速模式下,时钟频率可以达到400 kHz,高速模式下,时钟频率可以达到3.4MHZ。在超快速模块下,时钟频率可以达到5MHZ。

iic的工作过程

iic的写操作:

(1)sda信号初始状态为高电平,当sda拉低一个周期,表示传输传输

(2)开始后,sda写入一个字节的数据(串行),其中S6-S0为从设备的地址,用来选中从设备,WR为读写选择,当为高电平时,进行写操作

(3)随后从设备回应ack信号,此处标为ack1,本文设置传输的地址为16位,分为两次传输,从设备分别发出ack2跟ack3。

(4)D7-D0为传输的一字节数据

下图是sda信号各个bit表示:

iic的读操作

此时的data由从设备给出

iic的verilog代码(以写入地址16bit为例):

  iic分为IIDLE START,SLAVE,WR ,ACK1 ,REG1 ,ACK2 ,REG2 ,ACK3 ,DATA ,ACK4 ,STOP 

状态图如下:

代码如下:

  1. module iic(
  2.     input            sysclk       ,
  3.     input            rst_n        ,
  4.     input            i2c_en       ,        
  5.     input      [6:0] slave_addr   ,
  6.     input      [15:0]register_addr,
  7.     input      [7:0] write_data   ,
  8.     input            start        ,
  9.     input            slave_ack    ,
  10.     input            wr           ,//wr=1 write,wr=0 read
  11.     output reg [7:0] read_data   ,
  12.     output reg       i2c_clk      ,
  13.     inout            i2c_sda
  14. );
  15. parameter IDLE =12'b000000000001;
  16. parameter START=12'b000000000010;
  17. parameter SLAVE=12'b000000000100;
  18. parameter WR   =12'b000000001000;
  19. parameter ACK1 =12'b000000010000;
  20. parameter REG1 =12'b000000100000;
  21. parameter ACK2 =12'b000001000000;
  22. parameter REG2 =12'b000010000000;
  23. parameter ACK3 =12'b000100000000;
  24. parameter DATA =12'b001000000000;
  25. parameter ACK4 =12'b010000000000;
  26. parameter STOP =12'b100000000000;
  27. reg [12:0]state ;
  28. //clk_cnt
  29. reg[4:0] clk_cnt;
  30. always @(posedge sysclk or negedge rst_n) begin
  31.     if(rst_n==1'b0)
  32.        clk_cnt<=5'd0;
  33.     else if(clk_cnt==5'd19)
  34.         clk_cnt<=5'd0;
  35.     else
  36.         clk_cnt<=clk_cnt+1'b1;      
  37. end
  38. //i2c_clk
  39. always @(posedge sysclk or negedge rst_n) begin
  40.     if(rst_n==1'b0)
  41.        i2c_clk<=1'b0;
  42.     else if(clk_cnt<5'd19&&clk_cnt>5'd9)
  43.         i2c_clk<=1'b0;
  44.     else if(clk_cnt<5'd9)
  45.         i2c_clk<=1'b1;
  46.     else
  47.         i2c_clk<=i2c_clk;          
  48. end
  49. //cnt_slave
  50. reg[2:0]cnt_slave;
  51. always @(posedge i2c_clk or negedge rst_n) begin
  52.     if(rst_n==1'b0)
  53.     cnt_slave<=3'd0;
  54.     else if(state==SLAVE)
  55.     cnt_slave<=cnt_slave+1'b1;
  56.     else if(cnt_slave==3'd6)
  57.     cnt_slave<=3'd0;
  58.     else
  59.     cnt_slave<=cnt_slave;        
  60. end
  61. //cnt_reg1;
  62. reg[2:0]cnt_reg1;
  63. always @(posedge i2c_clk or negedge rst_n) begin
  64.     if(rst_n==1'b0)
  65.     cnt_reg1<=3'd0;
  66.     else if(state==REG1)
  67.     cnt_reg1<=cnt_reg1+1'b1;
  68.     else if(cnt_reg1==3'd7)
  69.     cnt_reg1<=3'd0;
  70.     else
  71.     cnt_reg1<=cnt_reg1;        
  72. end
  73. //cnt_data
  74. reg[2:0]cnt_data;
  75. always @(posedge i2c_clk or negedge rst_n) begin
  76.     if(rst_n==1'b0)
  77.     cnt_data<=3'd0;
  78.     else if(state==DATA)
  79.     cnt_data<=cnt_data+1'b1;
  80.     else if(cnt_data==3'd7)
  81.     cnt_data<=3'd0;
  82.     else
  83.     cnt_data<=cnt_data;        
  84. end
  85. /*//cnt_reg0
  86. reg[3:0]cnt_reg;
  87. always @(posedge i2c_clk or negedge rst_n) begin
  88.     if(rst_n==1'b0)'
  89.     cnt_reg<=34'd0;
  90.     else if(state==REG1||state==REG2)
  91.     cnt_reg<=cnt_reg+1'b1;
  92.     else if(cnt_reg==4'd15)
  93.     cnt_reg<=4'd0;
  94.     else
  95.     cnt_reg<=cnt_reg;        
  96. end//*/
  97. //cnt_reg2;
  98. reg[2:0]cnt_reg2;
  99. always @(posedge i2c_clk or negedge rst_n) begin
  100.     if(rst_n==1'b0)
  101.     cnt_reg2<=3'd0;
  102.     else if(state==REG2)
  103.     cnt_reg2<=cnt_reg2+1'b1;
  104.     else if(cnt_reg2==3'd7)
  105.     cnt_reg2<=3'd0;
  106.     else
  107.     cnt_reg2<=cnt_reg2;        
  108. end
  109. //state
  110. always @(posedge i2c_clk or negedge rst_n)
  111.     if(rst_n==1'b0) begin
  112.       state  <=IDLE;
  113.         end
  114.     else begin
  115.         case(state)
  116.          IDLE:begin
  117.             if(i2c_en==1'b1) begin
  118.             state  <=START;
  119.             end
  120.             else begin
  121.             state  <=IDLE;  
  122.             end
  123.          end
  124.          START:begin
  125.             if(start==1'b1)
  126.             state  <=SLAVE;
  127.             else
  128.             state  <=START;    
  129.             end
  130.          SLAVE:begin
  131.             if(cnt_slave==3'd6)
  132.             state  <=WR;
  133.             else
  134.             state  <=SLAVE;  
  135.             end
  136.          WR:begin
  137.                 state <=ACK1;    
  138.          end
  139.          ACK1:begin  
  140.             if(slave_ack==1'b0)
  141.             state<=REG1;  
  142.             else
  143.             state<=ACK1;    
  144.          end
  145.          REG1:begin
  146.             if(cnt_reg1==3'd7) begin
  147.             state<=ACK2;
  148.             end
  149.             else begin
  150.             state<=REG1;    
  151.             end
  152.         end
  153.          ACK2:begin  
  154.             if (slave_ack==1'b0)
  155.             state<=REG2;
  156.             else
  157.             state<=ACK2;    
  158.          end
  159.          REG2:begin  
  160.             if(cnt_reg2==3'd7) begin
  161.                 state<=ACK3;
  162.                 end
  163.             else begin
  164.                 state<=REG2;    
  165.                 end
  166.             end
  167.          ACK3:begin
  168.             if(slave_ack==1'b0)    
  169.             state <=DATA;
  170.             else
  171.             state <=ACK3;    
  172.                 end
  173.          DATA:begin
  174.             if(cnt_data==3'd7) begin
  175.                 state<=ACK4;
  176.                 end
  177.             else begin
  178.                 state<=DATA;
  179.                 end
  180.                 end
  181.          ACK4: begin
  182.             if(slave_ack==1'b0)
  183.             state <=STOP;      
  184.             else
  185.             state<=ACK4;    
  186.               end
  187.          STOP:begin
  188.              state<=IDLE;  
  189.          end  
  190.         default :begin
  191.           state<=IDLE;
  192.         end
  193.         endcase
  194.     end
  195. reg i2c_sda_out;
  196. wire out_en;
  197. assign out_en=((state==ACK1)||(state==ACK2)||(state==ACK3)||(state==ACK4)||(state==DATA&&wr==1'b0))?0:1;
  198. assign i2c_sda = (out_en)?i2c_sda_out:1'bz;
  199. //reg_data;
  200. reg[7:0]reg_data;
  201. always @(posedge sysclk or negedge rst_n) begin
  202.     if(rst_n==1'b0)
  203.     reg_data<=8'd0;
  204.     else if(state==START&&wr==1'b1)
  205.     reg_data<=write_data;    
  206.     else
  207.     reg_data<=reg_data;
  208. end
  209. //i2c_sda_out
  210. always @(posedge sysclk or negedge rst_n) begin
  211.     if(rst_n==1'b0)
  212.     i2c_sda_out<=1'b1                      ;
  213.     else if(state==IDLE)
  214.     i2c_sda_out<=1'b1                      ;
  215.     else if(state==START)
  216.     i2c_sda_out<=1'b0                      ;    
  217.     else if(state==SLAVE)
  218.     i2c_sda_out<=slave_addr[6-cnt_slave]   ;    
  219.     else if(state==WR&&wr==1'b1)
  220.     i2c_sda_out<=wr                        ;    
  221.     else if(state==ACK1)
  222.     i2c_sda_out<=slave_ack                 ;  
  223.     else if(state==REG1)
  224.     i2c_sda_out<=register_addr[15-cnt_reg1];
  225.     else if(state==ACK2)
  226.     i2c_sda_out<=slave_ack                 ;
  227.     else if(state==REG2)
  228.     i2c_sda_out<=register_addr[7-cnt_reg2] ;
  229.     else if(state==ACK3)
  230.     i2c_sda_out<=slave_ack                 ;                    
  231.     else if(state==DATA&&wr==1'b1)
  232.     i2c_sda_out<=reg_data[7-cnt_data]      ;
  233.     else if(state==ACK4)
  234.     i2c_sda_out<=slave_ack                 ;
  235.     else if(state==STOP)
  236.     i2c_sda_out<=1'b1                      ;
  237.     else
  238.     i2c_sda_out<=i2c_sda_out               ;  
  239. end
  240. reg [7:0] shift_reg;
  241. always @(posedge sysclk or negedge rst_n) begin
  242.     if(rst_n==1'b0)
  243.     shift_reg<=8'd0;
  244.     else if(state==DATA&&wr==1'b0)
  245.     shift_reg<={i2c_sda,shift_reg[7:1]} ;
  246.     else
  247.     shift_reg<=shift_reg;
  248. end    
  249. reg [2:0] read_data_cnt;
  250. always @(posedge sysclk or negedge rst_n) begin
  251.     if(rst_n==1'b0)
  252.     read_data_cnt<=3'd0;
  253.     else if(state==DATA&&wr==1'b0)
  254.     read_data_cnt<=read_data_cnt+1'b1;
  255.     else if(read_data_cnt==3'd7)
  256.     read_data_cnt<=3'd0;    
  257.     else
  258.     read_data_cnt<=read_data_cnt;        
  259.     end
  260. always @(posedge sysclk or negedge rst_n) begin
  261.     if(rst_n==1'b0)
  262.     read_data<=8'd0;
  263.     else if(state==DATA&&wr==1'b0&&read_data_cnt==3'd7)
  264.     read_data<=shift_reg;
  265.     else
  266.     read_data<=reg_data;        
  267. end
  268. endmodule

tb:

  1. module ii_tb();
  2. reg sysclk ;
  3. reg rst_n ;
  4. reg i2c_en ;
  5. reg [6:0] slave_addr ;
  6. reg [15:0]register_addr;
  7. reg [7:0] write_data ;
  8. reg start ;
  9. reg slave_ack ;
  10. reg wr ;
  11. wire[7:0] read_data ;
  12. wire i2c_clk ;
  13. wire i2c_sda ;
  14. iic iic_u(
  15. .sysclk (sysclk ),
  16. .rst_n (rst_n ),
  17. .i2c_en (i2c_en ),
  18. .slave_addr (slave_addr ),
  19. .register_addr(register_addr),
  20. .write_data (write_data ),
  21. .start (start ),
  22. .slave_ack (slave_ack ),
  23. .wr (wr ),
  24. .read_data (read_data ),
  25. .i2c_clk (i2c_clk ),
  26. .i2c_sda (i2c_sda )
  27. );
  28. initial begin
  29. sysclk =1'b0;
  30. rst_n =1'b0;
  31. i2c_en =1'b0;
  32. slave_addr =7'd0;
  33. register_addr=16'd0;
  34. write_data =8'd0;
  35. start =1'b0;
  36. slave_ack =1'b1;
  37. wr =1'b0;
  38. #10;
  39. rst_n =1'b1;
  40. #20;
  41. slave_addr =7'd25;
  42. i2c_en =1'b1;
  43. register_addr=16'd59;
  44. write_data =8'd32;
  45. start =1'b1;
  46. slave_ack =1'b0;
  47. wr =1'b1;
  48. end
  49. always #20 sysclk=!sysclk;
  50. endmodule

仿真波形

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

闽ICP备14008679号