Verilog组合逻辑代码经Design Vision综合生成FFGEN锁存器问题咨询
为什么我的组合逻辑Verilog代码综合出了锁存器?
这种情况我碰到过好多次了——明明用了always @(*)写组合逻辑,结果被Design Vision综合出了FFGEN(锁存器实例),核心原因很明确:你的case语句没有覆盖所有可能的输入组合,而且输出变量controls在部分输入路径下没有被明确赋值,综合器会默认生成锁存器来保持之前的输出值。
先把你的代码补全(结合你给出的片段还原):
module decoder( input [1:0] Op, input [5:0] Funct, output reg[9:0] controls ); // Main Decoder always @(*) begin case(Op) // Data-processing immediate 2'b00: if (Funct[5]) controls = 10'b0000101001; else controls = 10'b0000001001; // LDR 2'b01: controls = 10'b0001101000; // 你这里的代码被截断了,但显然缺少了Op为2'b10、2'b11的分支处理 endcase end endmodule
问题根源
组合逻辑的always @(*)块有个硬性要求:所有可能的输入组合下,输出变量必须被明确赋值。如果存在任何输入情况没给controls赋值,综合器会认为需要保留controls的旧值,自然就生成锁存器了。
你的Op是2位宽,总共有4种可能的取值,但代码里只处理了2'b00和2'b01,剩下的2'b10、2'b11完全没覆盖;不过好在2'b00分支里的if-else已经覆盖了Funct[5]的0和1两种情况,这部分没问题。
解决方法
有两种可靠的方式可以避免这个问题:
方法1:给case语句添加default分支
在case块末尾加上default分支,明确给controls赋一个合理的默认值(比如对应无效指令的控制信号):
always @(*) begin case(Op) 2'b00: if (Funct[5]) controls = 10'b0000101001; else controls = 10'b0000001001; 2'b01: controls = 10'b0001101000; // 其他指令类型的分支可以在这里补充 default: controls = 10'b0000000000; // 无效指令的默认控制信号 endcase end
方法2:在always块开头先赋默认值
先给controls一个初始默认值,再处理各个case分支,这样即使某个分支被遗漏,controls也不会出现未赋值的情况:
always @(*) begin controls = 10'b0000000000; // 先给默认值,确保所有路径都有赋值 case(Op) 2'b00: if (Funct[5]) controls = 10'b0000101001; else controls = 10'b0000001001; 2'b01: controls = 10'b0001101000; // 其他指令类型的分支可以在这里补充 endcase end
额外提示
我个人更推荐第二种方法,因为它能从根源上避免因分支遗漏导致的锁存器问题,代码也更健壮。另外,你可以再检查一下Funct的其他位是否需要处理,但从你给出的代码片段来看,2'b00分支的if-else已经覆盖了关键的Funct[5],这部分没问题。
内容的提问来源于stack exchange,提问作者LearningCurve
相关产品推荐
相关产品推荐

