1)實(shí)驗(yàn)平臺(tái):正點(diǎn)原子MPSoC開(kāi)發(fā)板
2)平臺(tái)購(gòu)買(mǎi)地址:https://detail.tmall.com/item.htm?id=692450874670
3)全套實(shí)驗(yàn)源碼+手冊(cè)+視頻下載地址: http://www.openedv.com/thread-340252-1-1.html
第二十八章 以太網(wǎng)ARP測(cè)試實(shí)驗(yàn)
在以太網(wǎng)中,一個(gè)主機(jī)和另一個(gè)主機(jī)進(jìn)行通信,必須要知道目的主機(jī)的MAC地址(物理地址),而目的MAC地址的獲取由ARP協(xié)議完成。本章我們來(lái)學(xué)習(xí)如何通過(guò)DFZU2EG/4EV MPSoC開(kāi)發(fā)板實(shí)現(xiàn)ARP協(xié)議的功能。
本章分為以下幾個(gè)章節(jié):
222828.1簡(jiǎn)介
28.2實(shí)驗(yàn)任務(wù)
28.3硬件設(shè)計(jì)
28.4程序設(shè)計(jì)
28.5下載驗(yàn)證
28.1簡(jiǎn)介
ARP概述
ARP(Address Resolution Protocol),即地址解析協(xié)議,是根據(jù)IP地址(邏輯地址)獲取MAC地址的一種TCP/IP協(xié)議。在以太網(wǎng)通信中,數(shù)據(jù)是以“幀”的格式進(jìn)行傳輸?shù)?,幀格式里面包含目的主機(jī)的MAC地址。源主機(jī)的應(yīng)用程序知道目的主機(jī)的IP地址,卻不知道目的主機(jī)的MAC地址。而目的主機(jī)的MAC地址直接被網(wǎng)卡接收和解析,當(dāng)解析到目的MAC地址非本地MAC地址時(shí),則直接丟棄該包數(shù)據(jù),因此在通信前需要先獲得目的的MAC地址,而ARP協(xié)議正是實(shí)現(xiàn)了此功能。
ARP協(xié)議的基本功能是通過(guò)目的設(shè)備的IP地址,查詢(xún)目的設(shè)備的MAC地址,以保證通信的順利進(jìn)行。MAC地址在網(wǎng)絡(luò)中表示網(wǎng)卡的ID,每個(gè)網(wǎng)卡都需要并有且僅有一個(gè)MAC地址。在獲取到目的MAC地址之后,將目的MAC地址更新至ARP緩存表中,稱(chēng)為ARP映射,下次通信時(shí),可以直接從ARP緩存表中獲取,而不用重新通過(guò)ARP獲取MAC地址。但一般ARP緩存表會(huì)有過(guò)期時(shí)間,過(guò)期后需要重新通過(guò)ARP協(xié)議進(jìn)行獲取。
ARP映射是指將IP地址和MAC地址映射起來(lái),分為靜態(tài)映射和動(dòng)態(tài)映射。
靜態(tài)映射指手動(dòng)創(chuàng)建一張ARP表,把IP地址和MAC地址關(guān)聯(lián)起來(lái)。手動(dòng)綁定之后,源主機(jī)在通信之前,就可以直接從ARP表中直接找到IP地址對(duì)應(yīng)的MAC地址,但這樣做有一定的局限性,因?yàn)镸AC地址可能會(huì)變化,比如:
1)機(jī)器可能更換NIC(網(wǎng)絡(luò)適配器),結(jié)果變成一個(gè)新的物理地址;
2)在某些局域網(wǎng)中,每當(dāng)計(jì)算機(jī)加電時(shí),他的物理地址都要改變一次。
3)移動(dòng)電腦可以從一個(gè)物理網(wǎng)絡(luò)轉(zhuǎn)移到另一個(gè)物理網(wǎng)絡(luò),這樣會(huì)改變物理地址。
要避免這些問(wèn)題出現(xiàn),必須定期維護(hù)更新ARP表,此類(lèi)比較麻煩而且會(huì)影響網(wǎng)絡(luò)性能。
動(dòng)態(tài)映射指使用協(xié)議來(lái)獲取相對(duì)應(yīng)的物理地址,之所以用動(dòng)態(tài)這個(gè)詞是因?yàn)檫@個(gè)過(guò)程是自動(dòng)完成的,一般應(yīng)用程序的用戶(hù)或系統(tǒng)管理員不必關(guān)心。已經(jīng)設(shè)計(jì)出用于實(shí)現(xiàn)動(dòng)態(tài)映射協(xié)議的有ARP和RARP(逆地址解析協(xié)議)兩種,如下圖所示。
圖 28.1.1 地址解析協(xié)議:RAP和RRAP
ARP把IP地址映射為物理地址,RARP把物理地址映射為IP地址。RRAP是被那些沒(méi)有磁盤(pán)驅(qū)動(dòng)器的系統(tǒng)使用(一般是無(wú)盤(pán)工作站或 X終端),此類(lèi)應(yīng)用較少,本章不做討論。
ARP協(xié)議分為ARP請(qǐng)求和ARP應(yīng)答,源主機(jī)發(fā)起查詢(xún)目的MAC地址的報(bào)文稱(chēng)為ARP請(qǐng)求,目的主機(jī)響應(yīng)源主機(jī)并發(fā)送包含本地MAC地址的報(bào)文稱(chēng)為ARP應(yīng)答。
當(dāng)主機(jī)需要找出這個(gè)網(wǎng)絡(luò)中的另一個(gè)主機(jī)的物理地址時(shí),它就可以發(fā)送一個(gè)ARP請(qǐng)求報(bào)文,這個(gè)報(bào)文包含了發(fā)送方的MAC地址和IP地址以及接收方的IP地址。因?yàn)榘l(fā)送方不知道接收方的物理地址,所以這個(gè)查詢(xún)分組會(huì)在網(wǎng)絡(luò)層中進(jìn)行廣播,即ARP請(qǐng)求時(shí)發(fā)送的接收方物理地址為廣播地址,用48’hff_ff_ff_ff_ff_ff表示。ARP請(qǐng)求的示意圖如下圖所示:
圖 28.1.2 ARP請(qǐng)求示意圖
上圖中的主機(jī)A發(fā)起ARP請(qǐng)求,由于發(fā)送的目的MAC地址為廣播地址,所以此時(shí)局域網(wǎng)中的所有主機(jī)都會(huì)進(jìn)行接收并處理這個(gè)ARP請(qǐng)求報(bào)文,然后進(jìn)行驗(yàn)證,查看接收方的IP地址是不是自己的地址。是則返回ARP應(yīng)答報(bào)文,不是則不響應(yīng)。
只有驗(yàn)證成功的主機(jī)才會(huì)返回一個(gè)ARP應(yīng)答報(bào)文,這個(gè)應(yīng)答報(bào)文包含接收方的IP地址和物理地址。ARP應(yīng)答的示意圖如下圖所示:
圖 28.1.3 ARP應(yīng)答示意圖
主機(jī)B利用收到的ARP請(qǐng)求報(bào)文中的請(qǐng)求方物理地址,以單播的方式直接發(fā)送給主機(jī)A,主機(jī)A將收到的ARP應(yīng)答報(bào)文中的目的MAC地址解析出來(lái),將目的MAC地址和目的IP地址更新至ARP緩存表中。當(dāng)再次和主機(jī)A通信時(shí),可以直接從ARP緩存表中獲取,而不用重新發(fā)起ARP請(qǐng)求報(bào)文。需要說(shuō)明的是,ARP緩存表中的表項(xiàng)有過(guò)期時(shí)間(一般為20分鐘),過(guò)期之后,需要重新發(fā)起ARP請(qǐng)求以獲取目的MAC地址。
ARP協(xié)議通過(guò)以太網(wǎng)進(jìn)行傳輸,那么必須也要按照以太網(wǎng)所規(guī)定的格式進(jìn)行傳輸,我們先來(lái)介紹下以太網(wǎng)的幀格式,隨后再來(lái)向大家詳細(xì)介紹ARP協(xié)議的具體格式。
以太網(wǎng)是目前應(yīng)用最廣泛的局域網(wǎng)通訊方式,同時(shí)也是一種協(xié)議。以太網(wǎng)協(xié)議定義了一系列軟件和硬件標(biāo)準(zhǔn),從而將不同的計(jì)算機(jī)設(shè)備連接在一起。我們知道串口通信單次只傳輸一個(gè)字節(jié),而以太網(wǎng)通信是以數(shù)據(jù)包的形式傳輸,其單包數(shù)據(jù)量達(dá)到幾十,甚至成百上千個(gè)字節(jié)。下圖為以太網(wǎng)通過(guò)ARP傳輸單包數(shù)據(jù)的格式,從圖中可以看出,以太網(wǎng)的數(shù)據(jù)包就是對(duì)協(xié)議的封裝來(lái)實(shí)現(xiàn)數(shù)據(jù)的傳輸,即ARP數(shù)據(jù)位于以太網(wǎng)幀格式的數(shù)據(jù)段。這里只是讓大家了解下以太網(wǎng)數(shù)據(jù)包的格式,后面會(huì)逐個(gè)展開(kāi)來(lái)講。
圖 28.1.4 以太網(wǎng)ARP數(shù)據(jù)包格式
以太網(wǎng)MAC幀格式
以太網(wǎng)技術(shù)的正式標(biāo)準(zhǔn)是IEEE 802.3,它規(guī)定了以太網(wǎng)傳輸數(shù)據(jù)的幀結(jié)構(gòu),我們可以把以太網(wǎng)MAC層理解成高速公路,我們必須遵循它的規(guī)則才能在上面通行,以太網(wǎng)MAC層幀格式如圖 28.1.5所示。
圖 28.1.5 以太網(wǎng)幀格式
以太網(wǎng)傳輸數(shù)據(jù)時(shí)按照上面的順序從頭到尾依次被發(fā)送和接收,我們下面進(jìn)一步解釋各個(gè)區(qū)域。
前導(dǎo)碼(Preamble):為了實(shí)現(xiàn)底層數(shù)據(jù)的正確闡述,物理層使用7個(gè)字節(jié)同步碼(0和1交替(55-55-55-55-55-55-55))實(shí)現(xiàn)數(shù)據(jù)的同步。
幀起始界定符(SFD,Start Frame Delimiter):使用1個(gè)字節(jié)的SFD(固定值為0xd5)來(lái)表示一幀的開(kāi)始,即后面緊跟著傳輸?shù)木褪且蕴W(wǎng)的幀頭。
目的MAC地址:即接收端物理MAC地址,占用6個(gè)字節(jié)。MAC地址從應(yīng)用上可分為單播地址、組播地址和廣播地址。單播地址:第一個(gè)字節(jié)的最低位為0,比如00-00-00-11-11-11,一般用于標(biāo)志唯一的設(shè)備;組播地址:第一個(gè)字節(jié)的最低位為1,比如01-00-00-11-11-11,一般用于標(biāo)志同屬一組的多個(gè)設(shè)備;廣播地址:所有48bit全為1,即FF-FF-FF-FF-FF-FF,它用于標(biāo)志同一網(wǎng)段中的所有設(shè)備。
源MAC地址:即發(fā)送端物理MAC地址,占用6個(gè)字節(jié)。
長(zhǎng)度/類(lèi)型:上圖中的長(zhǎng)度/類(lèi)型具有兩個(gè)意義,當(dāng)這兩個(gè)字節(jié)的值小于1536(十六進(jìn)制為 0x0600)時(shí),代表該以太網(wǎng)中數(shù)據(jù)段的長(zhǎng)度;如果這兩個(gè)字節(jié)的值大于1536,則表示該以太網(wǎng)中的數(shù)據(jù)屬于哪個(gè)上層協(xié)議,例如0x0800代表IP協(xié)議(網(wǎng)際協(xié)議)、0x0806代表ARP協(xié)議(地址解析協(xié)議)等。
數(shù)據(jù):以太網(wǎng)中的數(shù)據(jù)段長(zhǎng)度最小46個(gè)字節(jié),最大1500個(gè)字節(jié)。最大值1500稱(chēng)為以太網(wǎng)的最大傳輸單元(MTU,Maximum Transmission Unit),之所以限制最大傳輸單元是因?yàn)樵诙鄠€(gè)計(jì)算機(jī)的數(shù)據(jù)幀排隊(duì)等待傳輸時(shí),如果某個(gè)數(shù)據(jù)幀太大的話(huà),那么其它數(shù)據(jù)幀等待的時(shí)間就會(huì)加長(zhǎng),導(dǎo)致體驗(yàn)變差,這就像一個(gè)十字路口的紅綠燈,你可以讓綠燈持續(xù)亮一小時(shí),但是等紅燈的人一定不愿意的。另外還要考慮網(wǎng)絡(luò)I/O控制器緩存區(qū)資源以及網(wǎng)絡(luò)最大的承載能力等因素,因此最大傳輸單元是由各種綜合因素決定的。為了避免增加額外的配置,通常以太網(wǎng)的有效數(shù)據(jù)字段小于1500個(gè)字節(jié)。
幀檢驗(yàn)序列(FCS,F(xiàn)rame Check Sequence):為了確保數(shù)據(jù)的正確傳輸,在數(shù)據(jù)的尾部加入了4個(gè)字節(jié)的循環(huán)冗余校驗(yàn)碼(CRC校驗(yàn))來(lái)檢測(cè)數(shù)據(jù)是否傳輸錯(cuò)誤。CRC數(shù)據(jù)校驗(yàn)從以太網(wǎng)幀頭開(kāi)始即不包含前導(dǎo)碼和幀起始界定符。通用的CRC標(biāo)準(zhǔn)有CRC-8、CRC-16、CRC-32、CRC-CCIT,其中在網(wǎng)絡(luò)通信系統(tǒng)中應(yīng)用最廣泛的是CRC-32標(biāo)準(zhǔn)。
在這里還有一個(gè)要注意的地方就是以太網(wǎng)相鄰兩幀之間的時(shí)間間隔,即幀間隙(IFG,Interpacket Gap)。幀間隙的時(shí)間就是網(wǎng)絡(luò)設(shè)備和組件在接收一幀之后,需要短暫的時(shí)間來(lái)恢復(fù)并為接收下一幀做準(zhǔn)備的時(shí)間,IFG的最小值是96 bit time,即在媒介中發(fā)送96位原始數(shù)據(jù)所需要的時(shí)間,在不同媒介中IFG的最小值是不一樣的。不管10M/100M/1000M的以太網(wǎng),兩幀之間最少要有96bit time,IFG的最少間隔時(shí)間計(jì)算方法如下:
10Mbit/s最小時(shí)間為:96100ns = 9600ns;
100Mbit/s最小時(shí)間為:9610ns = 960ns;
1000Mbit/s最小時(shí)間為:96*1ns = 96ns。
接下來(lái)我們介紹ARP協(xié)議以及它和以太網(wǎng)MAC層的關(guān)系。在介紹ARP協(xié)議之前,我們先了解下TCP(傳輸控制協(xié)議)/IP(網(wǎng)際協(xié)議)協(xié)議簇。TCP/IP是網(wǎng)絡(luò)使用中最基本的通信協(xié)議,雖然從名字看上去TCP/IP包括兩個(gè)協(xié)議,TCP和IP,但TCP/IP實(shí)際上是一組協(xié)議,它包括上百個(gè)各種功能的協(xié)議,如:TCP、IP、ARP、UDP等。而TCP協(xié)議和IP協(xié)議是保證數(shù)據(jù)完整傳輸?shù)膬蓚€(gè)重要的協(xié)議,因此TCP/IP協(xié)議用來(lái)表示Internet協(xié)議簇。
TCP/IP協(xié)議不僅可以運(yùn)行在以太網(wǎng)上,也可以運(yùn)行在FDDI(光纖分布式數(shù)據(jù)接口)和WLAN(無(wú)線(xiàn)局域網(wǎng))上。反過(guò)來(lái),以太網(wǎng)的高層協(xié)議不僅可以是TCP/IP協(xié)議,也可以是IPX協(xié)議(互聯(lián)網(wǎng)分組交換協(xié)議)等,只不過(guò)以太網(wǎng)+TCP/IP成為IT行業(yè)中應(yīng)用最普遍的技術(shù)。下面我們來(lái)熟悉下ARP協(xié)議。
ARP協(xié)議
ARP協(xié)議屬于TCP/IP協(xié)議簇的一種,從前面介紹的圖 28.1.4可以看出,ARP協(xié)議位于以太網(wǎng)MAC幀格式的數(shù)據(jù)段,ARP數(shù)據(jù)包格式如下圖所示。
圖 28.1.6 ARP數(shù)據(jù)包格式
硬件類(lèi)型(Hardware type):硬件地址的類(lèi)型,1表示以太網(wǎng)地址。
協(xié)議類(lèi)型(Protocol type):要映射的協(xié)議地址類(lèi)型,ARP協(xié)議的上層協(xié)議為IP協(xié)議,因此該協(xié)議類(lèi)型為IP協(xié)議,其值為0x0800。
硬件地址長(zhǎng)度(Hardware size):硬件地址(MAC地址)的長(zhǎng)度,以字節(jié)為單位。對(duì)于以太網(wǎng)上IP地址的ARP請(qǐng)求或者應(yīng)答來(lái)說(shuō),該值為6。
協(xié)議地址長(zhǎng)度(Protocol size):IP地址的長(zhǎng)度,以字節(jié)為單位。對(duì)于以太網(wǎng)上IP地址的ARP請(qǐng)求或者應(yīng)答來(lái)說(shuō),該值為4。
OP(Opcode):操作碼,用于表示該數(shù)據(jù)包為ARP請(qǐng)求或者ARP應(yīng)答。1表示ARP請(qǐng)求,2表示ARP應(yīng)答。
源MAC地址:發(fā)送端的硬件地址。
源IP地址:發(fā)送端的協(xié)議(IP)地址,如192.168.1.102。
目的MAC地址:接收端的硬件地址,在ARP請(qǐng)求時(shí)由于不知道接收端MAC地址,因此該字段為廣播地址,即48’hff_ff_ff_ff_ff_ff。
目的IP地址:接收端的協(xié)議(IP)地址,如192.168.1.10。
以太網(wǎng)的幀格式、ARP數(shù)據(jù)格式到這里已經(jīng)全部介紹完了,關(guān)于通過(guò)以太網(wǎng)傳輸ARP報(bào)文的格式如下圖所示:
圖 28.1.7 以太網(wǎng)ARP數(shù)據(jù)包格式
由上圖可知,28字節(jié)的ARP數(shù)據(jù)位于以太網(wǎng)幀格式的數(shù)據(jù)段。由于以太網(wǎng)數(shù)據(jù)段最少為46個(gè)字節(jié),而ARP數(shù)據(jù)包總長(zhǎng)度為28個(gè)字節(jié),因此在ARP數(shù)據(jù)段后面需要填充18個(gè)字節(jié)的數(shù)據(jù),以滿(mǎn)足以太網(wǎng)傳輸格式的要求。這個(gè)填充的過(guò)程稱(chēng)為Padding(填充),填充的數(shù)據(jù)可以為任意值,但一般為0。
RGMII接口介紹
以太網(wǎng)的通信離不開(kāi)物理層PHY芯片的支持,以太網(wǎng)MAC和PHY之間有一個(gè)接口,常用的接口有MII、RMII、GMII、RGMII等。
MII(Medium Independent Interface,媒體獨(dú)立接口):MII支持10Mbps和100Mbps的操作,數(shù)據(jù)位寬為4位,在100Mbps傳輸速率下,時(shí)鐘頻率為25Mhz。
RMII(Reduced MII):RMII是MII的簡(jiǎn)化版,數(shù)據(jù)位寬為2位,在100Mbps傳輸速率下,時(shí)鐘頻率為50Mhz。
GMII(Gigabit MII):GMII接口向下兼容MII接口,支持10Mbps、100Mbps和1000Mbps的操作,數(shù)據(jù)位寬為8位,在1000Mbps傳輸速率下,時(shí)鐘頻率為125Mhz。
RGMII(Reduced GMII):RGMII是GMII的簡(jiǎn)化版,數(shù)據(jù)位寬為4位,在1000Mbps傳輸速率下,時(shí)鐘頻率為125Mhz,在時(shí)鐘的上下沿同時(shí)采樣數(shù)據(jù)。在100Mbps和10Mbps通信速率下,為單個(gè)時(shí)鐘沿采樣。
在千兆以太網(wǎng)中,常用的接口為RGMII和GMII接口。RGMII接口的優(yōu)勢(shì)是同時(shí)適用于10M/100M/1000Mbps通信速率,同時(shí)占用的引腳數(shù)較少。但RGMII接口也有其缺點(diǎn),就是在PCB布線(xiàn)時(shí)需要盡可能對(duì)時(shí)鐘、控制和數(shù)據(jù)線(xiàn)進(jìn)行等長(zhǎng)處理,且時(shí)序約束相對(duì)也更為嚴(yán)格。
為了節(jié)省引腳,DFZU2EG/4EV MPSoC開(kāi)發(fā)板板載的PHY芯片采用的接口為RGMII接口,下圖是MAC側(cè)與PHY側(cè)接口的連接。
圖 28.1.8 MAC側(cè)與PHY側(cè)接口連接
ETH_RXC:接收數(shù)據(jù)參考時(shí)鐘,1000Mbps速率下,時(shí)鐘頻率為125MHz,時(shí)鐘為上下沿同時(shí)采樣;100Mbps速率下,時(shí)鐘頻率為25MHz;10Mbps速率下,時(shí)鐘頻率為2.5MHz,ETH_RXC由PHY側(cè)提供。
ETH_RXCTL(ETH_RX_DV):接收數(shù)據(jù)控制信號(hào)。
ETH_RXD:四位并行的接收數(shù)據(jù)線(xiàn)。
ETH_TXC:發(fā)送參考時(shí)鐘,1000Mbps速率下,時(shí)鐘頻率為125MHz,時(shí)鐘為上下沿同時(shí)采樣;100Mbps速率下,時(shí)鐘頻率為25MHz;10Mbps速率下,時(shí)鐘頻率為2.5MHz,ETH_TXC由MAC側(cè)提供。
ETH_TXCTL(ETH_TXEN):發(fā)送數(shù)據(jù)控制信號(hào)。
ETH_TXD:四位并行的發(fā)送數(shù)據(jù)線(xiàn)。
ETH_RESET_N:芯片復(fù)位信號(hào),低電平有效。
ETH_MDC:數(shù)據(jù)管理時(shí)鐘(Management Data Clock),該引腳對(duì)ETH_MDIO信號(hào)提供了一個(gè)同步的時(shí)鐘。
ETH_MDIO:數(shù)據(jù)輸入/輸出管理(Management Data Input/Output),該引腳提供了一個(gè)雙向信號(hào)用于傳遞管理信息。
其中ETH_RXC、ETH_RXCTL和ETH_RXD為MAC接收側(cè)引腳;ETH_TXC、ETH_TXCTL和ETH_TXD為MAC發(fā)送側(cè)引腳;ETH_MDC和ETH_MDIO為MDIO接口引腳,用于配置PHY芯片內(nèi)部寄存器;ETH_RST_N為PHY芯片硬件復(fù)位信號(hào)。由于PHY芯片的內(nèi)部寄存器在默認(rèn)配置下也可以正常工作,因此本次實(shí)驗(yàn)沒(méi)有對(duì)MDIO接口進(jìn)行讀寫(xiě)操作,只用到了以太網(wǎng)的RGMII接口信號(hào)和復(fù)位信號(hào)。
RGMII使用4bit數(shù)據(jù)接口,在1000Mbps通信速率下,ETH_TXC和ETH_RXC的時(shí)鐘頻率為125Mhz,采用上下沿DDR(Double Data Rate)的方式在一個(gè)時(shí)鐘周期內(nèi)傳輸8位數(shù)據(jù)信號(hào),即上升沿發(fā)送/接收低4位數(shù)據(jù),下降沿發(fā)送/接收高4位數(shù)據(jù)。ETH_TXCTL和ETH_RXCTL控制信號(hào)同樣采用DDR的方式在一個(gè)時(shí)鐘周期內(nèi)傳輸兩位控制信號(hào),即上升沿發(fā)送/接收數(shù)據(jù)使能(TX_EN/RX_DV)信號(hào),下降沿發(fā)送/接收使能信號(hào)與錯(cuò)誤信號(hào)的異或值(TX_ERR xor TX_EN、RX_ERR xor RX_DV)。當(dāng)RX_DV為高電平(表示數(shù)據(jù)有效),RX_ERR為低電平(表示數(shù)據(jù)無(wú)錯(cuò)誤),則異或的結(jié)果值為高電平,因此只有當(dāng)ETH_RXCTL和ETH_TXCTL信號(hào)的上下沿同時(shí)為高電平時(shí),發(fā)送和接收的數(shù)據(jù)有效且正確。
當(dāng)RGMII工作在100Mbps時(shí),ETH_TXC和ETH_RXC的時(shí)鐘頻率為25Mhz,采用上升沿SDR的方式在一個(gè)周期內(nèi)傳輸4位數(shù)據(jù)。不過(guò)此時(shí)ETH_TXCTL和ETH_RXCTL控制信號(hào)仍采用上下沿DDR的傳輸方式。
當(dāng)RGMII工作在10Mbps時(shí),ETH_TXC和ETH_RXC的時(shí)鐘頻率為2.5Mhz,采用上升沿SDR的方式在一個(gè)周期內(nèi)傳輸4位數(shù)據(jù)。ETH_TXCTL和ETH_RXCTL控制信號(hào)也采用SDR的傳輸方式。
RGMII接口時(shí)序
PHY芯片的RGMII接口時(shí)序,其時(shí)鐘、控制信號(hào)和數(shù)據(jù)的對(duì)齊方式,一般由MDIO接口或者硬件上的特殊引腳進(jìn)行配置。
RGMII接收端口時(shí)鐘、控制信號(hào)和數(shù)據(jù)對(duì)齊的時(shí)序圖如下:
圖 28.1.9 RGMII接收端口信號(hào)對(duì)齊
由上圖可知,RXC的上下邊沿與RXD和RX_CTL信號(hào)對(duì)齊,相位相同。
RGMII接收端口時(shí)鐘和控制/數(shù)據(jù)信號(hào)增加延時(shí)的時(shí)序圖如下:
圖 28.1.10 RGMII接收信號(hào)增加時(shí)鐘延時(shí)
由上圖可知,RXC的上下邊沿與RXD和RX_CTL信號(hào)的中間位置對(duì)齊,RXC的時(shí)鐘周期為8ns,單個(gè)高電平或者低電平為4ns,RXC相對(duì)于RXD和RX_CTL延時(shí)約2ns。
YT8521 RGMII接收端口的信號(hào)對(duì)齊模式由硬件上的特殊引腳外接上下拉電阻進(jìn)行配置,如圖 28.1.11所示。從下圖中可以看出,當(dāng)管腳RXDLY(RXD0)接上拉電阻時(shí),表示RXC時(shí)鐘相對(duì)于RXD信號(hào),會(huì)增加約2ns的延時(shí)。而DFZU2EG/4EV MPSoC開(kāi)發(fā)板硬件原理圖中YT8521的管腳RXDLY(RXD0)連接的是上拉電阻,因此RXC和RXD之間會(huì)有約2ns的延時(shí),RGMII接收端口的時(shí)序圖如圖 28.1.10所示。
圖 28.1.11 RGMII接收端口模式配置
圖 28.1.12 YT8521 引腳分配
RGMII發(fā)送端口正常模式時(shí)序圖如下:
圖 28.1.13 RGMII發(fā)送端口正常模式
由上圖可知,RGMII發(fā)送端口正常模式下,需要滿(mǎn)足TXC的上下邊沿與TXD和TX_CTL信號(hào)對(duì)齊,相位相同。YT8521在硬件上面沒(méi)有做TX端的delay模式,可根據(jù)實(shí)際情況,選擇是否在代碼中進(jìn)行延時(shí)(因?yàn)橐话銓?duì)端設(shè)備的接收端會(huì)有延時(shí)處理的功能,因此發(fā)送端也可以不延時(shí)),延時(shí)后的時(shí)序圖如下所示:
圖 28.1.14 RGMII發(fā)送端口延時(shí)模式
由RGMII的接口時(shí)序可知,RGMII發(fā)送端口在TXC時(shí)鐘的上升沿傳輸TXD的低4位和TX_CTL的使能信號(hào);下降沿傳輸TXD的高4位和TX_CTL的錯(cuò)誤信號(hào)(實(shí)際上是使能信號(hào)和錯(cuò)誤信號(hào)的異或值);RGMII接收端口在RXC時(shí)鐘的上升沿傳輸RXD的低4位和RX_CTL的使能信號(hào);下降沿傳輸RXD的高4位和RX_CTL的錯(cuò)誤信號(hào)(實(shí)際上是使能信號(hào)和錯(cuò)誤信號(hào)的異或值)。
Xilinx原語(yǔ)
原語(yǔ)是Xilinx器件底層硬件中的功能模塊,它使用專(zhuān)用的資源來(lái)實(shí)現(xiàn)一系列的功能。相比于IP核,原語(yǔ)的調(diào)用方法更簡(jiǎn)單,但是一般只用于實(shí)現(xiàn)一些簡(jiǎn)單的功能。本章主要用到了BUFG、BUFIO、IDDRE1、ODDRE1、IDELAYE3和IDELAYCTRL。
BUFG:全局緩沖,BUFG的輸出到達(dá)FPGA內(nèi)部的IOB、CLB、塊RAM的時(shí)鐘延遲和抖動(dòng)最小。BUFG原語(yǔ)模板如下:
BUFG BUFG_inst (
.O(O), // 1-bit output: Clock output
.I(I) // 1-bit input: Clock input
);
除了BUFG外,常用的還有BUFR,BUFR是regional時(shí)鐘網(wǎng)絡(luò),它的驅(qū)動(dòng)范圍只能局限在一個(gè)clock region的邏輯。BUFR相比BUFG的最大優(yōu)勢(shì)是偏斜和功耗都比較小。
BUFIO:BUFIO是IO時(shí)鐘網(wǎng)絡(luò),其獨(dú)立于全局時(shí)鐘資源,適合采集源同步數(shù)據(jù)。它只能驅(qū)動(dòng)IO Block里面的邏輯,不能驅(qū)動(dòng)CLB里面的LUT,REG等邏輯。BUFIO原語(yǔ)模板如下:
BUFIO BUFIO_inst (
.O(O), // 1-bit output: Clock output (connect to I/O clock loads).
.I(I) // 1-bit input: Clock input (connect to an IBUF or BUFMR).
);
BUFIO在采集源同步IO數(shù)據(jù)時(shí),提供非常小的延時(shí),因此非常適合采集比如RGMII接收側(cè)的數(shù)據(jù),但是由于其不能驅(qū)動(dòng)FPGA的內(nèi)部邏輯,因此需要BUFIO和BUFG配合使用,以達(dá)到最佳性能。如ETH_RXC的時(shí)鐘經(jīng)過(guò)BUFIO,用來(lái)采集端口數(shù)據(jù);ETH_RXC經(jīng)過(guò)BUFG,用來(lái)作為除端口采集外的其他模塊的操作時(shí)鐘。
IDDRE1:在UltraScale系列設(shè)備的ILOGIC block中有專(zhuān)屬的registers來(lái)實(shí)現(xiàn)input double-data-rate(IDDRE1) registers,將輸入的上下邊沿DDR信號(hào),轉(zhuǎn)換成兩位單邊沿SDR信號(hào)。IDDR的原語(yǔ)結(jié)構(gòu)圖如下圖所示:
圖 28.1.15 IDDRE1原語(yǔ)結(jié)構(gòu)圖
C:輸入的高速時(shí)鐘;
D:輸入的1位DDR數(shù)據(jù);
Q1和Q2:分別是“C”時(shí)鐘上升沿和下降沿同步輸出的SDR數(shù)據(jù);
CB:高速時(shí)鐘C的反轉(zhuǎn);
R:置位/復(fù)位信號(hào),高有效;
IDDRE1原語(yǔ)模板如下:
IDDRE1 #(
.DDR_CLK_EDGE("OPPOSITE_EDGE"),
// IDDRE1 mode (OPPOSITE_EDGE, SAME_EDGE, SAME_EDGE_PIPELINED)
.IS_CB_INVERTED(1'b0), // Optional inversion for CB
.IS_C_INVERTED(1'b0) // Optional inversion for C
)
IDDRE1_inst (
.Q1(Q1), // 1-bit output: Registered parallel output 1
.Q2(Q2), // 1-bit output: Registered parallel output 2
.C(C), // 1-bit input: High-speed clock
.CB(CB), // 1-bit input: Inversion of High-speed clock C
.D(D), // 1-bit input: Serial Data Input
.R(R) // 1-bit input: Active High Async Reset
);
DDR_CLK_EDGE參數(shù)為IDDRE1的三種采集模式,分別為“OPPOSITE_EDGE”、“SAME_EDGE”和“SAME_EDGE_PIPELINED”模式。
OPPOSITE_EDGE模式的時(shí)序圖如下圖所示:
圖 28.1.16 IDDRE1“OPPOSITE_EDGE”模式時(shí)序圖
OPPOSITE_EDGE模式下,在時(shí)鐘的上升沿輸出的Q1,時(shí)鐘的下降沿輸出Q2。
SAME_EDGE模式的時(shí)序圖如下圖所示:
圖 28.1.17 IDDRE1“SAME_EDGE”模式時(shí)序圖
SAME_EDGE模式下,在時(shí)鐘的上升沿輸出Q1和Q2,但Q1和Q2不在同一個(gè)cycle輸出。
SAME_EDGE_PIPELINED模式的時(shí)序圖如下圖所示:
圖 28.1.18 IDDRE1“SAME_EDGE_PIPELINED”模式時(shí)序圖
SAME_EDGE_PIPELINED模式下,在時(shí)鐘的上升沿輸出Q1和Q2,Q1和Q2雖然在同一個(gè)cycle輸出,但整體延時(shí)了一個(gè)時(shí)鐘周期。在使用IDDRE1時(shí),一般采用此種模式。
ODDRE1:通過(guò)ODDRE1把兩路單端的數(shù)據(jù)合并到一路上輸出,上下沿同時(shí)輸出數(shù)據(jù),上升沿輸出a路,下降沿輸出b路;如果兩路輸入信號(hào)一路固定為1,另外一路固定為0,那么輸出的信號(hào)實(shí)際上是時(shí)鐘信號(hào)。
ODDRE1的原語(yǔ)結(jié)構(gòu)圖如下圖所示:
圖 28.1.19 ODDRE1原語(yǔ)結(jié)構(gòu)圖
C:輸入的高速時(shí)鐘;
Q:輸出的1位DDR數(shù)據(jù);
D1和D2:分別是“C”時(shí)鐘上升沿和下降沿同步輸入的SDR數(shù)據(jù)。
SR:置位/復(fù)位信號(hào),高有效
ODDRE1原語(yǔ)模板如下:
ODDRE1 #(
.IS_C_INVERTED(1'b0), // Optional inversion for C
.IS_D1_INVERTED(1'b0), // Unsupported, do not use
.IS_D2_INVERTED(1'b0), // Unsupported, do not use
.SIM_DEVICE("ULTRASCALE"),
// Set the device version (ULTRASCALE, ULTRASCALE_PLUS, ULTRASCALE_PLUS_ES1,ULTRASCALE_PLUS_ES2, VERSAL, VERSAL_ES1, VERSAL_ES2)
.SRVAL(1'b0)
//Initializes the ODDRE1 Flip-Flops to the specified value (1'b0, 1'b1)
)
ODDRE1_inst (
.Q(Q), // 1-bit output: Data output to IOB
.C(C), // 1-bit input: High-speed clock input
.D1(D1), // 1-bit input: Parallel data input 1
.D2(D2), // 1-bit input: Parallel data input 2
.SR(SR) // 1-bit input: Active High Async Reset
);
SIM_DEVICE參數(shù)為ODDRE1的七種設(shè)備版本,分別為UltraScale、UltraScale Plus、UltraScale Plus ES1、UltraScale Plus ES2、Versal、Versal ES1、Versal ES2。
28.2實(shí)驗(yàn)任務(wù)
本節(jié)實(shí)驗(yàn)任務(wù)是使用DFZU2EG/4EV MPSoC開(kāi)發(fā)板上的PL端以太網(wǎng)接口,和上位機(jī)實(shí)現(xiàn)ARP請(qǐng)求和應(yīng)答的功能。當(dāng)上位機(jī)發(fā)送ARP請(qǐng)求時(shí),開(kāi)發(fā)板返回ARP應(yīng)答數(shù)據(jù)。當(dāng)按下開(kāi)發(fā)板的PL Key1按鍵時(shí),開(kāi)發(fā)板發(fā)送ARP請(qǐng)求,此時(shí)上位機(jī)返回應(yīng)答數(shù)據(jù)。
28.3硬件設(shè)計(jì)
PL端千兆以太網(wǎng)接口部分的硬件設(shè)計(jì)原理和“MDIO接口讀寫(xiě)測(cè)試實(shí)驗(yàn)” 完全相同,請(qǐng)參考“MDIO接口讀寫(xiě)測(cè)試實(shí)驗(yàn)”中的硬件設(shè)計(jì)部分。
本實(shí)驗(yàn)中,各端口信號(hào)的管腳分配如下表所示:
表 28.3.1 以太網(wǎng)ARP測(cè)試實(shí)驗(yàn)管腳分配
對(duì)應(yīng)的XDC約束語(yǔ)句如下所示:
#時(shí)鐘周期約束
create_clock -name sys_clk_p -period 10.000 [get_ports sys_clk_p]
create_clock -period 8.000 -name eth_rxc [get_ports eth_rxc]
#IO管腳約束
set_property IOSTANDARD DIFF_HSTL_I_12 [get_ports sys_clk_p]
set_property IOSTANDARD DIFF_HSTL_I_12 [get_ports sys_clk_n]
set_property PACKAGE_PIN AE5 [get_ports sys_clk_p]
set_property PACKAGE_PIN AF5 [get_ports sys_clk_n]
set_property -dict {PACKAGE_PIN AH11 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]
set_property -dict {PACKAGE_PIN AD11 IOSTANDARD LVCMOS33} [get_ports key]
set_property -dict {PACKAGE_PIN E5 IOSTANDARD LVCMOS18} [get_ports eth_rxc]
set_property -dict {PACKAGE_PIN D5 IOSTANDARD LVCMOS18} [get_ports eth_rx_ctl]
set_property -dict {PACKAGE_PIN G6 IOSTANDARD LVCMOS18} [get_ports {eth_rxd[0]}]
set_property -dict {PACKAGE_PIN F6 IOSTANDARD LVCMOS18} [get_ports {eth_rxd[1]}]
set_property -dict {PACKAGE_PIN G8 IOSTANDARD LVCMOS18} [get_ports {eth_rxd[2]}]
set_property -dict {PACKAGE_PIN F7 IOSTANDARD LVCMOS18} [get_ports {eth_rxd[3]}]
set_property -dict {PACKAGE_PIN D6 IOSTANDARD LVCMOS18} [get_ports eth_txc]
set_property -dict {PACKAGE_PIN F8 IOSTANDARD LVCMOS18} [get_ports eth_tx_ctl]
set_property -dict {PACKAGE_PIN D7 IOSTANDARD LVCMOS18} [get_ports {eth_txd[0]}]
set_property -dict {PACKAGE_PIN E8 IOSTANDARD LVCMOS18} [get_ports {eth_txd[1]}]
set_property -dict {PACKAGE_PIN E9 IOSTANDARD LVCMOS18} [get_ports {eth_txd[2]}]
set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS18} [get_ports {eth_txd[3]}]
28.4程序設(shè)計(jì)
根據(jù)實(shí)驗(yàn)任務(wù),我們可以大致規(guī)劃出系統(tǒng)的控制流程:首先我們需要完成RGMII接口數(shù)據(jù)和GMII接口數(shù)據(jù)的轉(zhuǎn)換,以方便數(shù)據(jù)的采集和解析,在數(shù)據(jù)采集過(guò)程中所用到的延時(shí)原語(yǔ)參考時(shí)鐘由鎖相環(huán)輸出的時(shí)鐘提供;其次整個(gè)以太網(wǎng)幀格式與ARP協(xié)議的實(shí)現(xiàn)由ARP頂層模塊完成;ARP控制模塊負(fù)責(zé)檢測(cè)輸入的按鍵是否被按下,控制ARP頂層模塊發(fā)起請(qǐng)求與產(chǎn)生應(yīng)答等操作。由此畫(huà)出系統(tǒng)的功能框圖如下圖所示:
圖 28.4.1 以太網(wǎng)ARP測(cè)試系統(tǒng)框圖
GMII TO RGMII模塊負(fù)責(zé)將雙沿(DDR)數(shù)據(jù)和單沿(SDR)數(shù)據(jù)之間的轉(zhuǎn)換;ARP頂層模塊實(shí)現(xiàn)了以太網(wǎng)ARP數(shù)據(jù)包的接收、發(fā)送以及CRC校驗(yàn)的功能;ARP控制模塊根據(jù)輸入的PL Key1按鍵信號(hào)和接收到的ARP請(qǐng)求信號(hào),控制ARP頂層模塊發(fā)送ARP請(qǐng)求或者ARP應(yīng)答。
各模塊端口及信號(hào)連接如下圖所示:
圖 28.4.2 頂層模塊原理圖
由上圖可知,F(xiàn)PGA頂層模塊例化了以下四個(gè)模塊,GMII TO RGMII模塊(gmii_to_rgmii)、時(shí)鐘模塊、ARP頂層模塊(arp)和ARP控制模塊(arp_ctrl),實(shí)現(xiàn)了各模塊之間的數(shù)據(jù)交互。
其中ARP頂層模塊和GMII TO RGMII模塊內(nèi)部也例化了多個(gè)其它模塊,這樣設(shè)計(jì)的目的是為了方便模塊的重用。
頂層模塊的代碼如下:
1 module eth_arp_test(
2 input sys_clk_p ,
3 input sys_clk_n ,
4 input sys_rst_n , //系統(tǒng)復(fù)位信號(hào),低電平有效
5 input key , //PL功能按鍵1,用于觸發(fā)開(kāi)發(fā)板發(fā)出ARP請(qǐng)求
6 //PL以太網(wǎng)RGMII接口
7 input eth_rxc , //RGMII接收數(shù)據(jù)時(shí)鐘
8 input eth_rx_ctl, //RGMII輸入數(shù)據(jù)有效信號(hào)
9 input [3:0] eth_rxd , //RGMII輸入數(shù)據(jù)
10 output eth_txc , //RGMII發(fā)送數(shù)據(jù)時(shí)鐘
11 output eth_tx_ctl, //RGMII輸出數(shù)據(jù)有效信號(hào)
12 output [3:0] eth_txd //RGMII輸出數(shù)據(jù)
13 );
14
15 //parameter define
16 //開(kāi)發(fā)板MAC地址 00-11-22-33-44-55
17 parameter BOARD_MAC = 48'h00_11_22_33_44_55;
18 //開(kāi)發(fā)板IP地址 192.168.1.10
19 parameter BOARD_IP = {8'd192,8'd168,8'd1,8'd10};
20 //目的MAC地址 ff_ff_ff_ff_ff_ff
21 parameter DES_MAC = 48'hff_ff_ff_ff_ff_ff;
22 //目的IP地址 192.168.1.102
23 parameter DES_IP = {8'd192,8'd168,8'd1,8'd102};
24
25 //wire define
26 wire gmii_rx_clk; //GMII接收時(shí)鐘
27 wire gmii_rx_dv ; //GMII接收數(shù)據(jù)有效信號(hào)
28 wire [7:0] gmii_rxd ; //GMII接收數(shù)據(jù)
29 wire gmii_tx_clk; //GMII發(fā)送時(shí)鐘
30 wire gmii_tx_en ; //GMII發(fā)送數(shù)據(jù)使能信號(hào)
31 wire [7:0] gmii_txd ; //GMII發(fā)送數(shù)據(jù)
32
33 wire arp_rx_done; //ARP接收完成信號(hào)
34 wire arp_rx_type; //ARP接收類(lèi)型 0:請(qǐng)求 1:應(yīng)答
35 wire [47:0] src_mac ; //接收到目的MAC地址
36 wire [31:0] src_ip ; //接收到目的IP地址
37 wire arp_tx_en ; //ARP發(fā)送使能信號(hào)
38 wire arp_tx_type; //ARP發(fā)送類(lèi)型 0:請(qǐng)求 1:應(yīng)答
39 wire tx_done ; //發(fā)送的目標(biāo)MAC地址
40 wire [47:0] des_mac ; //發(fā)送的目標(biāo)IP地址
41 wire [31:0] des_ip ; //以太網(wǎng)發(fā)送完成信號(hào)
42
43 //*****************************************************
44 //** main code
45 //*****************************************************
46
47 assign des_mac = src_mac;
48 assign des_ip = src_ip ;
49 assign eth_txc = clk_125m_deg;
50
51 clk_wiz_0 u_clk_wiz_0
52 (
53 // Clock out ports
54 .clk_out1 (clk_125m_deg ), // output clk_out1
55 // Status and control signals
56 .reset (~sys_rst_n ), // input reset
57 .locked (locked ), // output locked
58 // Clock in ports
59 .clk_in1 (rgmii_txc ) // input clk_in1
60 );
61
62 //GMII接口轉(zhuǎn)RGMII接口
63 gmii_to_rgmii u_gmii_to_rgmii(
64 .gmii_rx_clk (gmii_rx_clk ),
65 .gmii_rx_dv (gmii_rx_dv ),
66 .gmii_rxd (gmii_rxd ),
67 .gmii_tx_clk (gmii_tx_clk ),
68 .gmii_tx_en (gmii_tx_en ),
69 .gmii_txd (gmii_txd ),
70
71 .rgmii_rxc (eth_rxc ),
72 .rgmii_rx_ctl (eth_rx_ctl ),
73 .rgmii_rxd (eth_rxd ),
74 .rgmii_txc (rgmii_txc ),
75 .rgmii_tx_ctl (eth_tx_ctl ),
76 .rgmii_txd (eth_txd )
77 );
78
79 //ARP通信
80 arp
81 #(
82 .BOARD_MAC (BOARD_MAC), //參數(shù)例化
83 .BOARD_IP (BOARD_IP ),
84 .DES_MAC (DES_MAC ),
85 .DES_IP (DES_IP )
86 )
87 u_arp(
88 .rst_n (sys_rst_n ),
89
90 .gmii_rx_clk (gmii_rx_clk),
91 .gmii_rx_dv (gmii_rx_dv ),
92 .gmii_rxd (gmii_rxd ),
93 .gmii_tx_clk (gmii_tx_clk),
94 .gmii_tx_en (gmii_tx_en ),
95 .gmii_txd (gmii_txd ),
96
97 .arp_rx_done (arp_rx_done),
98 .arp_rx_type (arp_rx_type),
99 .src_mac (src_mac ),
100 .src_ip (src_ip ),
101 .arp_tx_en (arp_tx_en ),
102 .arp_tx_type (arp_tx_type),
103 .des_mac (des_mac ),
104 .des_ip (des_ip ),
105 .tx_done (tx_done )
106 );
107
108 //ARP控制
109 arp_ctrl u_arp_ctrl(
110 .clk (gmii_rx_clk),
111 .rst_n (sys_rst_n ),
112
113 .key (key ),
114 .arp_rx_done (arp_rx_done),
115 .arp_rx_type (arp_rx_type),
116 .arp_tx_en (arp_tx_en ),
117 .arp_tx_type (arp_tx_type)
118 );
119
120 endmodule
頂層模塊主要完成對(duì)其余模塊的例化。在程序的第15行至第23行代碼定義了開(kāi)發(fā)板的MAC地址、IP地址、默認(rèn)的目的MAC地址和目的IP地址。開(kāi)發(fā)板的MAC地址為00:11:22:33:44:55;開(kāi)發(fā)板的IP地址為192.168.1.10;默認(rèn)目的MAC地址為ff:ff:ff:ff:ff:ff,這是一個(gè)廣播MAC地址,在收到上位機(jī)的請(qǐng)求或者應(yīng)答之后,ARP模塊會(huì)替換成實(shí)際的目的MAC地址。目的IP地址這里設(shè)置為192.168.1.102,因此大家在做本次實(shí)驗(yàn)時(shí),需要把電腦的以太網(wǎng)的IP地址改成192.168.1.102,或者將代碼中定義的DES_IP改成電腦的IP地址。
程序的第47行和48行代碼將收到的對(duì)端設(shè)備MAC地址和目的IP地址,作為開(kāi)發(fā)板發(fā)送時(shí)的目的MAC地址和IP地址。
gmii_to_rgmii模塊代碼如下:
1 module gmii_to_rgmii(
2 //以太網(wǎng)GMII接口
3 output gmii_rx_clk , //GMII接收時(shí)鐘
4 output gmii_rx_dv , //GMII接收數(shù)據(jù)有效信號(hào)
5 output [7:0] gmii_rxd , //GMII接收數(shù)據(jù)
6 output gmii_tx_clk , //GMII發(fā)送時(shí)鐘
7 input gmii_tx_en , //GMII發(fā)送數(shù)據(jù)使能信號(hào)
8 input [7:0] gmii_txd , //GMII發(fā)送數(shù)據(jù)
9 //以太網(wǎng)RGMII接口
10 input rgmii_rxc , //RGMII接收時(shí)鐘
11 input rgmii_rx_ctl, //RGMII接收數(shù)據(jù)控制信號(hào)
12 input [3:0] rgmii_rxd , //RGMII接收數(shù)據(jù)
13 output rgmii_txc , //RGMII發(fā)送時(shí)鐘
14 output rgmii_tx_ctl, //RGMII發(fā)送數(shù)據(jù)控制信號(hào)
15 output [3:0] rgmii_txd //RGMII發(fā)送數(shù)據(jù)
16 );
17
18 //*****************************************************
19 //** main code
20 //*****************************************************
21
22 assign gmii_tx_clk = gmii_rx_clk;
23
24 //RGMII接收
25 rgmii_rx u_rgmii_rx(
26 .gmii_rx_clk (gmii_rx_clk ),
27 .rgmii_rxc (rgmii_rxc ),
28 .rgmii_rx_ctl (rgmii_rx_ctl),
29 .rgmii_rxd (rgmii_rxd ),
30
31 .gmii_rx_dv (gmii_rx_dv ),
32 .gmii_rxd (gmii_rxd )
33 );
34
35 //RGMII發(fā)送
36 rgmii_tx u_rgmii_tx(
37 .gmii_tx_clk (gmii_tx_clk ),
38 .gmii_tx_en (gmii_tx_en ),
39 .gmii_txd (gmii_txd ),
40
41 .rgmii_txc (rgmii_txc ),
42 .rgmii_tx_ctl (rgmii_tx_ctl),
43 .rgmii_txd (rgmii_txd )
44 );
45
46 endmodule
由該模塊的端口可知,該模塊實(shí)現(xiàn)了雙沿(DDR)數(shù)據(jù)和單沿(SDR)數(shù)據(jù)之間的轉(zhuǎn)換。程序中第22行將GMII接收時(shí)鐘賦值給GMII發(fā)送時(shí)鐘,因此GMII的發(fā)送時(shí)鐘和接收時(shí)鐘實(shí)際上為同一個(gè)時(shí)鐘。GMII TO RGMII模塊例化了rgmii_rx模塊和rgmii_tx模塊。
rgmii_rx模塊代碼如下所示:
1 module rgmii_rx(
2 //以太網(wǎng)RGMII接口
3 input rgmii_rxc , //RGMII接收時(shí)鐘
4 input rgmii_rx_ctl, //RGMII接收數(shù)據(jù)控制信號(hào)
5 input [3:0] rgmii_rxd , //RGMII接收數(shù)據(jù)
6
7 //以太網(wǎng)GMII接口
8 output gmii_rx_clk , //GMII接收時(shí)鐘
9 output gmii_rx_dv , //GMII接收數(shù)據(jù)有效信號(hào)
10 output [7:0] gmii_rxd //GMII接收數(shù)據(jù)
11 );
12
13 //wire define
14 wire rgmii_rxc_bufg; //全局時(shí)鐘緩存
15 wire rgmii_rxc_bufio; //全局時(shí)鐘IO緩存
16 wire [1:0] gmii_rxdv_t; //兩位GMII接收有效信號(hào)
17
18 //*****************************************************
19 //** main code
20 //*****************************************************
21
22 assign gmii_rx_clk = rgmii_rxc_bufg;
23 assign gmii_rx_dv = gmii_rxdv_t[0] & gmii_rxdv_t[1];
24
25 //全局時(shí)鐘緩存
26 BUFG BUFG_inst (
27 .I (rgmii_rxc), // 1-bit input: Clock input
28 .O (rgmii_rxc_bufg) // 1-bit output: Clock output
29 );
30
31 //全局時(shí)鐘IO緩存
32 BUFIO BUFIO_inst (
33 .I (rgmii_rxc), // 1-bit input: Clock input
34 .O (rgmii_rxc_bufio) // 1-bit output: Clock output
35 );
36
37 //將輸入的上下邊沿DDR信號(hào),轉(zhuǎn)換成兩位單邊沿SDR信號(hào)
38 IDDRE1 #(
39 .DDR_CLK_EDGE ("SAME_EDGE_PIPELINED"),
40 // IDDRE1 mode (OPPOSITE_EDGE, SAME_EDGE, SAME_EDGE_PIPELINED)
41 .IS_CB_INVERTED (1'b0), // Optional inversion for CB
42 .IS_C_INVERTED (1'b0) // Optional inversion for C
43 )
44 IDDRE1_inst (
45 .Q1 (gmii_rxdv_t[0]), // 1-bit output: Registered parallel output 1
46 .Q2 (gmii_rxdv_t[1]), // 1-bit output: Registered parallel output 2
47 .C (rgmii_rxc_bufio), // 1-bit input: High-speed clock
48 .CB (~rgmii_rxc_bufio),// 1-bit input: Inversion of High-speed clock C
49 .D (rgmii_rx_ctl), // 1-bit input: Serial Data Input
50 .R (1'b0) // 1-bit input: Active High Async Reset
51 );
52
53 genvar i;
54 generate for (i=0; i<4; i=i+1)
55 begin : rxdata_bus
56 IDDRE1 #(
57 .DDR_CLK_EDGE ("SAME_EDGE_PIPELINED"),
58 // IDDRE1 mode (OPPOSITE_EDGE, SAME_EDGE, SAME_EDGE_PIPELINED)
59 .IS_CB_INVERTED (1'b0), // Optional inversion for CB
60 .IS_C_INVERTED (1'b0) // Optional inversion for C
61 )
62 IDDRE1_inst (
63 .Q1 (gmii_rxd[i]), // 1-bit output: Registered parallel output 1
64 .Q2 (gmii_rxd[4+i]), // 1-bit output: Registered parallel output 2
65 .C (rgmii_rxc_bufio), // 1-bit input: High-speed clock
66 .CB (~rgmii_rxc_bufio), // 1-bit input: Inversion of High-speed clock C
67 .D (rgmii_rxd[i]), // 1-bit input: Serial Data Input
68 .R (1'b0) // 1-bit input: Active High Async Reset
69 );
70 end
71 endgenerate
72
73 endmodule
該模塊通過(guò)調(diào)用BUFG、BUFIO、IDDRE1原語(yǔ),實(shí)現(xiàn)了RGMII接口輸入的DDR數(shù)據(jù)到SDR數(shù)據(jù)的轉(zhuǎn)換,輸入的rgmii_rx_ctl控制信號(hào)的轉(zhuǎn)換方法同樣類(lèi)似。rgmii_rx模塊信號(hào)轉(zhuǎn)換示意圖如下圖所示:
圖 28.4.3 rgmii_rx模塊信號(hào)轉(zhuǎn)換示意圖
時(shí)鐘專(zhuān)用引腳輸入的rgmii_rxc時(shí)鐘經(jīng)過(guò)BUFG后,得到gmii_rx_clk,該時(shí)鐘為全局緩沖時(shí)鐘,其到達(dá)FPGA內(nèi)部的IOB、CLB、塊RAM的時(shí)鐘延遲和抖動(dòng)非常小,為其他模塊提供操作時(shí)鐘;另外rgmii_rxc時(shí)鐘也經(jīng)過(guò)BUFIO,專(zhuān)門(mén)用于采集IO端口的數(shù)據(jù)。
rgmii_rx_ctl控制信號(hào)和4位rgmii_rxd數(shù)據(jù)經(jīng)過(guò)IDDRE1將雙沿1位數(shù)據(jù)轉(zhuǎn)換成單沿兩位數(shù)據(jù)。
另外,在程序的第53行至71行代碼通過(guò)generate for語(yǔ)句實(shí)現(xiàn)對(duì)IDDRE1的例化,由于輸入的數(shù)據(jù)引腳為4位數(shù)據(jù),因此這里共例化了4次。其等效于分別對(duì)輸入的IDDRE1例化4次,這里采用generate for的寫(xiě)法可以減少很多的代碼量,當(dāng)需要對(duì)某個(gè)模塊例化較多次數(shù)時(shí),這種寫(xiě)法能夠大大提高效率。
rgmii_tx模塊代碼如下所示:
1 module rgmii_tx(
2 //GMII發(fā)送端口
3 input gmii_tx_clk , //GMII發(fā)送時(shí)鐘
4 input gmii_tx_en , //GMII輸出數(shù)據(jù)有效信號(hào)
5 input [7:0] gmii_txd , //GMII輸出數(shù)據(jù)
6
7 //RGMII發(fā)送端口
8 output rgmii_txc , //RGMII發(fā)送數(shù)據(jù)時(shí)鐘
9 output rgmii_tx_ctl, //RGMII輸出數(shù)據(jù)有效信號(hào)
10 output [3:0] rgmii_txd //RGMII輸出數(shù)據(jù)
11 );
12
13 //*****************************************************
14 //** main code
15 //*****************************************************
16
17 assign rgmii_txc = gmii_tx_clk;
18
19 //輸出雙沿采樣寄存器 (rgmii_tx_ctl)
20 ODDRE1 #(
21 .IS_C_INVERTED (1'b0), // Optional inversion for C
22 .IS_D1_INVERTED (1'b0), // Unsupported, do not use
23 .IS_D2_INVERTED (1'b0), // Unsupported, do not use
24 .SIM_DEVICE ("ULTRASCALE"),
25 // Set the device version (ULTRASCALE, ULTRASCALE_PLUS,
26 // ULTRASCALE_PLUS_ES1,ULTRASCALE_PLUS_ES2)
27 .SRVAL(1'b0)
28 // Initializes the ODDRE1 Flip-Flops to the specified value (1'b0, 1'b1)
29 )
30 ODDRE1_tx_ctl (
31 .Q (rgmii_tx_ctl), // 1-bit output: Data output to IOB
32 .C (gmii_tx_clk), // 1-bit input: High-speed clock input
33 .D1 (gmii_tx_en), // 1-bit input: Parallel data input 1
34 .D2 (gmii_tx_en), // 1-bit input: Parallel data input 2
35 .SR (1'b0) // 1-bit input: Active High Async Reset
36 );
37
38 genvar i;
39 generate for (i=0; i<4; i=i+1)
40 begin : txdata_bus
41 ODDRE1 #(
42 .IS_C_INVERTED(1'b0), // Optional inversion for C
43 .IS_D1_INVERTED(1'b0), // Unsupported, do not use
44 .IS_D2_INVERTED(1'b0), // Unsupported, do not use
45 .SIM_DEVICE("ULTRASCALE"),
46 // Set the device version (ULTRASCALE, ULTRASCALE_PLUS,
47 // ULTRASCALE_PLUS_ES1,ULTRASCALE_PLUS_ES2)
48 .SRVAL(1'b0)
49 // Initializes the ODDRE1 Flip-Flops to the specified value (1'b0, 1'b1)
50 )
51 ODDRE1_inst (
52 .Q (rgmii_txd[i]), // 1-bit output: Data output to IOB
53 .C (gmii_tx_clk), // 1-bit input: High-speed clock input
54 .D1 (gmii_txd[i]), // 1-bit input: Parallel data input 1
55 .D2 (gmii_txd[4+i]), // 1-bit input: Parallel data input 2
56 .SR (1'b0) // 1-bit input: Active High Async Reset
57 );
58 end
59 endgenerate
60
61 endmodule
該模塊通過(guò)調(diào)用ODDRE1原語(yǔ)將輸入的單沿8位數(shù)據(jù)(gmii_txd)轉(zhuǎn)換成雙沿采樣的4位數(shù)據(jù)(rgmii_txd),gmii_tx_en和rgmii_tx_ctl信號(hào)的處理方法同樣類(lèi)似。rgmii_tx模塊信號(hào)轉(zhuǎn)換示意圖如下圖所示:
圖 28.4.4 rgmii_tx模塊信號(hào)轉(zhuǎn)換示意圖
gmii_tx_en數(shù)據(jù)使能信號(hào)和8位gmii_txd數(shù)據(jù)經(jīng)過(guò)ODDRE1將單沿2位數(shù)據(jù)轉(zhuǎn)換成雙沿1位數(shù)據(jù)。需要說(shuō)明的是,在程序的第38行至第59行同樣通過(guò)generate for語(yǔ)句實(shí)現(xiàn)原語(yǔ)的多次例化。
ARP頂層模塊實(shí)現(xiàn)了整個(gè)以太網(wǎng)幀格式與ARP協(xié)議的功能,其模塊端口及信號(hào)連接如下圖所示:
圖 28.4.5 ARP模塊原理圖
由上圖可知,ARP頂層模塊例化了ARP接收模塊(arp_rx)、ARP發(fā)送模塊(arp_tx)和CRC校驗(yàn)?zāi)K(crc32_d8)。
ARP接收模塊(arp_rx):ARP接收模塊負(fù)責(zé)解析以太網(wǎng)的數(shù)據(jù),判斷目的MAC地址和目的IP地址是否為開(kāi)發(fā)板的地址,然后按照ARP協(xié)議將數(shù)據(jù)解析出來(lái)。當(dāng)解析到正確的ARP數(shù)據(jù)包后,拉高arp_rx_done信號(hào),持續(xù)一個(gè)時(shí)鐘周期。arp_rx_type用于表示ARP數(shù)據(jù)包的類(lèi)型,0表示收到ARP請(qǐng)求包,1表示收到ARP應(yīng)答包。src_mac和src_ip分別是解析出的對(duì)端設(shè)備MAC地址和IP地址。
ARP發(fā)送模塊(arp_tx):ARP發(fā)送模塊根據(jù)以太網(wǎng)幀格式和ARP協(xié)議發(fā)送ARP請(qǐng)求或者ARP應(yīng)答數(shù)據(jù)。arp_tx_en和arp_tx_type分別表示ARP發(fā)送模塊的使能信號(hào)和發(fā)送ARP類(lèi)型。dec_mac和dec_ip分別設(shè)置對(duì)端設(shè)備MAC地址和IP地址。
CRC校驗(yàn)?zāi)K(crc32_d8):CRC校驗(yàn)?zāi)K是對(duì)ARP發(fā)送模塊的數(shù)據(jù)(不包括前導(dǎo)碼和幀起始界定符)做校驗(yàn),把校驗(yàn)結(jié)果值拼在以太網(wǎng)幀格式的FCS字段,如果CRC校驗(yàn)值計(jì)算錯(cuò)誤或者沒(méi)有的話(huà),那么電腦網(wǎng)卡會(huì)直接丟棄該幀導(dǎo)致收不到數(shù)據(jù)(有些網(wǎng)卡是可以設(shè)置不做校驗(yàn)的)。CRC32校驗(yàn)在FPGA實(shí)現(xiàn)的原理是LFSR(Linear Feedback Shift Register,線(xiàn)性反饋移位寄存器),其思想是各個(gè)寄存器儲(chǔ)存著上一次CRC32運(yùn)算的結(jié)果,寄存器的輸出即為CRC32的值。需要說(shuō)明的是,本次實(shí)驗(yàn)只對(duì)發(fā)送模塊做校驗(yàn),沒(méi)有對(duì)接收模塊做校驗(yàn)。這是由于我們可以直接通過(guò)解析出的數(shù)據(jù)來(lái)大致判斷接收是否正確,而發(fā)送模塊必須發(fā)送正確的校驗(yàn)數(shù)據(jù),否則發(fā)送的數(shù)據(jù)直接被電腦的網(wǎng)卡丟棄,導(dǎo)致ARP請(qǐng)求或者應(yīng)答失敗。
在簡(jiǎn)介部分我們向大家介紹過(guò),ARP的數(shù)據(jù)包格式包括前導(dǎo)碼+SFD、以太網(wǎng)幀頭、ARP數(shù)據(jù)(包括填充部分?jǐn)?shù)據(jù))和CRC校驗(yàn)。在接收以太網(wǎng)數(shù)據(jù)的過(guò)程中,這些不同部分的數(shù)據(jù)可以剛好對(duì)應(yīng)狀態(tài)機(jī)的不同狀態(tài)位,因此我們可以通過(guò)狀態(tài)機(jī)來(lái)解析以太網(wǎng)的數(shù)據(jù)。
ARP接收模塊通過(guò)狀態(tài)機(jī)來(lái)解析數(shù)據(jù),其狀態(tài)跳轉(zhuǎn)圖如下圖所示:
圖 28.4.6 ARP接收模塊狀態(tài)跳轉(zhuǎn)圖
接收模塊使用三段式狀態(tài)機(jī)來(lái)解析以太網(wǎng)包,從上圖可以比較直觀的看到每個(gè)狀態(tài)實(shí)現(xiàn)的功能以及跳轉(zhuǎn)到下一個(gè)狀態(tài)的條件。這里需要注意的一點(diǎn)是,在中間狀態(tài)如前導(dǎo)碼錯(cuò)誤、MAC地址錯(cuò)誤以及IP地址等錯(cuò)誤時(shí)跳轉(zhuǎn)到st_rx_end狀態(tài),而不是跳轉(zhuǎn)到st_idle狀態(tài)。因?yàn)橹虚g狀態(tài)在解析到數(shù)據(jù)錯(cuò)誤時(shí),單包數(shù)據(jù)的接收還沒(méi)有結(jié)束,如果此時(shí)跳轉(zhuǎn)到st_idle狀態(tài)會(huì)誤把有效數(shù)據(jù)當(dāng)成前導(dǎo)碼來(lái)解析,所以狀態(tài)跳轉(zhuǎn)到st_rx_end。而gmii_rx_dv信號(hào)為0時(shí),單包數(shù)據(jù)才算接收結(jié)束,所以st_rx_end跳轉(zhuǎn)到st_idle的條件是eth_rxdv=0,準(zhǔn)備接收下一包數(shù)據(jù)。因?yàn)榇a較長(zhǎng),只粘貼了第三段狀態(tài)機(jī)的接收ARP數(shù)據(jù)狀態(tài)和接收結(jié)束狀態(tài)源代碼,代碼如下:
186 st_arp_data : begin
187 if(gmii_rx_dv) begin
188 cnt <= cnt + 5'd1;
189 if(cnt == 5'd6)
190 op_data[15:8] <= gmii_rxd; //操作碼
191 else if(cnt == 5'd7)
192 op_data[7:0] <= gmii_rxd;
193 else if(cnt >= 5'd8 && cnt < 5'd14) //源MAC地址
194 src_mac_t <= {src_mac_t[39:0],gmii_rxd};
195 else if(cnt >= 5'd14 && cnt < 5'd18) //源IP地址
196 src_ip_t<= {src_ip_t[23:0],gmii_rxd};
197 else if(cnt >= 5'd24 && cnt < 5'd28) //目標(biāo)IP地址
198 des_ip_t <= {des_ip_t[23:0],gmii_rxd};
199 else if(cnt == 5'd28) begin
200 cnt <= 5'd0;
201 if(des_ip_t == BOARD_IP) begin //判斷目的IP地址和操作碼
202 if((op_data == 16'd1) || (op_data == 16'd2)) begin
203 skip_en <= 1'b1;
204 rx_done_t <= 1'b1;
205 src_mac <= src_mac_t;
206 src_ip <= src_ip_t;
207 src_mac_t <= 48'd0;
208 src_ip_t <= 32'd0;
209 des_mac_t <= 48'd0;
210 des_ip_t <= 32'd0;
211 if(op_data == 16'd1)
212 arp_rx_type <= 1'b0; //ARP請(qǐng)求
213 else
214 arp_rx_type <= 1'b1; //ARP應(yīng)答
215 end
216 else
217 error_en <= 1'b1;
218 end
219 else
220 error_en <= 1'b1;
221 end
222 end
223 end
224 st_rx_end : begin
225 cnt <= 5'd0;
226 //單包數(shù)據(jù)接收完成
227 if(gmii_rx_dv == 1'b0 && skip_en == 1'b0)
228 skip_en <= 1'b1;
229 end
st_arp_data狀態(tài)根據(jù)ARP協(xié)議解析數(shù)據(jù),在程序的第201行至第202行代碼判斷目的IP地址和OP操作碼是否正確,如果錯(cuò)誤,則丟棄該包數(shù)據(jù)。在程序的第211行至第214行代碼根據(jù)操作碼為arp_rx_type(接收到的ARP數(shù)據(jù)包類(lèi)型)賦值,當(dāng)接收到ARP請(qǐng)求包時(shí),arp_rx_type等于0;當(dāng)接收到ARP應(yīng)答包時(shí),arp_rx_type等于1。
ARP接收過(guò)程中采集的ILA波形圖如圖 28.4.7所示,gmii_rx_dv信號(hào)拉高表示此時(shí)輸入的數(shù)據(jù)有效,根據(jù)gmii_rxd的值來(lái)解析數(shù)據(jù)。從圖中可以看出,發(fā)送端的MAC地址和地址,以及當(dāng)前接收到的以太網(wǎng)數(shù)據(jù)包類(lèi)型為ARP(0x0806)。在接收完ARP數(shù)據(jù)包之后,拉高arp_rx_done信號(hào)表示接收完成,圖中arp_rx_type信號(hào)為低電平,表示當(dāng)前接收到的是ARP請(qǐng)求數(shù)據(jù)包。
圖 28.4.7 ARP接收采集ILA波形圖
ARP發(fā)送模塊則是根據(jù)以太網(wǎng)幀格式是ARP協(xié)議發(fā)送數(shù)據(jù),也就是接收模塊的逆過(guò)程,同樣也非常適合使用狀態(tài)機(jī)來(lái)完成發(fā)送數(shù)據(jù)的功能,狀態(tài)跳轉(zhuǎn)圖如下圖所示:
圖 28.4.8 ARP發(fā)送模塊狀態(tài)跳轉(zhuǎn)圖
發(fā)送模塊和接收模塊有很多相似之處,同樣使用三段式狀態(tài)機(jī)來(lái)發(fā)送以太網(wǎng)包,從上圖可以比較直觀的看到每個(gè)狀態(tài)實(shí)現(xiàn)的功能以及跳轉(zhuǎn)到下一個(gè)狀態(tài)的條件。
發(fā)送模塊的代碼中定義了數(shù)組來(lái)存儲(chǔ)前導(dǎo)碼+幀頭、以太網(wǎng)的幀頭、ARP數(shù)據(jù),在復(fù)位時(shí)初始化數(shù)組的值,部分源代碼如下。
66 reg [7:0] preamble[7:0] ; //前導(dǎo)碼+SFD
67 reg [7:0] eth_head[13:0]; //以太網(wǎng)首部
68 reg [7:0] arp_data[27:0]; //ARP數(shù)據(jù)
省略部分代碼……
155 //初始化數(shù)組
156 //前導(dǎo)碼 7個(gè)8'h55 + 1個(gè)8'hd5
157 preamble[0] <= 8'h55;
158 preamble[1] <= 8'h55;
159 preamble[2] <= 8'h55;
160 preamble[3] <= 8'h55;
161 preamble[4] <= 8'h55;
162 preamble[5] <= 8'h55;
163 preamble[6] <= 8'h55;
164 preamble[7] <= 8'hd5;
165 //以太網(wǎng)幀頭
166 eth_head[0] <= DES_MAC[47:40]; //目的MAC地址
167 eth_head[1] <= DES_MAC[39:32];
168 eth_head[2] <= DES_MAC[31:24];
169 eth_head[3] <= DES_MAC[23:16];
170 eth_head[4] <= DES_MAC[15:8];
171 eth_head[5] <= DES_MAC[7:0];
172 eth_head[6] <= BOARD_MAC[47:40]; //源MAC地址
173 eth_head[7] <= BOARD_MAC[39:32];
174 eth_head[8] <= BOARD_MAC[31:24];
175 eth_head[9] <= BOARD_MAC[23:16];
176 eth_head[10] <= BOARD_MAC[15:8];
177 eth_head[11] <= BOARD_MAC[7:0];
178 eth_head[12] <= ETH_TYPE[15:8]; //以太網(wǎng)幀類(lèi)型
179 eth_head[13] <= ETH_TYPE[7:0];
180 //ARP數(shù)據(jù)
181 arp_data[0] <= HD_TYPE[15:8]; //硬件類(lèi)型
182 arp_data[1] <= HD_TYPE[7:0];
183 arp_data[2] <= PROTOCOL_TYPE[15:8]; //上層協(xié)議類(lèi)型
184 arp_data[3] <= PROTOCOL_TYPE[7:0];
185 arp_data[4] <= 8'h06; //硬件地址長(zhǎng)度,6
186 arp_data[5] <= 8'h04; //協(xié)議地址長(zhǎng)度,4
187 arp_data[6] <= 8'h00; //OP,操作碼 8'h01:ARP請(qǐng)求 8'h02:ARP應(yīng)答
188 arp_data[7] <= 8'h01;
189 arp_data[8] <= BOARD_MAC[47:40]; //發(fā)送端(源)MAC地址
190 arp_data[9] <= BOARD_MAC[39:32];
191 arp_data[10] <= BOARD_MAC[31:24];
192 arp_data[11] <= BOARD_MAC[23:16];
193 arp_data[12] <= BOARD_MAC[15:8];
194 arp_data[13] <= BOARD_MAC[7:0];
195 arp_data[14] <= BOARD_IP[31:24]; //發(fā)送端(源)IP地址
196 arp_data[15] <= BOARD_IP[23:16];
197 arp_data[16] <= BOARD_IP[15:8];
198 arp_data[17] <= BOARD_IP[7:0];
199 arp_data[18] <= DES_MAC[47:40]; //接收端(目的)MAC地址
200 arp_data[19] <= DES_MAC[39:32];
201 arp_data[20] <= DES_MAC[31:24];
202 arp_data[21] <= DES_MAC[23:16];
203 arp_data[22] <= DES_MAC[15:8];
204 arp_data[23] <= DES_MAC[7:0];
205 arp_data[24] <= DES_IP[31:24]; //接收端(目的)IP地址
206 arp_data[25] <= DES_IP[23:16];
207 arp_data[26] <= DES_IP[15:8];
208 arp_data[27] <= DES_IP[7:0];
以上代碼在復(fù)位時(shí)對(duì)數(shù)組進(jìn)行初始化。
216 st_idle : begin
217 if(pos_tx_en) begin
218 skip_en <= 1'b1;
219 //如果目標(biāo)MAC地址和IP地址已經(jīng)更新,則發(fā)送正確的地址
220 if((des_mac != 48'b0) || (des_ip != 32'd0)) begin
221 eth_head[0] <= des_mac[47:40];
222 eth_head[1] <= des_mac[39:32];
223 eth_head[2] <= des_mac[31:24];
224 eth_head[3] <= des_mac[23:16];
225 eth_head[4] <= des_mac[15:8];
226 eth_head[5] <= des_mac[7:0];
227 arp_data[18] <= des_mac[47:40];
228 arp_data[19] <= des_mac[39:32];
229 arp_data[20] <= des_mac[31:24];
230 arp_data[21] <= des_mac[23:16];
231 arp_data[22] <= des_mac[15:8];
232 arp_data[23] <= des_mac[7:0];
233 arp_data[24] <= des_ip[31:24];
234 arp_data[25] <= des_ip[23:16];
235 arp_data[26] <= des_ip[15:8];
236 arp_data[27] <= des_ip[7:0];
237 end
238 if(arp_tx_type == 1'b0)
239 arp_data[7] <= 8'h01; //ARP請(qǐng)求
240 else
241 arp_data[7] <= 8'h02; //ARP應(yīng)答
242 end
243 end
在程序的第220行至241行代碼,根據(jù)輸入的發(fā)送類(lèi)型、目的MAC地址和IP地址,重新更新數(shù)組里的值。
265 st_arp_data : begin //發(fā)送ARP數(shù)據(jù)
266 crc_en <= 1'b1;
267 gmii_tx_en <= 1'b1;
268 //至少發(fā)送46個(gè)字節(jié)
269 if (cnt == MIN_DATA_NUM - 1'b1) begin
270 skip_en <= 1'b1;
271 cnt <= 1'b0;
272 data_cnt <= 1'b0;
273 end
274 else
275 cnt <= cnt + 1'b1;
276 if(data_cnt <= 6'd27) begin
277 data_cnt <= data_cnt + 1'b1;
278 gmii_txd <= arp_data[data_cnt];
279 end
280 else
281 gmii_txd <= 8'd0; //Padding,填充0
282 end
程序第265行至第282行代碼為發(fā)送ARP數(shù)據(jù)的狀態(tài)。我們前面講過(guò)以太網(wǎng)幀格式的數(shù)據(jù)部分最少是46個(gè)字節(jié),ARP數(shù)據(jù)只有28個(gè)字節(jié),因此在發(fā)送完ARP數(shù)據(jù)之后補(bǔ)充發(fā)送18個(gè)字節(jié),填充的數(shù)據(jù)為0。
283 st_crc : begin //發(fā)送CRC校驗(yàn)值
284 gmii_tx_en <= 1'b1;
285 cnt <= cnt + 1'b1;
286 if(cnt == 6'd0)
287 gmii_txd <= {~crc_next[0], ~crc_next[1], ~crc_next[2],~crc_next[3],
288 ~crc_next[4], ~crc_next[5], ~crc_next[6],~crc_next[7]};
289 else if(cnt == 6'd1)
290 gmii_txd <= {~crc_data[16], ~crc_data[17], ~crc_data[18],
291 ~crc_data[19], ~crc_data[20], ~crc_data[21],
292 ~crc_data[22],~crc_data[23]};
293 else if(cnt == 6'd2) begin
294 gmii_txd <= {~crc_data[8], ~crc_data[9], ~crc_data[10],
295 ~crc_data[11],~crc_data[12], ~crc_data[13],
296 ~crc_data[14],~crc_data[15]};
297 end
298 else if(cnt == 6'd3) begin
299 gmii_txd <= {~crc_data[0], ~crc_data[1], ~crc_data[2],~crc_data[3],
300 ~crc_data[4], ~crc_data[5], ~crc_data[6],~crc_data[7]};
301 tx_done_t <= 1'b1;
302 skip_en <= 1'b1;
303 cnt <= 1'b0;
304 end
305 end
程序的第283行至305行代碼為發(fā)送CRC校驗(yàn)值狀態(tài),發(fā)送模塊的CRC校驗(yàn)是由crc32_d8模塊完成的,發(fā)送模塊將輸入的crc的計(jì)算結(jié)果每4位高低位互換,按位取反發(fā)送出去,crc計(jì)算部分在后面闡述。
ARP發(fā)送過(guò)程中采集的ILA波形圖如圖 28.4.9所示,arp_tx_en信號(hào)作為開(kāi)始發(fā)送ARP數(shù)據(jù)包的觸發(fā)信號(hào),arp_tx_type為高電平,表示發(fā)送ARP應(yīng)答數(shù)據(jù)包。ARP應(yīng)答數(shù)據(jù)包中的目的MAC地址和目的IP地址從ARP接收數(shù)據(jù)包中獲取,gmii_tx_en拉高,表示gmii_txd數(shù)據(jù)有效,在發(fā)送完ARP數(shù)據(jù)包后,輸出一個(gè)脈沖信號(hào)(tx_done),表示發(fā)送完成。
圖 28.4.9 ARP發(fā)送采集的ILA波形圖
CRC校驗(yàn)?zāi)K主要完成對(duì)ARP發(fā)送模塊數(shù)據(jù)的校驗(yàn),由于代碼較長(zhǎng),這里不再貼出代碼。CRC32校驗(yàn)在FPGA實(shí)現(xiàn)的原理是線(xiàn)性反饋移位寄存器,其思想是各個(gè)寄存器儲(chǔ)存著上一次CRC32運(yùn)算的結(jié)果,寄存器的輸出即為CRC32的值。CRC32的原理與公式推導(dǎo)較復(fù)雜,只需稍作修改就可以直接使用,在此可不比深究。
ARP控制模塊的代碼如下:
1 module arp_ctrl(
2 input clk , //輸入時(shí)鐘
3 input rst_n , //復(fù)位信號(hào),低電平有效
4
5 input key , //PL功能按鍵1,用于觸發(fā)開(kāi)發(fā)板發(fā)出ARP請(qǐng)求
6 input arp_rx_done, //ARP接收完成信號(hào)
7 input arp_rx_type, //ARP接收類(lèi)型 0:請(qǐng)求 1:應(yīng)答
8 output reg arp_tx_en , //ARP發(fā)送使能信號(hào)
9 output reg arp_tx_type //ARP發(fā)送類(lèi)型 0:請(qǐng)求 1:應(yīng)答
10 );
11
12 //reg define
13 reg key_d0;
14 reg key_d1;
15
16 //wire define
17 wire pos_key; //key信號(hào)上升沿
18
19 //*****************************************************
20 //** main code
21 //*****************************************************
22
23 assign pos_key = ~key_d1 & key_d0;
24
25 //對(duì)arp_tx_en信號(hào)延時(shí)打拍兩次,用于采key的上升沿
26 always @(posedge clk or negedge rst_n) begin
27 if(!rst_n) begin
28 key_d0 <= 1'b0;
29 key_d1 <= 1'b0;
30 end
31 else begin
32 key_d0 <= key;
33 key_d1 <= key_d0;
34 end
35 end
36
37 //為arp_tx_en和arp_tx_type賦值
38 always @(posedge clk or negedge rst_n) begin
39 if(!rst_n) begin
40 arp_tx_en <= 1'b0;
41 arp_tx_type <= 1'b0;
42 end
43 else begin
44 if(pos_key == 1'b1) begin //檢測(cè)到輸入按鍵上升沿
45 arp_tx_en <= 1'b1;
46 arp_tx_type <= 1'b0;
47 end
48 //接收到ARP請(qǐng)求,開(kāi)始控制ARP發(fā)送模塊應(yīng)答
49 else if((arp_rx_done == 1'b1) && (arp_rx_type == 1'b0)) begin
50 arp_tx_en <= 1'b1;
51 arp_tx_type <= 1'b1;
52 end
53 else
54 arp_tx_en <= 1'b0;
55 end
56 end
57
58 endmodule
ARP控制模塊的代碼較簡(jiǎn)單,首先檢測(cè)輸入PL Key1按鍵的上升沿,當(dāng)檢測(cè)到上升沿之后,觸發(fā)ARP頂層模塊發(fā)起ARP請(qǐng)求信號(hào);同時(shí)檢測(cè)輸入的arp_rx_done和arp_rx_type信號(hào),當(dāng)接收上位機(jī)的ARP請(qǐng)求信號(hào)后,觸發(fā)ARP頂層模塊發(fā)送ARP應(yīng)答信號(hào),將開(kāi)發(fā)板的MAC地址發(fā)送給上位機(jī)。
28.5下載驗(yàn)證
將下載器一端連接電腦,另一端與開(kāi)發(fā)板上的JTAG下載口連接,將網(wǎng)線(xiàn)一端連接開(kāi)發(fā)板的PL網(wǎng)口(PL_ETH),另一端連接電腦的網(wǎng)口,最后連接電源線(xiàn)后撥動(dòng)開(kāi)關(guān)按鍵給開(kāi)發(fā)板上電。PL_ETH網(wǎng)口的位置如下圖所示。
圖 28.5.1 PL_ETH網(wǎng)口位置
點(diǎn)擊Vivado左側(cè)“Flow Navigator”窗口最下面的“Open Hardware Manager”,此時(shí)Vivado軟件識(shí)別到下載器,點(diǎn)擊“Hardware”窗口中“Program Device”下載程序,在彈出的界面中選擇“Program”下載程序。
程序下載完成后,PHY芯片會(huì)和電腦網(wǎng)卡進(jìn)行通信(自協(xié)商),如果程序下載正確并且硬件連接無(wú)誤的話(huà),我們點(diǎn)擊電腦右下角的網(wǎng)絡(luò)圖標(biāo),會(huì)看到本地連接剛開(kāi)始顯示的是正在識(shí)別,一段時(shí)間之后顯示未識(shí)別的網(wǎng)絡(luò),打開(kāi)方式如下圖所示(WIN7和WIN10操作可能存在差異,但基本相同)。
圖 28.5.2 點(diǎn)擊網(wǎng)絡(luò)圖標(biāo)
點(diǎn)擊圖 27.5.3中的“未識(shí)別的網(wǎng)絡(luò)(無(wú)Internet)”,彈出如下圖所示界面。
圖 28.5.3 網(wǎng)絡(luò)設(shè)置界面
點(diǎn)擊“更改適配器”選項(xiàng),彈出如下圖所示界面。
圖 28.5.4 “網(wǎng)絡(luò)適配器界面”
如果看到上圖“以太網(wǎng)”顯示未識(shí)別的網(wǎng)絡(luò)之后,說(shuō)明硬件連接和程序都是沒(méi)有問(wèn)題的,接下來(lái)設(shè)置以太網(wǎng)的IP地址,改成代碼中設(shè)置的目的IP地址,頂層模塊參數(shù)定義如下:
//目的IP地址 192.168.1.102
parameter DES_IP = {8’d192,8’d168,8’d1,8’d102};
因此接下來(lái)將電腦以太網(wǎng)的IP地址設(shè)置成192.168.1.102。鼠標(biāo)右擊圖 27.5.5中的以太網(wǎng),如下圖所示:
圖 28.5.5 鼠標(biāo)右擊“以太網(wǎng)”
點(diǎn)擊“屬性”,彈出如下圖所示界面。
圖 28.5.6 以太網(wǎng)“屬性”界面
鼠標(biāo)雙擊“Internet協(xié)議版本4(TCP/IPv4)”,彈出如下圖所示界面。
圖 28.5.7 設(shè)置以太網(wǎng)IP地址
在“Internet協(xié)議版本4(TCP/IPv4)”屬性界面中,選擇使用下面的IP地址,IP地址設(shè)置成192.168.1.102,并點(diǎn)擊確定完成設(shè)置。
接下來(lái)以管理員身份打開(kāi)電腦的命令的DOS命令窗口(注意必須以管理員身份打開(kāi)),打開(kāi)方式如下:
圖 28.5.8 打開(kāi)電腦DOS命令窗口
打開(kāi)DOS命令窗口后,在命令行中輸入“arp -a”,如下圖所示:
圖 28.5.9 輸入命令“arp -a”
輸入完成后,按下鍵盤(pán)的回車(chē)鍵,此時(shí)會(huì)彈出電腦中所有網(wǎng)絡(luò)接口的ARP緩存表,我們只需要關(guān)注以太網(wǎng)接口的ARP緩存表(IP地址為192.168.1.102),如下圖所示:
圖 28.5.10 以太網(wǎng)接口ARP緩存表
可以發(fā)現(xiàn),此時(shí)ARP緩存表中還沒(méi)有開(kāi)發(fā)板的MAC地址和IP地址,此時(shí)我們按下開(kāi)發(fā)板的PL Key1按鍵。按下后,開(kāi)發(fā)板會(huì)向電腦發(fā)起ARP請(qǐng)求,并且電腦會(huì)返回自己的MAC地址到開(kāi)發(fā)板。
需要說(shuō)明的是,在開(kāi)發(fā)板發(fā)起ARP請(qǐng)求時(shí),會(huì)將開(kāi)發(fā)板的MAC地址和IP地址都發(fā)給電腦,此時(shí)電腦就已經(jīng)獲取到了開(kāi)發(fā)板的MAC地址和IP地址,并更新至ARP的緩存表中,我們重新在DOS命令中輸入“arp -a”,如圖 28.5.11和圖 28.5.12所示。
圖 28.5.11 輸入“arp -a”
圖 28.5.12 開(kāi)發(fā)板的MAC地址更新至緩存表中
由上圖可知,此時(shí)以太網(wǎng)接口的ARP緩存表中已經(jīng)添加了開(kāi)發(fā)板的IP地址(192.168.1.10)和MAC地址(00-11-22-33-44-55),說(shuō)明開(kāi)發(fā)板發(fā)送ARP請(qǐng)求成功。如果大家操作失敗,請(qǐng)檢查開(kāi)發(fā)板的PL網(wǎng)口(GE_PL)是否通過(guò)網(wǎng)線(xiàn)連接電腦的網(wǎng)口,并且此時(shí)開(kāi)發(fā)板已經(jīng)下載程序以及通過(guò)按下PL Key1按鍵來(lái)觸發(fā)ARP請(qǐng)求。另外,如果電腦網(wǎng)口不支持千兆網(wǎng)通信,那么也會(huì)導(dǎo)致ARP操作失敗。
接下來(lái)我們?cè)賮?lái)通過(guò)電腦發(fā)起ARP請(qǐng)求,驗(yàn)證開(kāi)發(fā)板有沒(méi)有正確返回ARP應(yīng)答。我們先從以太網(wǎng)ARP緩存表中刪除開(kāi)發(fā)板的MAC地址,刪除方法是在DOS命令中輸入“arp -d”,并按下按鍵的回車(chē)鍵,如下圖所示:
圖 28.5.13 輸入“arp -d”
接下來(lái)重新在DOS命令中輸入“arp -a”,來(lái)驗(yàn)證是否刪除成功(如果沒(méi)有以管理員運(yùn)行會(huì)導(dǎo)致刪除失?。?,輸入完成后,如下圖所示;
圖 28.5.14 刪除開(kāi)發(fā)板MAC地址
此時(shí)我們之前獲取的開(kāi)發(fā)板MAC地址已經(jīng)刪除成功,接下來(lái)在DOS命令中輸入“ping 192.168.1.10”,來(lái)讓電腦發(fā)起ARP請(qǐng)求,如下圖所示。
圖 28.5.15 電腦發(fā)起“ARP”請(qǐng)求
需要說(shuō)明的是,ping是一個(gè)十分強(qiáng)大的TCP/IP工具,它可以用來(lái)檢測(cè)網(wǎng)絡(luò)的連通情況和分析網(wǎng)絡(luò)速度。ping命令是一個(gè)固定格式的ICMP(Internet控制報(bào)文協(xié)議)請(qǐng)求數(shù)據(jù)包,之后會(huì)發(fā)起ARP請(qǐng)求命令,所以我們這里是通過(guò)ping命令來(lái)間接發(fā)起ARP請(qǐng)求。由于開(kāi)發(fā)板并沒(méi)有實(shí)現(xiàn)ICMP協(xié)議,因此在ping時(shí)會(huì)請(qǐng)求超時(shí),但是在ping的過(guò)程中發(fā)起的ARP請(qǐng)求,開(kāi)發(fā)板會(huì)響應(yīng)并返回ARP應(yīng)答數(shù)據(jù)。
接下來(lái)再次在DOS命令中輸入“arp -a”,查詢(xún)是否成功獲取到開(kāi)發(fā)板MAC地址,如下圖所示:
圖 28.5.16 開(kāi)發(fā)板MAC地址獲取成功
由上圖可知,電腦正確獲取到開(kāi)發(fā)板的MAC地址,并更新至ARP緩存表中。到這里,開(kāi)發(fā)板實(shí)現(xiàn)的ARP協(xié)議就已經(jīng)全部驗(yàn)證成功了。
接下來(lái)介紹一個(gè)以太網(wǎng)通信時(shí)經(jīng)常使用的抓包軟件,該軟件位于開(kāi)發(fā)板所隨附的資料“6_軟件資料/1_軟件/Wireshark”目錄下,也可以直接在網(wǎng)上搜索下載,我們現(xiàn)在打開(kāi)Wireshark,界面如下圖所示:
圖 28.5.17 wireshark打開(kāi)界面
雙擊上圖所示的以太網(wǎng)或者先選中以太網(wǎng),再點(diǎn)擊上方紅框選中的藍(lán)色按鈕,即可開(kāi)始抓取本地連接的數(shù)據(jù)包,抓取界面如下圖所示:
圖 28.5.18 wireshark以太網(wǎng)打開(kāi)界面
從上圖可以看到,已經(jīng)抓取到其它應(yīng)用程序使用以太網(wǎng)發(fā)送的數(shù)據(jù)包,但是這些數(shù)據(jù)包并不是開(kāi)發(fā)板發(fā)送的數(shù)據(jù)包,我們這個(gè)時(shí)候按下開(kāi)發(fā)板的PL Key1按鍵,就可以在wireshark中抓取到數(shù)據(jù)包了,抓取到的數(shù)據(jù)包如下圖所示:
圖 28.5.19 wireshark抓取到的數(shù)據(jù)包
上圖中第38行數(shù)據(jù)包是開(kāi)發(fā)板發(fā)送給電腦的ARP請(qǐng)求包,第39行數(shù)據(jù)包是電腦發(fā)送給開(kāi)發(fā)板的ARP應(yīng)答包,此時(shí)雙擊第38行即可看到開(kāi)發(fā)板發(fā)送的詳細(xì)數(shù)據(jù),如下圖所示:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-403379.html
圖 28.5.20 wireshark抓取到的詳細(xì)數(shù)據(jù)
上圖中下方紅框?yàn)殚_(kāi)發(fā)板發(fā)送的16進(jìn)制數(shù)據(jù)(去掉前導(dǎo)碼、SFD和CRC值),可以看到,后面的18個(gè)0就是我們?cè)诎l(fā)送時(shí)填充的18個(gè)字節(jié)數(shù)據(jù)。需要說(shuō)明的是,當(dāng)打開(kāi)第39行電腦返回的ARP請(qǐng)求包時(shí),看不到填充的0,這是由于后面填充的數(shù)據(jù)是網(wǎng)卡自動(dòng)填充的,因此wireshark中會(huì)看不到。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-403379.html
到了這里,關(guān)于【正點(diǎn)原子FPGA連載】第二十八章 以太網(wǎng)ARP測(cè)試實(shí)驗(yàn) 摘自【正點(diǎn)原子】DFZU2EG/4EV MPSoC 之FPGA開(kāi)發(fā)指南V1.0的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!