You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用CocoTB测试Verilog模块间交互?两种实现方式咨询

用CocoTB测试多个Verilog模块交互的两种方法

被测模块代码

TX模块

// stream data to a receiver
module TX (
      input clk_i, rst_i,
      output data_o
      );
// 模块内部实现(略)
endmodule

RX模块

// receive data from a transmitter and synchronize to the data stream
module RX (
      input clk_i, rst_i, data_i,
      output sync_o
      );
// 模块内部实现(略)
endmodule

针对你的问题,有两种可行的实现方式,分别对应是否需要编写顶层Verilog测试模块:

方法一:使用顶层Verilog测试模块作为DUT

这是贴近传统Verilog测试流程的方式,步骤如下:

  1. 编写你提供的TX_RX_tb.v作为顶层模块,完成TX和RX的实例化与信号连接:
module TX_RX_tb(
      input clk_i, rst_i,
      output sync_o
      );

wire data;

TX TX_inst(.clk_i(clk_i), .rst_i(rst_i), .data_o(data));
RX RX_inst(.clk_i(clk_i), .rst_i(rst_i), .data_i(data), .sync_o(sync_o));
endmodule
  1. 编写CocoTB测试脚本,将这个顶层模块直接作为被测设计(DUT),控制输入并验证输出:
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge

@cocotb.test()
async def test_tx_rx_sync(dut):
    # 生成10MHz时钟
    clock = Clock(dut.clk_i, 10, units="ns")
    cocotb.start_soon(clock.start())
    
    # 执行复位
    dut.rst_i.value = 1
    await RisingEdge(dut.clk_i)
    dut.rst_i.value = 0
    await RisingEdge(dut.clk_i)
    
    # 等待同步完成并验证
    await RisingEdge(dut.sync_o)
    assert dut.sync_o.value == 1, "RX未成功同步TX"
    
    # 可扩展:添加特定数据发送与接收验证逻辑

这种方式的优势是和传统Verilog测试流程兼容,复杂模块间的连接逻辑用Verilog编写更直观,适合大型设计。

方法二:直接在CocoTB Python脚本中连接多个模块

CocoTB支持直接在Python中实例化多个Verilog模块,通过cocotb.Wire完成信号连接,无需额外编写顶层Verilog文件:

  1. 确保TX和RX的Verilog文件能被仿真器识别(比如在Makefile中指定源文件路径)
  2. 编写Python测试脚本,手动实例化模块并连接信号:
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.binary import BinaryValue

@cocotb.test()
async def test_tx_rx_direct_connect():
    # 实例化TX和RX模块
    tx = await cocotb.instantiate("TX", "tx_inst")
    rx = await cocotb.instantiate("RX", "rx_inst")
    
    # 创建连线连接TX的data_o与RX的data_i
    data_wire = cocotb.Wire(name="data", dtype=BinaryValue)
    tx.data_o <= data_wire
    rx.data_i <= data_wire
    
    # 给两个模块共享时钟
    clock = Clock(tx.clk_i, 10, units="ns")
    cocotb.start_soon(clock.start())
    rx.clk_i <= tx.clk_i
    
    # 执行复位
    tx.rst_i.value = 1
    rx.rst_i.value = 1
    await RisingEdge(tx.clk_i)
    tx.rst_i.value = 0
    rx.rst_i.value = 0
    await RisingEdge(tx.clk_i)
    
    # 验证同步状态
    await RisingEdge(rx.sync_o)
    assert rx.sync_o.value == 1, "RX未成功同步TX"

这种方式的好处是无需额外编写Verilog顶层文件,测试逻辑集中在Python中,适合快速验证小型模块间的交互。

选择建议

  • 若模块间连接逻辑复杂(如多组信号、跨时钟域),优先用方法一,Verilog编写连接更清晰。
  • 若只是快速验证简单模块的交互,方法二更高效,减少文件数量。

内容的提问来源于stack exchange,提问作者pbandlead

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:37:08