← ブログ一覧へ
FPGALiteXVexRiscvRISC-VDDR3ECP5SoCLiteDRAM开源工具

开源 FPGA 04|LiteX SoC 深潜:VexRiscv CPU + DDR3 + Ethernet 全配置

この記事は中国語で書かれ、Google 翻訳で自動翻訳されています。
中国語の原文を見る →
 _     _ _       __  __
| |   (_) |_ ___|\ \/ /
| |__ | |  _/ -_) >  <
|____|_|\__\___|/_/\_\

  ┌──────────────────────────────────────────┐
  │         LiteX SoC Architecture          │
  │                                          │
  │  Python ──► Migen/Amaranth ──► Verilog  │
  │     └────────────────────────────────┘  │
  │  VexRiscv │ LiteDRAM │ LiteEth │ UART  │
  └──────────────────────────────────────────┘

   开源 FPGA 实战系列 · 第 04 篇
   从 Python 代码到真实的 Linux SoC

系列第 4 篇 · 目标器件:Lattice ECP5-85F(OrangeCrab / ULX3S) 工具版本:LiteX 2024.04 · Migen 0.9 · nextpnr-ecp5 0.7 上一篇:形式验证入门


0. 这一篇要解决什么问题

前三篇在 iCE40 上做了点灯、时序优化、形式验证——这些都是”工具技能”。 这一篇要做真正的工程:在 ECP5 FPGA 上跑一个完整的 Linux SoC

你可能会问:软核 CPU + 软核 DDR 控制器,值得这么麻烦吗? 回答这个问题需要先理解 LiteX 在解决什么问题,然后看实测数字。

本篇目标:

  1. 理解 LiteX 的三层架构(Bus / Core / Platform)
  2. 用 Python 写完整的 SoC 定义(VexRiscv + DDR3 + 以太网)
  3. litex_sim 在软件里跑 RISC-V Linux(不需要硬件)
  4. 在 ECP5 上真实综合:看资源占用和 Fmax
  5. 测量 LiteDRAM DDR3 的实际带宽
  6. 理解软核 DDR vs Zynq 硬核的代价

本篇不覆盖:

  • 具体的 Linux 驱动开发
  • 自定义 IP 核集成(见系列后续篇章)
  • FPGA 原型到 ASIC 流片

1. LiteX 架构:三层模型

LiteX 三层架构 Python 配置 → SoC Core → Platform · 自顶向下生成 Verilog RTL Layer 3 · User App / Python 配置层 实例化 SoC:选 CPU、添加外设、配置时钟域 SoCCore(cpu_type="vexriscv") soc.add_uart() / add_ethernet() builder.build() → bitstream + csr.h elaborate Layer 2 · LiteX SoC Core (核心层) CPU + Wishbone/AXI Bus + Peripherals · 自动生成地址解码与 CSR CPU VexRiscv · Rocket PicoRV32 · NaxRiscv RV32I/IMC/IMA Wishbone / AXI-Lite Bus CSR (Control / Status Registers) memory map · address decoder → 自动产出 csr.json / csr.h Peripherals LiteDRAM · LiteEth LiteScope · LiteVideo UART · GPIO · I2C · SPI map I/O Layer 1 · Platform · FPGA 硬件抽象 引脚定义 · 时钟资源 · 综合工具链调用 ECP5Platform (nextpnr) Arty7Platform (vivado) IceBreakerPlatform (icestorm) 最终输出:Verilog RTL(约 15,000 – 30,000 行)经 Migen / Amaranth 生成
图 1 · LiteX 三层架构:用户 Python 配置驱动 SoC Core,再绑定到具体 Platform

1.1 Migen vs Amaranth 的关系

  • Migen:LiteX 的原始底层 HDL,由 M-Labs 开发,LiteX 一直用它
  • Amaranth(原名 nMigen):Migen 的继任者,语法更现代,更好的类型检查
  • LiteX 现状:内部仍以 Migen 为主,逐渐向 Amaranth 迁移。用 LiteX 时你不需要直接写 Migen,但理解它的 SignalModuleIfCase 语法有帮助
