碎碎思 · 2022年02月09日

Verilog/SV代码检查器-Lint 建模规则检查器与 Verilator

绪论

硬件设计是无情的,因此使用可以获得的任何错误的软件都是值得的。

在进行综合之前,简单的检查自己代码的一些潜在问题,有助于减少后续调整的时间。

Verilator是一个 Verilog 仿真器和 C++ 编译器,它还支持 linting:静态分析设计问题(代码校验工具)。Verilator 不仅可以发现综合工具可能忽略的问题,而且运行速度也很快。Verilator 也非常适合使用 SDL(https://projectf.io/posts/verilog-sim-verilator-sdl/) 进行图形仿真。

安装Verilator

Verilator 在大多数 Linux 发行版存储库中都可用,并将在Windows Subsystem for Linux上运行。

对于基于Debian和Ubuntu的 Linux 发行版,可以使用以下说明进行安装。

apt update
apt install verilator

在 macOS 上,可以通过Homebrew包管理器进行安装:

brew install verilator

linting 使用

对于独立模块,linting 本身很简单:

verilator --lint-only -Wall foo.v

--lint-only- 告诉 Verilator 进行 lint 但不生成任何仿真输出

-Wall- 打开额外的风格检查

如果一切顺利,将不会看到来自 Verilator 的消息。

如果 Verilator 发现潜在问题,它会提供明确的建议,包括如何禁用警告。Verilator 手册包括可能的警告列表(https://www.veripool.org/wiki/verilator/Manual-verilator#ERRORS-AND-WARNINGS)。

实例介绍

创建一个带有几个问题的简单“add”模块,然后对其进行 lint:

`default_nettype none

module add (
    input  wire clk,
    input  wire [3:0] x,
    input  wire [3:0] y,
    output reg z,
    output reg c
    );

    always @(posedge clk) begin
        z <= x + y;
    end
endmodule

上面是我们创建的文件,接下来我们使用linking看下上面文件潜在的问题。

$ verilator --lint-only -Wall add.v
%Warning-WIDTH: add.v:12:11: Operator ASSIGNDLY expects 1 bits on the Assign RHS, but Assign RHS's ADD generates 4 bits.
                           : ... In instance add
   12 |         z <= x + y;
      |           ^~
                ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.
%Warning-UNDRIVEN: add.v:8:16: Signal is not driven: 'c'
                             : ... In instance add
    8 |     output reg c
      |                ^
%Error: Exiting due to 2 warning(s)

第一个问题是宽度:x和y是 4 位宽,但z没有明确的宽度,所以只有 1 位宽。

我们可以通过这样做忽略宽度警告:

  always @(posedge clk) begin
        /* verilator lint_off WIDTH */
        z <= x + y;
        /* verilator lint_on WIDTH */
    end

但是,这样就隐藏了问题,会导致致命的错误。

相反,我们可以通过将宽度设置z为 4 位来修复它:

    output reg [3:0] z,

虽然这消除了 Verilator 警告,但它可能没有完全解决问题。

例如,如果x和y都是4'b1000会发生什么?加法会溢出,z的结果就是 4'b0000。此示例说明了 linting 的限制之一:它可以查看不同信号的宽度,但不能考虑应用于它们的所有逻辑。

因此,除了固定z 的宽度外,我们还可以将c其用作进位信号,这也解决了“Signal is not driven”警告:

复制 always @(posedge clk) begin {c,z} <= x + y; end 依赖和路径 如果一个模块依赖另一个模块会发生什么?Verilator 将在当前路径中搜索匹配的模块。如果您想在模块搜索路径中添加其他目录,我们可以使用-I. 例如,如果top.v依赖于../maths目录中的模块:

verilator --lint-only -Wall -I../maths top.v

可以使用多个-I参数来包含多个目录。

黑盒和空模块

大多数设计依赖于没有源的供应商原语或 IP 内核,例如使用 PLL 生成时钟。当尝试 lint 引用供应商原语的模块时,将收到如下错误:

%Error: clock_pix.sv:29:5: Cannot find file containing module: 'MMCME2_BASE'
   29 |     MMCME2_BASE #(
      |     ^~~~~~~~~~~
%Error: clock_pix.sv:29:5: This may be because there's no search path specified with -I<dir>.
   29 |     MMCME2_BASE #(
      |     ^~~~~~~~~~~
        ... Looked in:
             MMCME2_BASE
             MMCME2_BASE.v
             MMCME2_BASE.sv
             obj_dir/MMCME2_BASE
             obj_dir/MMCME2_BASE.v
             obj_dir/MMCME2_BASE.sv

出现以上错误的第一个想法可能是找到一种MMCME2_BASE从 lint 中排除的方法。遗憾的是:Verilog “不能不精雕细琢,这需要整个设计”。但是我们可以通过为原语创建一个空模块来解决这个问题。空模块包含 IO,但不包含任何逻辑。

例如,为 Xilinx 的 BUFG 原语创建了一个空模块:

module BUFG (
    input  wire logic I,
    output      logic O
    );

    // NULL MODULE

endmodule

创建空模块虽然有点浪费时间,但可以对整个设计进行 lint。要使用 null 模块,请确保它位于 Verilator 的搜索路径中(请参阅上一节)。

去除linking检测

如果需要在较大的设计或使用第三方来源的设计中消除 linter 警告,那么/* verilator lint_off */ 注释可能不切实际。从 Verilator 4.028 开始,可以创建避免检测文件来处理警告,而无需接触源代码。要了解更多信息,请参阅https://wallento.cs.hm.edu/post/20200612-verilator-waivers/

Linting Shell 脚本

如果有许多顶级模块或包含很多目录,可以使用 Makefile 或简单的 shell 脚本自动检查。

以下 shell 脚本检查位于同一目录中的所有顶级模块:

#!/bin/sh

DIR=`dirname $0`

echo "## Linting top modules in ${DIR}"
for f in ${DIR}/top_*\.*v; do
    echo "##   Checking ${f}";
    verilator --lint-only -Wall -I${DIR} -I${DIR}/../common $f;
done
原文:OpenFPGA
作者:碎碎思

相关文章推荐

更多FPGA技术干货请关注FPGA 的逻辑技术专栏。
推荐阅读
关注数
10597
内容数
559
FPGA Logic 二三事
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息