Tang nano 9kを貸してもらいました
先生がriscvのお勉強のためにアルディーノの異母兄弟のようなものを貸してくれました。verilogとかそういうレイヤのことはなにも知りませんが検索してひっかかった記事をもとにLチカさせていただこうと思います。
全体の流れ
- tang nano 9kにピンをはんだづけする(百均でたしか買えたかも...?)
- GOWIN EDAというIDEをダウンロードする
- ライセンス申請してライセンスファイルをもらう
- この記事に従ってverilogファイルを作成、ピン接続、FPGAに頑張ってもらう
1. GOWIN EDAのダウンロード
2. ライセンス申請
上のサイトから申請してください。
ライセンスファイルがない場合EDAだけあっても起動しませんので注意してください。なおライセンスを申請する際macアドレスを求められますが、power shellであるならipconfig all
の出力の物理アドレスの部分をコピペするといいです。
申請後は1日と経たず@gowinsemi.comからライセンスファイルの添付されたメールが来るので、それらのファイルをEDAをダウンロードしたら勝手にできるC直下にあるGOWINフォルダ直下に置きます。その後EDAを開いてライセンスファイルを指定すると使えるようになると思います。.licファイルを二つ貰うと思うのですが、ダウンロードしたEDAのバージョンによるものらしいので二つとも試してみるといいです。
3. 記事をもとにLチカ
記事のEDAのバージョンが少し前のものなので様子が違う画面だった||一瞬詰まったところだけ書きます。元記事が素晴らしく丁寧なのでそちらをもとに進めてください。
-
Prepare the code
verilogプログラムの解説をしてみます。verilogとはこういうときにこういうピンにこういう出力をしてね、と指定するためのものです。こういう入力の時はこうね、など条件指定もできます。ここで定義したピンをどうtang nano 9kに接続するのが後の3.2 constrainらしいです。tang nano 9kのボード上に備え付けのledを点灯するために適切なピンに接続しなければなりません。
module led (
input sys_clk, // clk input
input sys_rst_n, // reset input
output reg [5:0] led // 6 LEDS pin
);
reg [23:0] counter;
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
counter <= 24'd0;
else if (counter < 24'd1349_9999) // 0.5s delay
counter <= counter + 1'b1;
else
counter <= 24'd0;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
led <= 6'b111110;
else if (counter == 24'd1349_9999) // 0.5s delay
led[5:0] <= {led[4:0],led[5]};
else
led <= led;
end
endmodule
このVerilogプログラムは6つのLEDピンを制御するためのモジュールを定義しています。モジュールの名前は"led"です。
モジュールの入力と出力は次のようになっています。
- 入力:
- sys_clk: クロック信号の入力
- sys_rst_n: リセット信号の入力
- 出力:
- led: 6つのLEDピンの出力(6ビットのレジスタ)
このモジュールでは、クロック信号とリセット信号に応じて動作が制御されます。まず、カウンタレジスタ"counter"が定義されています。このレジスタは24ビットの幅を持ちます。どうしてかは知りません。
次に2つのalwaysブロックがあります。これらブロックは共通してクロックの立ち上がりエッジ(posedge)またはリセット信号の立ち下がりエッジ(negedge)が検出されるたびに実行されます。片方がconterを管理するものでもう片方がcounterをもとにledを管理するものです。
信号としてピンに流す値について注意なのですが0が1みたいなふるまいしてます。どうしてかはわかりませんがこのような負論理が便利である場合がこのボードなのかもしれません。counterの中などの値は普通に扱われています。
1つ目のalwaysブロックでは、もしリセット信号が0(アクティブ)であれば、カウンタは0にリセットされます。それ以外の場合、カウンタが24'd1349_9999(0.5秒)未満の場合は、カウンタを1増加させます。上記の条件に当てはまらない場合は、0.5秒経ったということなのでカウンタを0にリセットします。
2つ目のalwaysブロックでは、もしリセット信号が0であれば、LEDの出力は6'b111110(HDMI端子を右にしたときの一番上のLEDのみ点灯)に設定されます。それ以外の場合、カウンタが24'd1349_9999(0.5秒の遅延)と等しい場合は、LEDの出力を左に1ビットシフトします(ロケット鉛筆的に)。上記の条件に当てはまらない場合は、指定した遅延を経過していないということなのでLEDの出力はそのまま維持されます。
このプログラムは、カウンタを使用して0.5秒ごとに111110, 111101, 111011とLEDの状態を変化させることで、LEDピンを点滅させる動作を実現しています。また、リセット信号がアクティブな場合には、最初の状態に初期化されます。
以上、chatGPTからでした。
ちなみに噂で聞いたのですがverilogは命令が完全に同時に行われるのでalwaysブロックの前後関係を考える必要はないらしいです。その前後を変えてもちゃんと動きました。
またo.5秒の遅延を作るために24'd1349_9999という表現が用いられていますが、これはverilogでの定数の表現みたいです。0.1秒の遅延では24'd269_999になるので書き換えるとより高速にちかちかしてくれます。
3.2. Constrain
Ports(8)の中にある適当なピンを右クリックして接続を編集してください。よくわかりませんが、ピン12につないではいけないというのは何かを出力するためのものとして割り当てられてるからみたいです。このpdfとFloorPlannerウィンドウのPackage viewをみるところ、12, 4, 52ピンはそういう役割をもってるピンみたいです。
結果
参考記事
- https://wiki.sipeed.com/hardware/en/tang/Tang-Nano-9K/examples/led.html
- https://wiki.sipeed.com/hardware/en/tang/Tang-Nano-Doc/examples.html
-
https://github.com/sipeed/TangNano-9K-example
1番下のリポジトリから上のサイトにたどり着きました。このリポジトリにLチカからHDMI出力までたくさんの例がそろっているのでしばらく世話になるつもりです。
おわりに
もうちょっとだけLチカで遊んでからpicorvを動かせるようになるつもりです。面白い記事があったら紹介してくださるとうれしいです!何か間違った認識をしていましたら、指摘してくださると喜びます
ありがとうございました。