Yosys interface 语法不支持:modport 报错与普通端口绕道路线
更新时间:2026-10-31。本文是开源 EDA 排错系列的 FAQ 速查页,总入口见 Yosys interface 语法不支持排错中心。这里处理的是原生
read_verilog -sv在特定interface/modport写法上的前端报错,目标是保住可综合模块的端口与行为,而不是寻找一份虚构的完整 SystemVerilog 支持清单。
本文要回答的问题
unexpected ';', expecting '(' or '['为什么落在counter_if.producer bus;?- 这个报错能推出“所有 interface 写法都会被 Yosys 拒绝”吗?
- 怎样把接口里的时钟、请求和数据信号展开为普通模块端口?
- 改写之后,应该用哪些输出确认前端、层次和过程转换都已通过?
一、Yosys interface 语法不支持先定位到具体声明形式
本篇复现使用非 ANSI 端口列表:模块头只写 counter(bus),随后在模块体中用 counter_if.producer bus; 声明带 modport 的接口端口。modport 是接口给不同使用方准备的信号方向视图;问题不在计数器算法,而在 Yosys 0.33 的原生前端没有接受这一位置上的限定声明。
读这张图要守住中间那条线:改写的是模块连接方式,不是把 always_ff 里的计数行为重新设计一遍。右侧也限定了结论范围——一个报错样例和一条成功对照,只能证明这两种输入在该版本中的表现。
最小复现保留接口、modport、使用接口的计数器和顶层连接。真正触发错误的是第 9 行;删除顶层包装并不会把这条声明变成受支持的语法。
interface counter_if(input logic clk);
logic req;
logic [7:0] data;
modport producer(input clk, input req, output data);
endinterface
module counter(bus);
counter_if.producer bus;
always_ff @(posedge bus.clk) begin
if (bus.req)
bus.data <= bus.data + 1'b1;
end
endmodule错误里的分号就是声明末尾的分号,expecting '(' or '[' 是解析器在该位置仍期待其他语法形式的提示,不是要求你机械地给 bus 补括号或位宽。interface_exit=1 则确认前端以失败退出,尚未进入普通端口对照中的 proc 阶段。
二、绕行不是翻译 modport,而是恢复显式连接关系
普通端口改写要回答三个问题:模块实际读到哪些信号、驱动哪些信号、每个信号多宽。原计数器读取 bus.clk 和 bus.req,驱动 bus.data,因此展开后只需要 clk、req、data 三个端口。modport 名 producer 是接口视图的名字,不需要变成一个新端口。
| 原接口成员 | 普通端口 | 方向与宽度 | 改写依据 |
|---|---|---|---|
bus.clk | clk | input wire,1 位 | 时序块的时钟输入 |
bus.req | req | input wire,1 位 | 计数使能输入 |
bus.data | data | output reg [7:0] | 时序块驱动的 8 位数据 |
producer | 不保留 | 无 | modport 视图名,不是硬件信号 |
方向要以当前模块为参照,不要照抄另一个使用者的视角。这里的 data 在计数器内部由时序过程赋值,所以使用 output reg;如果拆成组合加法器和外部寄存器,端口声明也会跟着变化,那已经属于另一种电路结构。
三、普通端口版本只改声明与引用
下面的完整模块仍执行同一个动作:时钟上升沿到来且 req=1 时,8 位 data 加一。initial 只给这个最小样例一个确定初值,不应据此推断目标器件一定支持同一种初始化实现。
module counter(
input wire clk,
input wire req,
output reg [7:0] data
);
initial data = 8'd0;
always @(posedge clk) begin
if (req)
data <= data + 1'b1;
end
endmodule所有 bus. 前缀随接口一起消失,端口宽度没有变化。工程里继续改顶层例化:原来传入一个接口实例的位置,改为 .clk(clk)、.req(req)、.data(data) 的命名连接。若多个模块共用同一接口,每个模块都要按自己的读写关系展开,不能拿这一份三端口声明覆盖所有角色。
改写后执行的不只是 read_verilog,还串联了 hierarchy -top counter; proc; stat。这样至少能区分“文件恰好被读入”和“层次确定、过程已转换为单元”两种状态。
四、复跑证据:对照版生成加法器、触发器和多路器
以下摘录来自同一次运行。前端成功生成 counter,proc 为 data 建立正边沿触发器,最终统计为 3 个单元;plain_exit=0 表示这条普通端口路线完整返回成功。
Generating RTLIL representation for module `\counter'.
Successfully finished Verilog frontend.
Top module: \counter
Creating register for signal `\counter.\data' using process `\counter.$proc$plain_ports.v:8$1'.
created $dff cell `$procdff$6' with positive edge clock.
=== counter ===
Number of public wires: 3
Number of public wire bits: 10
Number of processes: 0
Number of cells: 3
$add 1
$dff 1
$mux 1
plain_exit=0
result=expected interface rejection and plain-port success$add、$dff、$mux 分别对应加一、8 位状态保存和使能分支形成的选择逻辑。这里统计的是寄存器传输级转换结果,不是某种工艺映射后的面积,也不能拿单元数推断时序或功耗。它的价值在于证明绕行版本已经越过原来的语法错误点。
统计中的 3 个公共线网也正好对应 clk、req、data,公共位宽合计为 10 位,即两个 1 位输入加一个 8 位输出。这个数字能辅助发现漏接或位宽被意外展开的问题,但仍不能代替端口连接检查:两个不同模块完全可能拥有相同的端口数量与总位宽。
五、按报错位置决定是否需要展开接口
实际项目可能同时存在其他 SystemVerilog 特性。不要见到 interface 文件就全部重写,应按下面的顺序缩小范围。红色是原始错误,蓝色是定位,橙色是改写,绿色是复跑通过,紫色是记录适用范围。
如果改完仍在另一行报错,应把新错误当作独立问题处理,不要继续无方向地删语法。特别是 hierarchy 报端口不存在或宽度不一致时,优先查顶层例化;那已经不同于本文的前端解析失败。
六、工程改写时保留三张清单
接口通常承载一组有名字的连接契约,展开之后,编译器不再替你保存这份契约。为避免几十处例化逐一手改后漂移,至少保留信号、方向和验证三张清单。
| 清单 | 必记内容 | 容易漏掉的检查 |
|---|---|---|
| 信号清单 | 原名、展开名、位宽、参数依赖 | 打包数组与条件生成是否仍一致 |
| 方向清单 | 每个模块自己的输入输出 | 不直接照搬其他 modport 视角 |
| 验证清单 | 工具版本、命令、退出码、单元统计 | 不用一次成功覆盖其他语法形式 |
本文没有运行仿真,也没有证明展开前后在所有激励下形式等价;对照实验只覆盖前端读取、层次处理和 proc。若原工程带测试台,应另行复跑功能回归。若接口还含任务、函数、clocking block 或参数化成员,也不能假设本篇三信号样例已经覆盖它们。
代码获取
本文最小复现、普通端口对照与运行脚本已整理到公开仓:https://github.com/derekzhuo/geek-doc.cn/tree/main/experiments/ts-yosys-interface-unsupported。进入该目录执行 bash run.sh,脚本会检查报错输入非零退出、普通端口输入零退出这两个条件。
实验环境
- 机器/系统:Mac / macOS(Darwin 25.5.0,x86_64),Docker 容器运行
- 工具版本:Yosys 0.33 (git sha1 2584903a060),镜像
geek-eda:0.2 - 日期:2026-10-31
- 完整命令:
bash run.sh;脚本以docker run --rm -v "$PWD:/work" -w /work geek-eda:0.2 yosys ...分别执行版本查询、报错复现和普通端口对照
这一篇在知识体系里的位置
本篇属于开源 EDA 排错簇的“SystemVerilog 前端语法边界”节点,处理 Yosys interface 语法不支持时的一条可验证绕道路线。其他报错仍应回到 Yosys interface 语法不支持排错中心 按错误阶段分流,不要把普通端口展开当成所有解析问题的通用修复。
总结
Yosys interface 语法不支持在这篇复现里具体指:Yosys 0.33 原生前端拒绝非 ANSI 端口声明中的 counter_if.producer bus;,在第 9 行报语法错误并退出 1。把 clk、req、data 展开为普通端口、同步修改例化后,同一计数器通过前端、hierarchy 和 proc,生成 $add、$dff、$mux 各 1 个。该结果只证明这条绕行路线有效,不代表其他 interface 形式或完整 SystemVerilog 功能都已得到支持。