2.1 IIC協議的FPGA實現(二)IIC協議的FPGA實現

2.1 IIC協議的FPGA實現

2.1.2 IIC協議的FPGA實現

在這裏插入圖片描述

              圖2 13 IIC模塊的建模圖
  圖2 13是 IIC 儲存模塊的建模圖,左邊是頂層信號,右邊則是溝通用的問答信號,寫入地址 iAddr,寫入數據 iData,還有讀出數據 oData。 Call/Done 有兩位,即表示該模塊有讀功能還有些功能。具體內容,我們還是來看代碼吧:
                代碼2 1 IIC代碼聲明

1.	parameter FCLK = 10'd125, FHALF = 10'd62, FQUARTER = 10'd31;  
2.	parameter THIGH = 10'd30, TLOW = 10'd65, TR = 10'd15, TF = 10'd15;  
3.	parameter THD_STA = 10'd30, TSU_STA = 10'd30, TSU_STO = 10'd30;  

  如代碼2 1 所示, FCLK 表示 400Khz 的週期, FHALF 表示 1/2 週期, FQUARTER 表示 1/4 週期。
在這裏插入圖片描述
                      圖2 14 起始位
  首先讓我們先瞧瞧起始位這枚拼圖。如圖2 14所示,左圖是起始位的理想時序,右圖是起始位的物理時序。 IIC 總線的起始位也就類似串口或者 PS/2 等傳輸協議的起始位,然而不同的是, IIC 總線的起始位是 SCL 拉高 TR + TSU_STA + THD_STA + TF 之久,換之 SDA 則是拉高 TR + THIGH 然後拉低 TF + TLOW。起始位總和所用掉的時間,恰恰好有一個速率的週期。對此, Verilog 則可以這樣描述,結果如下所示:
                  代碼2 2 IIC起始位產生代碼

1.	begin  
2.	     isQ = 1;  
3.	     rSCL <= 1'b1;  
4.	     if( C1 == 0 ) rSDA <= 1'b1;  
5.	     else if( C1 == (TR + THIGH) ) rSDA <= 1'b0;  
6.	     if( C1 == (FCLK) -1) begin C1 <= 10'd0; i <= i + 1'b1; end  
7.	     else C1 <= C1 + 1'b1;  
8.	end  

  如代碼2 2所示,第 2 行的 isQ = 1 表示設置 SDA 爲輸出狀態(即時結果),第 3 行則表示 SCL 一直持續拉高狀態,第 4~5 行表示 C1 爲 0 的時候 SDA 拉高,直到 C1 爲TR+THIGH 才拉低 SDA。第 6~7 行表示一個步驟所逗留的時間。
在這裏插入圖片描述
                      圖2 15 結束位
  圖2 15是結束位的時序圖, IIC 設備的操作好壞一般都取決結束位。保險起見, SCL 與SDA 都事先拉低 1/4 週期,緊接着 SCL 會拉高 TR+TSU_STO(或者 1/2 週期),最後又保持高電平 1/2 週期。反之, SDA 會拉低 1/2 週期,隨之拉高 TR+THIGH(或者 1/2週期)。對此, Verilog 可以這樣表示,結果如代碼2 3所示:
                    代碼2 3 IIC結束位代碼實現