# Migen 基本语法示例(LiteX 内部用)
from migen import *

class Counter(Module):
    def __init__(self):
        self.count = Signal(8)

        # 同步逻辑(always @(posedge clk))
        self.sync += self.count.eq(self.count + 1)

# 等价 Verilog:
# reg [7:0] count;
# always @(posedge clk) count <= count + 1;

2. VexRiscv:可配置的 RISC-V 软核

VexRiscv 是用 SpinalHDL 写的高性能 RISC-V 核心,在 LiteX 中广泛使用。

2.1 VexRiscv 配置选项

# LiteX 中 VexRiscv 的主要配置变体
# cpu_variant 字符串控制功能开关

# 最小配置(用于 iCE40)
# ~1200 LUT,无乘法,无 MMU
cpu_variant = "minimal"

# 标准配置(最常用)
# ~3000 LUT,含乘法器,无 MMU,RV32IM
cpu_variant = "standard"

# Linux 配置(需要 MMU 支持,用于跑 Linux)
# ~5000 LUT,RV32IMA + MMU + 中断控制器
cpu_variant = "linux"

# 全功能配置(含 FPU)
# ~8000 LUT,RV32IMAF + MMU + FPU(单精度浮点)
cpu_variant = "full"
配置LUT 数量Pipeline 级数MMUFPU适用场景
minimal~1,2005 级裸机固件,iCE40
standard~3,0005 级裸机 RTOS
linux~5,0005 级Linux(无浮点)
full~8,0005 级Linux + 科学计算

2.2 Pipeline 深度的影响

VexRiscv 采用 5 级流水线(Fetch → Decode → Execute → Memory → Writeback),最高频率约:

  • iCE40HX8K:~75 MHz
  • ECP5-85F:~100 MHz
  • Xilinx Artix-7:~120 MHz(通过 Vivado)

3. 完整 Python SoC 定义

3.1 安装 LiteX

# 安装 LiteX 生态(含 VexRiscv、LiteDRAM、LiteEth 等)
pip3 install migen
pip3 install litex

# 安装 litex-boards(板卡定义)
pip3 install litex-boards

# 或从源码安装(推荐,可以修改板卡定义)
git clone https://github.com/litex-hub/litex.git
cd litex && pip3 install -e .

git clone https://github.com/litex-hub/litex-boards.git
cd litex-boards && pip3 install -e .

# 安装 RISC-V 工具链(用于编译软件)
sudo apt install gcc-riscv64-unknown-elf
# 或通过 litex_setup.py 自动安装:
python3 litex/litex/tools/litex_setup.py --gcc riscv

# 验证
python3 -c "import litex; print(litex.__version__)"  # 2024.04

3.2 完整 SoC 定义代码

#!/usr/bin/env python3
# my_ecp5_soc.py
# ECP5 + DDR3 + Ethernet + UART 完整 SoC
# 目标板:ULX3S(Lattice ECP5-85F + 32MB SDRAM)
# 实际 DDR 用 LiteDRAM,板子需要有 DDR3

from migen import *
from litex.soc.cores.clock import ECP5PLL
from litex.soc.integration.soc_core import SoCCore, SoCCoreArgs
from litex.soc.integration.builder import Builder, BuilderArgs
from litex.soc.cores.uart import UARTWishbone
from litex.soc.cores.gpio import GPIOOut
from litex.soc.cores.spi_flash import SpiFlash
from litedram.phy import ECP5DDRPHY
from litedram.core import LiteDRAMCore
from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII
from liteeth.core import LiteEthUDPIPCore


