想象你拿到一块空地,要盖一栋房子。最稳妥的做法是什么?先画一张外观蓝图,告诉所有人“门朝哪开、窗户多宽”;再画一张内部施工图,规定“客厅在左、厨房在右”;再画一张水电线路图,标明每根管子的走向。然后各工队进场——水电工装水管、木工打柜子,互不干扰地同时施工;而厨房里,主厨必须按“先洗菜、再切菜、最后下锅”的顺序来。VHDL,就是用来“盖芯片”的这种语言。它描述的是机器里成千上万个逻辑门同时工作的样子,而不是程序的一行行顺序执行。它不仅要把“外观、布局、线路、工序”全部说清楚,还非常“较真”:材料型号必须写对,钢筋不能当木头用,写错了当场罢工——这正是 VHDL 闻名遐迩的强类型系统。

岗位关联

掌握 VHDL 的语法骨架,是进入 FPGA 数字设计、航空航天与国防等安全关键领域的通行证;这份“严格”的底子,会让你的硬件设计从一开始就远离低级错误。

目录
  1. 可视化演示
  2. 实体与架构体:外观蓝图与内部施工图
  3. 信号与变量:管线与便签的时空差异
  4. 数据类型系统:钢筋不能当木头
  5. 并发语句:多工队同时施工
  6. 进程与顺序语句:被敲门声唤醒的主厨
  7. 组合逻辑实例:从一块砖到加法器
  8. VHDL与Verilog对比:两本建筑规范
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

实体与架构体:外观蓝图与内部施工图

假设你要在空地上盖一栋房子,第一步绝不是让工人直接砌墙,而是先画一张“外观蓝图”:门朝哪个方向开、需要几个窗户、水电接入口留多宽。邻居和市政部门只看这张图,就能知道这栋房子“对外接什么”。VHDL 中的实体(entity)就是这张外观蓝图——它只管“对外的接口”长什么样,至于屋里怎么隔间、墙怎么砌,它一概不关心。

外观蓝图定下来之后,才轮到“内部施工图”来回答“房子怎么住”:客厅放哪、厨房放哪、楼梯怎么连。VHDL 中与之对应的概念叫做架构体(architecture),它负责描述电路内部的具体行为或结构实现。实体和架构体永远“成对出现”:实体说明“长什么样”,架构体说明“怎么实现”。二者分离,意味着同一张外观蓝图可以搭配多版施工图。

实体的语法骨架是 entity 加 port 声明。port 里的每个端口都要写清名字、方向和类型:

方向模式 in 表示“信号只能流入”,out 表示“只能流出”,inout 表示“既能进又能出”。用数学的语言描述,一个实体可以看作端口集合与方向模式的组合:

回到房子:只要外观蓝图不变,内部施工图可以换好几版——先按“经济型”布局,再改“豪华型”布局。VHDL 中同一个 entity 也可以搭配多个 architecture,仿真时再选哪张“施工图”上场。这种“接口与实现分离”的设计,正是 VHDL 应对大规模项目的底气。

E=(P,M),P={p1,p2,…,pn},M∈{IN,OUT,INOUT}E = (P, M), \quad P = \{p_1, p_2, \ldots, p_n\}, \quad M \in \{ \text{IN}, \text{OUT}, \text{INOUT} \}
这个公式说明:实体 = “有哪些接口” + “每个接口朝哪个方向”。方向一旦写死,就不能反着用——这正是 VHDL 严谨性的体现。
  1. 实体模型实体由端口集合与方向模式共同刻画,相当于房屋对外接口的“门牌号码”。
    E=(P,M)E = (P, M)
  2. 端口集合P 是所有端口的集合,每个端口好比墙上的一根电线,既要命名也要写明用途。
    P={p1,p2,…,pn}P = \{p_1, p_2, \ldots, p_n\}
  3. 方向约束M 只能取 IN、OUT、INOUT 三者之一,就像门窗方向确定后不能随意推翻。
    M∈{IN,OUT,INOUT}M \in \{ \text{IN}, \text{OUT}, \text{INOUT} \}