1.	begin  
2.	    isQ = 1'b1;  
3.	        
4.	    if( C1 == 0 ) rSCL <= 1'b0;  
5.	    else if( C1 == FQUARTER ) rSCL <= 1'b1;   
6.	       
7.	      if( C1 == 0 ) rSDA <= 1'b0;  
8.	      else if( C1 == (FQUARTER + TR + TSU_STO ) ) rSDA <= 1'b1;  
9.	        
10.	      if( C1 == (FQUARTER + FCLK) -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end  
11.	      else C1 <= C1 + 1'b1;   
12.	end  

  如代碼2 3所示,第 2 行表示 SDA 爲輸出狀態(即時),第 3~4 行表示 C1 爲 0 拉高SCL, C1 爲 1/4 週期就拉高。第 5~6 行表示, C1 爲 0 拉低 SDA, C1 爲 1/4 週期 + TR +TSU_STO 就拉高 SDA。第 7~8 行表示該步驟所逗留的時間。
在這裏插入圖片描述
                      圖2 16 釋放總線
  此外,結束位還有 Bus Free Time 這個時序參數,IIC 總線在閒置的狀態下 SCL 與 SDA等信號都持續高電平。主機發送結束位以示結束操作,然而主機持續拉高 SCL 信號與SDA 信號 TBUF 以示總線釋放。 TBUF 的有效時間從 SCL 信號與 SDA 信號拉高那一刻開始算起
  根據表2 2 所示, TBUF 是 65 個時鐘,結果如圖 16.6 所示, SDA 信號拉高之後, SCL與 SDA 信號只要持續保持 1/2 週期(即 62 個時),基本上就能滿足 TBUF。如果筆者是一位緊密控時狂人,可能無法接受這樣的結果,因爲滿足 TBUF 少了 3 個時鐘,爲此代碼2 3需要更動一下:
                    代碼 2 4 IIC結束位代碼修改

1.	if( C1 == ( FQUARTER + FCLK + 3) -1 )   
2.	     begin C1 <= 10'd0; i <= i + 1'b1; end  
3.	else C1 <= C1 + 1'b1;  

  如代碼 2 4所示,筆者爲第 1 行寫下 +3 表示該步驟多逗留 3 個時鐘,以致滿足 TBUF。
在這裏插入圖片描述
  不管對象是設備地址,數據地址,寫入數據,讀出數據,還是應答位,大夥都視爲數據位。 IIC 總線類似其他傳輸協議,它有時鐘信號也有上升沿與下降沿。如圖 16.7 所示,SCL 信號的下降沿導致設備設置(更新)數據,上升沿則是鎖存(讀取)數據。期間,TF+TLOW 表示時鐘信號的前半週期, TR+THIGH 則表示後半週期。此外,爲了確保數據成功打入寄存器,數據被上升沿鎖存哪一刻起, TSU_DAT 還有 THD_DAT 必須得到滿足。
在這裏插入圖片描述
                      圖2 17 數據位更新有效
  除此之外,爲了確保數據有效被更新,也必須確保 TAA 得到滿足,結果如圖2 17所示。理解完畢以後,就可以開始學習,寫一字節數據與讀一字節數據,還有應答位。
在這裏插入圖片描述
                        圖2 18 寫一字節
  IIC 總線一般都是一個字節一個字節讀寫數據,如圖2 18 所示,那是寫一字節的理想時序圖,一字節數據是從最高位開始寫起。對此, Verilog 可以這樣描述,結果如代碼2 5所示:
                      代碼2 5 IIC 總線寫一個字節

1.	7,8,9,10,11,12,13,14:  
2.	begin  
3.	    isQ = 1'b1;  
4.	    rSDA <= D1[14-i];  
5.	    if( C1 == 0 ) rSCL <= 1'b0;  
6.	    else if( C1 == (TF + TLOW) ) rSCL <= 1'b1;   
7.	    if( C1 == FCLK -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end  
8.	    else C1 <= C1 + 1'b1;  
9.	end  

  如代碼2 5 所示,第 1 行有 8 個步驟,表示寫一個字節。第 3 行 isQ 爲 1 表示 SDA 爲輸出狀態。第 4 行表示從最高位開始更新 SDA 的數據位。第 5~6 行表示, C1 爲 0 拉低SCL, C1 爲 TF+TLOW 則拉高 SCL。第 7~8 行表示該步驟逗留一個週期的時間。
在這裏插入圖片描述
                        圖2 19 應答位
  應答位是從機給予主機的回答, 0 爲是,1 爲否。然而,從旁觀看,讀取應答位也是讀取一位數據位。當主機完成寫入一個字節或者讀取一個字節數據的時候,從機都會產生應答位。主機拉低 SCL 那刻,從機便會發送應答位,然後主機會藉由上升沿讀取應答位。如圖2 19 所示,上升沿會產生在 TF + TLOW 之後,也是 1/2 週期。對此, Verilog 可以這樣表示,結果如代碼2 6所示:
                    代碼2 6 IIC應答位

1.	begin  
2.	    isQ = 1'b0;  
3.	      
4.	  if( C1 == FHALF ) isAck <= SDA;  
5.	    
6.	  if( C1 == 0 ) rSCL <= 1'b0;  
7.	  else if( C1 == FHALF ) rSCL <= 1'b1;  
8.	    
9.	  if( C1 == FCLK -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end  
10.	  else C1 <= C1 + 1'b1;   
11.	end  

  如代碼2 6所示,第 2 行表示 SDA 爲輸入狀態。第 4~5 行表示, C1 爲 0 拉低 SCL,C1 爲 1/2 週期則拉高 SCL。第 3 行表示, C1 爲 1/2 週期的時候讀取應答位。第 6~7 行表示該步驟逗留 1 個週期的時間。
在這裏插入圖片描述
                    圖2 20 讀一字節
  所謂讀一字節數據就是重複讀取 8 次應答位。如圖2 20所示, SCL 的下降沿導致從機更新數據,然後主機在 SCL 的上升沿讀取數據。此外,從機也會由高至低更新數據位。至於 Verilog 則可以這樣表示,結果如代碼2 7所示:
                    代碼2 7 IIC讀一字節

1.	19,20,21,22,23,24,25,26: // Read  
2.	begin  
3.	    isQ = 1'b0;  
4.	    if( C1 == FHALF ) D1[26-i] <= SDA;  
5.	    
6.	  if( C1 == 0 ) rSCL <= 1'b0;  
7.	  else if( C1 == FHALF  ) rSCL <= 1'b1;   
8.	    
9.	  if( C1 == FCLK -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end  
10.	  else C1 <= C1 + 1'b1;  
11.	end     

  如代碼2 7所示,第 1 行表示讀取一字節。第 3 行表示 SDA 爲輸入狀態,第 5~6 行表示, C1 爲 0 拉低 SCL, C1 爲 1/2 週期則拉高 SCL。第 4 行表示, C1 爲 1/2 週期的時候讀取數據,而且數據位由高至低存入 D1。第 7~8 行表示該步驟逗留一個週期的時間。
在這裏插入圖片描述
                    圖2 21 第二次起始位
  知道主機向從機讀取數據的時候,它必須改變設備地址的方向,因此讀操作又第二次起始位。如圖2 21所示,感覺上第二次起始位也是第一次起始位,不過爲了促使改變方向成功,第二次起始位相較第一次起始位的前後都拉低 1/4 週期。對此, Verilog 可以這樣表示,結果如代碼2 8所示:
                    代碼2 8 IIC第二次起始位

1.	begin  
2.	     isQ = 1'b1;  
3.	     if( C1 == 0 ) rSCL <= 1'b0;  
4.	     else if( C1 == FQUARTER ) rSCL <= 1'b1;  
5.	     else if( C1 == (FQUARTER + TR + TSU_STA + THD_STA + TF) ) rSCL <= 1'b0;  
6.	   
7.	     if( C1 == 0 ) rSDA <= 1'b0;  
8.	     else if( C1 == FQUARTER ) rSDA <= 1'b1;  
9.	     else if( C1 == ( FQUARTER + TR + THIGH) ) rSDA <= 1'b0;  
10.	   
11.	     if( C1 == (FQUARTER + FCLK + FQUARTER) -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end  
12.	     else C1 <= C1 + 1'b1;  
13.	end  

  如代碼2 8 所示,第 2 行表示 SDA 爲輸出狀態。第 3~5 行表示, C1 爲 0 拉低 SCL,C1 爲 1/4 週期拉高 SCL, C1 爲 1/4 週期 + TR + TSU_STA + THD_STA + TF 便拉低SCL。第 7~9 行表示, C1 爲 0 拉低 SDA, C1 爲 1/4 週期拉高 SDA, C1 爲 1/4 週期 + TR+ THIGH 便拉低 SDA。第 11~12 行表示該步驟停留一個週期的時間。
接下來是仿真驗證,結果如下:
在這裏插入圖片描述
在這裏插入圖片描述
                  圖 2 22 IIC總線仿真時序圖
  結合上述仿真波形圖和程序可以看出:
  起始位:SCLK爲高電平時,SDAT由高到低,指示IIC總線傳輸數據的開始;
  之後,傳送一個字節的數據,即4A,爲從機的地址,隨後,跟了一個高電平,爲應答位;
  之後,傳送一個字節的數據,即01,爲從機地址的子地址,隨後,跟了一個高電平,爲應答位;
  之後,傳送一個字節的數據,即08,爲上面子地址寄存器配置的數據,隨後,跟了一個高電平,爲應答位;
  最後,爲停止位,SCLK爲高電平時,SDAT由低到高,指示該次IIC總線傳輸數據的結束。
  由仿真結果可知,當傳送完一個字節後,SDAT爲一個脈衝的高電平,而不是從器件先將SDAT拉低再拉高,這樣也是可以的。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章