NetBSDでFPAG開発を始めてみる(NVCとVHDL)

この記事は、NetBSD Advent Calendar 2025の25日目の記事です。

はじめに

本当は、PyRTLで書いたロジックをTnag Nano 9Kで動かしてみたいのですが、これから勉強しないといけないので、しばらく先に進めそうにありません。 と言うことで、22日目23日目でVHDLを使ってみていましたが、その際に試していたNVCというVHDLのシミュレーターについて、試したことを書いておきたいと思います。

NVCできること

NVCは、GHDLとは違い、合成をすることはできません。 あくまで、IEEE 1076-2008のほとんどをシミュレーションできるだけのようです。 VHDLについては、普通の利用者は、GOWIN FPGA Designerを使うでしょうから、良いシミュレーターであるだけでも大きな意味があるのだと思います。 NVCはJ-Core Open Processorでも使われているようです。

NVCをインストールする

pkgsrc/cad/nvcとして、nvc-1.18.2を用意しました。 この後にインポートしておきたいと思います。

と言うことで、以下のようにインストールすれば良いでしょう。

# cd /usr/pkgsrc/cad/nvc
# make install

これによって、/usr/pkg/bin/nvcがインストールされます。 これを使って、22日目のGHDLによるシミュレーション用のMakefileに、NVCを使ったパターンも追加してみます。 analysisをするにはanalysisnvcターゲット、elaborateにはelaboratenvcターゲット、シミュレーションを実行してvcdウェーブフォームファイルを得るにはrunnvcターゲットを用意しました。

$ cat Makefile
TARG=   counter

GHDL_FLAGS+=    -fsynopsys

.PHONY: analysis elaborate run clean analysisnvc elaboratenvc runnvc

analysis: ${TARG}.vhdl
        ghdl -a ${GHDL_FLAGS} ${TARG}.vhdl
        ghdl -a ${GHDL_FLAGS} ${TARG}_tb.vhdl

analysisnvc: ${TARG}.vhdl ${TARG}_tb.vhdl
        nvc -a ${TARG}.vhdl ${TARG}_tb.vhdl

elaborate: work-obj93.cf
        ghdl -e ${GHDL_FLAGS} ${TARG}
        ghdl -e ${GHDL_FLAGS} ${TARG}_tb

elaboratenvc: analysisnvc
        nvc -e counter_tb

run: elaborate
        ghdl -r ${GHDL_FLAGS} --time-resolution=ns ${TARG}_tb --vcd=counter.vcd --stop-time=1ms

runnvc: elaboratenvc
        nvc -r --format=vcd --wave=counter-nvc.vcd --stop-time=1ms counter_tb

clean:
        rm -f counter.vcd
        rm -f work-obj93.cf
        rm -f counter-nvc.vcd
        rm -fr work

ただし、nvcの生成したcounter-nvc.vcdファイルのタイムスケールはfs単位になっていて、変更ができないようです。

結果のvcdファイルをGtkWaveで表示してみる

Zoom-outしていくと、下図のように表示できました。 既定の表示は非常にZoom-inされた状態ですが…。

これで、GHDLだけでなくシミュレーションを実行できるようになりました。 検証も確実さを上げることができそうです。

NetBSDでFPAG開発を始めてみる(PyRTL) 準備編

この記事は、NetBSD Advent Calendar 2025の24日目の記事です。

はじめに

21日目から23日目にかけて、安価に購入したFPGA基板であるTang Nano 9Kのための開発環境をNetBSD上に整え、基本的にはNetBSDだけで開発できることを確認しました。 でも、合成や配置配線にもベンダー特有の最適化が必要であるかもしれません。 また、GOWIN FPGA Designerでは、A/Dコンバーターなどの各種ロジックやArm Cortex-M0やRISC-Vなどのアーキテクチャーのマイクロコントローラーを選択するメニューがありました。 どこまで無料で使えるのか分かっていませんが、そういうものはNetBSD上では使いようがなさそうです。

とは言え、私がVerilogを学んだり、Tang Nano 9Kを購入したのは、PyRTLという教育用のHDLを使ってみたかったためでした。 なので、そういう便利なものは使えなくても困りません。 PyRTLはVerilogのソースコードを出力してくれるので、21日目のように作業できれば、最適化は別として、それで良いとも言えます。

ですが、マイナーなものを使うと、世界で最初に困る人になってしまいがちです。 PyRTLにはJupyer Notebook/JupyeterLabで学べるような教材が用意されているのですが、少なくとも2025年12月28日現在lpkgsrc経由で利用できるJupyter Notebook/JupyterLabではエラーになりウェーブフォームをウェブブラウザー上では見ることができません。 せっかくPyRTLにはシミュレーション機能が内蔵されているのに、それを活用することができません。

おそらくNetBSDで作業しているから発生する問題ではないと思われるものの、pkgsrc/cad/py-PyRTL-0.12が壊れているのは困りますので、直すことにしました。