class MySoC(SoCCore):
    """
    ECP5 SoC:VexRiscv Linux + DDR3 + Ethernet + UART + SPI Flash
    
    内存映射(自动生成):
    0x00000000 - 0x07FFFFFF  DDR3 SDRAM(128 MB)
    0x20000000 - 0x2000FFFF  内部 SRAM(boot ROM)
    0xF0000000 - 0xFFFFFFFF  CSR(控制/状态寄存器)
    """

    def __init__(self, platform, sys_clk_freq=int(75e6)):

        # ── 1. 初始化 SoCCore ──────────────────────────────────────
        SoCCore.__init__(
            self,
            platform       = platform,
            sys_clk_freq   = sys_clk_freq,

            # CPU 配置
            cpu_type       = "vexriscv",
            cpu_variant    = "linux",    # 含 MMU,支持跑 Linux
            cpu_reset_address = 0x20000000,  # 复位后从 SRAM 启动

            # UART 配置(调试串口)
            with_uart      = True,
            uart_name      = "serial",
            uart_baudrate  = 115200,

            # 计时器(Linux 必需)
            with_timer     = True,

            # 标识符
            ident          = "LiteX SoC on ECP5-85F",
            ident_version  = True,
        )

        # ── 2. 时钟/复位生成器(CRG)──────────────────────────────
        # ECP5 的 PLL:输入 25 MHz 晶振 → 75 MHz 系统时钟
        #                                → 375 MHz DDR3 时钟(75 * 5)
        self.submodules.crg = _CRG(platform, sys_clk_freq)

        # ── 3. DDR3 内存控制器(LiteDRAM)─────────────────────────
        # ECP5 片上 DDR PHY(硬核 PHY,无需外部芯片)
        self.submodules.ddrphy = ECP5DDRPHY(
            pads         = platform.request("ddram"),
            sys_clk_freq = sys_clk_freq,
        )
        # 设置 DDR3 PHY 复位时序
        self.comb += self.crg.stop.eq(self.ddrphy.init.stop)
        self.comb += self.crg.reset.eq(self.ddrphy.init.reset)

        # LiteDRAM DDR3 控制器
        self.add_sdram(
            "sdram",
            phy              = self.ddrphy,
            module           = MT41K128M16(sys_clk_freq, "1:2"),  # Micron DDR3-800
            l2_cache_size    = 8192,         # 8 KB L2 缓存
            l2_cache_min_data_width = 128,   # 128-bit 总线宽度
            with_wishbone_adapter = True,
        )

        # ── 4. 以太网(LiteEth RGMII)──────────────────────────────
        # ECP5 通过 RGMII 接口连接外部 PHY(例如 LAN8720A)
        self.submodules.ethphy = LiteEthPHYRGMII(
            clock_pads = platform.request("eth_clocks"),
            pads       = platform.request("eth"),
        )
        self.add_ethernet(
            phy          = self.ethphy,
            mac_address  = 0x12345678abcd,
            ip_address   = "192.168.1.50",
            with_icmp    = True,
        )

        # ── 5. SPI Flash(存储 bitstream + 软件镜像)───────────────
        self.add_spi_flash(
            name  = "spiflash",
            mode  = "4x",    # Quad SPI 模式(最高 ~50 MB/s)
            dummy_cycles = 6,
        )
        # 让 CPU 可以从 SPI Flash 启动(地址映射到 0x30000000)
        self.add_constant("SPIFLASH_PAGE_SIZE",    256)
        self.add_constant("SPIFLASH_SECTOR_SIZE",  0x10000)

        # ── 6. 板载 LED(CSR 控制)────────────────────────────────
        self.submodules.leds = GPIOOut(
            pads = platform.request("user_leds", 0),
        )
        self.add_csr("leds")

        # ── 7. LiteScope 逻辑分析仪(可选,调试用)────────────────
        # 注释掉可节省约 1000 LUT
        # from litescope import LiteScopeAnalyzer
        # analyzer_signals = [self.cpu.ibus, self.cpu.dbus]
        # self.submodules.analyzer = LiteScopeAnalyzer(
        #     analyzer_signals, depth=512, clock_domain="sys", csr_csv="analyzer.csv"
        # )