vhdl8 行
entity half_adder is  port (    a : in  std_logic;    b : in  std_logic;    s : out std_logic;    c : out std_logic  );end entity half_adder;

信号与变量:管线与便签的时空差异

继续盖房子。房子盖到一半,你会发现两件“传信息”的工具截然不同:房间之间靠水管和电线,客厅开水龙头,水流要沿着管道“走一会儿”才到厨房;而施工队长口袋里的小本子,上面记的每一笔都是“写下来立刻生效”,不需要任何运输时间。VHDL 里的信号(signal)和变量(variable),恰好就是这两种工具。

signal 是 VHDL 中模块间通信的主角:它声明在 architecture 或 process 外部,用 <= 赋值,可以把值从一个进程“运”到另一个进程。variable 则是进程内部的“私人便签”:用 := 赋值,立刻更新,只在本进程内可见,外界根本看不到。两者的综合结果也大不相同:信号常对应真实的连线或寄存器,变量往往只在仿真和运算中充当中间量。

两者的时序语义是最大的分水岭。写给 signal 的赋值,不能让读到它的语句“当场看见”,要经过一个极短的时间片——delta 延迟(可以理解成水流过管子的时间);而 variable 赋值立刻生效,下一行就能读到。用公式表达信号赋值的时间语义:

信号是“房间之间的水管”,变量是“队长口袋里的便签”。在设计加法器等组合逻辑时,临时中间步骤请用变量,跨模块传数据一定要用信号——用反了,轻则综合出意想不到的额外寄存器,重则整个电路的时序行为完全偏离预期。

s(t+Δ)=v(Δ 为 delta 延迟)s(t + \Delta) = v \quad (\Delta \text{ 为 delta 延迟})
公式说:你给信号 s 赋的新值 v,要等到下一个小时间片 Δ 之后才真正落到 s 上。这就像电话留言——你说完,对方过一会儿才听到。
  1. 赋值语句把右侧表达式的结果赋给左侧信号,是 VHDL 中最常见的数据搬运动作。
    s⇐vs \Leftarrow v
  2. 延迟时间片Δ 是 VHDL 仿真中极小的“运输时间”,信号要经过它才能让赋值结果可见。
    Δ=tn+1−tn\Delta = t_{n+1} - t_n
  3. 生效时刻新值在下一个时刻才真正落在目标信号上,如同水管里的水要流一会儿才到达厨房。
    s(t+Δ)=vs(t + \Delta) = v

数据类型系统:钢筋不能当木头

施工现场有严格的材料管理制度:钢筋、水泥、木材分门别类堆放,标签写明型号。再着急,施工员也不会把钢筋塞进木工刨床——那不是“不够灵活”,而是安全底线。VHDL 的强类型系统就是这个材料库房:类型不匹配,编译器当场拒绝,绝不和稀泥。

最常用的是四类“材料”。bit 只有 '0' 和 '1' 两种取值,像最简单的砖头;std_logic 是工业标准的九值逻辑,多出来的 Z(高阻)、U(未初始化)、X(未知)等状态,真实还原了电路上“这根线没接、这根线打架”的情况;std_logic_vector 是 std_logic 组成的位向量,如同成排码放的板条;integer 则是整数,方便做计数和循环。

std_logic 的九值逻辑集合,以及位向量代表数值的方式,可以写成:

正因如此,把 std_logic 直接塞给 integer 端口,或把 3 位向量当 4 位向量用,VHDL 都会当场报错——你得显式调用类型转换函数(如 unsigned、to_integer),相当于“材料入库前过秤换标签”。强类型让设计者在编译期就揪出一大批连线错误,施工还没开始,隐患已经少了大半。

L9={U,X,0,1,Z,W,L,H,−}且N=∑i=0n−1bi⋅2iL_9 = \{U, X, 0, 1, Z, W, L, H, -\} \quad \text{且} \quad N = \sum_{i=0}^{n-1} b_i \cdot 2^i
左边是九值逻辑“材料库”的全家福:U 未初始化、X 未知、Z 高阻等;右边告诉我们,一串 std_logic_vector 按位权加起来就是它代表的整数。
  1. 九值集合标准逻辑 std_logic 共有 9 个状态,比单纯 0/1 更能刻画真实电路的悬空、未知等情形。
    L9={U,X,0,1,Z,W,L,H,−}L_9 = \{U, X, 0, 1, Z, W, L, H, -\}
  2. 位权展开位向量从低位到高位,每一位乘以对应的 2 的幂次再求和,得到它表示的数值。
    N=∑i=0n−1bi⋅2iN = \sum_{i=0}^{n-1} b_i \cdot 2^i

