用Python给Verilog设计自仿(一):Cocotb环境初探-Anlogic-安路社区-FPGA CPLD-ChipDebug

用Python给Verilog设计自仿(一):Cocotb环境初探

1前言

很多FPGA/IC工程师擅长设计,但在仿真方面较为薄弱。我认为主要问题在于,完整的仿真实现学习成本较高,如学习UVM需要掌握大量新的内容。而单纯使用Verilog自仿又难以满足需求,以报文仿真为例,我们需要解析报文,若仅依赖Verilog自仿,就相当于要自己编写一个报文解析模块,工作量非常庞大。而Python在数据处理方面则更加高效,如果加以利用,完全可以快速构建一个完整的仿真模型。Cocotb的诞生,为硬件工程师提供了一条更轻量、更灵活的路径——用Python脚本直接驱动Verilog/VHDL仿真。

Cocotb是一款基于协程的协同仿真库,通过Python的简洁语法和丰富生态,可直接操作硬件端口、生成测试激励并断言结果,甚至能与SystemVerilog UVM混合验证 。相较于UVM需要从类库、方法学到脚本的完整学习,Cocotb只需掌握Python基础即可快速上手,且能复用Python生态中的数据处理、随机化测试等工具,将验证代码量减少70%以上。

如今,Cocotb已成为开源硬件项目的宠儿。例如GitHub高星项目verilog-ethernet利用Cocotb实现模块级自动化测试;AXI总线验证库(如cocotb-axi)通过Python脚本简化复杂协议测试。

本系列将从零搭建Cocotb环境,解析其协程调度、自动化测试与开源生态,让Python成为你手中最高效的“验证加速器”。

2安装前置条件

cocotb 的当前稳定版本需要: 

Python 3.6+ 

GNU Make 3+ 

Verilog 或 VHDL 仿真器,取决于您的 RTL 源代码

支持以下系统

#Supported Windows Versions
Windows 10 x86_64 
Windows 11 x86_64


#Supported macOS Versions
macOS 11 (Big Sur) 
macOS 12 (Monterey) x86_64 
macOS 13 (Ventura) x86_64

Cocotb建议Linux经验较少的用户使用下面列出的经过支持和测试的发行版,以确保cocotb的顺畅体验。当然其他版本Linux也不是不行。

Red Hat Enterprise Linux (RHEL) 7.7+ amd64, shipping with Python 3.6, pip 9, and glibc 2.17. Upstream support until June 2024.
Red Hat Enterprise Linux (RHEL) 8 amd64, shipping with Python 3.6 (newer versions of Python are available), pip 9, and glibc 2.28. Upstream support until May 2029.
Red Hat Enterprise Linux (RHEL) 9 amd64, shipping with Python 3.9 (newer versions of Python are available), pip 21, and glibc 2.34. Upstream support until May 2032.
Ubuntu 20.04 LTS amd64, shipping with Python 3.8, pip 20, glibc 2.31. Upstream support until April 2025.
Ubuntu 22.04 LTS amd64, shipping with Python 3.10, pip 22, glibc 2.35. Upstream support until April 2027.

请根据自己的系统安装对应的前置环境

#Linux-Debian
sudo apt-get install make python3 python3-pip libpython3-dev
#Linux-Red Hat
sudo yum install make python3 python3-pip python3-libs
#macOs
brew install python
#windows-Windows Subsystem for Linux(WSL)
conda install -c msys2 m2-base m2-make

3安装cocotb

安装cocotb

pip install "cocotb~=1.9"

装cocotb可重用的总线接口和测试台组件(可选)

cocotb-bus提供预定义的协议驱动模型(如AxiMaster、AxiStreamDriver),可直接调用读写事务方法,避免从底层信号操作开始编码,其测试台组件(如时钟生成器、复位控制器)可封装为通用模块

pip install cocotb[bus]

如果没有用户权限安装cocotb,可尝试在pip中添加–user选项。

4搭建测试环境

创建TestBench

一个典型的cocotb TestBench不需要额外的HDL代码。DUT作为顶级模块在仿真器中实例化,不需要任何HDL包装代码。 测试是用Python编写的。 在cocotb中,可以通过传递给每个测试的对象(dut)访问设计的所有内部内容,例如信号、端口、参数等。

# test_my_design.py (extended)
import cocotb
from cocotb.triggers import FallingEdge, Timer
async def generate_clock(dut):
    """Generate clock pulses."""
    for cycle in range(10):
        dut.clk.value = 0
        await Timer(1, units="ns")
        dut.clk.value = 1
        await Timer(1, units="ns")
@cocotb.test()
async def my_second_test(dut):
    """Try accessing the design."""
    await cocotb.start(generate_clock(dut))  # run the clock "in the background"
    await Timer(5, units="ns")  # wait a bit
    await FallingEdge(dut.clk)  # wait for falling edge/"negedge"
    dut._log.info("my_signal_1 is %s", dut.my_signal_1.value)
    assert dut.my_signal_2.value[0] == 0, "my_signal_2[0] is not 0!"

1.时钟信号驱动

#在顶层模块的clk端口上驱动10个周期的方波时钟。
async def generate_clock(dut):
    """Generate clock pulses."""
    for cycle in range(10):
        dut.clk.value = 0
        await Timer(1, units="ns")
        dut.clk.value = 1
        await Timer(1, units="ns")

2.监控与断言