class _CRG(Module):
    """时钟复位生成器:ECP5 PLL 25 MHz → 75 MHz + 375 MHz"""

    def __init__(self, platform, sys_clk_freq):
        self.rst    = Signal()
        self.stop   = Signal()
        self.reset  = Signal()

        self.clock_domains.cd_sys = ClockDomain()
        self.clock_domains.cd_init = ClockDomain(reset_less=True)

        # ECP5 PLL
        self.submodules.pll = pll = ECP5PLL()
        self.comb += pll.reset.eq(self.rst)
        pll.register_clkin(platform.request("clk25"), 25e6)

        # 系统时钟:75 MHz
        pll.create_clkout(self.cd_sys, sys_clk_freq, phase=11)

        # 初始化时钟(慢速,DDR 训练用)
        pll.create_clkout(self.cd_init, 10e6)

        # 复位
        self.specials += [
            AsyncResetSynchronizer(self.cd_sys,  ~pll.locked | platform.request("rst_n", loose=True) | self.reset),
        ]


def main():
    # 选择目标板
    from litex_boards.platforms import lattice_ecp5_evn
    platform = lattice_ecp5_evn.Platform()

    soc = MySoC(platform, sys_clk_freq=int(75e6))

    builder = Builder(
        soc,
        output_dir      = "build/ecp5_soc",
        csr_json        = "build/ecp5_soc/csr.json",
        csr_csv         = "build/ecp5_soc/csr.csv",
        compile_software = False,  # 先只生成硬件,不编译软件
    )

    # 构建选项
    builder.build(
        build_name = "ecp5_soc",
        # nextpnr 参数
        nextpnr_options = "--timing-allow-fail --placer heap",
    )


if __name__ == "__main__":
    main()

3.3 运行构建

# 生成 Verilog + 综合 + P&R
python3 my_ecp5_soc.py --build

# 输出目录结构:
# build/ecp5_soc/
# ├── gateware/
# │   ├── ecp5_soc.v          ← 生成的 Verilog(约 28,000 行)
# │   ├── ecp5_soc.lpf        ← 自动生成的约束文件
# │   └── ecp5_soc.bit        ← 最终 bitstream
# ├── software/
# │   ├── bios/               ← LiteX BIOS(固件)
# │   └── include/            ← 自动生成的头文件
# └── csr.json                ← 内存映射文档

# 烧写
openFPGALoader -b ulx3s build/ecp5_soc/gateware/ecp5_soc.bit

4. litex_sim:软件仿真运行 Linux

在花时间综合硬件之前,可以先用软件仿真验证软件栈:

# 安装仿真器后端
pip3 install verilator  # 或 apt install verilator

# 运行软件仿真
litex_sim \
  --cpu-type vexriscv \
  --cpu-variant linux \
  --with-sdram \
  --ram-size 256 \
  --with-ethernet \
  --with-uart-console \
  2>&1 | tee sim.log

仿真输出(Linux 启动过程):

LiteX v2024.04 (git SHA1: abc1234)

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 6.1.0 (gcc version 12.2.0 (GCC)) #1 SMP PREEMPT
[    0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 6.1.0 #1
[    0.000000] OF: fdt: Machine model: LiteX VexRiscv SoC
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000040000000-0x000000004fffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x40000000-0x4fffffff]  ← 256 MB DDR
[    0.020000] VexRiscv machine init
[    0.030000] LiteX UART driver loaded
[    0.050000] LiteEth driver loaded, MAC: 12:34:56:78:ab:cd
[    0.080000] LiteDRAM driver: 256 MB DDR3-800 initialized
[    0.100000] EXT4-fs (mmcblk0): mounted filesystem
[    0.120000] VFS: Mounted root (ext4 filesystem) on device 179:0
[    0.150000] Freeing unused kernel memory
[    0.160000] Run /init as init process

