首页 > 代码库 > 数字电路期末课程设计总结(三)IIC总线调用

数字电路期末课程设计总结(三)IIC总线调用

首先介绍一下IIC总线。高速设备为了抗干扰,大多数都用低压差分信号(LVDS)。差分线路由于传递差模信号,可以有效抑制共模噪声和串扰。IIC总线虽然由于速度限制不能驱动高速设备,多用于KHz级别的信号传递,不过依然有着比较广泛的用途。

IIC网上资料繁多,我就不再赘述。

写数据分三步:

1.主机发送地址位(写),从机应答。

2.主机发送控制字,从机应答。

3.主机发送数据。

读数据分四步:

1.主机发送地址位(写),从机应答。

2.主机发送控制字,从机应答。

3.主机发送地址位(读),从机应答。

3.主机接收数据。

这次主要实现的功能:

根据工作状态控制字决定AOUT端输出波形(波形控制字控制波形),

或是AIN0,AIN1,AIN3端读入不同传感器的数据。

顶层模块图:

IIC模块读(写)完毕后Done_Sig产生1个高脉冲,驱动RomAddressCtrl模块和StateToCtrlByte模块改变工作状态,

外部的State控制信号由StateToCtrlByte模块处理后产生对应的IIC控制字,

Done_Sig信号与State控制信号通过控制Start_Sig信号决定IIC模块读写状态。

技术分享

