[Verilog HDL]第五章 条件语句、循环语句、块语句、生成语句 本章全部语句属于行为级描述语句仅能放置在initial、always过程块内部模块顶层不能直接书写。本章语句分为两大类可综合硬件语句能生成真实电路、仿真专用语句仅用于 Testbench 测试无法综合。学习目标熟练使用 if/case 完成多路控制区分仿真循环与硬件生成循环掌握顺序 / 并行块仿真时序差异。一、5.1 if-else 条件语句 ★1. if 语句三种标准语法结构1.1 格式 1单 if 语句无 else 分支适用场景仅需要在特定条件下执行操作其余状态无赋值always (*) begin if(en) out in; end缺陷组合逻辑下缺少 else 分支会综合生成锁存器时序逻辑无此风险。1.2 格式 2if-else 双分支语句条件分为真假两路完整覆盖所有情况组合逻辑推荐使用不会产生锁存器。always (*) begin if(sel) out a; else out b; end1.3 格式 3if-else if 多分支优先级语句多层判断自带优先级从上至下匹配上层条件优先执行。always (*) begin if(addr 0) data 8d1; else if(addr 1) data 8d2; else data 8d0; end2. 书写规范细节单条执行语句可省略begin-end多条语句必须使用begin-end包裹复合块判断表达式支持逻辑运算 || !、比较运算 ! 简写写法if(!rst_n)等价于if(rst_n 0)。3. else 就近匹配规则易错点else 永远匹配离它最近、未配对的 if与缩进无关。错误示例if(a) if(b) y1; else y0; // 匹配内层if(b)而非外层if(a)解决方法多层嵌套统一添加begin-end明确代码块边界。4. 组合逻辑锁存器产生原理组合逻辑always (*)中若变量在部分 if 分支中未赋值综合工具会生成锁存器保存旧值导致电路功能异常。 规避方案完整书写 else 分支给变量赋予默认值在块开头统一给输出赋默认值。5. 硬件电路特性多层 if 语句会生成带优先级的多路选择电路适合优先级编码器、中断判断电路。\二、case 多路分支语句 ★★1. case 基础完整语法case(控制信号) 分支1: 执行语句; 分支2: 执行语句; default: 默认语句; // 必须添加防止锁存器 endcase所有分支取值必须互斥禁止出现重叠条件default 分支作用覆盖未枚举的 0/1/x/z 状态消除锁存器。2. case /casez/casex 匹配规则★★case严格逐位匹配0 只能匹配 0、1 匹配 1、x 匹配 x、z 匹配 z。casez忽略高阻 z?作为无关位通配符仅严格匹配 0/1常用于位屏蔽译码。casex同时忽略 x、z 不定态仅识别 0/1多用于仿真判断未知输入。3. 硬件特性case 所有分支优先级完全平等无先后顺序适合多路选择器。4. 实操代码示例3 位二进制译码器reg [7:0] y; always (*) begin case(addr) 3b000: y 8b00000001; 3b001: y 8b00000010; 3b010: y 8b00000100; default: y 8b00000000; endcase end三、if 与 case 语句核心对比总结对比项if-elsecase优先级自上而下上层优先所有分支平等无优先级适用电路优先级控制、中断判断多路选择器、译码器不定态处理仅判断 0/1无法屏蔽 x/z支持 casez/casex 处理无关位锁存器风险漏 else 产生锁存器缺少 default 产生锁存器四、多路分支电路实操案例四选一多路选择器完整综合代码module mux4( input [1:0] sel, input a,b,c,d, output reg out ); always (*) begin case(sel) 2b00: out a; 2b01: out b; 2b10: out c; 2b11: out d; default: out 1b0; // 规避锁存器 endcase end endmodule关键知识点敏感列表(*)自动包含 sel、a、b、c、d 所有输入。default 分支不可省略否则综合出现锁存器。综合后生成纯组合逻辑无触发器。五、 循环语句 ★在Verilog HDL中存在着4种类型的循环语句用来控制执行语句的执行次数。统一约束forever/repeat/while/for四类循环仅能写在 initial 仿真块。时序 / 组合 always 块中使用会报综合错误。1. forever 语句连续的执行语句。forever循环语句常用于产生周期性波形用来作为仿真测试信号。仿真示例initial begin clk 0; forever #10 clk ~clk; // 周期20ns时钟 end2. repeat语句连续执行一条语句n次。repeat语句中其表达式通常为常量表达式。适合存储器初始化、批量激励赋值。initial begin repeat(16) begin addr addr 1; #5; end end3. while语句执行一条语句直到某个条件不满足。先判断条件条件为真才执行循环体初始条件不成立则一次不运行。initial begin cnt 0; while(cnt 8) begin cnt cnt 1; end end4. for语句4.1 一般形式for(初始化循环条件更新语句)执行语句4.2 执行过程先给控制循环次数的变量赋初值。判定控制循环的表达式的值如为假则跳出循环语句如为真则执行指定的语句后转到第三步。执行一条赋值语句来修正控制循环变量次数的变量值然后返回第二步。initial begin for(i0;i16;ii1) begin mem[i] 0; end end六、顺序块与并行块 ★★块语句作用将多条语句打包为整体统一管理执行时序分为begin-end顺序块、fork-join并行块。1. 顺序块 begin-end内部语句按书写顺序逐条执行延时依次累加。无数据竞争组合 / 时序逻辑块默认使用。initial begin #10 a1; #20 b0; // 总延时30ns执行b赋值 end2. 并行块 fork-join块内所有语句同一时刻同步启动延时互不叠加。风险同一时刻修改同一寄存器产生数据竞争仿真结果随机。initial fork #10 a1; #20 b0; // a在10ns执行b在20ns执行互不干扰 join3.特性嵌套块顺序块、并行块可互相嵌套命名块给块自定义名称内部可定义局部变量disable 关键字强制终止指定命名块循环用于仿真跳出循环。七、生成块 generate ★★唯一可综合的循环结构编译阶段批量生成重复硬件电路用于参数化总线、多位加法器、阵列电路仅能写在模块顶层禁止放入 always/initial 内部。1. generate 通用语法限制generate 变量仅编译阶段有效仿真运行不存在内部可例化模块、门原语、assign 连续赋值禁止时序延时#必须包裹在generate-endgenerate关键字之间。2. 循环生成语句 generate for批量例化相同子模块实现 N 位硬件阵列。示例4 位逐进位加法器批量生成单元genvar i; generate for(i0;i4;ii1) begin full_adder u_adder(.a(a[i]),.b(b[i]),.cin(cin[i]),.sum(sum[i]),.cout(cout[i])); end endgenerate3. 条件生成语句generate if根据参数数值选择性生成不同硬件结构。应用场景根据位宽参数选择慢速 / 高速加法器。4. case 生成语句generate case多分支参数匹配根据参数切换硬件架构。八、综合实操案例案例 1四位同步计数器时序逻辑 if 语句module cnt4( input clk,rst_n, output reg [3:0] cnt ); always (posedge clk) begin if(!rst_n) cnt 4d0; // 同步复位 else cnt cnt 1b1; end endmodule知识点时序逻辑使用非阻塞赋值if 实现同步复位综合生成 4 组 D 触发器。九、核心总结语句分层可综合语句if/case/generate、仿真专用循环forever/for/repeat/while锁存器两大来源组合逻辑 if 无 else、case 无 default电路选型口诀优先级电路用 if平等多路选择用 case循环两类区分仿真 for运行时循环、generate for编译生成硬件仿真块区分begin 顺序执行、fork 并行执行并行块易产生数据竞争。十、思考题组合逻辑 if/case 分支不全为什么会生成锁存器如何规避case、casez、casex 三者匹配规则有什么区别分别适用什么场景fork 并行块数据竞争如何产生有哪些解决办法generate 循环和仿真 for 循环本质区别是什么能否互相替换forever、repeat、while、for 四类仿真循环各自适用场景十一、重难点汇总基础if 就近匹配、锁存器产生条件、多路选择器、同步计数器重点casez/casex 不定态匹配、fork 并行时序竞争、generate 编译展开原理高频易错仿真循环用于综合报错、组合时序赋值符号混用、缺少 default/else 分支。