IT技術(shu)互動(dong)交流(liu)平台

酷博平台官网

來源︰IT165收集(ji)  發布日期︰2020-02-26 00:11:14

在剖析了《深入淺(qian)出玩(wan)轉FPGA》的(de)串口代碼和IIC控制器代碼、xilinx官方的(de)xilinx的(de)iic控制器(參見(jian)書《FPGACPLD設(she)計工具──Xilinx ISE使用詳(xiang)解》)、《片上系di)成she)計思想(xiang)與源代碼分析》一書中帶有wishbone接口的(de)iic控制器後,本文嘗試對(dui)以上做一些(xie)總結,並分析不同的(de)iic控制器的(de)實現(xian)區(qu)別。

上一講,我們(men)分析了特權的(de)iic控制器的(de)實現(xian),這一講將(jiang)繼(ji)續(xu)另2種帶有總線接口和更充分實現(xian)iic協議的(de)例子。下(xia)一講講談談SOC架構中的(de)wishbone總線架構及外設(she)掛載(zai),以及一些(xie)軟硬件結合的(de)底(di)層(ceng)的(de)東西,主要參考《自(zi)己動(dong)手寫cpu》一書及相(xiang)關的(de)網頁資料等,敬(jing)請期待(dai)。

 

2、IIC控制器

2.2 xilinx的(de)iic控制器

該(gai)控制器主要是參考《FPGACPLD設(she)計工具──Xilinx ISE使用詳(xiang)解》第10章(zhang)和官方代碼,資料鏈接見(jian)文末給出的(de)下(xia)載(zai)鏈接地址。

iic協議的(de)知識同樣不再贅述,只是提幾點上一講中沒有或(huo)無需關注的(de)地方︰

1、I2C總線通信(xin)時,起始位後的(de)第一個字節用于尋址,該(gai)字節包(bao)含(han)7比特的(de)從機(ji)地址和1比特的(de)讀(du)寫指(zhi)示比特, 一般(ban)而言(yan),從機(ji)地址由(you)一個固定部分和一個可編(bian)程部分構成。

2、復合xi)袷shi)中,此時主機(ji)連續(xu)對(dui)從機(ji)進行多次讀(du)寫操作,因此在產(chan)生起始位、收發數(shu)據、產(chan)生停止位的(de)整個傳輸過程中,數(shu)據的(de)方jiao)蚍?啻胃謀洌  涓謀浞較(jiao)蚴保 骰ji)會重(zhong)新發出重(zhong)復起始位和從機(ji)地址(上一講中為(wei)什cai)me)讀(du)的(de)流(liu)程要復雜些(xie)的(de)原因)。

3、I2C總線在一個時刻(ke)只能有一個主機(ji),當(dang)I2C總線同時有兩個或(huo)更多的(de)器件想(xiang)成為(wei)主機(ji)時,就需要進行仲裁(cai),時鐘同步過程的(de)目的(de)是為(wei)仲裁(cai)提供(gong)一個確(que)定的(de)時鐘。SCL 線低(di)電平時間取決(jue)于低(di)電平時間最長的(de)主機(ji),高(gao)電平時間取決(jue)于高(gao)電平時間最短(duan)的(de)主機(ji)。主機(ji)只會在 I2C 總線空閑時產(chan)生起始位,但是在起始位的(de)保持(chi)時間 tHD;STA內可能有兩個或(huo)以上的(de)主機(ji)產(chan)生起始位,最終總線上的(de)起始位由(you)它們(men)之間的(de)線與運算決(jue)定,仲裁(cai)在隨後 SDA 線上發送的(de)比特中進行。如果一個主機(ji)具有從機(ji)功能,那麼(me)當(dang)它失去(qu)仲裁(cai)時,必須(xu)立即(ji)切換到從機(ji)狀態,因為(wei)它可能正在被(bei)其他(ta)主機(ji)尋址。

4、如圖

講完了這些(xie)關于iic協議的(de)點繼(ji)續(xu)下(xia)面的(de)部分.

I2C總線控制器的(de)主要作用是提供(gong)UC(Microcontroller,微控制器或(huo)單(dan)片機(ji))和I2C總線之間的(de)接口,為(wei)兩者之間的(de)通信(xin)提供(gong)物理層(ceng)協議的(de)轉換。這些(xie)I2C協議的(de)器件,就不能直(zhi)接和單(dan)片機(ji)外圍(wei)總線相(xiang)連,這些(xie)器件可以掛在一套I2C總線上,再通過I2C總線控制器和µC連起來,如圖所示。在SOC設(she)計中類似pin)男 樽 荒?橛玫梅淺(qian)6唷/p>

