
インターネット・プロトコル・スイート
リンク層とインターネット層を接続するLow-level APIを実装します。Low-level APIは、FPGAに実装されたEthernet MAC CoreとLocal Memoryをアクセスし、Ethernet Frameの送受信を行います。
APIの仕様
Ethernet Frameの送信
void ether_write_frame(int flen,unsigned char *fbuf);
- 説明
- fbufに格納された、長さflenのByteデータをEthernet Frameとして送信します。
- 戻り値
- なし
Ethernet Frameの受信
int ether_read_frame(unsigned char *fbuf);
- 説明
- 受信したEthernet Frameを、fbufにByteデータとして格納します。
- 戻り値
- fbufに格納したByteデータの長さ。
Ethernet Frameの送信フロー
Ethernet Frameの送信は、以下の手順で行います。
- FrameデータをCPUからFPGA内Local Memoryに転送
- Ethernet MAC CoreのMode RegisterのTXEN bitを1に設定
- Ethernet MAC CoreのTx Buffer DescriptorのTXPNTに、Frameデータを格納したLocal Memoryのアドレスを設定
- Tx Buffer DescriptorのRD bitを1に設定
- 送信完了のインタラプトを待つ
- インタラプトを解除

Ethernet Frameの送信フロー
FrameのCRCは、Ethernet MAC CoreからPHYへの転送時に計算されて付加されます。Tx Buffer Descriptorが有効化されると、Ethernet MAC CoreはTx Buffer Descriptorレジスタの設定に従って、送信データをLocal Memoryから読み出し、Ethernet FrameとしてPHYに出力します。
送信用API ether_write_frameの実装
コード実装は以下の通りです。
void ether_write_frame(int flen,unsigned char *fbuf) {
int i, flush;
struct st_txdesc_l txl;
unsigned int a;
// Tx Buffer Descriptorの設定
txl.LONG = 0;
txl.IRQ = 1; // Interrupt Request Enable
txl.PAD = 1; // PAD Enable
txl.CRC = 1; // CRC Enable
txl.WR = 1; // Wrap
// 送信データの設定
a = ETHER_BUF_TX_BASE; // Local Memoryの先頭アドレス
for (i=0; i< flen;i++) {
if (((a+i) % 4) == 3) flush = 1;
else flush = 0;
if (i == (flen -1)) flush = 1; // final data
ether_write_byte(a+i, fbuf[i], flush); // Byte単位でFrameデータをLocal Memoryにセット
}
// set TxBD ready for descriptor 0
txl.RD = 1; // Tx Buffer Descriptorを有効化
(*(volatile unsigned int *)(ETHER_BD_BASE)) = txl.LONG;
}
Ethernet Frameの受信フロー
Ethernet Frameの受信は、以下の手順で行います。
- Ethernet MAC CoreのMode RegisterのRXEN bitを1に設定
- Ethernet MAC CoreのRx Buffer DescriptorのRXPNTに、Frameデータを格納するLocal Memoryのアドレスを設定
- Ethernet MAC CoreのRx Buffer DescriptorのE(Empty)bitを1に設定
- 受信完了インタラプトを待つ
- インタラプトを解除
- FrameデータをLocal MemoryからCPUに転送

Ethernet Frameの受信フロー
PHYからEthernet Frameを受信すると、Ethernet MAC CoreはRx Buffer Descriptorレジスタの設定に従って、Ethernet FrameをLocal Memoryに格納します。受信Frameは、Rx Buffer DescriptorのRXPNTが示すLocal Memoryのアドレスに格納されます。FrameのCRCは、Local Memoryへの格納時に削除されます。
受信用API ether_read_frameの実装
コード実装は以下の通りです。
int ether_read_frame(unsigned char *fbuf) {
int i,j,p, size,s;
unsigned int x;
struct st_rxdesc_l rxl;
rxl.LONG = (*(volatile unsigned int *)(ETHER_BD_RX_BASE+ether_cur_rx_bd*8));
size = rxl.LEN; // 受信FrameのByte長を獲得
p =0;
s = size /4;
if ((size %4 ) != 0) s++;
for (i = 0; i< s; i++) { // 32bit単位でLocal Memoryからデータをリード
x =(*(volatile unsigned int *)(ETHER_BUF_RX_BASE+ether_cur_rx_bd*ETHER_BUFFER_SIZE+i*4));
for (j=0;j <4; j++) {
fbuf[p] = (x > (3-j)*8)&0xff; // fbufにByte単位で格納
p++;
}
}
rxl.LEN = 0;
rxl.E = 1; // Rx Buffer DescriptorのEmpty bitをセット
(*(volatile unsigned int *)(ETHER_BD_RX_BASE+ether_cur_rx_bd*8)) = rxl.LONG;
if (ether_cur_rx_bd == (ETHER_MAX_RX_BD-1))
ether_cur_rx_bd = 0;
else
ether_cur_rx_bd++;
return size; // Frameのデータサイズを返す
}