| 
 | 
 
1.接触IIC的人,网上都可以了解到IIC有着严格的时序图,IIC在传输过程中需要起始信号、停止信号、应答信号。 
 
开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变。 
 
 
停止信号:SCL为高电平时,SDA由低电平向高电平跳变。 
 
 
应答信号:应答信号由接受设备产生,在 SCL 为高电平时,接受设备将 SDA 拉为低电 
平表示传输正确,产生应答,否则为非应答 
 
 
 
 
 
2.下面基于fpga的IIC设计,该设计HMDI sil9136的IIC控制程序 
 
module sii_i2c_cfg( 
        input         clk, 
        input         rst, 
        input         start, 
        output  reg   check_done, 
        output   [7:0]odata, 
        output  reg   scl, 
        inout         sda 
 ); 
    reg   link_sda; 
    reg   sda_buf; 
   wire   link_sda_o; 
    wire   sda_buf_o; 
    reg   FF; 
    reg   [5:0]main_state; 
    reg   [5:0]iic_state; 
    reg   [7:0]sh8out_buf; 
    reg   [3:0]cnt; 
    reg   [7:0]rdata; 
    reg   [10:0]time_cnt; 
   reg   [10:0]wait_cnt; 
  assign odata=rdata; 
 
 assign        sda = (link_sda_o)?sda_buf_o:1'bz; 
 assign  sda_buf_o=(sda_buf)?1'bz:1'b0; 
 assign  link_sda_o=(link_sda)?1'b1:1'b0; 
 //i2c scl 
 always @(negedge clk or posedge rst) 
 if(rst) scl<=0; 
 else scl<=~scl; 
 //i2c sda 
 always @(posedge clk or posedge rst) 
 if(rst) 
  begin 
    main_state<=0; 
    FF<=0; 
    iic_state<=0; 
    sh8out_buf<=0; 
    cnt<=0; 
    rdata<=0; 
         check_done<=0; 
         time_cnt<=0; 
         wait_cnt<=0; 
  end 
  else 
    begin 
      case(main_state) 
            0: if(start) main_state<=1; 
               else main_state<=0; 
                   1: if(FF) 
                begin 
                  FF<=0; 
                  main_state<=2; 
                end 
               else 
                begin 
                  iic_write(8'h72,8'hC7,8'h00); 
                  main_state<=1; 
                end 
                          2: if(wait_cnt==10) 
                                  begin 
                                          wait_cnt<=0; 
                                          main_state<=3; 
                                  end 
                                  else wait_cnt<=wait_cnt+1; 
                          3: if(FF) 
              begin 
                  FF<=0; 
                  main_state<=4; 
              end 
              else 
              begin 
                  iic_write(8'h72,8'h1a,8'h01); 
                  main_state<=3; 
              end 
                          4: if(wait_cnt==10) 
                                  begin 
                                          wait_cnt<=0; 
                                          main_state<=5; 
                                  end 
                                  else wait_cnt<=wait_cnt+1; 
                                5: main_state<=5; 
 
          default: 
              begin 
                main_state<=0; 
                FF<=0; 
                iic_state<=0; 
                sh8out_buf<=0; 
                cnt<=0; 
                rdata<=0; 
              end 
               
      endcase 
    end 
     
task iic_write; 
input [7:0]   slv_addr; 
input        [7:0]   addr; 
input [7:0]   wdata; 
begin 
        case (iic_state) 
          0: 
          if(!scl)               //start 
          begin 
              link_sda    <= 1; 
              sda_buf     <= 1; 
              iic_state   <= 1; 
          end 
          1: 
          if(scl) 
          begin 
              sh8out_buf[7:0]   <= {slv_addr[7:1],1'b0}; 
              link_sda          <= 1;  
              sda_buf           <= 0; 
              iic_state         <= 2; 
          end 
          2: 
          if(!scl)              //device address 
          begin 
                if(cnt==8) 
                begin 
                    link_sda    <= 0; 
                    cnt         <= 0; 
                    iic_state   <= 3; 
                end 
                else 
                begin 
                    link_sda    <=  1; 
                    sda_buf     <=  sh8out_buf[7]; 
                    cnt         <=  cnt+1; 
                    sh8out_buf  <=  sh8out_buf<<1; 
                end 
          end 
          3: 
          if(scl&&!sda)          //ack 
          begin 
               iic_state       <= 4; 
              // link_sda        <=  1; 
               sh8out_buf[7:0]  <= addr; 
          end 
          4: 
         if(!scl)              //addr 
          begin 
                if(cnt==8) 
                begin 
                    link_sda    <= 0; 
                    cnt         <= 0; 
                    iic_state   <= 5; 
                end 
                else 
                begin 
                    link_sda    <=  1; 
                    sda_buf     <=  sh8out_buf[7]; 
                    cnt         <=  cnt+1; 
                    sh8out_buf  <=  sh8out_buf<<1; 
                end 
          end 
          5: 
          if(scl&&!sda)      //receive ack 
          begin 
              iic_state         <= 6; 
              //link_sda          <=  1; 
              sh8out_buf        <=wdata; 
          end 
          6: 
                         if(!scl)              //data 
          begin 
                if(cnt==8) 
                begin 
                    link_sda    <= 0; 
                    cnt         <= 0; 
                    iic_state   <= 7; 
                end 
                else 
                begin 
                    link_sda    <=  1; 
                    sda_buf     <=  sh8out_buf[7]; 
                    cnt         <=  cnt+1; 
                    sh8out_buf  <=  sh8out_buf<<1; 
                end 
          end 
          7: 
          if(scl&&!sda)      //receive ack 
          begin 
              iic_state       <= 8; 
            //  link_sda          <= 1; 
          end 
        8: 
          if(!scl)          //stop 
          begin 
            sda_buf           <= 0; 
            link_sda          <= 1; 
            iic_state         <= 9; 
          end 
        9: 
          if(scl) 
          begin 
            sda_buf         <= 1; 
            iic_state       <= 10; 
          end 
        10: 
          begin 
            FF                <= 1; 
            sh8out_buf        <= 0; 
            link_sda          <= 0; 
            iic_state         <= 0; 
          end 
        endcase  
end  
endtask 
 
task iic_read; 
input   [7:0]   slv_addr; 
input   [7:0]   addr; 
output  [7:0]   odata; 
begin 
        case (iic_state) 
          0: 
          if(!scl)               //start 
          begin 
              link_sda    <= 1; 
              sda_buf     <= 1; 
              iic_state   <= 1; 
          end 
          1: 
          if(scl) 
          begin 
              sh8out_buf[7:0]   <= {slv_addr[7:1],1'b0}; 
              link_sda          <= 1;  
              sda_buf           <= 0; 
              iic_state         <= 2; 
          end 
          2: 
          if(!scl)              //device address 
          begin 
                if(cnt==8) 
                begin 
                    link_sda    <= 0; 
                    cnt         <= 0; 
                    iic_state   <= 3; 
                end 
                else 
                begin 
                    link_sda    <=  1; 
                    sda_buf     <=  sh8out_buf[7]; 
                    cnt         <=  cnt+1; 
                    sh8out_buf  <=  sh8out_buf<<1; 
                end 
          end 
          3: 
          if(scl&&!sda)          //ack 
          begin 
               iic_state       <= 4; 
               //link_sda        <=  1; 
               sh8out_buf[7:0]  <= addr; 
          end 
          4: 
                         if(!scl)              //write addr 
          begin 
                if(cnt==8) 
                begin 
                    link_sda    <= 0; 
                    cnt         <= 0; 
                    iic_state   <= 5; 
                end 
                else 
                begin 
                    link_sda    <=  1; 
                    sda_buf     <=  sh8out_buf[7]; 
                    cnt         <=  cnt+1; 
                    sh8out_buf  <=  sh8out_buf<<1; 
                end 
          end 
          5: 
          if(scl&&!sda)      //receive ack 
          begin 
              iic_state        <= 6; 
          end 
          6: 
             if(!scl)                         //restart 
              begin 
               link_sda         <= 1; 
               sda_buf          <= 1; 
               iic_state        <= 7; 
            end 
          7: 
          if(scl) 
          begin 
              sh8out_buf[7:0]   <= {slv_addr[7:1],1'b1}; 
              link_sda          <= 1;  
              sda_buf           <= 0; 
              iic_state         <= 8; 
          end 
          8:if(!scl)              //device address 
          begin 
                if(cnt==8) 
                begin 
                    link_sda    <= 0; 
                    cnt         <= 0; 
                    iic_state   <= 9; 
                end 
                else 
                begin 
                    link_sda    <=  1; 
                    sda_buf     <=  sh8out_buf[7]; 
                    cnt         <=  cnt+1; 
                    sh8out_buf  <=  sh8out_buf<<1; 
                end 
          end 
          9: 
          if(scl&&!sda)      //receive ack 
          begin 
              iic_state        <= 10; 
          end 
         10: 
          if(scl)                                               //read data 
                        begin 
                                 if(cnt==7) 
                                    begin 
                                                cnt                                 <= 0; 
                                                //odata[0]        <=sda; 
                                                iic_state       <= 11; 
                                        end 
                                 else 
                                        begin 
                                            odata[7-cnt]<=sda; 
                                                 cnt<=cnt+1; 
                                        end 
                                end 
          11: 
          if(!scl)      //send ack 
            begin 
              sda_buf     <= 1; 
              link_sda    <= 1; 
               
            end 
          else 
            begin 
              iic_state        <= 12; 
            end 
         12: 
          if(!scl)          //stop 
          begin 
            sda_buf<=0; 
            link_sda         <= 1; 
            iic_state        <= 13; 
          end 
        13: 
          if(scl) 
          begin 
            sda_buf<=1; 
            iic_state       <= 14; 
          end 
        14: 
          begin 
            FF<=1; 
            sh8out_buf         <= 0; 
            link_sda           <= 0; 
            iic_state          <= 0; 
          end 
        endcase  
end  
endtask 
 
endmodule |   
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?我要注册 
 
 
 
x
 
 
 
 
 |