I2C 總線控制器包(bao)含(han)兩個主要部分,一是微控制器接口,簡稱µC接口,二是 I2C Master/Slave 接口,即(ji)I2C接口,通過這兩個接口,I2C總線控制器實現(xian)了微控制器外圍(wei)總線和 I2C 總線的(de)連接。那麼(me)這里的(de)微控制器接口是哪種控制器?是否(fu)是哪種總線協議,根據readme文件可以發現(xian)原來是 MC68307單(dan)片機(ji),是一款(kuan)集(ji)成的(de)多總線處理器。

講清楚了原理,我們(men)來看(kan)看(kan)具體設(she)計︰

This zip file contains the following folders:
-- Verilog Source Files:
i2c_blk_ver.v - top level file
i2c_control_blk_ver.v - control function for the I2C master/slave
shift8_blk_ver.v - shift register
uc_interface_blk_ver.v - uC interface function for an 8-bit 68000-like uC
upcnt4_blk_ver.v - 4-bit up counter

可以看(kan)到5個文件。uc_interface_blk_ver.v 實現(xian)了一些(xie)寄存(cun)器以及對(dui)下(xia)層(ceng)模塊的(de)控制信(xin)號,shift8_blk_ver.v是串行收發,upcnt4_blk_ver.v是4位計數(shu)器,i2c_blk_ver.v 是頂層(ceng),例化了uc_interface_blk_ver和i2c_control_blk_ver。i2c_control_blk_ver則實現(xian)了仲裁(cai),start等收發流(liu)程狀態機(ji)等。整體架構如下(xia)圖︰

整個思路還是很清楚的(de)。接口處主要是一些(xie)寄存(cun)器,寄存(cun)器的(de)信(xin)號到iic中控制pin)撞ceng)的(de)運轉。

µC 接口主要包(bao)含(han)狀態寄存(cun)器MBSR、控制寄存(cun)器MBCR、地址寄存(cun)器MADR、數(shu)據寄存(cun)器MBDR 和地址譯碼/總線接口模塊。狀態寄存(cun)器指(zhi)示I2C總線控制器的(de)當(dang)前狀態,如傳送是否(fu)完成、總線是否(fu)忙等信(xin)息,控制寄存(cun)器是µC控制I2C總線控制器的(de)主要途徑,通過置0/置1可以完成I2C總線控制器使能、中斷使能、Master/Slave模式(shi)選擇、產(chan)生起始位等操作。地址寄存(cun)器保存(cun)著I2C總線控制器作為(wei)Slave時的(de)地址。數(shu)據寄存(cun)器用于保存(cun)接收或(huo)是待(dai)發送的(de)數(shu)據。

下(xia)面分析源代碼,由(you)于源代碼眾多,只能摘出部分,梳理主要思路和重(zhong)要信(xin)號線,大家可以下(xia)載(zai)我注釋的(de)代碼。

i2c_blk_ver.v 頂層(ceng)文件︰

 

module i2c_blk (sda, scl, addr_bus, data_bus, as, ds, r_w, dtack, irq, mcf, clk,  reset); parameter I2C_ADDRESS = 16'b0000000000000000; // I2C bus signals inout sda; inout scl; // uC interface signals input [23:0] addr_bus; inout [7:0] data_bus; input as;  // address strobe, active low input ds;  // data strobe, active low input r_w;  // read/write output dtack;  // data transfer acknowledge 給處理器的(de),表示數(shu)據是否(fu)準備好了 output irq;  // interrupt request inout mcf;  // temporary output for testing 給處理器,表示jing) 涫欠fu)結束 // clock and reset input clk; input reset;
這個是頂層(ceng)的(de)輸入輸出,不是什cai)me)特殊的(de)總線結構,比較(jiao)好理解,pdf中有詳(xiang)細(xi)的(de)中文解釋每個信(xin)號的(de)含(han)義。

 

接下(xia)來是一些(xie)wire型,實際上就是那些(xie)寄存(cun)器中有含(han)義的(de)每一位,即(ji)各(ge)種控制信(xin)號線,便于例化的(de) i2c_control I2C_CTRL與 uC_interface #(I2C_ADDRESS) uC_CTRL模塊間的(de)接口互聯。

