You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Verilator不识别casez语句及??通配符的解决方法咨询

RISC-V译码器Verilator兼容的通配符解决方案

问题核心

你的代码中使用了??通配符和case分支内的assign语法,这两点都是Verilator兼容性问题的根源:

  1. Verilator对SystemVerilog的casez/casex通配符支持有限,不识别多字符的??写法;
  2. 在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

关键调整点

  1. 用always_comb块实现组合逻辑,避免case分支内的assign;
  2. 用7'b?替代7'b???????,Verilator支持单个?作为casez的位通配符;
  3. 直接使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 22:08:07