エラーの内容

まず、私は以下のようなJupyter NotebookとJupyterLabのパッケージをインストールしています。 これ以外にも関連するものはありますが、そこまで厳密である必要はないでしょう。

py314-jupyter-lsp-2.3.0
py314-jupyter_server_terminals-0.5.3
py314-jupyter_client-8.7.0
py314-jupyterlab-4.4.10
py314-jupyter_core-5.9.1
py314-jupyterlab-pygments-0.3.0
py314-jupyter_events-0.12.0
py314-jupyterlab-server-2.28.0
py314-jupyter_server-2.17.0

エラーの内容は非常に簡単です。ipynb-examples/example1-combologic.ipynbと言う教材のStep 2の3個目のセルのsim.tracer.render_trace(symbol_len=2)が失敗します。 エラーメッセージはJavascript Error: $ is not definedです。 FirefoxのDevelopert toolのconsoleには何も出ていませんが、Jupyter Notebook/JupyterLabの画面上に表示されるエラーです。

実を言うと、ipynb-examples/example1-combologic.ipynbは、examples/example1-combologic.pyから自動生成されています。 と言うことで、examples/example1-combologic.pyの内容をそのままJupyter Notebook/JupyterLabの1つのセルで実行して、どこがいけないのか調査することにしました。

エラーを調査する

ipynbファイルを保存すると、以下のような内容が含まれています。 この内容は元々のipynbにはありません。 どこかで自動的に挿入されているはずです。

(snip)
$.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/skins/default.js"),
$.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/wavedrom.min.js"),
(snip)

ここまで特徴的であれば、/usr/pkg/lib以下を探しても迷うことはありません。 pyrtl/simulation.pyというファイルに含まれていることが分かりました。 そして、この$は、jQueryが提供されることが期待されているようです。 ですが、私のインストールしているJupyter NotebookもJupyterLabも、ウェブブラウザー上でjQueryの$は提供していないようです。 少なくとも$.getScript関数は使えません。

どこかでjQueryのgetScript関数は使うなと言われたような記憶もありますが、最新版では使えるのかもしれません。 いずれにしても、PyRTLの教材を動かすのには十分なはずです。 と言うことで、jQueryを読み込んだ後に、問題の箇所を実行するようにすれば良さそうです。

エラーを修正する

オリジナルのPyRTL-0.12のソースコードで関連する箇所を以下に示します。 この中の1775行目からのjs_code変数の中身を書き換えれば良さそうです。 改めて見ると、問題の箇所は、当然ですがJupyter Notebook/JupyterLabで実行した場合のみ呼び出されるようになっています。

  1760          if _currently_in_jupyter_notebook():
  1761              from IPython.display import (
  1762                  HTML,
  1763                  Javascript,
  1764                  display,
  1765              )
  1766
  1767              from pyrtl.visualization import trace_to_html
  1768
  1769              htmlstring = trace_to_html(
  1770                  self, trace_list=trace_list, sortkey=_trace_sort_key
  1771              )
  1772              html_elem = HTML(htmlstring)
  1773              display(html_elem)
  1774              # print(htmlstring)
  1775              js_stuff = """
  1776              $.when(
  1777              $.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/skins/default.js"),
  1778              $.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/wavedrom.min.js"),
  1779              $.Deferred(function( deferred ){
  1780                  $( deferred.resolve );
  1781              })).done(function(){
  1782                  WaveDrom.ProcessAll();
  1783              });"""
  1784              display(Javascript(js_stuff))

Jupyter NotebookやJupyterLabを実行できるウェブブラウザーであれば、fetch関数やpromiseのサポートは持っているはずな気がします。 と言うことで、安直ですがfetchして実行する関数を用意し、jQueryを読み込んだ後に、promiseを使って、既存のロジックを実行させることにしました。

以下のようなパッチを作成して適用しました。