接下(xia)來從頂層(ceng)往下(xia),uC_interface模塊︰

 

 // Internal I2C Bus Registers // Address Register (Contains slave address) inout [7:0] madr; // Control Register inout men;  // I2C Enable bit inout mien;  // interrupt enable inout msta;  // Master/Slave bit inout mtx;  // Master read/write inout txak;  // acknowledge bit inout rsta;  // repeated start output mbcr_wr;  // indicates that the control reg has been written // Status Register input mcf;  // end of data transfer input maas;  // addressed as slave input mbb;  // bus busy input mal;  // arbitration lost input srw;  // slave read/write input mif;  // interrupt pending input rxak;  // received acknowledge output mal_bit_reset; // indicates that the MAL bit should be reset output mif_bit_reset; // indicates that the MIF bit should be reset input msta_rst;  // resets the MSTA bit if arbitration is lost // Data Register inout [7:0] mbdr_micro; input [7:0] mbdr_i2c; output mbdr_read;
可以看(kan)到實際上這個模塊的(de)很多輸出信(xin)號就是這些(xie)寄存(cun)器的(de)位,控制更底(di)層(ceng)的(de)如何實現(xian)。可以參考pdf查(cha)詢具體的(de)寄存(cun)器(8位)的(de)某一位是什cai)me)含(han)義。比如狀態寄存(cun)器都是input型,因為(wei)他(ta)主要反饋給uc當(dang)前狀態,不對(dui)底(di)層(ceng)的(de)狀態機(ji)控制。數(shu)據寄存(cun)器中mbdr_micro是inout型,表示是uc總線那一端的(de),mbdr_i2c是input型,表示是從iic接收到的(de)那一端的(de)。

 

 

 // State Machine Signals `define STATE_TYPE_IDLE 2'd0 `define STATE_TYPE_ADDR 2'd1 `define STATE_TYPE_DATA_TRS 2'd2 `define STATE_TYPE_ASSERT_DTACK 2'd3 // Constant Declarations parameter RESET_ACTIVE = 1'b0; // Base Address for I2C Module (addr_bus[23:8]) parameter MBASE = UC_ADDRESS; // Register Addresses (5 Total): // Address Register (MBASE + 8Dh) `define MADR_ADDR 8'b10001101 // Control Register (MBASE + 91h) `define MBCR_ADDR 8'b10010001 // Status Register (MBASE + 93h) `define MBSR_ADDR 8'b10010011 // Data I/O Register (MBASE + 95h) `define MBDR_ADDR 8'b10010101
uc部分的(de)狀態機(ji),µC和 I2C總線控制器之間的(de)交互要用到 I2C總線控制器內部的(de)寄存(cun)器,寄存(cun)器的(de)地址是24位的(de),其中高(gao)16比特為(wei)I2C總線控制器的(de)基址,低(di)8位用于區(qu)別不同寄存(cun)器。接下(xia)來定義了10多個wire型的(de)中間變量,這些(xie)事狀態機(ji)中產(chan)生的(de)操縱控制狀態機(ji)的(de)。由(you)于wire型變量不能再always中賦chi)擔 院竺嬗you)用這種方式(shi)定義一個相(xiang)應的(de)reg型變量。

 

 

// Address match wire address_match;
 reg visual_0_address_match; assign address_match = visual_0_address_match;

加(jia)上了visual_0的(de)前綴,這樣做的(de)好me)Γ課蟻xiang)一是時鐘同步,reg信(xin)號由(you)clock打一拍同步,也便于去(qu)除毛(mao)刺,因為(wei)assign信(xin)號直(zhi)接相(xiang)連,稍有抖(dou)動(dong)就有毛(mao)刺,reg信(xin)號打拍子可以避免這種問題。二是可以yue)承xie)信(xin)號做類似案件檢測一樣的(de)消抖(dou),舉例︰

 

51 input as; 
221 begin      visual_0_as_int //這里又(you)有一個時鐘的(de)延(yan)遲一拍      visual_0_as_int_d1//經過一個時鐘的(de)延(yan)遲一拍,為(wei)了檢測到正確(que)的(de)下(xia)降沿而沒有抖(dou)動(dong)的(de)干擾      visual_0_ds_int <= ds;      if ((!as && as_int_d1 && addr_bus[23:8] == MBASE))//低(di)8位是區(qu)別那個寄存(cun)器        visual_0_address_match <= 1'b1;      else        visual_0_address_match <= 1'b0;    end
135   reg visual_0_as_int;  assign as_int = visual_0_as_int;
138  reg visual_0_as_int_d1;  assign as_int_d1 = visual_0_as_int_d1;

 

 

