zoukankan      html  css  js  c++  java
  • 数字电路期末课程设计总结(三)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选择模块,选择输出波形对应的ROM
    28                 .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 = 11'd85;
     21      parameter FREQ24 = 11'd170;
     22      parameter FREQ34 = 11'd255;
     23      parameter FREQ   = 11'd341;    //    时间参量,对应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 <= 5'd0;
     41                      Go <= 5'd0;
     42                      C1 <= 11'd0;
     43                      rData <= 8'd0;
     44                      rSCL <= 1'b1;
     45                      rSDA <= 1'b1;
     46                      isAck <= 1'b1;
     47                     isDone <= 1'b0;
     48                      isOut <= 1'b1;
     49                 end
     50           else if( Start_Sig[0] )
     51               case( i )
     52                     
     53                     0: // Start
     54                      begin
     55                           isOut = 1;
     56                      
     57                           rSCL <= 1'b1;
     58                           
     59                           if( C1 == 0 ) rSDA <= 1'b1; 
     60                           else if( C1 == FREQ24 ) rSDA <= 1'b0;  
     61                           
     62                           if( C1 == FREQ -1) begin C1 <= 11'd0; i <= i + 1'b1; end
     63                           else C1 <= C1 + 1'b1;
     64                      end
     65                       
     66                      1: // Write Device Addr
     67                      begin rData <= {4'b1001, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end
     68                      
     69                      2: // Wirte Word Addr
     70                      begin rData <= Addr_Sig; i <= 5'd7; Go <= i + 1'b1; end
     71                     
     72                      3: // Write Data
     73                      begin rData <= WrData; i <= 5'd7; Go <= i + 1'b1; end
     74                      
     75                      /*************************/
     76                      
     77                      4: // Stop
     78                      begin
     79                           isOut = 1'b1;
     80                           
     81                           if( C1 == 0 ) rSCL <= 1'b0;
     82                           else if( C1 == FREQ14 ) rSCL <= 1'b1; 
     83                           
     84                           if( C1 == 0 ) rSDA <= 1'b0;
     85                           else if( C1 == FREQ34 ) rSDA <= 1'b1;
     86                            
     87                           if( C1 == FREQ14 + FREQ -1 ) begin C1 <= 11'd0; i <= i + 1'b1; end
     88                           else C1 <= C1 + 1'b1; 
     89                      end
     90                      
     91                      5:
     92                      begin isDone <= 1'b1; i <= i + 1'b1; end
     93                      
     94                      6: 
     95                      begin isDone <= 1'b0; i <= 5'd0; end
     96                      
     97                      /*******************************/ //function
     98                      
     99                      7,8,9,10,11,12,13,14:
    100                      begin
    101                           isOut = 1'b1;
    102                           rSDA <= rData[14-i];
    103                           
    104                           if( C1 == 0 ) rSCL <= 1'b0;
    105                           else if( C1 == FREQ24 ) rSCL <= 1'b1; 
    106                           
    107                           if( C1 == FREQ -1 ) begin C1 <= 11'd0; i <= i + 1'b1; end
    108                           else C1 <= C1 + 1'b1;
    109                      end
    110                      
    111                      15: // waiting for acknowledge
    112                      begin
    113                           isOut = 1'b0;
    114                           if( C1 == FREQ34 ) isAck <= SDA;
    115                           
    116                           if( C1 == 0 ) rSCL <= 1'b0;
    117                           else if( C1 == FREQ24 ) rSCL <= 1'b1;
    118                           
    119                           if( C1 == FREQ -1 ) begin C1 <= 11'd0; i <= i + 1'b1; end
    120                           else C1 <= C1 + 1'b1; 
    121                      end
    122                      
    123                      16:
    124                      if( isAck != 0 ) i <= 5'd0;
    125                      else i <= Go; 
    126                      
    127                      /*******************************/ // end function
    128                         
    129                 endcase
    130                 
    131           else if( Start_Sig[1] ) 
    132               case( i )
    133                 
    134                     0: // Start
    135                      begin
    136                           isOut = 1;
    137                           
    138                           rSCL <= 1'b1;
    139                           
    140                           if( C1 == 0 ) rSDA <= 1'b1; 
    141                           else if( C1 == FREQ24 ) rSDA <= 1'b0;  
    142                           
    143                           if( C1 == FREQ -1 ) begin C1 <= 11'd0; i <= i + 1'b1; end
    144                           else C1 <= C1 + 1'b1;
    145                      end
    146                       
    147                      1: // Write Device Addr
    148                      begin rData <= {4'b1001, 3'b000, 1'b0}; i <= 5'd9; Go <= i + 1'b1; end
    149                      
    150                      2: // Wirte Word Addr
    151                      begin rData <= Addr_Sig; i <= 5'd9; Go <= i + 1'b1; end
    152                     
    153                      3: // Start again
    154                      begin
    155                           isOut = 1'b1;
    156                           
    157                           if( C1 == 0 ) rSCL <= 1'b0;
    158                           else if( C1 == FREQ14 ) rSCL <= 1'b1;
    159                           else if( C1 == FREQ14 + FREQ ) rSCL <= 1'b0;
    160                           
    161                           if( C1 == 0 ) rSDA <= 1'b0; 
    162                           else if( C1 == FREQ14 ) rSDA <= 1'b1;
    163                           else if( C1 == FREQ34 ) rSDA <= 1'b0;  
    164                           
    165                           if( C1 == FREQ + FREQ24 -1 ) begin C1 <= 11'd0; i <= i + 1'b1; end
    166                           else C1 <= C1 + 1'b1;
    167                      end
    168                      
    169                      4: // Write Device Addr ( Read )
    170                      begin rData <= {4'b1001, 3'b000, 1'b1}; i <= 5'd9; Go <= i + 1'b1; end
    171                     
    172                      5: // Read Data
    173                      begin rData <= 8'd0; i <= 5'd19; Go <= i + 1'b1; end
    174                      
    175                      6: // Stop
    176                      begin
    177                           isOut = 1'b1;
    178                      
    179                           if( C1 == 0 ) rSCL <= 1'b0;
    180                           else if( C1 == FREQ14 ) rSCL <= 1'b1; 
    181                           
    182                           if( C1 == 0 ) rSDA <= 1'b0;
    183                           else if( C1 == FREQ34 ) rSDA <= 1'b1;                           
    184                           
    185                           if( C1 == 50 + FREQ -1 ) begin C1 <= 11'd0; i <= i + 1'b1; end
    186                           else C1 <= C1 + 1'b1; 
    187                      end
    188                      
    189                      7:
    190                      begin isDone <= 1'b1; i <= i + 1'b1; end
    191                      
    192                      8: 
    193                      begin isDone <= 1'b0; i <= 5'd0; end
    194                      
    195                      /*******************************/ //function
    196                     
    197                      9,10,11,12,13,14,15,16:
    198                      begin
    199                           isOut = 1'b1;
    200                           
    201                           rSDA <= rData[16-i];
    202                           
    203                           if( C1 == 0 ) rSCL <= 1'b0;
    204                           else if( C1 == FREQ24 ) rSCL <= 1'b1; 
    205                           
    206                           if( C1 == FREQ -1 ) begin C1 <= 11'd0; i <= i + 1'b1; end
    207                           else C1 <= C1 + 1'b1;
    208                      end
    209                    
    210                      17: // waiting for acknowledge
    211                      begin
    212                           isOut = 1'b0;
    213                          
    214                           if( C1 == FREQ34 ) isAck <= SDA;
    215                           
    216                           if( C1 == 0 ) rSCL <= 1'b0;
    217                           else if( C1 == FREQ24 ) rSCL <= 1'b1;
    218                           
    219                           if( C1 == FREQ -1 ) begin C1 <= 11'd0; i <= i + 1'b1; end
    220                           else C1 <= C1 + 1'b1; 
    221                      end
    222                      
    223                      18:
    224                      if( isAck != 0 ) i <= 5'd0;
    225                      else i <= Go;
    226                      
    227                      /*****************************/
    228                      
    229                      19,20,21,22,23,24,25,26: // Read
    230                      begin
    231                          isOut = 1'b0;
    232                          if( C1 == FREQ34 ) rData[26-i] <= SDA;
    233                           
    234                           if( C1 == 0 ) rSCL <= 1'b0;
    235                           else if( C1 == FREQ24 ) rSCL <= 1'b1; 
    236                           
    237                           if( C1 == FREQ -1 ) begin C1 <= 11'd0; i <= i + 1'b1; end
    238                           else C1 <= C1 + 1'b1;
    239                      end      
    240                      
    241                      27: // no acknowledge
    242                      begin
    243                          isOut = 1'b1;
    244                          //if( C1 == 100 ) isAck <= SDA;
    245                           
    246                           if( C1 == 0 ) rSCL <= 1'b0;
    247                           else if( C1 == FREQ24 ) rSCL <= 1'b1;
    248                           
    249                           if( C1 == FREQ -1 ) begin C1 <= 11'd0; i <= Go; end
    250                           else C1 <= C1 + 1'b1; 
    251                      end
    252                      
    253                      /*************************************/ // end fucntion
    254                 
    255                 endcase
    256         
    257      /***************************************/
    258         
    259      assign Done_Sig = isDon;
    260      assign RdData = rData;
    261      assign SCL = rSCL;
    262      assign SDA = isOut ? rSDA : 1'bz; 
    263     
    264     /***************************************/    
    265 
    266                 
    267 endmodule
    268     

     StateToCtrlByte模块:

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

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

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

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

     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               begin
    19                      RegStart <= 2'b00;
    20                 end
    21         else
    22               case( Done_Sig )            
    23                     0:     if(State==5'b00100)RegStart <= 2'b01;else RegStart <= 2'b10; 
    24                      1:    begin RegStart <= 2'b00; RegReadDataOut <= RdData;end
    25                 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 //    endcase
    34     
    35     assign    IICCtrlByte = State[0]==1?8'd0:(State[1]==1?8'd1:(State[2]==1?8'd64:8'd3));
    36     assign    ReadDataOut = RegReadDataOut;
    37     assign     Start_Sig = RegStart;
    38     //光照 AIN0     8'b00000000;     00001
    39     //温度 AIN1    8'b00000001;    00010
    40     //频率输出    8'b01000000;    00100
    41     //内部电阻分压    AIN3    8'b00000011;    01000
    42 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;                            //    状态变量    i
    13         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                 begin
    21                     i <= 4'd0;
    22                     RegisStart         <= 2'b00;
    23                 end
    24             else
    25                 case( Done_Sig )
    26                 
    27                         0: RegisStart <= 2'b01; 
    28                      
    29                         1:    begin RegisStart <= 2'b00; i <= 4'd0; RegRomAddress <= RegRomAddress + FreqChoose;end
    30 
    31                 endcase
    32                 
    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
  • 相关阅读:
    openjudge 2750
    hexo部署云服务器
    freemaker传输数据问题
    FormData在axios中的骚操作
    Docker安装与初次使用
    docker-compose实现前后端分离的自动化部署
    centos7下设置静态ip
    centos7 安装mariadb 并配置主从复制
    centos7安装solr服务
    centos7安装redis
  • 原文地址:https://www.cnblogs.com/nwpuxuezha/p/4263562.html
Copyright © 2011-2022 走看看