季節のe7UDP/IP IPコアのサンプル(二種)

e7UDP/IP IPコアを使うと,FPGAで簡単にUDPパケットをやりとりできます.

…と言っておきながら,分かりやすいサンプルがなかったので用意してみました.

  • ボタンを押したらUDPパケットを送信する回路
  • UDPで送られてきた文字列の大文字を小文字に変換して送り返す回路

の二種類です.

※ 実際に使用を試すにはコアと,トップモジュールのHDLが必要です.

ボタンを押したらUDPパケットを投げる回路

何をさておき,まずはソースコードをおいておきます.

長いですか?たしかに,一見長いように見えますが,実際にパケットを投げている部分は

という部分です.

この部分は大きく二つのパートで構成されていて,

前半のifで構成されているパートでは,

  • パケット送信中(tx_counter > 0)は毎サイクルパケット送信カウンタをインクリメントする
  • パケット送信開始前(tx_counter = 0)で,送信可能(Ack=’1′)なら送信を開始する
  • パケット送信開始前に送信可能でない(Ack=’0′)ならコアに送信リクエストをだす

という処理をしています.

後半のcaseで構成されているパートでは,クロックにあわせて,UDPパケットを送るための情報をコアに供給しています.

0〜3クロックではパケットヘッダに相当するデータを,4クロック目以降(今回は1クロックだけ)がペイロードに相当するデータを送っています.

パケットを受け取って送り返す回路

今度は,送り返すだけ,の簡単な回路を作ってみます.といっても単に折り返すだけでは,応用しようとする場合の例として分かりにくいので,

  • 受け取ったUPDパケットのデータをメモリに格納する
  • メモリから読み出しつつ,大文字を小文字に変換する

というサンプルを用意してみました.

このHDLでは大きく次の3つのステートを定義しています.一つずつ少し丁寧にみていきます.

  • パケットがくるまで待つ(IDLE)
  • 来たパケットを受信する(RECV)
  • パケットを送信する(SEND)

パケットがくるまで待つ

パケットが来るまでまつ部分のコードはこうです

e7UDP/IP IPコアは,コアにパケットが到着するとpI0Enを’1’にするので,このステートでは,単にそれを待ち続けています.待っている間は,コアにパケットが到着したらデータを送ってよい,という意味でpI0Ackを’1’にしているというのがポイントでしょうか.

パケットが到着したら,受信ステートに遷移します.

来たパケットを受信する

次は来たパケットを受信しながらメモリに書く部分をみてみます.

コアは受信したデータをサイクル毎に32bitずつ出力してきます.なので,ここでは,受信ルーチンではその出力データを取りこぼすことなく処理する必要があります.送信するとき同様,0〜3サイクルの間はヘッダに関する情報を,4サイクル目以降でペイロードデータを出力してきます.

この回路では,4サイクル以降のデータだけをメモリに書き出しています.

コアは受信したUDPパケットの出力を終えると,pI0Enを’0’にするので,そのタイミングで受信を終えて,送信ステートに遷移しています.

パケットを送信する

最後は送信部分です.本質的には,ボタンを押してパケットを送る回路と変わりはありません.

前半のifの部分では,送信を開始するまでと,送信中のカウンタを処理していて,caseの部分がデータをコアに供給している部分です.

4サイクル以降がペイロードなので,この部分でメモリから読み出したデータに大文字→小文字変換関数を適用した結果をコアに供給しています.

使ってみる

“ボタンを押したらパケットを送る”くらいであればtcpdumpでみればいいのですが,今回はパケットを入力してあげないといけないので,ちょっとプログラムを書いてみます.

RubyでUDP投げる,なら,こんな感じでしょうか.もっとエレガントにかけるかもしれませんが.

引数に与えた文字列が,大文字が小文字に変換された出力されます.

最後に

卒論や修論に向けての実装も佳境を迎えるこの季節,e7UDP/IPを使って面倒なI/O部分は楽してみませんか?(e7UDP/IPの使い方ではまっても責任はとれませんが…)

シェアする

  • このエントリーをはてなブックマークに追加

フォローする