您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關怎么進行IIC協議的FPGA實現,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
??????????????圖1 13 IIC模塊的建模圖
??圖1 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 行表示一個步驟所逗留的時間。
????????????圖3 15 結束位
??圖3 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 行表示該步驟所逗留的時間。
?????????????圖4 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拉低再拉高,這樣也是可以的。
以上就是怎么進行IIC協議的FPGA實現,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。