1.2 一份电路的三种讲法:建模视角


文档摘要

1.2 一份电路的三种讲法:建模视角 本节摘要:Verilog 用三种建模视角描述电路:结构化建模像装配清单,数据流建模像逻辑函数表,行为级建模像响应规则说明书。三种讲法可以混用,综合器最终会把它们全部翻译成门电路。分清自己站在哪一层,是避免「仿真对、上板错」的第一道防线。 上一节交代了语言的来路,这一节回答一个更实际的问题:面对同一个电路,Verilog 提供哪几种讲法,各自适合什么场合。这是建模视角的「立案登记」——后面所有章节的语法,都能归进这三种讲法里。 别把三种讲法当成三种语言 初学者最常见的误判,是把结构化、数据流、行为级当成三门不同的东西。其实它们是同一门语言里并存的描述粒度,写在同一份文件里都合法。

1.2 一份电路的三种讲法:建模视角

本节摘要:Verilog 用三种建模视角描述电路:结构化建模像装配清单,数据流建模像逻辑函数表,行为级建模像响应规则说明书。三种讲法可以混用,综合器最终会把它们全部翻译成门电路。分清自己站在哪一层,是避免「仿真对、上板错」的第一道防线。

上一节交代了语言的来路,这一节回答一个更实际的问题:面对同一个电路,Verilog 提供哪几种讲法,各自适合什么场合。这是建模视角的「立案登记」——后面所有章节的语法,都能归进这三种讲法里。

别把三种讲法当成三种语言

初学者最常见的误判,是把结构化、数据流、行为级当成三门不同的东西。其实它们是同一门语言里并存的描述粒度,写在同一份文件里都合法。真正的区别在于「你描述的是电路的哪一面」:是元件之间的接线(结构)、是输出与输入的逻辑函数关系(数据流)、还是电路对事件的响应规则(行为)。

三种讲法的证据力不同。结构化描述最接近真相——你实例化一个门,综合后就真的是那个门,没有解释空间。数据流描述次之——assign 写的是逻辑表达式,综合器会做布尔化简,结果可能与你的表达式形态不同但逻辑等价。行为级描述弹性最大——always 块只规定响应规则,具体长成什么电路由综合器推断,推断错了不怪它,怪你没把规则写清楚。

别把三种讲法当成三种语言

三种讲法同台:一个选择器审三次

以二选一多路选择器为例——信号 sel 为高选 a,为低选 b。这个电路小到一眼能看穿,正好用来对比讲法差异。

结构化写法,直接实例化门原语,自己当装配工:

module mux2_struct( input wire a, b, sel, output wire y ); wire sel_n; // sel 的反相 wire ch_a; // a 与 sel 相与 wire ch_b; // b 与 sel 反相相与 not g1(sel_n, sel); and g2(ch_a, a, sel); and g3(ch_b, b, sel_n); or g4(y, ch_a, ch_b); endmodule

数据流写法,把逻辑函数一行写完:

module mux2_dataflow( input wire a, b, sel, output wire y ); assign y = (a & sel) | (b & ~sel); endmodule

行为级写法,描述响应规则而不画门:

module mux2_behavior( input wire a, b, sel, output reg y // 过程块内赋值的目标要声明为 reg ); always @(*) begin if (sel) y = a; else y = b; end endmodule

案例展开:三种写法的综合对账。 背景是想确认「讲法不同是否导致电路不同」。操作:把三个模块分别交给综合工具跑同一工艺库,比对网表与面积报告。结果值得细看:结构化版本几乎原样保留四个门,因为结构描述没有解释空间;数据流版本被工具化简,两个与门、一个或门、一个非门保持,连线可能重排,逻辑等价;行为级版本综合出的电路与前两者等价,具体结构取决于工具——多数工具会生成与数据流版本相同的门,也有些会映射到库里的多路选择器单元。解读:三种讲法殊途同归,「讲法」影响的是综合器的工作方式和你代码的可读性、可维护性,而不是电路的逻辑功能。变式:把选择条件改成三选一、四选一,行为级写法的优势立刻显现——case 语句加几行就行,结构化写法则要手工装配的门数翻倍,此时没人再坚持画门。

混用与层次

真实工程里三种讲法混着用。顶层模块用结构化方式把几个子模块装配起来;子模块内部的组合逻辑用 assign 写;时序逻辑用 always 写。这种「层次化装配加内部行为描述」是 RTL 工程的标准形态,1.3 节讲模块语法时会给出完整骨架。

抽象层级还有个方向感:越偏行为级,代码越短、仿真越慢、综合解释空间越大;越偏结构级,代码越长、控制力越强。所谓 RTL(寄存器传输级),大致是数据流与行为级的混合层——它足够抽象让人类写得动,又足够具体让综合器推得出确定电路。全书的重点就钉在这一层。

为什么这个概念值一章的押金

建模视角是全书的检索系统。第三章讲赋值语义,本质是数据流与行为级各自遵守的规则;第五章门级建模就是结构化视角的展开;第八章综合流程,讲的就是三种讲法如何被统一翻译成门。以后你读任何一份陌生代码,第一步就是分辨:这段是接线、是函数、还是规则?分对了,后面的工具行为就能预判;分错了,连报错信息都看不懂。

还有个工程上的推论:review 别人代码时,对结构化描述提意见要谨慎——它就是设计者的明确意图,改成「更简洁的写法」可能违背本意(比如故意手工例化的触发器链,可能是为了精确控制布局)。而对行为级描述则要多问一句——这里综合器会推断出什么?两者审查的注意力方向相反,这正是分清视角的实际用处。

三个常见追问

问:三种讲法可以在一个模块里混用吗

不仅可以,而且是标准形态。顶层装配用结构化,组合逻辑用 assign,时序逻辑用 always——一份模块三层齐备各管一段。真正要避免的不是混用,而是「同一信号多处驱动」:一个输出只能属于一种讲法,混着驱动是编译错误。

问:行为级写得越抽象越好吗

分场景。可综合 RTL 里,抽象要停在「综合器能确定推断」的边界内——无限循环、动态数据结构这类软件级抽象没有电路对应物。测试台里则相反,越抽象越好:事务级、协议级的描述让用例易读易维护。所以「抽象到什么程度」的答案取决于这份代码给谁执行——给综合器就停在 RTL,给仿真器可以一路抽象上去。

问:评审时如何快速判断一段代码的层级

看关键词。出现实例化语句是结构化;出现 assign 是数据流;出现 always 要再看敏感形式——通配敏感是组合行为级,边沿敏感是时序行为级。这个三秒判断法在 review 大文件时非常省力:先扫关键词把代码分段归类,再对每段用对应的评审标准。结构段看连接一致性,数据流段看表达式正确性,行为段看综合推断结果。

本节要点回顾

  • 三种讲法并存:结构化讲接线,数据流讲函数,行为级讲规则,同一份代码可混用;
  • 解释空间递增:结构化几乎无解释空间,数据流做等价化简,行为级靠综合器推断;
  • 选择器对账结论:三种写法综合结果逻辑等价,差异在结构形态与维护成本;
  • RTL 的位置:寄存器传输级是数据流与行为级的混合层,是全书的作战区域;
  • 评审方向相反:结构化描述尊重原意少动,行为级描述要多推敲综合推断结果。

下一节进入语言的基本容器:模块怎么定义、端口怎么声明、层次怎么搭。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U