Welcome to LiteX Linux!
litex-linux login:

仿真比真实硬件慢约 1000x,但可以在没有开发板的情况下验证软件。


5. ECP5 真实综合结果

5.1 综合命令

# 完整综合流程(ECP5-85F)
python3 my_ecp5_soc.py --build 2>&1 | tee build.log

# 关键综合步骤输出:
# [INFO] Yosys: synth_ecp5 started
# [INFO] Yosys: 28,432 lines of Verilog read
# [INFO] Yosys: abc9 optimization...
# [INFO] Yosys: stat report:

5.2 资源占用报告

Yosys stat for ecp5_soc (synth_ecp5):

=== ecp5_soc ===

   LUT4:                        8,142
   TRELLIS_FF:                  4,891
   TRELLIS_BRAM:                   48    (96 Kbits used)
   EHXPLLL:                         2    (2 PLL)
   DDRDLL:                          1
   TRELLIS_IO:                    124

ECP5-85F capacity:
   LUT:  83,640   → 8,142 / 83,640 = 9.7%
   FF:   83,640   → 4,891 = 5.8%
   BRAM: 208      → 48 / 208 = 23.1%

细分资源占用:

模块LUT 数量备注
VexRiscv CPU(linux variant)~5,000含 MMU、乘法器
LiteDRAM DDR3 控制器~1,500含 L2 cache、ECC
LiteEth MAC + UDP/IP~800含 ARP、ICMP
UART + Timer + GPIO~200简单外设
SPI Flash 控制器~150Quad SPI
总线互联 + 地址解码~300Wishbone crossbar
LiteX BIOS + Bootloader~192BRAM
总计~8,142ECP5-85F 的 9.7%

5.3 时序结果

nextpnr-ecp5 timing report:

Max frequency for clock 'sys':  76.8 MHz (target: 75.0 MHz → PASS)
Max frequency for clock 'init': 12.3 MHz (target: 10.0 MHz → PASS)

Critical path: VexRiscv execute stage → memory stage
  Source: cpu/datapath/alu_result[31]  
  Sink:   cpu/datapath/mem_result[31]
  Slack:  +2.4 ns

实际运行在 75 MHz,留有 1.8 MHz 余量。


6. LiteDRAM 带宽测试

6.1 带宽测试程序

LiteX 自带 memtest 工具,通过串口运行:

# 连接串口(上电后进入 LiteX BIOS)
picocom -b 115200 /dev/ttyUSB1

# BIOS 提示符下运行内存测试
litex> memtest

# 输出:
# Memory at 0x40000000 (256 MB)
# Test 1: Writing...  done in 1.34 s
# Test 1: Reading...  done in 1.27 s
# Bandwidth (write): 190.5 MB/s
# Bandwidth (read):  200.3 MB/s
#
# Sequential burst (128-byte):
# Write: 612 MB/s
# Read:  598 MB/s

6.2 带宽数字解读

测试类型理论值LiteDRAM 实测效率
DDR3-800(单通道,×16 宽度)1,600 MB/s--
顺序突发读(128B 块)1,600 MB/s598 MB/s37%
顺序突发写(128B 块)1,600 MB/s612 MB/s38%
随机访问(单字节)-~12 MB/s<1%
CPU Dhrystone 测试-142 DMIPS @ 75 MHz-

为什么效率只有 37%?

  • LiteDRAM 用软核控制器(跑在 75 MHz),而 DDR3-800 需要 400 MHz 的 PHY 时钟
  • PHY 时钟由片上 PLL 生成,但软核的命令调度效率不如硬核
  • L2 缓存(8 KB)命中率对随机访问影响巨大
  • 对比:Zynq 硬核 DDR(400 MHz)实测顺序读可达 ~1,200 MB/s

