集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 20108|回复: 18

基于FPGA的hdmi sil9136 IIC通信设计

[复制链接]
cgq081616 发表于 2015-8-13 14:37:46 | 显示全部楼层 |阅读模式
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
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通信设计
4798345 发表于 2017-4-13 16:48:32 | 显示全部楼层
感谢楼主分享
小舍YZ 发表于 2017-4-21 15:59:26 | 显示全部楼层
IIC通信设计
zxopen08 发表于 2017-6-3 12:15:05 | 显示全部楼层
基于FPGA的hdmi sil9136 IIC通信设计
zhangyukun 发表于 2017-8-11 08:51:10 | 显示全部楼层
感谢楼主分享
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2024-11-23 11:15 , Processed in 0.105469 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表