可以看(kan)見(jian)從221行開始,獲取as輸入,經過幾個中間變量的(de)周轉,在if中通過!as && as_int_d1來達到類似案件去(qu)抖(dou)的(de)效果。另外有些(xie)變量是對(dui)外輸出的(de),也需變成reg型。 這部分的(de)實際工作流(liu)程如圖︰
根據上圖的(de)流(liu)程︰第一個always塊, // Process:SYNCH_INPUTS 判斷as是否(fu)有有效的(de)下(xia)降沿,然(ran)後總線的(de)高(gao)16位是否(fu)是正確(que)的(de)我們(men)這個iic設(she)備在真(zhen)個cpu外設(she)總線上的(de)地址。為(wei)真(zhen),則visual_0_address_match信(xin)號為(wei)1,起始對(dui)應為(wei)address_match,這個成為(wei)後續(xu)的(de)控制判斷,狀態機(ji)的(de)重(zhong)要依據。接下(xia)來是uc模塊的(de)主狀態機(ji)︰

 

 always @(prs_state or as or as_int_d1 or ds_int or address_match) begin visual_0_next_state <= prs_state;//2位的(de)變量,4個狀態 visual_0_dtack_com <= 1'b1; visual_0_dtack_oe <= 1'b0; case (prs_state) `STATE_TYPE_IDLE ://引用定義的(de)變量 // ----------- IDLE State (00) ------------- // Wait for falling edge of as if (as_int_d1 && !as)//as表示輸入地址有效信(xin)號,低(di)有效,這里的(de)as_int_d1實際上是一個類似按鍵(jian)去(qu)抖(dou)的(de)效果,延(yan)遲了2拍,追蹤信(xin)號就可以發現(xian)  // falling edge of AS  visual_0_next_state <= `STATE_TYPE_ADDR; `STATE_TYPE_ADDR : // ---------- ADDR State (01) -------------- // Check that this module is being address if (address_match)//225行由(you)輸入的(de)bus決(jue)定,也是打了一拍,做到時鐘同步  // Wait for ds to be asserted, active low  if (!ds_int)//由(you)輸入的(de)ds決(jue)定  visual_0_next_state <= `STATE_TYPE_DATA_TRS;  else  visual_0_next_state <= `STATE_TYPE_ADDR; else  // this module is not being addressed  visual_0_next_state <= `STATE_TYPE_IDLE; `STATE_TYPE_DATA_TRS : begin // -------- DATA_TRS State (10) ------------ // Read or write from enabled register visual_0_next_state <= `STATE_TYPE_ASSERT_DTACK;//過渡態,為(wei)了給出oe的(de)信(xin)號,內部控制線 visual_0_dtack_oe <= 1'b1;//前面被(bei)置為(wei)0了的(de) end `STATE_TYPE_ASSERT_DTACK : begin // ------ ASSERT_DTACK State (11) ---------- // Assert dtack to uProcessor visual_0_dtack_com <= 1'b0;//前面被(bei)置為(wei)1了的(de) visual_0_dtack_oe <= 1'b1; // Wait for rising edge of as and ds if ((!as_int_d1) && (!ds_int))//鎖存(cun)操作,直(zhi)至DTACK有效,甚至可以分析鎖存(cun)了幾個時鐘?  visual_0_next_state <= `STATE_TYPE_ASSERT_DTACK; else if ((as_int_d1) && (ds_int))  visual_0_next_state <= `STATE_TYPE_IDLE; end endcase end
</pre><pre code_snippet_id="1669606" snippet_file_name="blog_20160502_10_3192142" name="code" class="plain">注意在848行處︰// set SDA and SCL assign sda = (sda_oe == 1'b1 ? 1'b0 : 1'bz); assign scl = (scl_out_reg == 1'b0 ? 1'b0 : 1'bz); assign scl_not = (~ (scl)) ; // sda_oe is set when master and arbitration is not lost and data to be output = 0 or // when slave and data to be output is 0 assign sda_oe = (((master_slave == 1'b1 && arb_lost == 1'b0 && sda_out_reg ==   1'b0) (master_slave == 1'b0 && slave_sda == 1'b0)   stop_scl_reg == 1'b1) ? 1'b1 : 1'b0);
所以sda實際上經由(you)sda_out_reg,visual_0_sda_out_reg,sda_out,visual_0_sda_out控制,即(ji)下(xia)圖狀態機(ji)中的(de)visual_0_sda_out實際代表了sda,同樣scl也一樣。

 

 

 

該(gai)狀態機(ji)還是比較(jiao)清晰的(de)。

