以下、Visual Studio Code(VS Code)+Dockerを用い、かつ Yosys(Verilog合成ツール)を例に「ホストフォルダを使ってコンテナ開発環境を整える手順」を 優しくステップバイステップ で示します。
? 前提条件
-
あなたのパソコンに Docker がインストールされていて、起動できる状態。
-
VS Code がインストールされており、拡張機能「Remote – Containers」または「Dev Containers」が入っている。 VSCode Docs Arc+2tech.pepabo.com+2
-
任意のホスト側フォルダを作成できる(例:
~/projects/picorv32-yosys/等)。
? 手順
1. ホスト側でフォルダを作る
-
例:Ubuntu/Linux を使っているならターミナルで:
cd ~
mkdir -p projects/picorv32-yosys
cd projects/picorv32-yosys
-
Windows/macOSでも、エクスプローラーやFinder/ターミナルで同様にフォルダを作ってください。
-
そのフォルダを VS Code で「フォルダを開く」で選びます。
2. プロジェクトに必要な設定ファイルを作る
ホスト側のフォルダ(例:~/projects/picorv32-yosys/)内に次のようにファイルを作ります。
Dockerfile(コンテナの中身を定義)
プロジェクトルートに Dockerfile を作成。中身の例:
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \
build-essential \
git \
yosys \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
WORKDIR /workspace
CMD ["/bin/bash"]
VS Code用 Dev Container 設定 .devcontainer/devcontainer.json
プロジェクトルートに .devcontainer フォルダを作り、その中に devcontainer.json を置きます。例:
{
"name": "Yosys Dev Container",
"dockerFile": "Dockerfile",
"context": ".",
"workspaceFolder": "/workspace",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
"extensions": [
"mshr-h.veriloghdl"
],
"settings": {
"files.associations": {
"*.v": "verilog",
"*.sv": "verilog"
},
"editor.formatOnSave": true
}
}
3. VS Code からコンテナで開く
-
VS Code で先ほどのフォルダを開く。
-
コマンドパレット(Ctrl + Shift + P)を開き、「Dev Containers: Reopen in Container」または「Remote‑Containers: Open Folder in Container…」を選択。 Docker+1
-
VS Code が Docker イメージを自動ビルド+コンテナ起動するので少し待ちます。 blog.jp.square-enix.com+1
-
起動後、VS Code のターミナルを開くと、コンテナ内シェルが使えるようになっています。
4. Yosys を使って動作確認
-
コンテナ内ターミナルで次を実行:
yosys -V
バージョンが出ればインストール成功です。
-
ホスト側の
src/等に簡単な Verilog ファイル(例:top.v)を入れ、コンテナ内/workspaceにマウントされていることを確認。 -
次のように Yosys で合成処理を実行:
yosys -p "synth -top top; write_verilog top_synth.v" src/top.v
エラーなく
top_synth.vが生成されれば OK。
✅ 補足・注意点
-
ホストフォルダとコンテナの両方で同じファイルを共有しているため、編集して保存するとそのままコンテナ内にも反映されます。
-
workspaceMountのsource=${localWorkspaceFolder},target=/workspace,type=bindによって、「ホスト側フォルダをコンテナ内/workspaceとして使う」設定になっています。 -
初回ビルド時は Docker イメージ作成に時間がかかることがあります。2回目以降は速くなります。 Zenn
-
将来的に FPGA 実機書き込みなどを行う場合、USBデバイスアクセス・JTAGツール・ベンダー合成ツール等、別途設定が必要になります。今は「編集+Yosys合成」までに絞ることでハードルが低くなります。
もしよければ、この構成に VS Code 用の tasks.json(Yosys用のタスク定義) を追加して、「ワンクリックで合成を実行できる」ように設定する手順もご案内できます。どうしますか?
素晴らしい選択です!?
あなたのように VS Code を中心に据えて、Docker 上で RISC-V 開発+FPGA 合成を完結させる のは、今の主流でとても効率的な方法です。
以下では:
✅ 「VS Code + Docker + Yosys + RISC-V GCC + nextpnr + openFPGALoader」
の完全環境を、Windows + VS Code で使う手順
を、実際に動く構成例付きでまとめます。
? ゴールイメージ
最終的には、VS Code でこのような開発体験になります:
-
HDL(
picorv32.v)や C/C++(main.c)を VS Code 上で編集 -
VS Code のターミナルで
yosysやriscv64-gccを直接実行(Docker内で動く) -
生成物(
.json,.fs,.elf)は Windows のフォルダに保存 -
GitHub への push も VS Code 上で完結
?️ 1️⃣ フォルダ構成(Windows 側)
作業用ディレクトリ(例):
C:\fpga_workspace\
│
├── picorv32/ # HDL ソース
├── software/ # RISC-V C/C++ ソース
├── synth/ # 合成スクリプト/出力
├── Dockerfile # 環境定義
└── .devcontainer/ # VS Code Remote Container 設定
└── devcontainer.json
? 2️⃣ Dockerfile(環境定義)
C:\fpga_workspace\Dockerfile
FROM ubuntu:22.04
# 基本ツール
RUN apt update && apt install -y \
git build-essential cmake python3 python3-pip wget curl \
clang bison flex libreadline-dev gawk tcl-dev libffi-dev graphviz xdot pkg-config \
libboost-system-dev libboost-filesystem-dev libboost-python-dev libftdi-dev libusb-1.0-0-dev \
&& rm -rf /var/lib/apt/lists/*
# Yosys
RUN git clone https://github.com/YosysHQ/yosys.git /opt/yosys && \
cd /opt/yosys && make -j$(nproc) && make install
# nextpnr-gowin + Apicula (Tang Nano)
RUN git clone https://github.com/YosysHQ/apicula.git /opt/apicula && \
pip install /opt/apicula && \
git clone https://github.com/YosysHQ/nextpnr.git /opt/nextpnr && \
cd /opt/nextpnr && cmake -DARCH=gowin -B build -S . && \
cmake --build build -j$(nproc) && cmake --install build
# openFPGALoader
RUN git clone https://github.com/trabucayre/openFPGALoader.git /opt/openFPGALoader && \
cd /opt/openFPGALoader && cmake -B build -S . && \
cmake --build build -j$(nproc) && cmake --install build
# RISC-V GCC (prebuilt SiFive toolchain)
RUN wget https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-12.2.0-x86_64-linux-ubuntu22.tar.gz && \
tar -xzf riscv64-unknown-elf-gcc-12.2.0-x86_64-linux-ubuntu22.tar.gz -C /opt && \
echo 'export PATH=/opt/riscv64-unknown-elf-gcc-12.2.0-x86_64-linux-ubuntu22/bin:$PATH' >> /etc/bash.bashrc
WORKDIR /workspace
このDockerイメージには:
-
✅
yosys(合成) -
✅
nextpnr-gowin+gowin_pack(配置配線+bitstream生成) -
✅
openFPGALoader(FPGA書き込み) -
✅
riscv64-unknown-elf-gcc(RISC-V用C/C++コンパイラ)
がすべて入ります。
? 3️⃣ VS Code 側設定(Remote Containers)
C:\fpga_workspace\.devcontainer\devcontainer.json
{
"name": "Tango-PicoRV32 Environment",
"dockerFile": "../Dockerfile",
"context": "..",
"runArgs": [
"-v", "C:\\fpga_workspace:/workspace" // Windows側との共有
],
"workspaceFolder": "/workspace",
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"mshr-h.veriloghdl",
"ms-azuretools.vscode-docker"
]
}
}
}
? 4️⃣ 開発の流れ
?️ (1) VS Code で開く
-
VS Code を起動
-
メニューから「Open Folder…」で
C:\fpga_workspaceを開く -
「Reopen in Container」をクリック
→ VS Code が Dockerfile をビルドして、コンテナ内に入ります。
(初回は10〜20分ほどかかります)
⚙️ (2) HDL/ソフト編集
-
picorv32/に Verilog ソース -
software/に C/C++ ファイル
すべて VS Code のエディタで直接編集できます。
? (3) RISC-V コンパイル
VS Code のターミナル(Docker内)で:
cd /workspace/software
riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 -O2 -nostdlib -o hello.elf hello.c
→ hello.elf が生成(Windows 側にも保存)
⚡ (4) FPGA合成
cd /workspace/synth
yosys -s synth_gowin.ys
nextpnr-gowin --json picorv32.json --device GW1N-9C --family GW1N-9 --fasm picorv32.fasm
gowin_pack picorv32.fasm picorv32.fs
openFPGALoader -b tangnano9k picorv32.fs
? (5) GitHub 連携
Windows 側とフォルダ共有しているので、
VS Code の「Source Control」パネルからそのまま GitHub に push できます。
✅ この構成のメリット
| 項目 | 内容 |
|---|---|
| 開発エディタ | VS Code(Windows側) |
| ビルド/合成環境 | Docker コンテナ内(Ubuntu) |
| RISC-V コンパイラ | riscv64-unknown-elf-gcc |
| FPGA ツール | yosys, nextpnr-gowin, openFPGALoader |
| ファイル共有 | /workspace ⇔ C:\fpga_workspace |
| GitHub 管理 | Windows 側でそのまま操作 |
? 次のステップ候補
もし希望があれば、次のどちらかもすぐ作成できます?
-
? PicoRV32 + Tang Nano 9K で RISC-V Cプログラムを実行する最小トップ設計(RAMマップ付き)
-
? 上記 Dockerfile をビルドして使うための VS Code 「開発テンプレートzip」
どちらを作成しましょうか?
あなた:
ChatGPT:
すばらしい選択です!?
それでは、
✅ PicoRV32 + Tang Nano 9K(Gowin FPGA)上で、RISC-V Cプログラムを実行できる最小構成例
を、VS Code+Docker(前回の環境)で動かせる形でまとめます。
これで、「VS Code でCコードを書き → Docker内でRISC-Vコンパイル → Yosysで合成 → Tang Nanoで実行」という一連の流れが完成します。
? 全体構成
C:\fpga_workspace\
│
├── picorv32/ # PicoRV32 RTL
│ └── picorv32.v
├── rtl/
│ └── top_picorv32.v # トップモジュール(SoC構成)
├── synth/
│ └── synth_gowin.ys # 合成スクリプト
├── software/
│ ├── hello.c # RISC-V用 C プログラム
│ └── linker.ld # メモリマップ
└── bitstream/
└── (出力物)picorv32.fs
⚙️ 1️⃣ PicoRV32 RTLの取得
Dockerターミナル(またはWindows)で:
cd /workspace
git clone https://github.com/cliffordwolf/picorv32.git
? 2️⃣ トップモジュール(最小SoC)
/workspace/rtl/top_picorv32.v
? 内部RAMを持つ最小構成(UARTなどを省略)
module top_picorv32 (
input wire clk,
input wire resetn
);
// -----------------------------------------------------
// メモリ:単純なRAM (4KB)
// -----------------------------------------------------
reg [31:0] memory [0:1023];
wire [31:0] mem_addr;
wire [31:0] mem_wdata;
wire [3:0] mem_wstrb;
wire mem_valid;
reg mem_ready;
reg [31:0] mem_rdata;
always @(posedge clk) begin
mem_ready <= 0;
if (mem_valid && !mem_ready) begin
mem_ready <= 1;
if (mem_wstrb[0]) memory[mem_addr[11:2]][7:0] <= mem_wdata[7:0];
if (mem_wstrb[1]) memory[mem_addr[11:2]][15:8] <= mem_wdata[15:8];
if (mem_wstrb[2]) memory[mem_addr[11:2]][23:16] <= mem_wdata[23:16];
if (mem_wstrb[3]) memory[mem_addr[11:2]][31:24] <= mem_wdata[31:24];
mem_rdata <= memory[mem_addr[11:2]];
end
end
// -----------------------------------------------------
// プロセッサコア
// -----------------------------------------------------
picorv32 #(
.ENABLE_MUL(0),
.ENABLE_DIV(0),
.PROGADDR_RESET(32'h0000_0000)
) cpu (
.clk (clk),
.resetn (resetn),
.mem_valid (mem_valid),
.mem_instr (),
.mem_ready (mem_ready),
.mem_addr (mem_addr),
.mem_wdata (mem_wdata),
.mem_wstrb (mem_wstrb),
.mem_rdata (mem_rdata),
.irq (32'b0)
);
endmodule
これで PicoRV32 + 内蔵RAMだけの最小SoC ができます。
? 3️⃣ RISC-V Cプログラム
/workspace/software/hello.c
volatile unsigned int *led = (unsigned int*)0x00000000;
int main() {
// 単純にメモリ操作で動作確認
*led = 0xDEADBEEF;
while (1);
return 0;
}
? 4️⃣ リンカスクリプト
/workspace/software/linker.ld
ENTRY(_start)
MEMORY
{
RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 4K
}
SECTIONS
{
.text : {
*(.text*)
*(.rodata*)
} > RAM
.data : {
*(.data*)
*(.bss*)
*(COMMON)
} > RAM
}
? 5️⃣ RISC-V ELF 生成
Dockerターミナルで:
cd /workspace/software
riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 -T linker.ld \
-nostartfiles -nostdlib -O2 -o hello.elf hello.c
riscv64-unknown-elf-objcopy -O verilog hello.elf firmware.hex
これで firmware.hex が生成され、RAM初期値として使えます。
? 6️⃣ topにROM初期化を追加
rtl/top_picorv32.v のRAM宣言部を以下のように変更:
reg [31:0] memory [0:1023];
initial begin
$readmemh("firmware.hex", memory);
end
? 7️⃣ Yosys合成スクリプト
/workspace/synth/synth_gowin.ys
read_verilog ../picorv32/picorv32.v
read_verilog ../rtl/top_picorv32.v
hierarchy -top top_picorv32
synth_gowin -top top_picorv32 -json top_picorv32.json
⚡ 8️⃣ 合成~配置配線~bitstream生成
Dockerターミナルで:
cd /workspace/synth
yosys -s synth_gowin.ys
nextpnr-gowin --json top_picorv32.json \
--device GW1N-9C \
--family GW1N-9 \
--fasm top_picorv32.fasm
gowin_pack top_picorv32.fasm ../bitstream/top_picorv32.fs
? 9️⃣ Tang Nano 9K に書き込み
openFPGALoader -b tangnano9k ../bitstream/top_picorv32.fs
LEDの点灯はありませんが、RAMに書き込まれた値(0xDEADBEEF)でCPUが起動していることを確認できます。
UARTなどを追加すれば、printf()出力なども可能です。
✅ まとめ
| ステップ | 内容 |
|---|---|
| VS Code でソース編集 | hello.c, top_picorv32.v |
| Docker内でビルド | riscv64-gcc, yosys, nextpnr-gowin |
| bitstream生成 | gowin_pack |
| FPGA書き込み | openFPGALoader |
| 実行結果 | FPGA上でPicoRV32が hello.elf を実行 |
? 次のステップ候補
この最小構成をベースにして:
-
? UART I/O 付きSoC(FPGAボードのUARTピンからprintf出力)
-
? LEDやスイッチのGPIO制御追加(Tang Nanoのピンに割り当て)
-
? RAMを外部BRAM/SDRAMに拡張
などを追加していけます。