最后更新:2026-08-17
面向对象:从未接触过可重构仪器的人或 AI。本文只讲"怎么写一份能编译通过的设计文件",不涉及硬件原理。

0. 先说结论(TL;DR)

一个设计文件就是把两样东西写出来:

  1. 用了哪些仪器模块modules):像搭积木一样选模块、命名、可选地指定版本和物理槽位。
  2. 模块之间怎么连connections):把一个模块的输出端口接到另一个模块的输入端口。

一个最小的、能编译的文件只有这么长:

modules:
  - name: dds1
    type: DDS
    version: null
    parameters: {}
  - name: osc1
    type: Oscilloscope
    version: null
    parameters: {}
connections:
  - from: dds1.sin_out
    to: osc1.in0

1. 文件结构与顶层键

文件必须是 UTF-8 编码的 YAML。顶层只有两个键,两个都必须存在

modules: [...]      # 模块清单(数组)——可以为空 [],空则仅生成基础设施(无仪器模块)
connections: [...]  # 连接清单(数组)——可以为空 []

2. 模块条目(modules 数组的每个元素)

2.1 字段总览

- name: adc1           # 必填:实例名,全文件唯一
  type: AD402x         # 必填:模块类型,必须是第 4 节表中的 type
  version: null        # 必填键:null 表示用最新版;写具体版本号表示锁定版本
  parameters: {}       # 必填键:模块参数,不填参数就写空对象 {}
  phy_slot: SB1        # 可选:物理槽位,纯逻辑模块不需要
  ports: [...]         # 可省略、会被忽略(见 2.6)

2.2 各字段规则

字段是否必需规则
name必需实例名。建议只用小写字母、数字、下划线(会变成 C 标识符和 TCL 名字,不能有连字符/空格/点)。全文件内唯一
type必需必须与第 4 节表中的 type 完全一致(大小写敏感)。写了表里没有的类型 → 编译报错
version键必须存在值写 null(或空字符串)→ 自动用仓库最新版本;写 "0.2.1" 这类点分数字字符串 → 锁定该版本。注意:version: 这个键本身不能删,删了模块会被静默跳过(控制台打印 import failed);若该模块还在 connections 里被引用,则整个编译直接失败
parameters键必须存在不传参数就写 {}。传了模块不认识的参数名 → 编译报错(见 2.4)
phy_slot可选物理槽位,见第 5 节。纯逻辑模块写不写都会被忽略
ports可省略编译器导入时完全忽略这个字段,端口一律由模块类型决定(见 3.1)。不写、少写、写错都不影响编译,可以不写

2.3 version 取值示例

- name: dds1
  type: DDS
  version: null        # 用最新版(推荐,最省心)
- name: dds2
  type: DDS
  version: "1.2.1"     # 锁定 1.2.1(必须是在仓库里存在的版本,否则报错)
version: null 里的 null 是 YAML 的空值字面量,不是字符串。也可以写 version: "" 或直接 version:(留空)。

2.4 parameters 取值示例

- name: osc1
  type: Oscilloscope
  parameters:
    n_channels: 4      # 通道数
    addr_width: 12     # 采集深度(寻址位宽)
- name: scan1
  type: ScanController
  parameters:
    n_channels: 2
    max_npoints: 4096

哪些模块有哪些参数,见第 4 节表。规则:

2.5 phy_slot 取值规则

2.6 为什么不用写 ports

模块的真实端口是由模块类型决定的(在 PL IP 里定义),设计文件里的 ports 字段导入时被忽略。编译器在导出 Outputs/design.yaml 时会自己重新生成完整端口信息。所以:


3. 连接规则(connections

3.1 端口从哪来

端口是每个模块类型的固定属性(见第 4 节表)。连接时只能引用表中列出的端口名,写成 模块实例名.端口名

3.2 端口种类规则(最重要的一条)

一条连接必须把一个【输出】端口和一个【输入】端口连在一起:

connections:
  - from: dds1.sin_out   # 输出端口
    to:   osc1.in0       # 输入端口

3.3 其它约束


4. 模块速查表

端口方向: 表示输出(可作为 from), 表示输入(可作为 to)。
"物理槽位"列为空的 = 纯逻辑模块,无 phy_slot
type输出端口(→)输入端口(←)物理槽位parameters
AD402xdataoutSB1~SB8
AD4005dataoutSB1~SB8
AD5791datainSB1~SB8
AD5541datainSB1~SB8
ADDA_HF_AXIadc_indac_outJ2 / J3
DigiIOHFdigital_indigital_outSB1~SB8
PhaseAnalyzerphase_out freq_out locked clk_outSB1~SB8
PulseCounterpulse_in
DigiMuxsig_outsig_in0sig_in{n-1}n_channels(默认 2,任意正整数)
DDSphase_out sin_out cos_out signal_out trigger_outfreq_ext amplitude_ext offset_ext trigger_in
LockIn_HFx_data y_data r_data p_dataref_phase signal_in
PIDchannel_ychannel_x
LowPassdataoutdatain
Oscilloscopein0in{n-1}n_channels(默认 2,须 2 的幂)、addr_width(默认 10)
ScanControllermotivin0in{n-1}n_channels(默认 1,须 2 的幂)、max_npoints(默认 1024)
AWGwaveform_outtrigger_in无(波形缓冲固定 1024 点)

补充说明:


5. 物理槽位(phy_slot

槽位是硬件板卡上的物理插口,编译器据此把模块的引脚映射到 FPGA 的物理引脚:

槽位位置适用模块
SB1 ~ SB8SPI 母板AD402x、AD4005、AD5791、AD5541、DigiIOHF、PhaseAnalyzer
J2J3高速子卡ADDA_HF_AXI

6. 完整示例

6.1 测量闭环:ADC → PID → DAC

# 一个带物理 IO 的闭环:AD402x 采样 → PID 处理 → AD5791 输出
modules:
  - name: adc1
    type: AD402x
    version: null
    parameters: {}
    phy_slot: SB1
  - name: pid1
    type: PID
    version: null
    parameters: {}
  - name: dac1
    type: AD5791
    version: null
    parameters: {}
    phy_slot: SB2
connections:
  - from: adc1.dataout
    to: pid1.channel_x
  - from: pid1.channel_y
    to: dac1.datain

6.2 锁相放大链路:DDS → LockIn → Oscilloscope

modules:
  - name: dds1
    type: DDS
    version: null
    parameters: {}
  - name: lockin1
    type: LockIn_HF
    version: null
    parameters: {}
  - name: osc1
    type: Oscilloscope
    version: null
    parameters:
      n_channels: 4
      addr_width: 12
connections:
  - from: dds1.sin_out
    to: lockin1.signal_in
  - from: dds1.cos_out
    to: lockin1.ref_phase
  - from: lockin1.x_data
    to: osc1.in0
  - from: lockin1.y_data
    to: osc1.in1

6.3 高速 ADDA + 扫描控制器

modules:
  - name: ddfa1
    type: ADDA_HF_AXI
    version: null
    parameters: {}
    phy_slot: J2
  - name: scan1
    type: ScanController
    version: null
    parameters:
      n_channels: 2
      max_npoints: 4096
  - name: dds1
    type: DDS
    version: null
    parameters: {}
connections:
  - from: ddfa1.adc_in
    to: scan1.in0
  - from: dds1.sin_out
    to: ddfa1.dac_out

7. 常见错误与排查

症状原因解决
控制台打印 ... import failed 且该模块没进设计模块条目的 versionparameters 键缺失;或类型名写错补上 version: nullparameters: {};核对 type 与表一致。若该模块被 connections 引用,后续还会报 Module or port not found
报错 Module or port not found in connection ...connections 里引用了不存在的模块或端口;或该模块因 version/parameters 键缺失被跳过核对实例名、类型端口名(第 4 节表);检查被引用模块是否真的加载成功
报错 target port is not an out port一条连接的两个端口是同一类(两个都是输出,或两个都是输入)保证每条连接是"一个输出 + 一个输入"
报错 target is already driven两个输出同时接同一个输入让每个输入只保留一个 from
报错 n_channels must be power of 2Oscilloscope / ScanController 的 n_channels 不是 2 的幂改为 1、2、4、8……
报错 Version ... not found in repositoryversion 写的版本在仓库里不存在改成 null 用最新版,或改成仓库里存在的版本
编译通过,但某模块没有物理引脚phy_slot 填了不存在的槽位(如 SB9)核对槽位:SPI 类 SB1~SB8,ADDA_HF 用 J2/J3
version 想省略不写不行必须写 version: 键(值可为 null)