数字电路期末课程设计总结(三)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

 

posted @ 2015-01-31 02:33  法师漂流  阅读(1032)  评论(0编辑  收藏  举报