cgq081616 发表于 2015-8-13 14:37:46

基于FPGA的hdmi sil9136 IIC通信设计

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,
        outputreg   check_done,
        output   odata,
        outputreg   scl,
        inout         sda
);
    reg   link_sda;
    reg   sda_buf;
   wire   link_sda_o;
    wire   sda_buf_o;
    reg   FF;
    reg   main_state;
    reg   iic_state;
    reg   sh8out_buf;
    reg   cnt;
    reg   rdata;
    reg   time_cnt;
   reg   wait_cnt;
assign odata=rdata;

assign        sda = (link_sda_o)?sda_buf_o:1'bz;
assignsda_buf_o=(sda_buf)?1'bz:1'b0;
assignlink_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    slv_addr;
input           addr;
input    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   <= {slv_addr,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;
                  cnt         <=cnt+1;
                  sh8out_buf<=sh8out_buf<<1;
                end
          end
          3:
          if(scl&&!sda)          //ack
          begin
               iic_state       <= 4;
            // link_sda      <=1;
               sh8out_buf<= 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;
                  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;
                  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      slv_addr;
input      addr;
output   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   <= {slv_addr,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;
                  cnt         <=cnt+1;
                  sh8out_buf<=sh8out_buf<<1;
                end
          end
          3:
          if(scl&&!sda)          //ack
          begin
               iic_state       <= 4;
               //link_sda      <=1;
               sh8out_buf<= 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;
                  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   <= {slv_addr,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;
                  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      <=sda;
                                                iic_state       <= 11;
                                        end
                               else
                                        begin
                                          odata<=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

zhiweiqiang33 发表于 2015-8-18 11:21:39

值得一看 ,谢谢分享!

zxopenwgb 发表于 2017-2-22 14:36:26

挺好的资料

zxopen08 发表于 2017-4-12 09:44:10

基于FPGA的hdmi sil9136 IIC通信设计

小舍YZ 发表于 2017-4-13 13:52:20

谢谢分享。。。。。。。。。。。:lol

4798345 发表于 2017-4-13 16:48:32

感谢楼主分享

小舍YZ 发表于 2017-4-21 15:59:26

IIC通信设计:lol:lol:lol

zxopen08 发表于 2017-6-3 12:15:05

基于FPGA的hdmi sil9136 IIC通信设计

hhnb 发表于 2017-8-10 20:41:50

谢谢分享!!

zhangyukun 发表于 2017-8-11 08:51:10

感谢楼主分享
页: [1] 2
查看完整版本: 基于FPGA的hdmi sil9136 IIC通信设计