next_state信(xin)號通過幾個中間變量的(de)周轉,還是賦給了prs_state實現(xian)狀態跳轉,292的(de)always塊即(ji)實現(xian)了這種從next_state到prs_state的(de)驅動(dong)。dtack_com是一個狀態機(ji)變化的(de)中間信(xin)號,轉化成dtack_int變成dtack信(xin)號,dtack_oe決(jue)定是否(fu)輸出dtack信(xin)號。注意這3條語句每kan)謂淳透攏   isual_0_dtack_com與visual_0_dtack_oe這里每kan)偽bei)重(zhong)置。首先是idle狀態,檢測到有效的(de)as信(xin)號。進入addr狀態,監測地址是否(fu)匹配,數(shu)據是否(fu)來了,來了就進入trs,否(fu)則繼(ji)續(xu)等。Trs狀態是過渡態,為(wei)了給出visual_0_dtack_oe信(xin)號,進入dtack狀態,visual_0_dtack_com與visual_0_dtack_oe被(bei)設(she)置表明(ming)數(shu)據已經放到uc與iic的(de)總線上。等待(dai)ds失效,回到idle狀態。那麼(me)更多的(de)過程實際上是根據狀態機(ji)的(de)中間變量,在別的(de)always塊中實現(xian)的(de),可以分析下(xia)兩者間的(de)相(xiang)對(dui)時間關系。

接下(xia)來的(de)always實現(xian)visual_0_prs_state <= next_state;驅動(dong)狀態更迭。接下(xia)來是判斷那個24位的(de)地址是映射到那個寄存(cun)器,每個寄存(cun)器給出一個信(xin)號線,若選中xing)蛭wei)1,驅動(dong)下(xia)一個always塊中的(de)數(shu)據具體傳到哪個寄存(cun)器中。下(xia)個always塊中,實現(xian)了對(dui)不同狀態下(xia)的(de)一些(xie)信(xin)號量的(de)設(she)置,而沒有xing)謚 暗de)狀態機(ji)中實現(xian)。每根信(xin)號線的(de)含(han)義可以查(cha)pdf。mbcr_wr代表了mbcr是被(bei)讀(du)了還是被(bei)寫了。其實Status Register是只讀(du)的(de),寫的(de)話會產(chan)生復位。其他(ta)幾個寄存(cun)器類似,比較(jiao)好理解,理解關于數(shu)據寄存(cun)器的(de)數(shu)據流(liu)向。這里面的(de)8位數(shu)據都是一個clk完成,注意與上面的(de)dtack的(de)含(han)義在時序上是否(fu)沖突,因為(wei)dtack是表征數(shu)據已經準備好

最後就是幾個assign語句,根據上面的(de)信(xin)號處理是否(fu)有中斷,dtack,決(jue)定是傳輸進來某個信(xin)號還是給出某個信(xin)號。

總的(de)來說結構比較(jiao)清晰,模塊化比較(jiao)清晰。狀態機(ji)采用了分段式(shi)的(de)寫法。

i2c_control_blk_ver.v文件

它的(de)接口主要是uc接口文件中的(de)寄存(cun)器的(de)信(xin)號線。分zhi)鴝ㄒ?聳shu)據流(liu)程的(de)狀態機(ji)和scl信(xin)號的(de)狀態機(ji)。接下(xia)來是一堆的(de)中間信(xin)號的(de)定義和類似pin)募jia)上visual_0後的(de)reg處理。

接下(xia)來首先例化了upcnt4模塊用來統計bit數(shu)。這是一個不封頂的(de)4位計數(shu)器,但是可以輸入一個4位數(shu)據來修(xiu)改計數(shu)值。接下(xia)來再例化一個用于clk的(de)計數(shu),達到分頻(pin)的(de)效果。接下(xia)來是例化了2個SHIFT8_blk,改模塊可以load和輸出1個8位數(shu),也可串行接收和發送一個一位數(shu)。例化了2個第一個是iic端的(de),一個是uc端的(de)。接下(xia)來是總線仲裁(cai),主要是msta_rst與arb_lost位。當(dang)為(wei)主機(ji),scl_in為(wei)scl的(de)采樣。有待(dai)重(zhong)點分析?

接下(xia)來是scl信(xin)號的(de)一個狀態機(ji)︰