顶层代码如下:

 1 module     I2C4In1 2 ( 3         input         clock,        //    时钟线 4         input         reset,        //    复位线 5         input[4:0]    State,        //    工作状态控制字 6       7  8          9         inout          SDA,        //    IIC数据线10         input[2:0]     WaveChoose,    //    波形控制字11         input[7:0]     FreqChoose,    //    相位控制字12         13         output         SCL,        //    IIC时钟线14         output[7:0]    ReadDataOut //    读数据输出15 );    16   17         /***************************/     18         RomAddressCtrl        U1(                //    ROM地址控制模块19                 .Done_Sig(Done_Sig),        //    IIC结束信号20                 .clock(clock),                //    时钟线21                 .reset(reset),                //    复位线22                 .FreqChoose(FreqChoose),    //    相位控制字23                 .isStart(isStart),            //    ROM输出IIC使能24                 .RomAddress(RomAddress)        //    ROM地址25         );26     27         WaveRomChoose    U4(                    //    ROM选择模块,选择输出波形对应的ROM28                 .WaveChoose(WaveChoose),    //    波形控制字29                 .address(RomAddress),        //    ROM地址30                 .clock(clock),                //    时钟线31                 .q(RomData)                 //    ROM数据输出32         );33         wire[7:0]    RomData;                //    模块间连线34         wire[10:0]    RomAddress;                //    模块间连线35         wire[1:0]    isStart;                //    模块间连线36         wire[1:0]    Start_Sig;                //    模块间连线37                                             //    IIC控制字输出模块38         StateToCtrlByte    U3(clock,reset,State,IICCtrlByte,isStart,Start_Sig,Done_Sig,RdData,ReadDataOut);39         /***************************/40         wire[7:0]    IICCtrlByte;            //    模块间连线41         wire[7:0]    RdData;                    //    模块间连线42         wire        Done_Sig;                //    模块间连线43 44         iic_func_module U2                    //    IIC模块45         (46             .clock( clock ),47             .reset( reset ),48             .Start_Sig(Start_Sig ),49             .Addr_Sig( IICCtrlByte ),50             .WrData( RomData ),51             .RdData( RdData ),52             .Done_Sig( Done_Sig ),53             .SCL( SCL ),54             .SDA( SDA )55         );56          57 58 endmodule

 

地址:1001000(0/1)

技术分享A2A1A0见下图,都连了地,所以都是0.

技术分享

 

 

IIC代码如下(源于黑金FPGA社区):

 

  1 module iic_func_module  2 (  3      input clock,  4      input reset,  5        6      input [1:0]Start_Sig,    //    IIC使能信号,10为读,01为写  7      input [7:0]Addr_Sig,    //    控制字  8      input [7:0]WrData,        //    写数据  9      output [7:0]RdData,    //    读数据 10      output Done_Sig,        //    转换完成信号,一个高脉冲 11       12      output SCL,            //    IIC时钟线 13      inout SDA                //    IIC数据线 14  15       16 ); 17  18     /*************************/ 19      20      parameter FREQ14 = 11d85; 21      parameter FREQ24 = 11d170; 22      parameter FREQ34 = 11d255; 23      parameter FREQ   = 11d341;    //    时间参量,对应50MHz时钟 24       25     /*************************/ 26       27     reg [4:0]i; 28     reg [4:0]Go; 29     reg [10:0]C1; 30     reg [7:0]rData; 31     reg rSCL; 32     reg rSDA; 33     reg isAck; 34     reg isDone; 35     reg isOut;      36       37      always @ ( posedge clock or negedge reset ) 38          if( !reset ) 39               begin 40                      i <= 5d0; 41                      Go <= 5d0; 42                      C1 <= 11d0; 43                      rData <= 8d0; 44                      rSCL <= 1b1; 45                      rSDA <= 1b1; 46                      isAck <= 1b1; 47                     isDone <= 1b0; 48                      isOut <= 1b1; 49                 end 50           else if( Start_Sig[0] ) 51               case( i ) 52                      53                     0: // Start 54                      begin 55                           isOut = 1; 56                       57                           rSCL <= 1b1; 58                            59                           if( C1 == 0 ) rSDA <= 1b1;  60                           else if( C1 == FREQ24 ) rSDA <= 1b0;   61                            62                           if( C1 == FREQ -1) begin C1 <= 11d0; i <= i + 1b1; end 63                           else C1 <= C1 + 1b1; 64                      end 65                        66                      1: // Write Device Addr 67                      begin rData <= {4b1001, 3b000, 1b0}; i <= 5d7; Go <= i + 1b1; end 68                       69                      2: // Wirte Word Addr 70                      begin rData <= Addr_Sig; i <= 5d7; Go <= i + 1b1; end 71                      72                      3: // Write Data 73                      begin rData <= WrData; i <= 5d7; Go <= i + 1b1; end 74                       75                      /*************************/ 76                       77                      4: // Stop 78                      begin 79                           isOut = 1b1; 80                            81                           if( C1 == 0 ) rSCL <= 1b0; 82                           else if( C1 == FREQ14 ) rSCL <= 1b1;  83                            84                           if( C1 == 0 ) rSDA <= 1b0; 85                           else if( C1 == FREQ34 ) rSDA <= 1b1; 86                             87                           if( C1 == FREQ14 + FREQ -1 ) begin C1 <= 11d0; i <= i + 1b1; end 88                           else C1 <= C1 + 1b1;  89                      end 90                       91                      5: 92                      begin isDone <= 1b1; i <= i + 1b1; end 93                       94                      6:  95                      begin isDone <= 1b0; i <= 5d0; end 96                       97                      /*******************************/ //function 98                       99                      7,8,9,10,11,12,13,14:100                      begin101                           isOut = 1b1;102                           rSDA <= rData[14-i];103                           104                           if( C1 == 0 ) rSCL <= 1b0;105                           else if( C1 == FREQ24 ) rSCL <= 1b1; 106                           107                           if( C1 == FREQ -1 ) begin C1 <= 11d0; i <= i + 1b1; end108                           else C1 <= C1 + 1b1;109                      end110                      111                      15: // waiting for acknowledge112                      begin113                           isOut = 1b0;114                           if( C1 == FREQ34 ) isAck <= SDA;115                           116                           if( C1 == 0 ) rSCL <= 1b0;117                           else if( C1 == FREQ24 ) rSCL <= 1b1;118                           119                           if( C1 == FREQ -1 ) begin C1 <= 11d0; i <= i + 1b1; end120                           else C1 <= C1 + 1b1; 121                      end122                      123                      16:124                      if( isAck != 0 ) i <= 5d0;125                      else i <= Go; 126                      127                      /*******************************/ // end function128                         129                 endcase130                 131           else if( Start_Sig[1] ) 132               case( i )133                 134                     0: // Start135                      begin136                           isOut = 1;137                           138                           rSCL <= 1b1;139                           140                           if( C1 == 0 ) rSDA <= 1b1; 141                           else if( C1 == FREQ24 ) rSDA <= 1b0;  142                           143                           if( C1 == FREQ -1 ) begin C1 <= 11d0; i <= i + 1b1; end144                           else C1 <= C1 + 1b1;145                      end146                       147                      1: // Write Device Addr148                      begin rData <= {4b1001, 3b000, 1b0}; i <= 5d9; Go <= i + 1b1; end149                      150                      2: // Wirte Word Addr151                      begin rData <= Addr_Sig; i <= 5d9; Go <= i + 1b1; end152                     153                      3: // Start again154                      begin155                           isOut = 1b1;156                           157                           if( C1 == 0 ) rSCL <= 1b0;158                           else if( C1 == FREQ14 ) rSCL <= 1b1;159                           else if( C1 == FREQ14 + FREQ ) rSCL <= 1b0;160                           161                           if( C1 == 0 ) rSDA <= 1b0; 162                           else if( C1 == FREQ14 ) rSDA <= 1b1;163                           else if( C1 == FREQ34 ) rSDA <= 1b0;  164                           165                           if( C1 == FREQ + FREQ24 -1 ) begin C1 <= 11d0; i <= i + 1b1; end166                           else C1 <= C1 + 1b1;167                      end168                      169                      4: // Write Device Addr ( Read )170                      begin rData <= {4b1001, 3b000, 1b1}; i <= 5d9; Go <= i + 1b1; end171                     172                      5: // Read Data173                      begin rData <= 8d0; i <= 5d19; Go <= i + 1b1; end174                      175                      6: // Stop176                      begin177                           isOut = 1b1;178                      179                           if( C1 == 0 ) rSCL <= 1b0;180                           else if( C1 == FREQ14 ) rSCL <= 1b1; 181                           182                           if( C1 == 0 ) rSDA <= 1b0;183                           else if( C1 == FREQ34 ) rSDA <= 1b1;                           184                           185                           if( C1 == 50 + FREQ -1 ) begin C1 <= 11d0; i <= i + 1b1; end186                           else C1 <= C1 + 1b1; 187                      end188                      189                      7:190                      begin isDone <= 1b1; i <= i + 1b1; end191                      192                      8: 193                      begin isDone <= 1b0; i <= 5d0; end194                      195                      /*******************************/ //function196                     197                      9,10,11,12,13,14,15,16:198                      begin199                           isOut = 1b1;200                           201                           rSDA <= rData[16-i];202                           203                           if( C1 == 0 ) rSCL <= 1b0;204                           else if( C1 == FREQ24 ) rSCL <= 1b1; 205                           206                           if( C1 == FREQ -1 ) begin C1 <= 11d0; i <= i + 1b1; end207                           else C1 <= C1 + 1b1;208                      end209                    210                      17: // waiting for acknowledge211                      begin212                           isOut = 1b0;213                          214                           if( C1 == FREQ34 ) isAck <= SDA;215                           216                           if( C1 == 0 ) rSCL <= 1b0;217                           else if( C1 == FREQ24 ) rSCL <= 1b1;218                           219                           if( C1 == FREQ -1 ) begin C1 <= 11d0; i <= i + 1b1; end220                           else C1 <= C1 + 1b1; 221                      end222                      223                      18:224                      if( isAck != 0 ) i <= 5d0;225                      else i <= Go;226                      227                      /*****************************/228                      229                      19,20,21,22,23,24,25,26: // Read230                      begin231                          isOut = 1b0;232                          if( C1 == FREQ34 ) rData[26-i] <= SDA;233                           234                           if( C1 == 0 ) rSCL <= 1b0;235                           else if( C1 == FREQ24 ) rSCL <= 1b1; 236                           237                           if( C1 == FREQ -1 ) begin C1 <= 11d0; i <= i + 1b1; end238                           else C1 <= C1 + 1b1;239                      end      240                      241                      27: // no acknowledge242                      begin243                          isOut = 1b1;244                          //if( C1 == 100 ) isAck <= SDA;245                           246                           if( C1 == 0 ) rSCL <= 1b0;247                           else if( C1 == FREQ24 ) rSCL <= 1b1;248                           249                           if( C1 == FREQ -1 ) begin C1 <= 11d0; i <= Go; end250                           else C1 <= C1 + 1b1; 251                      end252                      253                      /*************************************/ // end fucntion254                 255                 endcase256         257      /***************************************/258         259      assign Done_Sig = isDon;260      assign RdData =http://www.mamicode.com/ rData;261      assign SCL = rSCL;262      assign SDA = isOut ? rSDA : 1bz; 263     264     /***************************************/    265 266                 267 endmodule268     

 StateToCtrlByte模块:

State决定IICCtrlByte(IIC控制字)。针对27-41行的写法,我做了一些思考。最初用的是锁存器写法。

1     always@(State)    2     case(State)3         5b00001:    RegIICCtrlByte <= 8b00000000;4         5b00010:    RegIICCtrlByte <= 8b00000001;5         5b00100:    RegIICCtrlByte <= 8b01000000;6         5b01000:    RegIICCtrlByte <= 8b00000011;7     endcase

后来发现存在bug,信号有时会过不去。于是改成了组合逻辑式写法

1 assign    IICCtrlByte = State[0]==1?8d0:(State[1]==1?8d1:(State[2]==1?8d64:8d3));

 StateToCtrlByte:

 1 module    StateToCtrlByte(clock,reset,State,IICCtrlByte,isStart,Start_Sig,Done_Sig,RdData,ReadDataOut); 2     input[4:0]    State; 3     input[1:0]    isStart; 4     input        Done_Sig; 5     input        clock,reset; 6     input[7:0]    RdData;        //IIC模块读操作数据输入 7      8     output[1:0]    Start_Sig; 9     output[7:0]    IICCtrlByte;10     output[7:0]    ReadDataOut;    //    IIC模块读操作数据输出11     12     reg[1:0]        RegStart;13     reg[7:0]        RegReadDataOut;14 //    reg[7:0]        RegIICCtrlByte;15     16     always @ ( posedge clock or negedge reset )    17        if( !reset ) 18               begin19                      RegStart <= 2b00;20                 end21         else22               case( Done_Sig )            23                     0:     if(State==5b00100)RegStart <= 2b01;else RegStart <= 2b10; 24                      1:    begin RegStart <= 2b00; RegReadDataOut <= RdData;end25                 endcase        26     27 //    always@(State)    28 //    case(State)29 //        5‘b00001:    RegIICCtrlByte <= 8‘b00000000;30 //        5‘b00010:    RegIICCtrlByte <= 8‘b00000001;31 //        5‘b00100:    RegIICCtrlByte <= 8‘b01000000;32 //        5‘b01000:    RegIICCtrlByte <= 8‘b00000011;33 //    endcase34     35     assign    IICCtrlByte = State[0]==1?8d0:(State[1]==1?8d1:(State[2]==1?8d64:8d3));36     assign    ReadDataOut = RegReadDataOut;37     assign     Start_Sig = RegStart;38     //光照 AIN0     8‘b00000000;     0000139     //温度 AIN1    8‘b00000001;    0001040     //频率输出    8‘b01000000;    0010041     //内部电阻分压    AIN3    8‘b00000011;    0100042 endmodule
 1 //    相位累加模块 2 module RomAddressCtrl(Done_Sig,clock,reset,FreqChoose,isStart,RomAddress); 3  4         input    Done_Sig; 5         input clock; 6         input reset; 7         input[7:0] FreqChoose; 8  9         output[1:0]     isStart;                //    输出使能。01写操作,00中止10         output[10:0]    RomAddress;                //    ROM地址11 12         reg [3:0]    i;                            //    状态变量    i13         reg [1:0]    RegisStart;                    //    输出使能寄存器14         reg[10:0]    RegRomAddress;                //    ROM地址寄存器15         16 //    相位累加模块17 //    收到IIC结束信号Done_Sig后                18         always @ ( posedge clock or negedge reset )    19             if( !reset )20                 begin21                     i <= 4d0;22                     RegisStart         <= 2b00;23                 end24             else25                 case( Done_Sig )26                 27                         0: RegisStart <= 2b01; 28                      29                         1:    begin RegisStart <= 2b00; i <= 4d0; RegRomAddress <= RegRomAddress + FreqChoose;end30 31                 endcase32                 33         assign     isStart         =    RegisStart;34         assign    RomAddress        =    RegRomAddress;35         36 endmodule
 1 module    WaveRomChoose(WaveChoose,address,clock,q); 2  3     input            clock; 4     input[2:0]     WaveChoose; 5     input[10:0] address; 6      7     output[7:0] q; 8      9     wire[7:0]    SinData;10     wire[7:0]    SquData;11     wire[7:0]    TriData;12     13     rom_sin    U1(14             .address(address),15             .clock(clock),16             .q(SinData)17     );18     19     rom_squ    U2(20             .address(address),21             .clock(clock),22             .q(SquData)23     );24     25     rom_tri    U3(26             .address(address),27             .clock(clock),28             .q(TriData)29     );30     31     assign    q = WaveChoose[0]?SinData:(WaveChoose[1]?SquData:TriData);32 endmodule

 

数字电路期末课程设计总结(三)IIC总线调用