7. 与 Zynq PS 硬核 DDR 的对比

这是一个值得严肃对待的对比,不是”开源一定更好”的宣传:

┌─────────────────────────────────────────────────────────────────┐
│                软核 DDR vs 硬核 DDR 对比                         │
│                                                                 │
│  LiteX SoC(ECP5 + LiteDRAM)                                   │
│  ┌─────────────┐    ┌──────────────────┐    ┌──────────────┐   │
│  │ VexRiscv    │    │  LiteDRAM DDR3   │    │  DDR3 DRAM   │   │
│  │ (软核 CPU)  │←→│  (软核控制器)    │←→│  (片外)     │   │
│  │ ~75 MHz     │    │  ~75 MHz 系统    │    │  400 MHz PHY │   │
│  └─────────────┘    └──────────────────┘    └──────────────┘   │
│  LUT 占用:~8,000   带宽:~600 MB/s         延迟:~100 ns       │
│                                                                 │
│  Zynq-7020(PS 硬核)                                           │
│  ┌─────────────┐    ┌──────────────────┐    ┌──────────────┐   │
│  │ ARM Cortex  │    │  PS DDR 控制器   │    │  DDR3 DRAM   │   │
│  │ A9 × 2      │←→│  (硬核,已优化)  │←→│  (片外)     │   │
│  │ ~667 MHz    │    │  ~533 MHz        │    │  533 MHz PHY │   │
│  └─────────────┘    └──────────────────┘    └──────────────┘   │
│  PL LUT 占用:0     带宽:~1,200 MB/s       延迟:~20 ns        │
└─────────────────────────────────────────────────────────────────┘
对比维度LiteX(ECP5 软核)Zynq-7020(PS 硬核)
CPU 频率75 MHz667 MHz(ARM A9 × 2)
CPU 性能~100 DMIPS~2,000 DMIPS × 2
DDR 带宽(顺序)~600 MB/s~1,200 MB/s
DDR 延迟~100 ns~20 ns
FPGA LUT 占用8,142(9.7% of 85F)0(PS 是独立硬核)
稳定性需要 DDR 训练,偶尔失败出厂标定,高度稳定
价格(FPGA 芯片)ECP5-85F:~$35Zynq-7020:~$80
Linux 启动时间~15 秒~3 秒
工具链全开源(nextpnr + LiteX)需要 Vivado
灵活性可替换 CPU 核(换成 RISC-V V 扩展、AI 加速器等)PS 固定,不可改变

结论: 软核 DDR 的代价是真实的——带宽只有硬核的 50%,延迟高 5x,还占用大量 FPGA 资源。但它的价值也是真实的:你可以在 PL 逻辑里实现定制化的 DMA、协处理器,并且直接集成到同一个 Wishbone 总线上。

🚧 避坑 1:VexRiscv MMU 必须配合特定 Linux 版本

LiteX 维护着自己 fork 的 Linux 内核(litex-hub/linux-on-litex-vexriscv), 里面包含针对 VexRiscv MMU 的特定补丁。

不要直接用主线 Linux 内核跑 VexRiscv,会有:

  • TLB flush 指令不兼容
  • Timer 中断处理差异
  • 某些 RISC-V 扩展缺失(如 Zicsr)

正确方式:

# 使用 LiteX 维护的 Linux 分支
git clone https://github.com/litex-hub/linux-on-litex-vexriscv.git
cd linux-on-litex-vexriscv
# 按 README 操作,会自动下载正确版本的内核、rootfs、dtb
./make.py --board ulx3s --build

🚧 避坑 2:LiteDRAM 训练失败排查

DDR3 需要在上电时做”训练”(training)——校准读写时序,补偿板卡上的走线延迟。 如果训练失败,内存会随机出错(bit flip),表现为 Linux 内核崩溃或内存测试失败。

排查步骤:

1. 看串口输出,找到 "LiteDRAM Training" 部分
   - "OK" 表示训练通过
   - "KO" 表示训练失败,后面的数字是失败的 DQ lane

2. 常见原因:
   a) 板卡 DDR 走线不对称(>25ps 差异)→ 调整 PCB
   b) PLL 输出频率不准确 → 微调 PLL 倍频数
   c) DDR3 芯片型号不匹配 → 检查 LiteDRAM 的 module 参数

3. 临时解决方法:降低 DDR 频率
   # 从 DDR3-800 降到 DDR3-666
   self.add_sdram("sdram", module=MT41K128M16(sys_clk_freq, "1:2"), ...)
   # 修改 PLL 输出频率(sys_clk_freq)

🚧 避坑 3:PHY reset 时序

ECP5 的 DDR PHY 有特定的上电时序要求:

  1. 必须先让 PHY 时钟稳定(PLL locked)
  2. 然后才能释放 PHY reset
  3. 然后才能开始 DDR 训练

LiteX 的 CRG 模块里 self.crg.stopself.crg.reset 信号就是为此设计的。 如果你自定义 CRG,必须确保这两个信号的连接正确,否则会出现随机的 DDR 初始化失败。

参考 litex-boards 里任何 ECP5 板的 CRG 实现,不要从头写。


8. 本篇 checklist / 验证步骤

  • 安装 LiteX:python3 -c "import litex; print(litex.__version__)" 正常
  • 运行 litex_sim --cpu-type vexriscv --cpu-variant standard,看到 LiteX BIOS 提示符
  • 运行带 --cpu-variant linux 的仿真,看到 Linux 启动 dmesg
  • 生成 ECP5 Verilog:python3 my_ecp5_soc.py(不加 --build),检查 build/ecp5_soc/gateware/ecp5_soc.v
  • (有开发板时)完整构建:python3 my_ecp5_soc.py --build
  • 检查综合报告:LUT 占用应该在 8,000-10,000 之间
  • 检查时序报告:Fmax ≥ 75 MHz

9. 下一篇预告

开源 FPGA 05:cocotb 仿真 将用 Python 替代 Verilog testbench:

  • 测试第 01 篇的 UART TX 模块:Python 发字节 → 检查串行时序
  • @cocotb.test() / await Timer() / await RisingEdge() API
  • cocotb + Verilator:仿真速度提升 10-50x
  • 用 Python hypothesis 做属性测试

如果你已经有了 LiteX SoC,cocotb 可以让你在综合到硬件之前,对每个 IP 核(UART、以太网、SPI)做完整的单元测试。


参考资料

资源链接 / 文档号说明
LiteX 官方文档github.com/litex-hub/litex/wiki安装、使用、板卡列表
VexRiscvgithub.com/SpinalHDL/VexRiscvCPU 源码,配置选项详解
LiteDRAMgithub.com/enjoy-digital/litedramDDR2/3/4 控制器,含带宽测试工具
LiteEthgithub.com/enjoy-digital/liteeth以太网 MAC/UDP/IP 栈
linux-on-litex-vexriscvgithub.com/litex-hub/linux-on-litex-vexriscv运行 Linux 的完整指南
litex-boardsgithub.com/litex-hub/litex-boards100+ 开发板定义
ECP5 数据手册Lattice DS1044ECP5-85F 资源、DDR PHY 规格
LiteDRAM 带宽报告enjoy-digital.fr/litedram各 DDR 配置的实测带宽

🦞 Kaiyo 的硬件工程日志

第一次用 litex_sim 看到 Linux 启动的那一刻,感觉很奇妙——一个完全由 Python 定义的 SoC,运行着一个完整的 Linux 系统。这种从抽象到具体的透明感,正是 LiteX 的魅力。软核 DDR 的带宽确实只有硬核的一半,但换来的是完全的可定制性和可观察性——在半导体设计的原型验证阶段,这往往比性能更重要。