@@ -1773,6 +1773,16 @@ class SimulationTrace:
             display(html_elem)
             # print(htmlstring)
             js_stuff = """
+            function fetchAndRunScript(uri) {
+              return fetch(uri)
+                .then(resp => resp.text())
+                .then(scrtext => {
+                  const scrfunc = new Function(scrtext);
+                  scrfunc();
+                })
+                .catch(err => console.error('Cannot load script:', err));
+            }
+            fetchAndRunScript("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js").then(() => {
             $.when(
             $.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/skins/default.js"),
             $.getScript("https://cdnjs.cloudflare.com/ajax/libs/wavedrom/1.6.2/wavedrom.min.js"),
@@ -1780,7 +1790,7 @@ class SimulationTrace:
                 $( deferred.resolve );
             })).done(function(){
                 WaveDrom.ProcessAll();
-            });"""
+            });});"""
             display(Javascript(js_stuff))
         else:
             self.render_trace_to_text(

こうすることで、ウェブブラウザー上でウェーブフォームを表示させることができるようになりました。 これで、FPGAに実装する前のチェックが簡単になります。

pkgsrc/cad/py-PyRTL-0.12nb1としてcommitしておこうと思います。

NetBSDでFPAG開発を始めてみる(VHDL) (2/2)

この記事は、NetBSD Advent Calendar 2025の23日目の記事です。

はじめに

22日目の記事では、GHDLを導入し、VerilogのプログラムをVHDLに移植して、そのウェーブフォームを見て、どうやら正しく移植できていそうということが確認できました。 今回は、YosysでVHDLで書かれたロジックを合成し、FPAGに反映してみます。

ghdl-yosys-pluginを導入する

ghdl-yosys-pluginをpkgsrc/devel/ghdl-yosys-pluginとしてインポートしました。 これを以下のようにインストールしておきます。 21日目を参照して、pkgsrc/devel/nextpnr-himbaechelとpkgsrc/devel/openFPGALoaderをインストールしておいてください。 pkgsrc/deve/yosysは、以下のようpkgsrc/devel/ghdl-yosys-pluginをインストールすると、依存パッケージとしてインストールされます。 もちろん、先にインストールされていても全く問題ありません。

# cd /usr/pkgsrc/devel/ghdl-yosys-plugin
# make install

合成と配置配線、ロードを実行する

元々のverilog用のMakefileを改造して、以下のようなVHDL用のMakefileを用意しておきます。

$ cat Makefile
BOARD=tangnano9k
FAMILY=GW1N-9C
DEVICE=GW1NR-LV9QN88PC6/I5

all: counter.fs

# Analysis
analysis: counter.vhdl
        ghdl -a -fsynopsys counter.vhdl

# Synthesis
counter.json: analysis
        yosys -m ghdl -p "ghdl -fsynopsys counter; synth_gowin -top counter -json counter.json"

# Place and Route
counter_pnr.json: counter.json
        nextpnr-himbaechel --json counter.json --write counter_pnr.json --freq 27 --device ${DEVICE} --vopt family=${FAMILY} --vopt cst=${BOARD}.cst

# Generate Bitstream
counter.fs: counter_pnr.json
        gowin_pack-3.14 -d ${FAMILY} -o counter.fs counter_pnr.json

# Program Board
load: counter.fs
        openFPGALoader -b ${BOARD} counter.fs -f

.PHONY: load analysis
.INTERMEDIATE: counter_pnr.json counter.json

また、なんとなくVerilogで小文字だった入出力のポート名称を大文字にしてしまったので、Tang Nano 9Kの端子への接続を指定するtangnano9k.cstファイルも以下のように作成しておきます。

$ cat tangnano9k.cst
IO_LOC "CLK" 52;
IO_PORT "CLK" PULL_MODE=UP;
IO_LOC "LED[0]" 10;
IO_LOC "LED[1]" 11;
IO_LOC "LED[2]" 13;
IO_LOC "LED[3]" 14;
IO_LOC "LED[4]" 15;
IO_LOC "LED[5]" 16;

ここまで来たら、実際にTang Nano 9KをNetBSDマシンに接続して、以下のように実行します。

$ make load

書き込みが終わると、Tang Nano 9Kの橙色のLCDの点滅が開始されます。 どうやらVerilogの場合と同様に2進数でカウントアップしてくれているようです。

これで、VerilogだけでなくVHDLでも、Tang Nano 9Kを利用できそうです。

でも私の本当の目的はPyRTLを使ってみることなのです。 これについても機会を見付けて試してみて、書いておきたいと思います。

NetBSDでFPAG開発を始めてみる(VHDL) (1/2)

この記事は、NetBSD Advent Calendar 2025の22日目の記事です。

はじめに

21日目では、Sipeed tang Nano 9KというGowin製のFPGAの搭載された基板を使い、Gowinの提供する開発ツールであるGOWIN FPGA Designner (21日目の記事ではGowin EDAと書きましたが、実際にインストールして起動してライセンスを割り当ててみたところ、こういう名前のソフトウェアでした)を使わずに、NetBSDだけでFPGAをプログラムしてみました。

その際は、Tang Nano 9Kで動くことが分かっているものでないと動作確認にもならないため、GitHubで公開されているlushaylabs/tangnano9k-series-examplesリポジトリーのcounterという例をpkgsrcに合わせて修正したものを使っていました。 この例はVerilogで書かれており、私が多少は分かるというのも良い点でした。

ただ、私はVHDLも体験してみたいと思っていました。 VHDLで書かれたものをyosysで扱えるものとして、ghdl-yosys-pluginというYosysのプラグインが用意されています。 まだ実験段階で扱えないVHDLの機能もあるのかもしれませんが、今回はこのghdl-yosys-pluginを使うために、VHDLでcounterを書き直して、シミュレーションを実行したいと思います。 明日は、Tang Nano 9Kをプログラムして、実際に動かしてみたいと思います。

VHDLを学ぶ環境を作る

VHDLのシミュレーションをするには、GHDLNVCが使えそうです。 ただ、今回はghdl-yosys-pluginを使うつもりですので、GHDLを使うことにしました。 GHDLは、pkgsrc/cad/ghdlとしてNetBSD上でも利用できます。 以下のようにインストールすれば良いでしょう。

# cd /usr/pkgsrc/cad/ghdl
# make install

これによって、ghdlコマンドを利用できるようになります。 実際の使い方は、後ほど試して行く中で探って行きたいと思います。

Verilogで書かれたcounterをVHDLに移植する

ところで、私は全くVHDLを知りませんでした。 ただ、かつてVHDLを学ぼうと思ったことはあったようで、図解VHDL実習 --ゼロから分かるハードウェア記述言語-- 堀 桂太郎著という本を持っていました。 第2版も出ているようですが、私が持っていて参照したのは無印のものです。 これで、VHDLでのロジック記載の基本的構造と、テストベンチの書き方を学ぶことができました。 もう少しちゃんと読めば、VHDLの良さを理解できそうです。 また、テストベンチの書き方については、GHDLのドキュメントも参考になりました。

Verilogで書かれたcounterは以下のようです。

$ cat counter.v
module counter
(
    input clk,
    output [5:0] led
);

localparam WAIT_TIME = 13500000;
reg [5:0] ledCounter = 0;
reg [23:0] clockCounter = 0;

always @(posedge clk) begin
    clockCounter <= clockCounter + 1;
    if (clockCounter == WAIT_TIME) begin
        clockCounter <= 0;
        ledCounter <= ledCounter + 1;
    end
end

assign led = ~ledCounter;
endmodule

これを逐一VHDLで書き直してみると、以下のようになりそうです。 VHDLでよくある書き方になっているとは思いませんが、一応後で実行するテストベンチの結果を見る限り機能は移植できているっぽいです。 第一印象としては、Verilogより固めに書かないといけないような印象を持ちました。

$ cat counter.vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter is
        Port (CLK : in std_logic;
              LED : out std_logic_vector(5 downto 0));
end counter;

architecture behavior of counter is
        constant WAIT_TIME : integer := 13500000;
        signal ledCounter : std_logic_vector(5 downto 0) := "000000";
        signal clockCounter : std_logic_vector(23 downto 0) := "000000000000000000000000";
begin
        process(CLK)
        begin
                if(CLK'event and CLK = '1') then
                        clockCounter &t;= clockCounter + 1;
                        if(clockCounter = WAIT_TIME) then
                                clockCounter <= "000000000000000000000000";
                                ledCounter <= ledCounter + 1;
                        end if;
                end if;
        end process;

        LED <= not ledCounter;
end behavior;

VHDLで書いたプログラムをテストする

上で移植したプログラムが想定通り動くはずかは、FPGAに書き込む前にテストしておきたいです。 openFPGALoaderで書き込む際には、今の利用方法だとフラッシュメモリーに書き込むようなので、書き換え回数も上限があります。 図解VHDL実習でのテストベンチの書き方の説明と、GHDLのドキュメントにある実例を元に、Verilogで書く場合をVHDLに移植するイメージで書くと、以下のようでテストベンチは良さそうです。

$ cat counter_tv.vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter_tb is
end counter_tb;

architecture behavior of counter_tb is
        component counter
                Port (CLK : in std_logic;
                      LED : out std_logic_vector(5 downto 0));
        end component;

        for counter_0: counter use entity work.counter;
        signal CLK : std_logic := '0';
        signal LED : std_logic_vector(5 downto 0) := "000000";
begin
        counter_0: counter port map (CLK => CLK, LED => LED);

        process
        begin
                CLK <= not CLK;
                wait for 1 ns;
        end process;
end behavior;

また、counter.vhdlも待ちサイクルがテストするにはあまりに長いので、以下のように3回のクロック立ち上がりで次のLED店頭パターンになるように書き変えておきます。 おそらく、こんな改造をすることなくテストする方法もあってしかるべきだと思いますが、分かっていません。

$ cat counter.vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter is
        Port (CLK : in std_logic;
              LED : out std_logic_vector(5 downto 0));
end counter;

architecture behavior of counter is
        --constant WAIT_TIME : integer := 13500000;
        -- 3 is only for testbench
        constant WAIT_TIME : integer := 3;
        signal ledCounter : std_logic_vector(5 downto 0) := "000000";
        signal clockCounter : std_logic_vector(23 downto 0) := "000000000000000000000000";
begin
        process(CLK)
        begin
                if(CLK'event and CLK = '1') then
                        clockCounter &t;= clockCounter + 1;
                        if(clockCounter = WAIT_TIME) then
                                clockCounter &t;= "000000000000000000000000";
                                ledCounter &t;= ledCounter + 1;
                        end if;
                end if;
        end process;

        LED &t;= not ledCounter;
end behavior;

ghdlコマンドはステップを積み上げて実行しないと、VCDウェーブフォームファイルを得られません。 以下のようなmakefileを使って、make runと実行すれば、VCDウェーブフォームファイルを正常に得られると思います。 得られたVCDウェーブフォームファイル (counter.vcd)は。pkgsrc/cad/gtkwaveで閲覧することができます。 3回のクロック立ち上がりで次のLCD点灯パターンになるので、6nsごとにLED[5:0]が変わっていることが分かると思います。

$ cat Makefile
TARG=   counter

GHDL_FLAGS+=    -fsynopsys

.PHONY: analysis elaborate run clean

analysis: ${TARG}.vhdl
        ghdl -a ${GHDL_FLAGS} ${TARG}.vhdl
        ghdl -a ${GHDL_FLAGS} ${TARG}_tb.vhdl

elaborate: work-obj93.cf
        ghdl -e ${GHDL_FLAGS} ${TARG}
        ghdl -e ${GHDL_FLAGS} ${TARG}_tb

run: elaborate
        ghdl -r ${GHDL_FLAGS} --time-resolution=ns ${TARG}_tb --vcd=counter.vcd --stop-time=1ms

clean:
        rm -f counter.vcd
        rm -f work-obj93.cf

23日目は、ここで移植したVHDLによるcounterをyosysで合成し、nextpnrで配置配線し、FPGAをプログラムして、動作を確認してみます。

NetBSDでFPAG開発を始めてみる

この記事は、NetBSD Advent Calendar 2025の21日目の記事です。

はじめに

Verilogや他のHDL (Hardware Description Language; ハードウェア記述言語)を勉強して来ましたが、シミュレーションだけでハードウェアとして実現したことはありませんでした。 XilinxやAlteraのFPGAを搭載した基板は高価ですし、LatticeやMicrochip (旧Actel)のFPGA基板で良いものがどれかも良く分かりません。 そもそも、何も分からない段階で真に良いものを選べる気もしません。

誰が言及していたのか全く記憶から消えてしまいましたが、ディジタル回路とVerilog入門というチュートリアルを読みました。 Verilogについて納得が行くまで解説がされている感じはしなくて、ちょっと悩んでしまう気がしましたが、おもしろいチュートリアルだと思います。 その中で、秋月電子通商で売られているSipeed製のTang Nano 9Kという基板が紹介されていました。 これには、中国のGowin Semiconductor製のFPGAが搭載されています。 記事中の2,500円という価格よりは値上げされて、2,710円 (消費税込みで2,980円)になっていましたが、3,000円せずに購入できるのは、最初の一歩としては手軽です。

Gowin Semiconductor社は、Gowin EDAという開発環境を提供しています。WindowsとLinuxで利用できるようです。 Apply LicenseのページからWindows用のGowin EDAのライセンスを申請すると、5分もせずにライセンスファイルが返送されて来ました。 ですが、まだインストールしていません。 近々試してみないといけません。

一方で、ウェブ検索をすると、Tang Nano 9KはYosys等のオープンソースなツールのみで扱うことも可能なようです。 と言うことで、NetBSD/amd64 11.99.4のみでTang Nano 9Kをプログラムしてみました。

必要なソフトウェアを用意する

Verilogを勉強するには、非常に小規模なロジック以外に書いたことがありませんので、Icarus Verilogを使って来ました。 ですが、これは単なるシミュレーターなので、ハードウェアに書き込むのには使えません。 FPGAで自分が書いたロジックを動かすには、シミュレーターで正常に動くはずであることを確認し、合成して、配置と配線をして、FPGAが読み込めるデータに変換し、書き込む(プログラムする)という流れが必要なはずです。

Gowin製のFPGAの場合、オープンソースなツールとしては、合成はYosysで、配置と配線はnextpnrで、データ(ビットストリームと呼ばれている)への変換はapycula、プログラムするのはopenFPGALoaderを使えば良いようです。

ちょうどpkgsrc-2025Q4のフリーズが終わったので、ちゃんとアップデートやインポートをしないといけませんが、それはこの記事を書いた後にすることにして、必要なツールは以下のようにインストールすれば良いでしょう。 pkgsrc/devel/openFPGALoaderはpkgsrc/devel/libftdi1を使いますが、libftdi1はpkgsrc/devel/swig4がインストールされていると、swig3がインストールされていてもswig4を使ってしまい、ビルドすることができません。 ですので、まずはswig4は削除しておく必要があります。 swig4は基本的には何かのFull dependencyになっていることはなさそうですから、問題にはならないはずと思います。

# pkg_delete swig4
# cd /usr/pkgsrc/devel/yosys
# make install
# cd /usr/pkgsrc/devel/nextpnr-himbaechel
# make install
# cd /usr/pkgsrc/devel/py-apycula
# make install
# cd /usr/pkgsrc/devel/openFPGALoader
# make install

一方で、自分の書いたVerilogのコードをプログラムしても、ちゃんと動かない場合に、これらのツールが動いているか否かの動作確認ができる気がしません。 github.com/lushaylabs/tangnano9k-series-examplesにある、counterというプロジェクトを利用して動作確認することにします。 ただ、現状では古いツールチェイン用の記述になっていますし、pkgsrcのやり方には沿っていないので、私がforkして修正点を反映させたものを今回は利用します。 以下のように、手元に取得しておきます。

$ git clone git@github.com:ryoon/tangnano9k-series-examples.git
$ cd tangnano9k-series-examples
$ git pull origin newer-toolchain-pkgsrc
$ git switch newer-toolchain-pkgsrc

実際に合成からプログラムまでを実行してみる

counter/Makefileに実行すべきコマンドは既に記載されています。 まずはTang Nano 9KをNetBSDマシンに接続してみます。 Tang Nano 9KにはUSB A to USB Type-Cケーブルが付属していますが、手元に出してあったいつも使っているケーブルを利用しました。 dmesgは以下のようです。 普通にugen(4)として認識されている状態です。

ugenif0 at uhub1 port 2 configuration 1 interface 0
ugenif0: SIPEED (0x0403) JTAG Debugger (0x6010), rev 2.00/5.00, addr 2
ugenif1 at uhub1 port 2 configuration 1 interface 1
ugenif1: SIPEED (0x0403) JTAG Debugger (0x6010), rev 2.00/5.00, addr 2

/dev/ugen0.*/dev/ugen1.*はrootユーザーしか読み書きできないので、私のユーザーはwheelグループに所属していますので、以下のようにパーミッションを変更しておきます。

# chmod 660 /dev/ugen0.*
# chmod 660 /dev/ugen1.*

と言うことで、まずは実行してみましょう。 以下のように実行すれば、FPGAのプログラムまで完了します。 CRC Check: Successになれば正常終了しているはずです。

$ make load
(snip)
openFPGALoader -b tangnano9k counter.fs -f
empty
write to flash
Jtag frequency : requested 6.00MHz   -> real 6.00MHz
Parse file Parse counter.fs:
Done
DONE
Jtag frequency : requested 2.50MHz   -> real 2.00MHz
Erase SRAM DONE
Erase FLASH DONE
Erasing FLASH: [==================================================] 100.00%
Done
write Flash: [==================================================] 100.00%
Done
CRC check: Success

正常終了すると、以下の写真のようにTang Nano 9K内蔵のLEDが橙色に点滅します。

Tang Nano 9Kには、LUTはLUT4ということで、4入力で1出力なのでしょうか。 また9Kということで、LUTは8640個あるそうです。 パッケージにはEntry-Level FPGA Kit For RISC-Vと書かれていますが、NetBSDが動くようなRISC-V環境が作れる訳ではない仕様な気がします。 でも、自分で書いたHDLのコードが、シミュレーションではなく実際のFPGAで動かせるというのは、学習を一歩先に進めるのには役立ちそうです。

NetBSD上でYubiKey 5 NFCの各機能を使ってみる (2)

この記事は、NetBSD Advent Calendar 2025の18日目の記事です。

はじめに

(1)では各機能を概観しました。 今回は、私がYubiKey 5 NFCで利用しようと当初から考えていたパスキーによるログインを試したいと思います。

現状を確認する

実を言いますと、既に3つのFIDO credentialsが登録済みになっています。 ですが、実際に意味があるのは1つだけです。 その状況を確認してみます。

また、FIDO機能のためのPINも設定済みです。 これはykman-3.14 fido access change-pinで設定したはずです。

$ ykman-3.14 fido info
AAGUID:                       XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
PIN:                          8 attempt(s) remaining
Minimum PIN length:           4
Always Require UV:            Off
Credential storage remaining: 97

$ ykman-3.14 fido credentials list
Enter your PIN: (あらかじめ設定したPINを入力してEnterキーを押す)
Credential ID  RP ID                Username          Display name
XXXXXXXX...    webauthn.io          ryoon
YXXXXXXX...    login.microsoft.com  ????????@hotmail.com
ZXXXXXXX...    google.com           ????????@gmail.com

この3番目のgmail.comのusernameのものだけが実際に有用なものです。 webauthn.ioのものは、pkgsrc/www/firefoxの動作確認の際に作ったものです。 login.microsoft.comのものは、設定途中で進まなくなってしまい、実際にMicrosoftアカウントには紐付いていません。

と言うことで、不要なものはまず削除してしまいましょう。

$ ykman-3.14 fido credentials delete XXXXXXXX
Enter your PIN: (あらかじめ設定したPINを入力してEnterキーを押す)
Delete webauthn.io ryoon  (XXXXXXXX(snip))? [y/N]: y (yと入力してEnterキーを押す)
Deleting credential, DO NOT REMOVE YOUR YUBIKEY!
Credential deleted.
$ ykman-3.14 fido credentials delete YXXXXXXX
Enter your PIN: (あらかじめ設定したPINを入力してEnterキーを押す)
Delete login.microsoft.com ????????@hotmail.com  (YXXXXXXX(snip))? [y/N]: y
Deleting credential, DO NOT REMOVE YOUR YUBIKEY!
Credential deleted.

これでFIDO credentialsの状況を再度確認してみましょう。

$ ykman-3.14 fido credentials list
Enter your PIN:
Credential ID  RP ID       Username          Display name
ZXXXXXXX...    google.com  ????????@gmail.com

必要なものを残して、削除できていました。

登録してみる

GoogleアカウントとMicrosoftアカウントで使うように設定してみました。 全く問題ないと言いたいところですが、そうは行きませんでした。 利用しているのは、pkgsrc/www/firefox-146.0.1です。

登録の手順は、GoogleやMicrosoftのウェブサイトを確認してもらえば良いでしょう。

結果から言うと、Googleアカウントは、既に上でも触れたように使えています。 登録もログインも想定通りにできます。 ですが、Microsoftアカウントは、パスキーの設定はでき、YubiKey 5 NFCに登録もできますが、 NetBSD/amd64 11.99.4上のFirefox 146.0.1では、ログイン時にパスキーを使ったログインはできませんでした。 選択肢にも出て来ません。 Windows 11 25H2上のFirefox 146.0.1 (64ビット版)では、パスキーでのログインが提案されます。

いずれ、証券会社等の最近パスキーに熱心なサービスでも使えるか試してみたいと思います。 ただ、現時点でNTTドコモのdアカウント等はYubiKey 5 NFCでの設定はできない所までは分かっています。

NetBSD上でYubiKey 5 NFCの各機能を使ってみる (1)

この記事は、NetBSD Advent Calendar 2025の17日目の記事です。

はじめに

以前、YubiKey 5 NFCを日本国内の代理店から購入したのですが、その直後にそのYubiKey 5 NFCのファームウェアには脆弱性が見付かってしまいました。 しかも、FIDO credentialsの登録数が十分ではなく、あまり活用できない常態でした。 今回は、YubiKeyの公式オンラインストアからファームウェアバージョン5.7.4のものを購入しました。 これは既存の脆弱性はないようですし、FIDO credentialsの登録可能数も十分のようです。

YubiKey 5 NFCはいろいろな機能があるようです。製品紹介のページの表を見ると、 以下の9つの機能があるようです。ただ、YubiKeyの提供する機能と1:1と言う訳ではないような気もします。 各機能をNetBSD/amd64-currentから使ってみたいと思います。

  1. WebAuthn
  2. FIDO (CTAP 1, 2, 2.1)
  3. Universal Second Factor (U2F)
  4. Smart Card / PIV
  5. Yubico OTP
  6. OATH - HOTP (Event)
  7. OATH - TOTP (Time)
  8. OpenPGP
  9. Secure Static Password

NetBSDでYubiKeyを管理するツールをインストールする

YubiKey Managerのページには、QTで書かれたGUIツールと、CLIのツールの2つが紹介されています。 pkgsrcにはいずれも収録されているのですが、今回はCLIツールであるykmanコマンドの方を使ってみます。 以下のようにインストールすれば良いでしょう。 今回はPython 3.14ベースで使ってみます。 ちなみに、NetBSDで正常に使えるのは、py314-yubikey-manager-5.8.0nb1以降のバージョンです。

# /usr/pkgsrc/security/py-yubikey-manager
# make install

ところが、これだけでは全てのYubiKey 5 NFCの機能を使うことができません。 py314-yubikey-manager-5.8.0nb1は、機能ごとにpcscd(8)経由かuhid(4)経由でYubiKey 5 NFCにアクセスします。 uhid(4)は追加のソフトウェアは不要 えすが、pcscd(8)経由でアクセスするには、以下のように実行する必要があります。

; ccidパッケージがpcscd(8)経由でSmart Cardとしてアクセスするのに必要です。
# /usr/pkgsrc/security/ccid
# make install
; その上で、pcscd(8)を起動させておく必要があります。
# cp /usr/pkg/share/examples/rc.d/pcscd /etc/rc.d
# echo "psccd=YES" >> /etc/rc.conf
# service pcscd start

ここまで実施すれば、YubiKey 5 NFCの機能にアクセスすることはできるように見えます。 現時点で全ての動作を確認してはいないので、必要になったら追加のセットアップを考えたいと思います。

YubiKey 5 NFCの情報を取得する

yumanコマンドは、複数のPythonインタープリターで動くものを共存できるように、alternative frameworkでPythonインタープリターのバージョン番号付きのコマンド名にするようになっています。 Python 3.14ベースの場合には、ykmanコマンドはykman-3.14という名前になっているはずです。

何のオプションも指定せずにykmanコマンドを実行すると、使えるオプションとサブコマンドを表示させることができます。 以下のように表示されるので、一通り情報を表示させてみます。

Usage: ykman-3.14 [OPTIONS] COMMAND [ARGS]...

  Configure your YubiKey via the command line.

  Examples:

    List connected YubiKeys, only output serial number:
    $ ykman list --serials

    Show information about YubiKey with serial number 123456:
    $ ykman --device 123456 info

Options:
  -d, --device SERIAL             specify which YubiKey to interact with by
                                  serial number
  -r, --reader NAME               specify a YubiKey by smart card reader name
                                  (can't be used with --device or list)
  -t, --scp-ca FILENAME           specify the CA to use to verify the SCP11
                                  card key (CA-KLCC)
  -s, --scp CRED                  specify private key and certificate chain
                                  for secure messaging, can be used multiple
                                  times to provide key and certificates in
                                  multiple files (private key, certificates in
                                  leaf-last order), OR SCP03 keys in hex
                                  separated by colon (:) K-ENC:K-MAC[:K-DEK]
  -p, --scp-password PASSWORD     specify a password required to access the
                                  --scp file, if needed
  -l, --log-level [error|warning|info|debug|traffic]
                                  enable logging at given verbosity level
  --log-file FILE                 write log to FILE instead of printing to
                                  stderr (requires --log-level)
  --diagnose                      show diagnostics information useful for
                                  troubleshooting
  -v, --version                   show version information about the app
  --full-help                     show --help output, including hidden
                                  commands
  -h, --help                      show this message and exit

Commands:
  info     show general information
  list     list connected YubiKeys
  script   run a python script
  config   configure the YubiKey, enable or disable applications
  fido     manage the FIDO applications
  hsmauth  manage the YubiHSM Auth application
  oath     manage the OATH application
  openpgp  manage the OpenPGP application
  otp      manage the YubiOTP application
  piv      manage the PIV application

これによると、infoで全体の情報を表示させ、fido、hsmauth、oath、openpgp、otp、pivという6つのサブコマンドで機能を管理できるようです。

$ ykman-3.14 info
Device type: YubiKey 5 NFC
Serial number: XXXXXXXX
Firmware version: 5.7.4
Form factor: Keychain (USB-A)
Enabled USB interfaces: OTP, FIDO, CCID
NFC transport is enabled

Applications    USB     NFC
Yubico OTP      Enabled Enabled
FIDO U2F        Enabled Enabled
FIDO2           Enabled Enabled
OATH            Enabled Enabled
PIV             Enabled Enabled
OpenPGP         Enabled Enabled
YubiHSM Auth    Enabled Enabled

ここで見ると、FIDO U2FとFIDO2は別々の機能になっているようです。 できることも違ったはずなので、当然かもしれません。

6つのサブコマンドでinfoコマンドを実行した結果を掲載したいと思います。

$ ykman-3.14 fido info
AAGUID:                       XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
PIN:                          8 attempt(s) remaining
Minimum PIN length:           4
Always Require UV:            Off
Credential storage remaining: 97
$ ykman-3.14 hsmauth info
YubiHSM Auth version:             5.7.4
Management key retries remaining: 8/8
$ ykman-3.14 oath info
OATH version:        5.7.4
Password protection: disabled
$ ykman-3.14 openpgp info
OpenPGP version:            3.4
Application version:        5.7.4
PIN tries remaining:        3
Reset code tries remaining: 0
Admin PIN tries remaining:  3
Require PIN for signature:  Once
KDF enabled:                False
$ ykman-3.14 otp info
Slot 1: programmed
Slot 2: empty
$ ykman-3.14 piv info
PIV version:              5.7.4
PIN tries remaining:      3/3
PUK tries remaining:      3/3
Management key algorithm: AES192
WARNING: Using default PIN!
WARNING: Using default PUK!
WARNING: Using default Management key!
CHUID: No data available
CCC:   No data available

このYubiKey 5 NFCは、実は既にFirefox経由でPINの設定と3つのFIDO credentialsを登録済みになっています。 今日はここまでにして、次回はfidoサブコマンドで管理できる機能を使ってみたいと思います。

NetBSDでFPAG開発を始めてみる(NVCとVHDL)

この記事は、 NetBSD Advent Calendar 2025 の25日目の記事です。 はじめに 本当は、PyRTLで書いたロジックをTnag Nano 9Kで動かしてみたいのですが、これから勉強しないといけないので、しばらく先に進めそうにありません。 ...