并发语句:多工队同时施工

墙砌好、管线铺好后,多个工队同时进场:水电工装水管,木工打柜子,油漆工刷墙。没有人规定“水电工先干完木工才能动”——他们各看各的图纸、各干各的活,同时进行。硬件电路天生如此:门电路一上电就全都在工作,没有先后。

在 VHDL 的 architecture 中,写在 process 外面的语句默认就是并发的,它们没有书写先后之分,仿真时每一时刻都被同时“扫描”。最常用的三类并发语句包括:并发信号赋值(用 <= 直接把表达式赋给一个信号)、条件信号赋值 WHEN、选择信号赋值 SELECT。WHEN 相当于“看条件给值”,SELECT 相当于“按选择子的取值查表给值”。

用 WHEN 语句写一个 4 选 1 多路选择器,数学本质是逐行扫描的分支枚举:

并发语句的“同时性”是硬件的灵魂。回到房子:水电工和木工互不等候,任何一方的状态变化都会立即被其他人“看见”。写 VHDL 时,一旦你理解了“架构体里没有先后顺序”,你就抓住了它与软件语言最本质的区别。

y={d0when s="00"d1when s="01"d2when s="10"d3when othersy = \begin{cases} d_0 & \text{when } s = "00" \\ d_1 & \text{when } s = "01" \\ d_2 & \text{when } s = "10" \\ d_3 & \text{when others} \end{cases}
公式总结:y 的输出由选择向量 s 决定,WHEN 从上到下检查,匹配即输出对应数据;others 兜底保证每个输入组合都有输出。
  1. 枚举匹配当选择向量 s 等于 “00“ 时输出 d0,等于 ”01” 时输出 d1,如同工人按号牌认领对应材料。
    s="00"⇒y=d0s = "00" \Rightarrow y = d_0
  2. 全条件覆盖others 捕获所有剩余组合,保证组合逻辑没有“忘记赋值”的空洞,避免综合出锁存器。
    when others⇒y=d3\text{when others} \Rightarrow y = d_3

进程与顺序语句:被敲门声唤醒的主厨

多工队同时在干活,但厨房里是另一番景象:只有一位主厨,他的作业手册写得清清楚楚——先洗菜、再切菜、最后下锅。你绝不能让他“同时”炒菜和切菜——人只有一双手。VHDL 中的进程(process)就是这位主厨:它内部用顺序语句工作,但整个 process 在架构体里仍然与外界并发。

一个 process 有两个关键部件:敏感列表和语句体。敏感列表相当于“敲门声”——列表里的信号一旦发生变化,进程就被“唤醒”从头执行一遍;语句体内部按顺序执行 IF、CASE 等语句。执行完之后如果敏感列表没再变化,进程就“睡觉”,绝不空转。这种“事件驱动”的机制,让硬件仿真既精确又高效。

IF 语句是优先级结构,CASE 语句是并行分支结构。它们的语义分别是“先问队长再问副队长”和“直接看号牌进对应窗口”。用公式表达 IF 的优先级:

回到厨房:主厨可以被打断(敏感列表变化)、可以按手册顺序执行(顺序语句),但他依然是整栋房子的一分子,他干活时别的工队不会等他。理解“进程内部顺序、进程之间并发”这句话,你就掌握了 VHDL 建模的钥匙。

y={a,if s1=′1′b,else if s2=′1′c,otherwisey = \begin{cases} a, & \text{if } s_1 = '1' \\ b, & \text{else if } s_2 = '1' \\ c, & \text{otherwise} \end{cases}
公式要点:IF 一条一条往下问,s1 优先权最高;前面的条件不满足才轮到后面的,最后 otherwise 兜底。
  1. 优先级判断s1 是最高优先级的条件,它为 '1' 时直接输出 a,后面的分支不再检查。
    if s1=′1′⇒y=a\text{if } s_1 = '1' \Rightarrow y = a
  2. 次优分支只有 s1 不成立时才检查 s2,成立则输出 b,像是先问队长再问副队长。
    else if s2=′1′⇒y=b\text{else if } s_2 = '1' \Rightarrow y = b
  3. 兜底输出所有条件都不满足时给 c,保证每个输入组合都有一条出路。
    otherwise⇒y=c\text{otherwise} \Rightarrow y = c

组合逻辑实例:从一块砖到加法器

讲了这么多“图纸”,终于到了搬砖时刻。房子由一块块砖垒成,数字电路则由一个个逻辑门拼成。与门、或门、非门就是最基本的“砖”,而加法器是组合逻辑的“样板间”——它没有记忆,输出只取决于当前输入,像一面镜子,照什么是什么。

VHDL 支持三种建模风格。门级建模最底层,直接实例化门电路元件,相当于施工图上画出一块块砖的位置;数据流建模用逻辑表达式描述信号之间的关系,相当于写出“墙由砖按此排列构成”的公式;行为级建模用 process 加 IF/CASE 描述功能,相当于只规定“这面墙要能承重 3 吨”,不管砖怎么排。

以半加器为例:它把两个一位数 A、B 相加,输出和位 S 与进位 C。数据流风格只需两行:

全加器再多考虑一个低位进位 Cin,其逻辑表达式为:

半加器虽小,五脏俱全。它演示了数据流建模“用表达式讲故事”的简洁,也演示了组合逻辑“无记忆、纯映射”的本质。等你把半加器封装成 entity,再在更高层例化它,就完成了“用砖砌墙、用墙盖房”的第一次封装之旅。

S=A⊕B⊕Cin,Cout=(A⋅B)+(Cin⋅(A⊕B))S = A \oplus B \oplus C_{in}, \quad C_{out} = (A \cdot B) + (C_{in} \cdot (A \oplus B))
公式解读:和位 S 是三个输入做异或,体现“奇数个 1 结果为 1”;进位 C_out 在三个输入里至少两个为 1 时输出 1,就像三个人举手表决,两人以上赞成才算通过。
  1. 和位计算三个输入逐位异或,奇数个 1 则 S 为 1,如同投票中赞成票为奇数则动议通过。
    S=A⊕B⊕CinS = A \oplus B \oplus C_{in}
  2. 进位生成AB 同时为 1 时必然进位,加上 Cin 与 A⊕B 同时为 1 的“第三个 1”情况,共同决定进位。
    Cout=(A⋅B)+(Cin⋅(A⊕B))C_{out} = (A \cdot B) + (C_{in} \cdot (A \oplus B))
vhdl2 行
s <= a xor b;c <= a and b;

VHDL与Verilog对比:两本建筑规范

同样是盖房子,世界上存在两本著名的建筑规范。VHDL 像是国家工程建设标准:每个材料都要按型号报验、每道工序都要签字,流程严谨但推进较慢;Verilog 则像老师傅的口头约定:几行话就把活交代清楚,上手快、写起来随意,但出错的概率也更高。它们竞争了很多年,至今仍各有地盘。

VHDL 诞生于美国国防部的 VHSIC 计划,骨子里刻着“安全与可维护”;Verilog 脱胎于 C 语言的思维习惯,更贴近快速原型与商业芯片。两者的核心差异集中在三个维度:强类型 vs 弱类型(VHDL 不允许类型混用,Verilog 会自动截断扩展)、语法严谨度(VHDL 关键字不区分大小写、语句结尾必须有分号)、文件组织(VHDL 强调库、实体、架构分离,Verilog 顶层模块一个文件走天下)。

这种“严谨”换来了什么?最直观的收益是错误被提前发现。定义错误中在编译期被发现的比例 η:

两个规范没有绝对的优劣,只有合不合适:航空、航天、国防等安全关键领域,宁可多花三倍书写时间,也要换回“错误早暴露”的确定性;消费电子、AI 芯片的快速迭代场景,则更青睐 Verilog 的轻快灵活。选型就像选施工规范——先看清楚你要盖的是百年大坝,还是临时仓库。

ηearly=Ncompile-timeNtotal且ηVHDL>ηVerilog\eta_{early} = \frac{N_{compile\text{-}time}}{N_{total}} \quad \text{且} \quad \eta_{VHDL} > \eta_{Verilog}
公式说明:强类型和严格语义把大量错误挡在仿真与流片之前,相当于施工前多了一道强制图纸审查,图省事省下来的时间,最后都会在返工里加倍还回去。
  1. 错误全景N_total 是项目生命周期里的全部错误,包括编译、仿真、上板后才暴露的问题。
    Ntotal=Ncompile+Nsim+NboardN_{total} = N_{compile} + N_{sim} + N_{board}
  2. 早期发现比例η 越高,说明错误越早在编译期被拦下,修复成本越低,返工越少。
    ηearly=Ncompile-timeNtotal\eta_{early} = \frac{N_{compile\text{-}time}}{N_{total}}

AI 应用场景

边缘 AI 推理加速器中的 FPGA 开发

阶段:模型部署与硬件加速

解决的问题:AI 推理算法要在边缘设备实时运行,传统 CPU 串行执行无法满足时延要求。AI 工程师借助 FPGA 将卷积、池化等算子流水化,但并行电路“同时工作”的特性极易出错。VHDL 的强类型系统让位宽不匹配、端口方向错误在编译期就被拦截,避免把时间浪费在电路仿真与上板调试上。

具体案例:某智能安防摄像头项目,用 FPGA 实现 YOLO 前处理的缩放与归一化模块。工程师用 std_logic_vector 精确声明 16 位定点位宽,用并发语句同时驱动三路 RGB 像素流水线,再用 process 按帧同步信号实现状态机,最终将预处理时延从 12ms 压到 1.8ms。

航空航天飞行控制的安全关键设计

阶段:安全关键系统的芯片验证与部署

解决的问题:飞行控制、卫星姿态管理等系统对硬件设计有严苛的可靠性要求。手写逻辑与宽松语法会埋下“类型混用、信号悬空”的隐患,轻则功能异常,重则影响飞行安全。VHDL 设计评审时,编译器就是第一道“图纸审查员”。

具体案例:某卫星姿态控制 FPGA 中,用 VHDL 实现三模冗余投票器与看门狗逻辑。得益于强类型检查,团队在综合前就发现了 37% 的连线与位宽错误;严格的实体/架构分离,也让多个外包团队可以并行开发同一芯片的不同架构体版本。

Python 演示

python57 行
class Signal:    """模拟 VHDL 信号:赋值带 delta 延迟"""     def __init__(self, name, value=0):        self.name = name        self.value = value        self.next_value = value     def assign(self, v):        self.next_value = v  # 只写入候车区,不立刻生效     def update(self):        self.value = self.next_value  # delta 周期结束时统一到站  def full_adder_signal_sim(a, b, cin):    """信号语义:所有语句同时读取旧值,再一起更新"""    t1 = Signal("t1")    t2 = Signal("t2")    t3 = Signal("t3")    s = Signal("s")    cout = Signal("cout")     for cycle in range(3):        t1.assign(a ^ b)        t2.assign(a & b)        t3.assign(cin & t1.value)        s.assign(cin ^ t1.value)        cout.assign(t3.value | t2.value)        for sig in (t1, t2, t3, s, cout):            sig.update()        print("delta {}: s={} cout={}".format(cycle + 1, s.value, cout.value))    return s.value, cout.value  def full_adder_variable_sim(a, b, cin):    """变量语义:赋值立即生效,下一行即可读取"""    t1 = a ^ b    t2 = a & b    s = cin ^ t1    t3 = cin & t1    cout = t3 | t2    return s, cout  def main():    a, b, cin = 1, 1, 1    print("输入: a={} b={} cin={}".format(a, b, cin))    s, cout = full_adder_variable_sim(a, b, cin)    print("变量模拟(立即生效): s={} cout={}".format(s, cout))    print()    s, cout = full_adder_signal_sim(a, b, cin)    print("信号模拟(延迟生效): 最终 s={} cout={}".format(s, cout))  if __name__ == "__main__":    main()
目的:用 Python 模拟 VHDL 中“信号延迟更新”与“变量立即生效”两种语义,在 1+1+1=3 的全加器上直观展示为什么信号赋值要等 delta 延迟。
  1. self.next_value = v信号赋值先去“候车区”,不碰当前值
  2. t1.assign(a ^ b)并发赋值在同一时刻把所有表达式算完,只写 next_value
  3. t3.assign(cin & t1.value)读到的是 t1 的“旧值”,这正是 delta 延迟的来源
  4. cout.assign(t3.value | t2.value)同一时刻全部读旧值,复现 VHDL 并发读的语义
  5. for sig in (t1, t2, t3, s, cout): sig.update()模拟一个 delta 周期:所有信号同时“到站”
  6. s = cin ^ t1变量语义下,上一行刚算的 t1 立刻可用,无需等待
  7. if __name__ == "__main__": main()可执行入口,直接运行即可对照两种语义的输出差异

常见误区

误区我刚学 VHDL 时,习惯把 architecture 里的语句当 C 代码看,从上到下一行行分析执行顺序,结果怎么都对不上。

正解在架构体中,写在 process 外部的语句全都是并发语句,仿真器在每一个时刻同时“扫描”它们,与书写顺序无关。只有 process 或 function 内部才是顺序执行。这好比一栋房子多个工队同时施工,图纸上谁先谁后并不重要。

为何常见:绝大多数人先学软件语言,顺序执行的惯性思维太强;而硬件描述语言本质上就是描述“时刻同时工作的门电路”。

误区signal 用 `<=`,variable 用 `:=`,既然都能存值,那随便用哪个都行吧?

正解两者语义完全不同。信号有 delta 延迟,赋值要“过一会儿才生效”,用于进程间通信;变量立即生效,只存在于进程内部。把该用信号的场合用变量,等于把房间间的水管换成了队长口袋里的便签——隔壁房间根本看不到。

为何常见:语法看起来都是“赋值”,初学者容易只记符号不记背后的时序语义。

误区反正都是连线,我把 in 端口当输出用,编译器应该能综合通过。

正解VHDL 把端口方向视为合同条款。in 只能读、out 只能写,强行反用轻则仿真结果诡异,重则综合直接报错。这就像门窗设计为朝外开,你偏要朝内推,施工图审查这一关就过不了。

为何常见:Verilog 对端口方向约束较弱,习惯 Verilog 的人转到 VHDL 时最容易踩这个坑。

误区同样的功能,VHDL 写起来比 Verilog 多一半代码,新项目谁还用它?

正解啰嗦的代价换来的是强类型检查和严格语义,错误在编译期大量暴露。航空航天、国防、铁路信号等安全关键领域至今大量使用 VHDL,这正是“严谨”的长期价值——前期多写字,后期少返工。

为何常见:以代码行数衡量语言价值,忽略了可靠性与可维护性的隐性收益,属于典型的“以码量论英雄”。

面试题

Q1. VHDL 中 entity(实体)的主要作用是什么?

单选题 · easy

  • A.描述电路内部的具体连线方式
  • B.声明模块对外的端口与方向← 正确答案
  • C.定义进程内部的临时变量
  • D.指定 FPGA 芯片的物理布局

答案:B。entity 相当于房子的外观蓝图,只负责对外接口(端口)及其方向,不关心内部实现。A 是架构体的职责,C 是变量的事,D 属于布局布线工具。

Q2. 在 VHDL 中,signal 与 variable 最本质的区别是什么?

单选题 · easy

  • A.书写符号不同,功能完全一样
  • B.信号有延迟而变量立即生效← 正确答案
  • C.变量可以有多个驱动源
  • D.信号不能用于组合逻辑

答案:B。信号像房间间的水管,赋值要经过 delta 延迟;变量像手边便签,写下来立刻生效。A 错在忽略语义差异,C 说反了(多个驱动源恰恰要小心的是信号),D 更是错误——组合逻辑里信号是大主角。

Q3. std_logic 类型共包含几个逻辑状态?

单选题 · easy

  • A.两个状态
  • B.四个状态
  • C.九个状态← 正确答案
  • D.十六个状态

答案:C。std_logic 是工业标准九值逻辑:U、X、0、1、Z、W、L、H、-,共 9 个状态。两个状态是 bit 的规模;四个和十六个都是误记。多状态让仿真能表达高阻、未初始化等真实电路情况。

Q4. 架构体(architecture)中写在 process 外部的语句是什么执行方式?

单选题 · easy

  • A.从上到下依次顺序执行
  • B.并发执行,不分先后← 正确答案
  • C.只在时钟上升沿执行
  • D.只在复位时执行一次

答案:B。架构体中 process 外部的语句都是并发语句,仿真时同刻扫描,与书写顺序无关,如同多个工队同时施工。只有 process 内部才是顺序执行。

Q5. 关于 process(进程)的敏感列表,下列说法正确的有?

多选题 · mid

  • A.敏感列表中的信号发生变化时进程被唤醒← 正确答案
  • B.敏感列表决定进程内部语句的执行顺序
  • C.进程执行完后若无变化则休眠等待← 正确答案
  • D.敏感列表只能包含一个时钟信号

答案:AC。敏感列表相当于“敲门声”——列表里的信号一变化,进程就被唤醒从头执行一遍,执行完没有新变化就休眠。进程内部的顺序由语句本身决定而非敏感列表,B 错;D 错在敏感列表可以包含多个信号。

Q6. 用 WHEN 语句实现组合逻辑时,最后必须加上什么?

单选题 · mid

  • A.加入时钟沿控制
  • B.else 或 others 兜底← 正确答案
  • C.加入一个复位信号
  • D.显式类型转换函数

答案:B。WHEN 是条件并发赋值,必须保证所有输入组合都有输出,否则会综合出锁存器。兜底分支就是“所有情况没匹配时给个默认值”,如同查表必须有最后一行,防止查不到结果。

Q7. 下列哪些属于 VHDL 相对 Verilog 的优势?

多选题 · mid

  • A.强类型系统避免大量连线错误← 正确答案
  • B.语法更严谨,适合安全关键领域← 正确答案
  • C.代码行数更少,上手更快
  • D.严格的语义利于大规模项目维护← 正确答案

答案:ABD。强类型、严谨语法、严格语义是 VHDL 的三大标签,尤其适合航太国防等安全关键领域。C 恰恰相反,VHDL 代码通常更长、学习曲线更陡,这是它的代价而非优势。

Q8. 半加器的和位 S 与进位 C 的正确表达式是?

单选题 · mid

  • A.S=A与B; C=A异或B
  • B.S=A异或B; C=A与B← 正确答案
  • C.S=A或B; C=A与B
  • D.S=A异或B; C=A或B

答案:B。半加器把两个一位数相加,和位由异或得到(不同为 1),进位由与门得到(全 1 才进位),即 S=A 异或 B、C=A 与 B,对应“奇数个 1 结果为 1,两个 1 才进位”的规则。

Q9. 关于 VHDL 信号赋值的 delta 延迟,下列说法正确的有?

多选题 · hard

  • A.信号的新值要在当前仿真时间片结束后才可见← 正确答案
  • B.变量赋值也遵循同样的延迟规则
  • C.组合逻辑经过若干 delta 周期后收敛到稳定值← 正确答案
  • D.delta 延迟导致仿真速度一定比 Verilog 慢

答案:AC。信号赋值有 delta 延迟,新值要在下个时间片才可见;组合逻辑正是靠多轮 delta 传播最终收敛。B 错误,变量赋值立即生效;D 错误,delta 周期极短,与仿真速度没有必然关系。

Q10. 端口模式 INOUT 表示什么含义?

单选题 · easy

  • A.信号只能流入不能流出
  • B.信号只能流出不能流入
  • C.既能流入也能流出的双向口← 正确答案
  • D.不连接任何信号的悬空口

答案:C。INOUT 就是双向端口,既当入口也当出口,如同带双向门的门厅。A 是 IN,B 是 OUT,D 是未连接(open),均与双向端口的定义不符。