Skip to content
Takeshi MATSUYA edited this page Jun 19, 2015 · 22 revisions

#10G Ethernet by FPGA (study of XGMII) #FPGAで10G Ethernet (XGMIIの勉強)

1. Abstract

Figure 1 shows the whole, I will show optical connector, SFP+ module, PCS/PMA core on FPGA and user logic circuit from the right. I will explain them from the right.

図1は,全体を表し,画面右側より,光コネクタ,SFP+モジュール,FPGA内のPCS/PMAコアとユーザーロジック回路を示します. 以下に,右側から順に追って解説します.

<Figure1 Block>

<図1 全体図>

<Picture1 SFP+module(left)とFiber LC connector(right)>

<写真1 SFP+モジュール(左)と光LCコネクタ(右)>

1-1. SFP+ module

A SFP+ module and FPGA are connected by SERDES and I2C. SERDES is used for transmitting ethernet packet. I2C is used for getting information about module. As for standard specific of SFP+ module, please refer to SFF-8431.

ROM inside the module In rom inside the module, a vendor code or various information are written. As for ROM contents, please refer to [SFP+ モジュール内ROMについて](https://github.com/tmatsuya/wiki/wiki/SFP ROM).

SFP+モジュールとFPGAの接続は,SERDES (SERializer/DESerializer)I2C 通信によって行われ, イサーネットパケットの送受信用にSERDES,モジュールに関する情報の取得用にI2Cを使います. SFP+ モジュールの標準仕様についてはSFF-8431をご覧ください.

モジュール内にあるROMはベンダーや各種物理情報が記載されています ROMの内容については,[SFP+ モジュール内ROMについて](https://github.com/tmatsuya/wiki/wiki/SFP ROM)をご覧ください.

1-2. 10G PCS/PMA Core

PMA provides converting parallel into serial and serial into parallel. PCS provides encoding, decoding 64b/66b, XGMII (10 Gigabit Media Independent Interface) I/F and MDIO (Management Data Input Output) I/F.

PMA (Physical Medium Attachment) は,SFP+モジュール側シリアル(TD/RD)とパラレルの変換を, PCS (Physical Coding Sublayer) は,64b/66bの符号化,復号化を行い,FPGAやASIC内のロジックに対して XGMII (10 Gigabit Media Independent Interface)とMDIO (Management Data Input Output)を提供します.

1-3. User logic/ユーザーロジック

Some user logics.

多くのユーザーロジックでは,FIFOやバスをインターフェイスとするMAC (Media Access Control) コアを経由して, パケットの送信,受信の指示が行われることが多いですが,本チュートリアルでは XGMII 経由で行います.

2. XGMII (10 Gigabit Media Independent Interface)

図2で示すように,XGMIIは10G Ethernetのインターフェイスで下記の信号より構成されています.

  1. 送信データ32ビット (XGMII_TXD),送信制御4ビット (XGMII_TXC)
  2. 受信データ32ビット (XGMII_RXD),受信制御4ビット (XGMII_RXC)
  3. 上記を156.25MHzのクロックで,DDR (Double Data Rate)で転送

DDRの場合,クロックの立ち上がりエッジと立ち上がりエッジで転送するため, 片側32ビットデータ転送を実質2倍のクロックである312.5MHzで動作できる回路が必要になります. Kintex/Virtex-7では,動作可能な周波数ではありますが, FPGAで使う場合は,(設計に余裕を持たせるため?に)クロックを半分の156.25MHzに落とし, バス幅を倍の片側64ビットデータにして動作せることがよくあります. このウェブページでは前者の32ビット幅で312.5MHz動作させるものをXGMII (32ビット版), 後者の64ビット幅で156.25MHz動作させるものをXGMII (64ビット版)と以後呼び, 特にビット幅の記述がなければ,64ビット版のXGMIIについて解説します.

XGMIIの標準仕様については,IEEE P802.3ae 10 Gigabit Ethernet Task Force XGMII Updateをご覧ください.

<図2 XGMIIインターフェイス (32 bit)>

2-1. XGMII_RXD/TXD と XGMII_RXC/TXC について

表1はXGMII(64ビット版),表2はXGMII(32ビット版)で使われる信号の一覧です. 信号名がXGMII_RXで始まるものは受信,XGMII_TXではじまるものが送信, 信号名がDで終わるものがデータ,Cで終わるものが制御信号をあらわします. 64ビット版 XGMIIでは,一度に8バイトを転送し,先頭バイトは下位ビットから割り当てられます. 表1で示すように,受信の+0バイト目は,XGMII_RXD[7:0],+1バイト目はXGMII_RXD[15:8], 最後の+7バイト目はXGMII_RXD[63:56]となります. 転送したものがデータである場合は,該当制御信号が 0 となり, 制御コードである場合は,制御信号が 1 となります. +0バイト目の制御信号は,XGMII_RXC[0],+1バイト目ではXGMII_RXC[1]です.

<表1 XGMII ポート (64 bit)>

信号名 方向 (ユーザ視点) 位置 内容
xgmii_clk Input 156.25MHzクロック
xgmii_rxd[ 7: 0] Input 受信 0バイト目 データまたは制御コード
xgmii_rxd[15: 8] Input 受信 1バイト目 データまたは制御コード
xgmii_rxd[23:16] Input 受信 2バイト目 データまたは制御コード
xgmii_rxd[31:24] Input 受信 3バイト目 データまたは制御コード
xgmii_rxd[39:32] Input 受信 4バイト目 データまたは制御コード
xgmii_rxd[47:40] Input 受信 5バイト目 データまたは制御コード
xgmii_rxd[55:48] Input 受信 6バイト目 データまたは制御コード
xgmii_rxd[63:56] Input 受信 7バイト目 データまたは制御コード
xgmii_rxc[0] Input 受信 0バイト目 0:データ 1:制御コード
xgmii_rxc[1] Input 受信 1バイト目 0:データ 1:制御コード
xgmii_rxc[2] Input 受信 2バイト目 0:データ 1:制御コード
xgmii_rxc[3] Input 受信 3バイト目 0:データ 1:制御コード
xgmii_rxc[4] Input 受信 4バイト目 0:データ 1:制御コード
xgmii_rxc[5] Input 受信 5バイト目 0:データ 1:制御コード
xgmii_rxc[6] Input 受信 6バイト目 0:データ 1:制御コード
xgmii_rxc[7] Input 受信 7バイト目 0:データ 1:制御コード
xgmii_txd[ 7: 0] Output 送信 0バイト目 データまたは制御コード
xgmii_txd[15: 8] Output 送信 1バイト目 データまたは制御コード
xgmii_txd[23:16] Output 送信 2バイト目 データまたは制御コード
xgmii_txd[31:24] Output 送信 3バイト目 データまたは制御コード
xgmii_txd[39:32] Output 送信 4バイト目 データまたは制御コード
xgmii_txd[47:40] Output 送信 5バイト目 データまたは制御コード
xgmii_txd[55:48] Output 送信 6バイト目 データまたは制御コード
xgmii_txd[63:56] Output 送信 7バイト目 データまたは制御コード
xgmii_txc[0] Output 送信 0バイト目 0:データ 1:制御コード
xgmii_txc[1] Output 送信 1バイト目 0:データ 1:制御コード
xgmii_txc[2] Output 送信 2バイト目 0:データ 1:制御コード
xgmii_txc[3] Output 送信 3バイト目 0:データ 1:制御コード
xgmii_txc[4] Output 送信 4バイト目 0:データ 1:制御コード
xgmii_txc[5] Output 送信 5バイト目 0:データ 1:制御コード
xgmii_txc[6] Output 送信 6バイト目 0:データ 1:制御コード
xgmii_txc[7] Output 送信 7バイト目 0:データ 1:制御コード

<表2 XGMII ポート (32 bit)>

信号名 方向 (ユーザ視点) 位置 内容
xgmii_clk Input 312.5MHzクロック
xgmii_rxd[ 7: 0] Input 受信 0バイト目 データまたは制御コード
xgmii_rxd[15: 8] Input 受信 1バイト目 データまたは制御コード
xgmii_rxd[23:16] Input 受信 2バイト目 データまたは制御コード
xgmii_rxd[31:24] Input 受信 3バイト目 データまたは制御コード
xgmii_rxc[0] Input 受信 0バイト目 0:データ 1:制御コード
xgmii_rxc[1] Input 受信 1バイト目 0:データ 1:制御コード
xgmii_rxc[2] Input 受信 2バイト目 0:データ 1:制御コード
xgmii_rxc[3] Input 受信 3バイト目 0:データ 1:制御コード
xgmii_txd[ 7: 0] Output 送信 0バイト目 データまたは制御コード
xgmii_txd[15: 8] Output 送信 1バイト目 データまたは制御コード
xgmii_txd[23:16] Output 送信 2バイト目 データまたは制御コード
xgmii_txd[31:24] Output 送信 3バイト目 データまたは制御コード
xgmii_txc[0] Output 送信 0バイト目 0:データ 1:制御コード
xgmii_txc[1] Output 送信 1バイト目 0:データ 1:制御コード
xgmii_txc[2] Output 送信 2バイト目 0:データ 1:制御コード
xgmii_txc[3] Output 送信 3バイト目 0:データ 1:制御コード

2-2. 制御コード

XGMII_?XC の該当位置のビットが 1 の場合,XGMII_?XDはデータではなく制御コードをあらわします. 表3に制御コードの一覧を示します.

Idleの場合は,データ転送が行われていない期間であることを示します.

Startは,フレームの転送開始を意味します.

Terminateは,フレーム転送終了を意味し,FCS (Frame Check Sequence)の後に挿入されます.

<表3 XGMII データと制御コード>

名前 xgmii_txc / rxc xgmii_txd / rxd コメント
Data 0 (?xdにデータ) 00 - FF データ送/受信中
Idle 1 (?xdに制御コード) 07 データ未転送期間
Start 1 (?xdに制御コード) FB フレーム開始を示す
Terminate 1 (?xdに制御コード) FD フレーム終了を示す
Error 1 (?xdに制御コード) FE エラー

2-3. MII (Media Independent Interface)向けパケット構造

図3は,60バイトのパケット構造をOS層(図の上)と,MII層(図の下)で比較したものです. OS層では,先頭よりL2ヘッダーであるDestination MACからはじまり,データの最後で終わります. MII層では,プリアンブル (7バイトの55H)とStart Frame Delimiter (D5H)の8バイトが先頭に付与され, 最後に4バイトのFrame Check Sequenceが付与されます. これは,10/100Base-TのMIIや1000BASE-TのGMII (Gigabit Media Independent Interface)の構造ですが, XGMIIもほぼ,これと同じ構造で転送する必要があります.(違いについては,次節で述べます)

<図3 60バイトパケットのOS層とMII層での比較>

2-4. XGMIIを用いた転送タイミング

図4は,XGMIIを用いて,図3の60バイトパケットを受信したものです. まず先頭サイクル(一番左)では,8バイトともアイドルである 07 の制御コードを転送し, すべてが制御信号のため,XGMII_RXC[7:0]はすべてのビットが 1 になっています.

次のサイクル(左から2番目)で,プリアンブルとSFDの合計8バイトを転送します. 制御コードの "Start" は,先頭プリアンブル位置のみ置き換えられ, 2バイト目以降のプリアンブルとSFDはデータとして転送されます.

次のサイクル(左から3番目)から,OS層での先頭パケットが転送されはじめます.

パケットの最後のサイクル(右から3番目)で,"70 9D D3 D7"のFCSを転送し, 次のサイクル(右から2番目)で,制御コードの "Finish" を転送し,アイドリング状態となります.

64ビット版 XGMIIを使っている注意点として,XGMIIは32ビット単位で転送しているため, パケットの先頭位置が32ビットずれることがあります.

図5は,図4と同じパケットを32ビットずれた状態で表現したものです.

<図4 XGMII(64bit)経由でのパケット受信(0ビット目開始)>

<図5 XGMII(64bit)経由でのパケット受信(32ビット目開始)>

3. KC705ボードでXGMIIを使うには

3-1. トランシーバの構成

Xilinx 7シリーズでXGMIIを使うためには,10Gbps以上のSERDES機能をサポートする GT-X,GT-H,GT-Zなどのトランシーバが必要になります. 図6はKintex-7を使った,KC705評価ボードのトランシーバ構成です. ひとつのバンクは,2つのリファレンスクロック(図左側)と4つのSERDESチャンネル(図右側)から構成され, KC705では4つのバンクを持ち,合計16チャンネルまでのSERDESをサポートしています.

SERDESチャンネルを使うためには,必ず適切な周波数のリファレンスクロックが必要で, 利用可能なリファレンスクロックは同じバンク内か,または上下隣のバンクのみです. 例えば,バンク115のチャンネルはバンク117や118のリファレンスクロックを利用することはできません。

<図6 KC705トランシーバ割り当て>

3-2. SFP+のリファレンスクロックの選択

SFP+のSERDESはバンク117のX0Y10チャンネルに割り当てられています. この場合のリファレンスクロックソースですが, まず,Kintex-7 FPGA コネクティビティキットでは, FM-S14拡張ボード上にあるバンク118の"REFCLK1_FMC_HPC_CLK"を参照していますが,KC705ボード単体では利用できません.

次に,Virtex-7 FPGA VC709 コネクティビティキットでは, 任意周波数を生成できる内蔵のSi5324をプログラムして, XGMIIに必要なリファレンスクロックを生成しています. KC705でもSi5324(表記上ではSi5326)を搭載しているため,本チュートリアルでもこの手法が使えますが, Si5324のプログラムをするために,ソフトコアCPUであるPicoBlaze (KCPSM6)を用意する必要があり, 回路規模が大きくなるとともに,論理合成と配置配線にかかる時間を削減したいので,この手法は今回採用しません.

KC705には,プログラマブル発振器のSi570が内蔵されていて,初期値は156.25MHzで,これはXGMIIで使用するものと同じです. 従って,これをそのまま利用したいのですが,このクロックはトランシーバのリファレンスクロックと接続されていません. しかし,幸いなことにSFP+のチャンネルがあるバンク117には外部のSMA端子よりリファレンスクロックをとることができるのでこれを活用することにします.

3-3. KC705ボード用SFP+のリファレンスクロック準備

XGMII用の156.25MHzリファレンスクロックとしてSi570の初期値を利用します. しかし前節で述べたように,Si570はSERDESのリファレンスクロックに接続されていないため,リファレンスクロックと接続されている外部向けSMA端子を利用する必要があります. そのため,写真2を用いて配線の解説をします.

  1. 写真左下にあるJ15とJ16のSMAコネクタがMGT Clockで,バンク117のリファレンスクロックの入力
  2. 写真右上にあるJ13とJ14のSMAコネクタがUSER GPIOの出力
  3. SMAケーブル2本を使って,J13とJ16,J14とJ15を接続する

以上によって,USER GPIOの出力をバンク117のSMAリファレンスクロックへ入力できます. 写真3が接続後です.

<写真2 KC705 SMAコネクタとボードリビジョン(赤枠内)>

<写真3 KC705 SMAケーブル接続例>

次に,回路のトップモジュールに以下の図7を記述をすることによって, Si570からの入力を,SMAのUSER GPIOへ出力することが出来, バンク117にあるSMA MGTリファレンスクロックにXGMIIで必要な156.25MHzを供給できます.

IBUFDSとOBUFDSは差動プリミティブで,IBUFDSは差動信号の入力をOBUFDSは差動信号の出力をおこないます. ソース1では,Si570からの差動入力をそのまま,SMA GPIOの差動出力へ接続しています.

module top (
// SI570 user clock (input 156.25MHz)
input wire si570_refclk_p,
input wire si570_refclk_n,
// USER SMA GPIO clock (output to USER SMA clock)
output wire user_sma_gpio_p,
output wire user_sma_gpio_n,
// SMA MGT reference clock (input from USER SMA GPIO for SFP+ module)
input wire sma_mgt_refclk_p,
input wire sma_mgt_refclk_n);

wire clksi570;
IBUFDS IBUFDS_0 (
        .I(si570_refclk_p),
        .IB(si570_refclk_n),
        .O(clksi570)
);
OBUFDS OBUFDS_0 (
        .I(clksi570),
        .O(user_sma_gpio_p),
        .OB(user_sma_gpio_n)
);

<図7 KC705 SMAケーブル接続例>

4. 主要コードの解説

4-1. ディレクトリとファイル構成

<表4 ディレクトリとファイル構成>

ディレクトリまたはファイル 説明
ether10g/ トップディレクトリ
ether10g/boards/ ボード依存モジュール
ether10g/boards/*/Makefile Makefile
ether10g/boards/*/constraints/ 制約ファイル
ether10g/boards/*/ip_catalogs/ Xilinx IP cores
ether10g/boards/*/rtl/ RTLファイル
ether10g/boards/*/rtl/top.v トップモジュール(ボード依存)
ether10g/boards/*/rtl/app.v ユーザートップモジュール
ether10g/boards/*/synthesis/ 論理合成用
ether10g/boards/*/test/ シミュレーション用
ether10g/cores/ 共通モジュール
ether10g/cores/crc32/ FCS用CRC32計算モジュール
ether10g/cores/xgmiisync/ XGMII受信開始位置同期モジュール

4-2. 単純なパケット送信

module app (
input  wire        sys_rst,
input  wire        xgmii_clk,
output wire [63:0] xgmii_txd,
output wire  [7:0] xgmii_txc,
input  wire [63:0] xgmii_rxd,
input  wire  [7:0] xgmii_rxc);

reg [9:0] tx_counter = 10'h0;
reg [63:0] txd;
reg [7:0] txc;
always @(posedge xgmii_clk) begin
        if (sys_rst) begin
                 tx_counter <= 10'h0;
        end else begin
                 tx_counter <= tx_counter + 10'h1;
                 case (tx_counter)
                 10'h00: {txc, txd} <= {8'h01, 64'hd5_55_55_55_55_55_55_fb};
                 10'h01: {txc, txd} <= {8'h00, 64'h11_00_ff_ff_ff_ff_ff_ff};
                 10'h02: {txc, txd} <= {8'h00, 64'h00_45_00_08_66_44_33_22};
                 10'h03: {txc, txd} <= {8'h00, 64'h11_40_00_00_00_00_32_00};
                 10'h04: {txc, txd} <= {8'h00, 64'ha8_c0_65_01_a8_c0_9f_f5};
                 10'h05: {txc, txd} <= {8'h00, 64'h1a_00_09_00_09_00_66_02};
                 10'h06: {txc, txd} <= {8'h00, 64'h00_00_55_e9_9b_be_00_00};
                 10'h07: {txc, txd} <= {8'h00, 64'h00_00_03_4c_ce_53_cc_00};
                 10'h08: {txc, txd} <= {8'h00, 64'hc5_2a_99_cb_00_00_cc_00};
                 10'h09: {txc, txd} <= {8'hff, 64'h07_07_07_07_07_07_07_fd};
                 default:{txc, txd} <= {8'hff, 64'h07_07_07_07_07_07_07_07};
                 endcase
        end
end

assign xgmii_txd = txd;
assign xgmii_txc = txc;
endmodule

<図8 単純なパケット送信(FCS固定)>

$ sudo tcpdump -i eth1 -xx
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
01:15:30.275971 IP 192.168.1.101.discard > 192.168.2.102.discard: UDP, length 22
	0x0000:  ffff ffff ffff 0011 2233 4466 0800 4500
	0x0010:  0032 0000 0000 4011 f59f c0a8 0165 c0a8
	0x0020:  0266 0009 0009 001e 0000 be9b e955 0000
	0x0030:  00cc 53ce 4c03 0000 00cc 0000 0000 0000

<図9 tcpdumpの結果>

4-3. FCS (Frame Check Sequence)を考慮したパケット送信

reg crc_init = 1'b0;
wire crc_data_en;
assign crc_data_en = ~crc_init;
wire [31:0] crc64_out, crc64_outrev;
assign crc64_outrev = ~{crc64_out[24],crc64_out[25],crc64_out[26],crc64_out[27],crc64_out[28],crc64_out[29],crc64_out[30],crc64_out[31], crc64_out[16],crc64_out[17],crc64_out[18],crc64_out[19],crc64_out[20],crc64_out[21],crc64_out[22],crc64_out[23], crc64_out[ 8],crc64_out[ 9],crc64_out[10],crc64_out[11],crc64_out[12],crc64_out[13],crc64_out[14],crc64_out[15], crc64_out[ 0],crc64_out[ 1],crc64_out[ 2],crc64_out[ 3],crc64_out[ 4],crc64_out[ 5],crc64_out[ 6],crc64_out[ 7]};

crc32_d64 crc32_d64_inst (
	.rst(crc_init),
	.clk(~xgmii_clk),
	.crc_en(crc_data_en),
	.data_in({
txd[00],txd[01],txd[02],txd[03],txd[04],txd[05],txd[06],txd[07],txd[08],txd[09],
txd[10],txd[11],txd[12],txd[13],txd[14],txd[15],txd[16],txd[17],txd[18],txd[19],
txd[20],txd[21],txd[22],txd[23],txd[24],txd[25],txd[26],txd[27],txd[28],txd[29],
txd[30],txd[31],txd[32],txd[33],txd[34],txd[35],txd[36],txd[37],txd[38],txd[39],
txd[40],txd[41],txd[42],txd[43],txd[44],txd[45],txd[46],txd[47],txd[48],txd[49],
txd[50],txd[51],txd[52],txd[53],txd[54],txd[55],txd[56],txd[57],txd[58],txd[59],
txd[60],txd[61],txd[62],txd[63]
}),	// 64bit
	.crc_out(crc64_out)	// 32bit
);
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
	TX_FCS: begin
		{txc, txd} <= {8'hf0, 32'h07_07_07_fd, crc64_outrev[7:0], crc64_outrev[15:8], crc64_outrev[23:16], crc64_outrev[31:24]};
		gap_count <= inter_frame_gap - 32'd1;
		tx_state <= TX_GAP;
	end

<図10 パケット送信(FCS計算)>

4-4. パケット受信

	RX_DATA: begin
		rx_counter <= rx_counter + 10'h1;
		if (xgmii_rxc2 == 8'hff) begin
			rx_state <= RX_IDLE;
		end else begin
			case (rx_counter)
			10'h00: begin
				rx_mac_dst[47:40] <= xgmii_rxd2[ 7: 0];// Ethernet hdr: Dest MAC
				rx_mac_dst[39:32] <= xgmii_rxd2[15: 8];
				rx_mac_dst[31:24] <= xgmii_rxd2[23:16];
				rx_mac_dst[23:16] <= xgmii_rxd2[31:24];
				rx_mac_dst[15: 8] <= xgmii_rxd2[39:32];
				rx_mac_dst[ 7: 0] <= xgmii_rxd2[47:40];
				rx_mac_src[47:40] <= xgmii_rxd2[55:48];// Ethernet hdr: Src  MAC
				rx_mac_src[39:32] <= xgmii_rxd2[63:56];
			end
			10'h01: begin
				rx_mac_src[31:24] <= xgmii_rxd2[ 7: 0];
				rx_mac_src[23:16] <= xgmii_rxd2[15: 8];
				rx_mac_src[15: 8] <= xgmii_rxd2[23:16];
				rx_mac_src[ 7: 0] <= xgmii_rxd2[31:24];
				rx_ftype[15:8]    <= xgmii_rxd2[39:32];// Ethrenet hdr: Frame Type
				rx_ftype[ 7:0]    <= xgmii_rxd2[47:40];
			end

<図11 パケット受信>

5. ビルドと動作確認

5-1. 準備

ソースコードの展開

git clone https://github.com/tmatsuya/wiki.git

<図12 ソースコードの展開>

5-2. コンソールによる論理合成

cd ether10g/boards/kc705
make clean ; make

<図13 コンソールによる論理合成>

5-3. GUI環境での論理合成

cd ether10g/boards/kc705
make clean ; make gui

<図14 GUIによる論理合成>

5-4. FPGAへの書き込み

cd ether10g/boards/kc705
make load

<図15 FPGAへの書き込み>

5-5. Flash ROMへの書き込み

cd ether10g/boards/kc705
make flash

<図16 Flash ROMへの書き込み>

5-6. パケット送信動作確認

$ sudo tcpdump -i eth1 -n 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
22:05:41.588606 IP 192.168.1.101.discard > 192.168.2.102.discard: UDP, length 22
22:05:41.688608 IP 192.168.1.101.discard > 192.168.2.102.discard: UDP, length 22
22:05:41.788607 IP 192.168.1.101.discard > 192.168.2.102.discard: UDP, length 22
22:05:41.888607 IP 192.168.1.101.discard > 192.168.2.102.discard: UDP, length 22
22:05:41.988607 IP 192.168.1.101.discard > 192.168.2.102.discard: UDP, length 22
22:05:42.088607 IP 192.168.1.101.discard > 192.168.2.102.discard: UDP, length 22
22:05:42.188607 IP 192.168.1.101.discard > 192.168.2.102.discard: UDP, length 22
22:05:42.288607 IP 192.168.1.101.discard > 192.168.2.102.discard: UDP, length 22
22:05:42.388608 IP 192.168.1.101.discard > 192.168.2.102.discard: UDP, length 22

<図17 パケット送信データのtcpdump>

5-7. パケット受信動作確認

最後に受信したパケットの任意の位置をLEDで表示します. 任意の位置は,4つあるDIPスイッチの内容が,図17のcase節に対応したものです. 例えば,DIPスイッチを"1100"と指定した場合は,16進数のC (case文上では4'hc)にあたるので, フレームタイプの先頭1バイトがLEDに表示されます.

写真4が,実行写真で,フレームタイプの先頭が16進数の08 を表示しています. (IPv4のフレームタイプは 0800Hです)

case (dipsw[3:0])
	4'h0: led_r <= rx_mac_dst[47:40];
	4'h1: led_r <= rx_mac_dst[39:32];
	4'h2: led_r <= rx_mac_dst[31:24];
	4'h3: led_r <= rx_mac_dst[23:16];
	4'h4: led_r <= rx_mac_dst[15: 8];
	4'h5: led_r <= rx_mac_dst[ 7: 0];
	4'h6: led_r <= rx_mac_src[47:40];
	4'h7: led_r <= rx_mac_src[39:32];
	4'h8: led_r <= rx_mac_src[31:24];
	4'h9: led_r <= rx_mac_src[23:16];
	4'ha: led_r <= rx_mac_src[15: 8];
	4'hb: led_r <= rx_mac_src[ 7: 0];
	4'hc: led_r <= rx_ftype[15: 8];
	4'hd: led_r <= rx_ftype[ 7: 0];
	default: led_r <= 8'h00;
endcase

<図17 DIPスイッチに対応したパケット位置>

<写真4 フレームタイプ1バイト目を指定(DIPSWが1100)し08Hを表示(LEDが0000 1000)>