I2C 總線控制器復位後處于IDLE 狀態,不驅動(dong)SCL 和SDA,此時I2C 總線上的(de)其他(ta)Master 可以控制SCL 和SDA。如果I2C 總線控制器處于Master 模式(shi),而且I2C 總線處于空閑狀態,μC 通過置位MBCR 寄存(cun)器的(de)MSTA 比特使GEN_START 信(xin)號為(wei)高(gao),那麼(me)狀態機(ji)進入START 狀態。

在 START 狀態,SCL 保持(chi)為(wei)高(gao)電平,同時驅動(dong)SDA 信(xin)號變低(di),從而在I2C 總線上產(chan)生一個起始位。系di)呈敝蛹剖shu)器啟動(dong)計數(shu),直(zhi)到滿(man)足I2C 規範要求的(de)起始ji)跫3chi)時間(>4ns),狀態機(ji)進入SCL_LOW_EDGE狀態。

在 SCL_LOW_EDGE 狀態,狀態機(ji)使SCL 產(chan)生一個下(xia)降沿並復位系di)呈敝蛹剖shu)器,然(ran)後在下(xia)一個時鐘沿到來時進入SCL_LOW 狀態。

在SCL_LOW 狀態,SCL 保持(chi)為(wei)低(di),同時進行計數(shu),直(zhi)到產(chan)生規定的(de)SCL 低(di)電平時間(>4.7ns)。產(chan)生規定的(de) SCL 低(di)電平時間後,如果失去(qu)仲裁(cai),那麼(me)完成一個字節的(de)傳輸之後狀態機(ji)回到IDLE 狀態,否(fu)則狀態機(ji)進入SCL_HI_EDGE 狀態。

在 SCL_HI_EDGE 狀態中,狀態機(ji)釋放SCL 線,希望產(chan)生SCL 上升(sheng)沿,但是SCL 線可能被(bei)其他(ta)Master 置低(di),因此狀態機(ji)並不直(zhi)接轉移pin)CL_HI 狀態,而是等待(dai)SCL 信(xin)號變高(gao)之後才進入SCL_HI 狀態。

進入 SCL_HI 狀態後,系di)呈敝蛹剖shu)器進行計數(shu),以產(chan)生I2C規範要求的(de)SCL高(gao)電平時間(>4.0ns),如果檢測到重(zhong)復起始ji)跫huo)停止條件,狀態機(ji)將(jiang)在1/2SCL 高(gao)電平時間之後轉移pin)START狀態重(zhong)新開始,或(huo)轉移pin)IDLE狀態,否(fu)則產(chan)生要求的(de) SCL高(gao)電平時間後狀態機(ji)進入 SCL_LOW_EDGE狀態,繼(ji)續(xu)產(chan)生下(xia)一個 SCL脈沖。

接下(xia)來是狀態機(ji)的(de)驅動(dong)visual_0_scl_state <=next_scl_state;接下(xia)來是visual_0_sda_in這類信(xin)號,這個處理,visual_0_scl_in並不是由(you)scl扇出,僅僅是對(dui)這個信(xin)號的(de)一個采樣。也是上面我們(men)判斷scl是否(fu)被(bei)別人(ren)拉高(gao)的(de)依據。

後面是start和stop信(xin)號產(chan)生和檢測的(de)一個信(xin)號線的(de)處理,也包(bao)括(kuo)主從機(ji)的(de)。在下(xia)來就是主狀態機(ji)了︰

 

復位後,狀態機(ji)在 IDLE 狀態,當(dang)檢測到 START 信(xin)號時,轉移pin)EADER 狀態。START信(xin)號由(you) I2C 總線上的(de)起始位觸發,觸發這個起始位的(de) Master 可以是 I2C 總線控制器本身或(huo)其他(ta)的(de) I2C 總線主機(ji)。

在 HEADER 狀態,如果 I2C 總線控制器處于 Master 模式(shi),它會把(ba) MBDR 中的(de)數(shu)據作為(wei)HEADER 發送到 I2C 總線上,以尋址特定的(de) Slave。不管 I2C 總線控制器處于 Master 還是Slave模式(shi),在HEADER 狀態時,I2C 總線控制器都會接收總線上的(de)數(shu)據,保存(cun)到 I2C Header Shift Register 中,收到8 個比特後,狀態機(ji)轉移至 ACK_HEADER 狀態。

