🎯 結論:あなたが採用すべきオープンツール構成(picoRV32 版)
| 種類 | 推奨 |
|---|---|
| CPU | picoRV32(本家完全オープン) |
| 合成 | Yosys (synth_gowin) |
| PnR(配置配線) | nextpnr-gowin |
| ビットストリーム生成 | nextpnr-gowin(内蔵 gowin_pack) |
| FPGA 書き込み | openFPGALoader |
| Cコンパイル | xPack riscv-none-elf-gcc(newlib-nano) |
これにより、Gowin IDE 一切不要で完全オープンフローが実現できます。
📐 Tango Nano 9K picoRV32 SoC(最小構成)
以下を作ることを想定:
+----------------------------+
| picoRV32 CPU (RV32IMC) |
| +--------------+
| | BRAM (RAM) | → 16〜32 KB
| +--------------+
| MMIO バス: Wishbone風 |
| +--------------+
| LED レジスタ | 0x0100_0000
| UART Lite (TXのみ) | 0x0200_0000
| +--------------+
+----------------------------+
📘 オープンソースフローのセットアップ
✔ 1. Yosys + nextpnr-gowin + openFPGALoader のインストール
Ubuntu/Debian(簡単版)
sudo apt install yosys nextpnr openfpgaloader
最新安定版(推奨)
YosysHQ の prebuilt package を使う(実習でトラブル少ない)。
https://github.com/YosysHQ/oss-cad-suite-build
インストール後:
export PATH=$HOME/oss-cad-suite/bin:$PATH
✔ 2. picoRV32 の導入
公式(Clifford Wolf)から取得:
git clone https://github.com/YosysHQ/picorv32
利用する HDL:
-
picorv32.v(CPU本体) -
必要なら
picosoc/も参考にできる
✔ 3. 最小 SoC(例)を作成
以下は Tango Nano 9K 用 完全オープン picoRV32 SoC テンプレート Verilog
※あなたの目的向けに調整済み
🧩 soc_top.v(ひな形)
module soc_top (
input wire clk,
input wire resetn,
output wire led,
output wire uart_tx
);
// ---------------------------
// Clock / Reset
// ---------------------------
wire reset = ~resetn;
// ---------------------------
// Memory: BRAM 32KB
// ---------------------------
reg [31:0] mem [0:8191]; // 32KB / 4 bytes
wire mem_valid;
wire mem_instr;
wire [3:0] mem_wstrb;
wire [31:0] mem_addr;
wire [31:0] mem_wdata;
reg [31:0] mem_rdata;
always @(posedge clk) begin
if (mem_valid && |mem_wstrb && mem_addr < 32'h00008000) begin
if (mem_wstrb[0]) mem[mem_addr[14:2]][ 7: 0] <= mem_wdata[ 7: 0];
if (mem_wstrb[1]) mem[mem_addr[14:2]][15: 8] <= mem_wdata[15: 8];
if (mem_wstrb[2]) mem[mem_addr[14:2]][23:16] <= mem_wdata[23:16];
if (mem_wstrb[3]) mem[mem_addr[14:2]][31:24] <= mem_wdata[31:24];
end
end
always @(posedge clk) begin
mem_rdata <= mem[mem_addr[14:2]];
end
// ---------------------------
// MMIO - LED (0x0100_0000)
// ---------------------------
reg led_reg = 0;
wire led_sel = mem_valid && mem_addr == 32'h01000000;
always @(posedge clk) begin
if (led_sel && |mem_wstrb)
led_reg <= mem_wdata[0];
end
assign led = led_reg;
// ---------------------------
// MMIO - UART TX (0x0200_0000)
// ---------------------------
reg uart_tx_reg = 1'b1;
wire uart_sel = mem_valid && mem_addr == 32'h02000000;
always @(posedge clk) begin
if (uart_sel && |mem_wstrb)
uart_tx_reg <= mem_wdata[0];
end
assign uart_tx = uart_tx_reg;
// ---------------------------
// CPU Instantiation
// ---------------------------
picorv32 #(
.ENABLE_MUL(1),
.ENABLE_DIV(0),
.ENABLE_IRQ(0),
.STACKADDR(32'h00007FFC)
) cpu (
.clk (clk),
.resetn (resetn),
.mem_valid (mem_valid),
.mem_instr (mem_instr),
.mem_ready (1),
.mem_addr (mem_addr),
.mem_wdata (mem_wdata),
.mem_wstrb (mem_wstrb),
.mem_rdata (mem_rdata)
);
endmodule
これだけで picoRV32 + RAM + LED + UART のミニ SoC になります。
📦 Cプログラム(xPack GCC 用)
main.c
#define LED (*(volatile unsigned int*)0x01000000)
#define UART (*(volatile unsigned int*)0x02000000)
void uart_putc(char c) {
UART = c;
}
int main() {
LED = 1;
uart_putc('A');
while (1) {}
}
📄 リンカスクリプト(.ld)
link.ld
ENTRY(_start)
MEMORY {
RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 32K
}
SECTIONS {
.text : {
*(.text*)
*(.rodata*)
} > RAM
.data : {
*(.data*)
} > RAM
.bss : {
*(.bss*)
*(COMMON)
} > RAM
}
🛠 ビルドコマンド(xPack)
riscv-none-elf-gcc -Os -march=rv32im -mabi=ilp32 \
-ffreestanding -nostdlib -nostartfiles \
-Wl,-Bstatic,-T,link.ld \
-o firmware.elf main.c
BIN出力:
riscv-none-elf-objcopy -O binary firmware.elf firmware.bin
🏗 FPGA ビルド(完全オープンフロー)
1) 合成(Yosys)
yosys -p "read_verilog picorv32.v soc_top.v; synth_gowin -top soc_top -json soc.json"
2) 配置配線(nextpnr-gowin)
nextpnr-gowin --device GW1NR-LV9QN88C6/I5 --json soc.json --write soc.fs
3) FPGA 書き込み(openFPGALoader)
openFPGALoader -b tangnano9k soc.fs
🎉 これで、Gowin IDE を一切使わずに picoRV32 SoC が Tango Nano 9K を動きます!
📩 最後に質問
次はどれを進めたいですか?
-
uart_tx を“本物の UART(ボーレート生成あり)”に改良
-
RAM/ROM を FPGA の本物の BRAM(SB_RAM40)に置き換える
-
Wishbone バス化して周辺 IP を増やすひな形
-
Makefile を自動生成
-
ローダ(UART/USBからRAMに書き込む MiniLoader)を作る
どれを作りましょう?
xPack riscv-none-elf-gcc(newlib-nano 付き)
はい、**xPack riscv-none-elf-gcc(newlib-nano 付き)**は、以下の手順で簡単にインストールできます。
Windows / macOS / Linux 共通で使える方法です。
✅ 最短手順(推奨)
ステップ 1:xpm をインストール
xPack のパッケージマネージャです(npm を使用)。
npm install --global xpm
npm が無ければ:
-
Ubuntu / Debian:
sudo apt install npm -
Arch:
sudo pacman -S npm -
macOS:Homebrew で
brew install node -
Windows:Node.js セットアップに npm が含まれます
ステップ 2:xPack RISC-V Embedded GCC をインストール
最新安定版(推奨):
riscv-none-elf-gcc 12.3.0-1.1
xpm install --global @xpack-dev-tools/riscv-none-elf-gcc@12.3.0-1.1
ステップ 3:PATH を通す
Linux / macOS:
export PATH="$HOME/.local/xPacks/riscv-none-elf-gcc/12.3.0-1.1/bin:$PATH"
.bashrc に追加して自動化:
echo 'export PATH="$HOME/.local/xPacks/riscv-none-elf-gcc/12.3.0-1.1/bin:$PATH"' >> ~/.bashrc
Windows:
パスは以下:
%USERPROFILE%\.local\xPacks\riscv-none-elf-gcc\12.3.0-1.1\bin
これを「システムの環境変数」に追加します。
⭐ newlib-nano が含まれているか確認
次のコマンドで確認できます:
riscv-none-elf-gcc --print-multi-lib
出力に nano.specs が付いていれば OK。
さらに、以下で newlib-nano を使ったビルドができます:
-specs=nano.specs
⭐ 動作確認
riscv-none-elf-gcc -v
riscv-none-elf-ld -v
riscv-none-elf-gdb --version
問題なく表示されればインストール成功です。
🧪 簡易テスト
// hello.c
int main() {}
ビルド:
riscv-none-elf-gcc -Os -march=rv32im -mabi=ilp32 \
-specs=nano.specs \
-c hello.c
成功すれば OK。
✨ 補足:インストール場所まとめ
| OS | デフォルトのインストールパス |
|---|---|
| Linux | $HOME/.local/xPacks/riscv-none-elf-gcc/<version>/bin |
| macOS | 同上 |
| Windows | %USERPROFILE%\.local\xPacks\riscv-none-elf-gcc\<version>\bin |
必要であれば:
✅ Makefile(picoRV32 用)
✅ newlib-nano 用リンカスクリプト(最適化済み)
✅ UART printf のミニ実装
などもすぐ作ります。