Verilator不识别casez语句及??通配符的解决方法咨询
RISC-V译码器Verilator兼容的通配符解决方案
问题核心
你的代码中使用了??通配符和case分支内的assign语法,这两点都是Verilator兼容性问题的根源:
- Verilator对SystemVerilog的
casez/casex通配符支持有限,不识别多字符的??写法; - 在case分支内直接使用
assign属于连续赋值,会导致同一信号被多个驱动,不符合组合逻辑的规范写法。
以下是两种可行的解决方案:
方案一:修正casez写法(兼容Verilator)
调整代码为标准组合逻辑写法,替换Verilator不支持的通配符语法:
// 第一步:用always_comb块生成指令类型信号(替换原case内的assign) always_comb begin r_type = 1'b0; i_type = 1'b0; s_type = 1'b0; b_type = 1'b0; u_type = 1'b0; j_type = 1'b0; case(opcode) 7'b0110011: r_type = 1'b1; 7'b0010011: i_type = 1'b1; 7'b0000011: i_type = 1'b1; 7'b0100011: s_type = 1'b1; 7'b1100011: b_type = 1'b1; 7'b0110111: u_type = 1'b1; 7'b1101111: j_type = 1'b1; endcase end // 第二步:修正casez的通配符和赋值方式 always_comb begin // 初始化所有控制信号为0,避免生成 latch add = 1'b0; sub = 1'b0; sll = 1'b0; slt = 1'b0; sltu = 1'b0; xorr = 1'b0; srl = 1'b0; sra = 1'b0; orr = 1'b0; andd = 1'b0; addi = 1'b0; slti = 1'b0; sltiu = 1'b0; xori = 1'b0; ori = 1'b0; andi = 1'b0; slli = 1'b0; srli = 1'b0; srai = 1'b0; casez({opcode, funct3, funct7}) // R-type指令 {7'b0110011, 3'b000, 7'b0000000} : add = 1'b1; {7'b0110011, 3'b000, 7'b0100000} : sub = 1'b1; {7'b0110011, 3'b001, 7'b0000000} : sll = 1'b1; {7'b0110011, 3'b010, 7'b0000000} : slt = 1'b1; {7'b0110011, 3'b011, 7'b0000000} : sltu = 1'b1; {7'b0110011, 3'b100, 7'b0000000} : xorr = 1'b1; {7'b0110011, 3'b101, 7'b0000000} : srl = 1'b1; {7'b0110011, 3'b101, 7'b0100000} : sra = 1'b1; {7'b0110011, 3'b110, 7'b0000000} : orr = 1'b1; {7'b0110011, 3'b111, 7'b0000000} : andd = 1'b1; // I-type算术/逻辑立即数指令(用7'b?替代7'b???????) {7'b0010011, 3'b000, 7'b?} : addi = 1'b1; {7'b0010011, 3'b010, 7'b?} : slti = 1'b1; {7'b0010011, 3'b011, 7'b?} : sltiu = 1'b1; {7'b0010011, 3'b100, 7'b?} : xori = 1'b1; {7'b0010011, 3'b110, 7'b?} : ori = 1'b1; {7'b0010011, 3'b111, 7'b?} : andi = 1'b1; // I-type移位立即数指令 {7'b0010011, 3'b001, 7'b0000000} : slli = 1'b1; {7'b0010011, 3'b101, 7'b0000000} : srli = 1'b1; {7'b0010011, 3'b101, 7'b0100000} : srai = 1'b1; endcase end
关键调整点
- 用
always_comb块实现组合逻辑,避免case分支内的assign; - 用
7'b?替代7'b???????,Verilator支持单个?作为casez的位通配符; - 直接使用
opcode参与casez匹配,减少中间信号依赖,提升工具兼容性。
方案二:使用if-else+case嵌套(最大兼容性)
完全放弃casez/casex,改用分层判断的方式,所有Verilog/SV工具都支持:
always_comb begin // 初始化所有控制信号为0 add = 1'b0; sub = 1'b0; sll = 1'b0; slt = 1'b0; sltu = 1'b0; xorr = 1'b0; srl = 1'b0; sra = 1'b0; orr = 1'b0; andd = 1'b0; addi = 1'b0; slti = 1'b0; sltiu = 1'b0; xori = 1'b0; ori = 1'b0; andi = 1'b0; slli = 1'b0; srli = 1'b0; srai = 1'b0; // 按指令类型分类判断 if (opcode == 7'b0110011) begin // R-type指令 case({funct3, funct7}) {3'b000, 7'b0000000} : add = 1'b1; {3'b000, 7'b0100000} : sub = 1'b1; {3'b001, 7'b0000000} : sll = 1'b1; {3'b010, 7'b0000000} : slt = 1'b1; {3'b011, 7'b0000000} : sltu = 1'b1; {3'b100, 7'b0000000} : xorr = 1'b1; {3'b101, 7'b0000000} : srl = 1'b1; {3'b101, 7'b0100000} : sra = 1'b1; {3'b110, 7'b0000000} : orr = 1'b1; {3'b111, 7'b0000000} : andd = 1'b1; endcase end else if (opcode == 7'b0010011) begin // I-type算术/逻辑立即数指令 case(funct3) 3'b000 : addi = 1'b1; 3'b010 : slti = 1'b1; 3'b011 : sltiu = 1'b1; 3'b100 : xori = 1'b1; 3'b110 : ori = 1'b1; 3'b111 : andi = 1'b1; 3'b001 : slli = 1'b1; 3'b101 : begin // 移位立即数区分逻辑/算术移位 if (funct7 == 7'b0000000) srli = 1'b1; else if (funct7 == 7'b0100000) srai = 1'b1; end endcase end // 可继续添加其他指令类型的判断(S-type/B-type等) end
优点
- 完全不依赖casez/casex,兼容性覆盖所有仿真器和综合工具;
- 逻辑分层清晰,便于后续扩展和维护。
内容的提问来源于stack exchange,提问作者Lovis XII
相关产品推荐
相关产品推荐