在 ACK_HEADER 狀態,如果 I2C 總線控制器處于 Master 模式(shi),它會采樣 SDA 線,以判 斷 所 尋 址 的(de)Slave 是 否(fu) 響(xiang) 應 。 如 果 沒 有 響(xiang) 應 , 狀 態 機(ji) 轉 移 到STOP 狀 態 , 通 知SCL/START/STOPGenerator 產(chan)生STOP 信(xin)號,中止傳輸。如果 Slave 產(chan)生了響(xiang)應比特,狀態機(ji)根據 Header 的(de)最低(di)位判斷發起的(de)是發送操作還是接收操作,然(ran)後轉移pin)RCV_DATA 狀態或(huo) XMIT_DATA 狀態。如果I2C 控制器處于Slave 模式(shi),電路會不斷比較(jiao) Header Shift Register 的(de)內容(rong)和 I2C 總線控制器地址寄存(cun)器 MADR 的(de)內容(rong)是否(fu)相(xiang)等,如果相(xiang)等,說明(ming)本I2C總線控制器被(bei)其他(ta) Master 尋址,于是 I2C 總線控制器立即(ji)轉換到 Slave 模式(shi),並把(ba)狀態寄存(cun)器 MBSR 的(de) MAAS 比特置 1,指(zhi)示 I2C 總線控制器被(bei)其他(ta) Master 尋址。同時MBSR 的(de)SRW 比特記錄Header 的(de)最低(di)位,以便µC 判斷Master 請求的(de)是讀(du)還是寫操作。

在 RCV_DATA 狀態, I2C 總線控制器處于接收狀態(即(ji)主機(ji)接收狀態或(huo)從機(ji)接收狀態),狀態機(ji)讀(du)入 I2C 總線上的(de)數(shu)據並保存(cun)到移位寄存(cun)器中,讀(du)完 8 比特的(de)數(shu)據後進入ACK_DATA 狀態,發出響(xiang)應比特。響(xiang)應比特的(de)取值根據 I2C 總線控制器是 Master 還是 Slave有所不同,當(dang)I2C 總線控制器是Slave 時,響(xiang)應比特應為(wei) 0,表示正常接收;當(dang) I2C 總線控制器是Master 時,如果已經收到了足夠(gou)的(de)數(shu)據,響(xiang)應比特要設(she)置為(wei) 1,通知 Slave 停止發送,否(fu)則響(xiang)應比特應為(wei) 0,通知Slave 繼(ji)續(xu)發送。響(xiang)應比特的(de)值由(you) MBCR 的(de) TXAK 位決(jue)定, µC 可以在適當(dang)的(de)時候(hou)寫入。檢測到 I2C 總線上的(de)停止位時,狀態機(ji)轉移pin)STOP 狀態。

在 XMIT_DATA 狀態, I2C 總線控制器處于發送狀態(即(ji)主機(ji)發送,或(huo)從機(ji)發送狀態),狀態機(ji)把(ba)數(shu)據寄存(cun)器 MBDR 的(de)數(shu)據移位輸出到 SDA 線上,發送 8 比特後進入GET_ACK_DATA 狀態,收到jiao)xiang)應比特後,狀態機(ji)回到 XMIT_DATA 狀態,繼(ji)續(xu)發送下(xia)一個字節。如果沒有收到jiao)xiang)應比特,說明(ming)發送結束或(huo)出錯,狀態機(ji)轉到 STOP 狀態。

在 STOP 狀態,如果處于 Master 模式(shi),主狀態機(ji)通知 SCL/START/STOP Generator 產(chan)生停止位。下(xia)一個時鐘沿到來時,狀態機(ji)自(zi)動(dong)轉移pin)IDLE 狀態。

後面就是start stop檢測模塊,還有一些(xie)寄存(cun)器信(xin)號線的(de)產(chan)生。

可以看(kan)到這種設(she)計思路是分層(ceng)次模塊的(de)。uc那一端是根據數(shu)據交互的(de)流(liu)程,讀(du)寫控制寄存(cun)器,然(ran)後寄存(cun)器的(de)信(xin)號輸出給底(di)層(ceng)去(qu)實現(xian)各(ge)種控制。而底(di)層(ceng)也是分區(qu)塊,2個狀態機(ji),一個實現(xian)scl信(xin)號的(de)置高(gao)和置低(di),期間有仲裁(cai)檢測,主從機(ji)的(de)切換,結束起始位的(de)判斷等等,另一個實現(xian)iic與外部設(she)備通信(xin)時的(de)交互流(liu)程,如先尋址,在等待(dai)確(que)認,再續(xu)寫之類的(de)。中間有很多信(xin)號線去(qu)同步控制別的(de)always塊或(huo)者被(bei)別的(de)信(xin)號線控制。還有起始,結束檢測的(de)always塊,針對(dui)各(ge)個寄存(cun)器的(de)賦chi)檔de)專門的(de)always塊等等。