# 打印my_signal_1的实时值
ut._log.info("my_signal_1 is %s", dut.my_signal_1.value)
# 断言my_signal_2[0]是否为低电平,失败时抛出错误
assert dut.my_signal_2.value[0] == 0, "my_signal_2[0] is not 0!"
# 打印my_signal_1的实时值
ut._log.info("my_signal_1 is %s", dut.my_signal_1.value)
# 断言my_signal_2[0]是否为低电平,失败时抛出错误
assert dut.my_signal_2.value[0] == 0, "my_signal_2[0] is not 0!"

3.测试函数与协程控制

# 使用@cocotb.test()装饰器定义测试用例
@cocotb.test()
async def basic_test(dut):
    # 创建时钟驱动协程(后台运行)
    cocotb.start_soon(generate_clock(dut))  
    # 给信号赋值(二进制字面量语法)
    dut.my_signal_1.value = 0b1010  
    # 等待3个时钟周期后读取信号
    await ClockCycles(dut.clk, 3)  
    current_value = dut.my_signal_2.value
注意:
  • 使用@cocotb.test()装饰器标记需要运行的测试函数。每个@cocotb.test()函数独立运行,仿真器会在测试间自动复位DUT。
  • 使用.value = value语法为信号赋值
  • 使用.value获取信号的当前值
  • 显示的测试是顺序运行的,从开始到结束。每个await表达式都会暂停测试的执行,直到测试等待的事件发生并且仿真器将控制权返回给cocotb。必须通过await Timer()或await ClockCycles()主动推进仿真时间,否则陷入死循环。
  • 建议使用dut._log.debug()/info()/error()分级输出调试信息
创建MakeFile

# Makefile
# defaults
SIM ?= icarus
TOPLEVEL_LANG ?= verilog
VERILOG_SOURCES += $(PWD)/my_design.sv
# use VHDL_SOURCES for VHDL files
# TOPLEVEL is the name of the toplevel module in your Verilog or VHDL file
TOPLEVEL = my_design
# MODULE is the basename of the Python test file
MODULE = test_my_design
# include cocotb's make rules to take care of the simulator setup
include $(shell cocotb-config --makefiles)/Makefile.sim

SIM:模拟器,默认使用icarus,可支持以下模拟器

ctivehdl cvc ghdl icarus ius modelsim nvc questa riviera vcs verilator xcelium

TOPLEVEL_LAN: 顶层模块语言在我们的例子中是Verilog

VERILOG_SOURCES/VHDL_SOURCES:设计源文件
TOPLEVEL:要实例化的顶层模块或实体,在我们的例子中是my_design
MODULE:包含测试的文件,不带.py扩展名,在我们的例子中是test_my_design.py
 
如果我们使用VCS需要配置成以下MakeFile:

# Makefile

# defaults
SIM ?= vcs 
TOPLEVEL_LANG ?= verilog

VERILOG_SOURCES += $(PWD)/my_design.sv
# use VHDL_SOURCES for VHDL files

# TOPLEVEL is the name of the toplevel module in your Verilog or VHDL file
TOPLEVEL = my_design

# MODULE is the basename of the Python test file
MODULE = test_my_design

# 指定VCS编译选项
EXTRA_ARGS += -full64 -cpp g++-4.8 -cc gcc-4.8 -LDFLAGS "-Wl,--no-as-needed" -debug_access+all


# include cocotb's make rules to take care of the simulator setup
include $(shell cocotb-config --makefiles)/Makefile.sim

创建Verilog顶层文件

// This file is public domain, it can be freely copied without restrictions.
// SPDX-License-Identifier: CC0-1.0

module my_design(input logic clk);

  timeunit 1ns;
  timeprecision 1ns;

  logic my_signal_1;
  logic my_signal_2;

  assign my_signal_1 = 1'bx;
  assign my_signal_2 = 0;

    //verdi波形仿真,如果不用verdi则不需要
    initial begin
      $fsdbDumpfile("my_design.fsdb");
      $fsdbDumpvars(0, my_design);
    end
endmodule

注意:这三个文件需放在同级文件夹中

图片[1]-用Python给Verilog设计自仿(一):Cocotb环境初探-Anlogic-安路社区-FPGA CPLD-ChipDebug

5初探

执行:

make

也可以指定对应的仿真器执行:

make SIM=vcs

可以看到执行了多长时间和用例是否通过

图片[2]-用Python给Verilog设计自仿(一):Cocotb环境初探-Anlogic-安路社区-FPGA CPLD-ChipDebug
查看波形:

verdi -sv +v2k my_design.sv -ssf my_design.fsdb
图片[3]-用Python给Verilog设计自仿(一):Cocotb环境初探-Anlogic-安路社区-FPGA CPLD-ChipDebug
本测试使用的是Cocotb+VCS+Verdi的仿真环境,如果使用其他工具仿真需要用其他的命令,建议参考cocotb和仿真器的官方文档。

7写在最后

本文详细拆解了 Cocotb验证框架的环境搭建与仿真流程,涵盖Python环境配置、仿真器联动与基础操作,助你快速迈出硬件验证自动化的第一步。

下期主要更新,Makefile实战,用模块化Makefile模板实现一键编译、仿真、调试;DUT实战演练,以D触发器模块为例,演示从测试平台搭建到波形分析的完整链路;

 

 

 

请登录后发表评论

    没有回复内容