2.3 OR1200的(de)iic控制器

這是一個帶wishbone總線結構的(de)iic接口,所以yuan)湊斬?ceng)框(kuang)圖來畫(hua)輸入輸出信(xin)號,可以發現(xian)輸入一段全是wb接口的(de)信(xin)號線,輸出就是2根scl和sda,但是注意的(de)是這里並不是scl與sda︰

 

// I2C signals// i2c clock lineinput scl_pad_i; // SCL-line input//?不是inout結構?output scl_pad_o; // SCL-line output (always 1'b0)output scl_padoen_o; // SCL-line output enable (active low)// i2c data lineinput sda_pad_i; // SDA-line inputoutput sda_pad_o; // SDA-line output (always 1'b0)output sda_padoen_o; // SDA-line output enable (active low)
實際上我們(men)需要在這個三(san)態門添(tian)加(jia)更高(gao)的(de)設(she)計層(ceng)次︰

 

 

assign scl = scl_padoen_o ? 1'bz : scl_pad_o;assign sda = sda_padoen_o ? 1'bz : sda_pad_o;assign scl_pad_i = scl;assign sda_pad_i = sda;

 

定義了不同的(de)寄存(cun)器,包(bao)括(kuo)時鐘分頻(pin)的(de)寄存(cun)器,支(zhi)持(chi)異步復位。wb_adr_i信(xin)號決(jue)定具體對(dui)yue)囊桓黽拇cun)器操作。然(ran)後是寄存(cun)器的(de)值的(de)修(xiu)改。這個top模塊中沒有定義狀態機(ji),是由(you)于wb接口的(de)原因,不想(xiang)2.2的(de)實現(xian)方式(shi)是有這麼(me)一個流(liu)程的(de)。而這里因為(wei)是有統一的(de)wb接口的(de)原因,所以簡單(dan)的(de)多。另外wb接口的(de)很多信(xin)號線可以根據自(zi)己的(de)需求去(qu)修(xiu)改其功能含(han)義的(de)。

但是這個僅僅是主機(ji),並沒有實現(xian)完整的(de)iic接口,沒有仲裁(cai)等。

top中例化了i2c_master_byte_ctrl,i2c_master_byte_ctrl中例化了更低(di)層(ceng)次的(de)i2c_master_bit_ctrl。i2c_master_byte_ctrl中也是一個主狀態機(ji)維持(chi)著start、發、收、ack等交互流(liu)程,i2c_master_bit_ctrl將(jiang)start、stop、rd、wr都分成了好幾段,維持(chi)著一個龐大的(de)狀態機(ji) ,里面是對(dui)sda,scl信(xin)號線的(de)高(gao)低(di)的(de)控制。也是模塊化的(de)比較(jiao)清晰,就不仔細(xi)講了

說幾點感受吧︰

1、對(dui)于這種zhi)冉jiao)復雜的(de)設(she)計,實際上模塊的(de)劃分非qian)Vzhong)要,理清楚各(ge)個模塊間的(de)互聯,每根信(xin)號線的(de)含(han)義。比如這里uc那一端的(de)分段式(shi)狀態機(ji),與寄存(cun)器的(de)設(she)計pin)取/p>

2、該(gai)例程比較(jiao)復雜,非qian)7痹櫻 瀉芏嗟de)信(xin)號線。各(ge)信(xin)號線之間的(de)連接比較(jiao)繁雜,特別是還有仲裁(cai)這一塊,不好理解。所有對(dui)于這種zhi)叢擁de)設(she)計,沒有詳(xiang)細(xi)的(de)注釋很難理解。另外針對(dui)iic的(de)協議,大家ye)de)理解和設(she)計思路不一樣,可以有很多種實現(xian)方式(shi),包(bao)括(kuo)一些(xie)個人(ren)的(de)寫法習慣,如對(dui)于狀態,對(dui)中間信(xin)號的(de)定義與處理等,都jia)脅鉅/p>

3、很多的(de)小技巧,對(dui)于信(xin)號的(de)命名,打節拍的(de)處理等等

Tag標簽︰串口  控制器  
  • 酷博平台官网

About IT165 - 廣告服務 - 隱私聲明(ming) - 版權申明(ming) - 免責條款(kuan) - 網站地圖 - 網友投稿 - 聯系方式(shi)
本站內容(rong)來自(zi)于互聯網,僅供(gong)用于網絡技術(shu)學習,學習中請遵循相(xiang)關法律法規
酷博平台官网 | 下一页