- Verible 是由 Google 发起、Chips Alliance 维护的开源 SystemVerilog / Verilog 开发工具套件,核心是围绕 IEEE 1800-2017 SystemVerilog 语法的完整解析器,提供代码格式化、风格检查、语法验证、语言服务器以及代码混淆(Obfuscate)等功能。
一、Verible 核心工具组件
| 工具名 | 功能 | 典型用途 |
|---|---|---|
| verible-verilog-format | 自动格式化 Verilog/SV 代码 | 统一缩进、对齐、换行,CI 集成保证风格一致 |
| verible-verilog-lint | 风格与规则检查(Linter) | 检测命名不规范、禁止语法、未使用信号等 |
| verible-verilog-syntax | 语法解析与检查 | 验证文件能否被正确解析,可输出语法树 JSON |
| verible-verilog-obfuscate | 源码混淆/去标识化 | 把 module/信号名替换为无意义字符串 |
| verible-verilog-ls | LSP 语言服务器 | VS Code / Vim 实时报语法错误、自动补全 |
- 对硬件工程师来说,Verible 可用于统一团队代码风格(格式化)+ 给敏感 RTL 做轻量混淆(去标识化)。

二、安装
- Linux:从 https://github.com/chipsalliance/verible/releases 下载静态二进制包,解压后将
bin/加入PATH

-
echo 'export PATH="$PATH:/VERIBLE路径/verible/bin"' >> ~/.bashrc -
echo 'export PATH="$PATH:~/音乐/verible-v0.0-4080-ga0a8d8eb-linux-static-x86_64/verible-v0.0-4080-ga0a8d8eb/bin"' >> ~/.bashrc -
Windows:下载 Windows 版 Release 包或 WSL 下用 Linux 版
三、常用命令示例
代码格式化(最常用)
# 格式化单个文件(原地修改)
verible-verilog-format --inplace design.sv
# 批量格式化
verible-verilog-format --inplace $(find . -name "*.v" -o -name "*.sv")
# 指定列宽
verible-verilog-format --column_limit=120 design.sv

语法检查
$ verible-verilog-syntax design.sv // 基本语法检查
$ verible-verilog-syntax --printtree design.sv
2>&1 | head -n 10
Parse Tree:
Node @0 (tag: kDescriptionList) {
Node @0 (tag: kModuleDeclaration) {
Node @0 (tag: kModuleHeader) {
Leaf @0 (#"module" @1581-1587: "module")
Leaf @2 (#SymbolIdentifier @1588-1601: "RS232Driver_s")
Node @5 (tag: kParenGroup) {
Leaf @0 (#'(' @1602-1603: "(")
Node @1 (tag: kPortDeclarationList) {
$ verible-verilog-syntax --printtokens design.sv // 打印 token(看词法分析)
Lexed and filtered tokens:
(#"module" @1581-1587: "module")
(#SymbolIdentifier @1588-1601: "RS232Driver_s")
(#'(' @1602-1603: "(")
(#SymbolIdentifier @1788-1791: "clk")
(#',' @1791-1792: ",")
(#SymbolIdentifier @1820-1826: "nReset")
(#',' @1826-1827: ",")
(#SymbolIdentifier @2066-2074: "RS232TXD")
(#',' @2074-2075: ",")
(#SymbolIdentifier @2106-2114: "RS232RXD")
(#',' @2114-2115: ",")
(#SymbolIdentifier @2379-2387: "tDataReq")
(#',' @2387-2388: ",")
(#SymbolIdentifier @2434-2439: "tData")
(#',' @2439-2440: ",")
(#SymbolIdentifier @2480-2485: "tBusy")
(#',' @2485-2486: ",")
(#SymbolIdentifier @2786-2793: "rDataEn")
(#',' @2793-2794: ",")
(#SymbolIdentifier @2859-2864: "rData")
$ verible-verilog-syntax --helpfull
verible-verilog-syntax: usage: verible-verilog-syntax [options] <file> [<file>...]
Flags from external/abseil-cpp~/absl/flags/parse.cc:
--flagfile (comma-separated list of files to load flags from); default: ;
--fromenv (comma-separated list of flags to set from the environment [use
'export FLAGS_flag1=value']); default: ;
--tryfromenv (comma-separated list of flags to try to set from the
environment if present); default: ;
--undefok (comma-separated list of flag names that it is okay to specify on
the command line even if the program does not define a flag with that
name); default: ;
Flags from verible/verilog/parser/verilog-parser.cc:
--verilog_trace_parser (Trace verilog parser); default: false;
Flags from verible/verilog/tools/syntax/verilog-syntax.cc:
--error_limit (Limit the number of syntax errors reported. (0: unlimited));
default: 0;
--export_json (Uses JSON for output. Intended to be used as an input for
other tools.); default: false;
--lang (Selects language variant to parse. Options:
auto: SystemVerilog-2017, but may auto-detect alternate parsing modes
sv: strict SystemVerilog-2017, with explicit alternate parsing modes
lib: Verilog library map language (LRM Ch. 33)
); default: auto;
--printrawtokens (Prints all lexed tokens, including filtered ones.);
default: false;
--printtokens (Prints all lexed and filtered tokens); default: false;
--printtree (Whether or not to print the tree); default: false;
--show_diagnostic_context (prints an additional line on which the diagnostic
was found,followed by a line with a position marker); default: false;
--verifytree (Verifies that all tokens are parsed into tree, prints
unmatched tokens); default: false;
Try --helpfull to get a list of all flags or --help=substring shows help for
flags which include specified substring in either in the name, or description or
path.
风格检查(Lint)
$verible-verilog-lint design.sv
design.sv:32:8-20: Declared module does not match the first dot-delimited component of file name: "design" [Style: file-names] [module-filename]
design.sv:85:13-26: Explicitly define a storage type for every parameter and localparam, (pRS232BandRate). [Style: constants] [explicit-parameter-storage-type]
design.sv:86:13-31: Explicitly define a storage type for every parameter and localparam, (pRS232BandRate_half). [Style: constants] [explicit-parameter-storage-type]
- 文件名和module名不一致
- 参数没有指定类型
代码混淆(Obfuscate)
$ verible-verilog-obfuscate --helpfull
verible-verilog-obfuscate: usage: verible-verilog-obfuscate [options] < original > output
verilog_obfuscate mangles Verilog code by changing identifiers.
All whitespaces and identifier lengths are preserved.
Output is written to stdout.
Flags from external/abseil-cpp~/absl/flags/parse.cc:
--flagfile (comma-separated list of files to load flags from); default: ;
--fromenv (comma-separated list of flags to set from the environment [use
'export FLAGS_flag1=value']); default: ;
--tryfromenv (comma-separated list of flags to try to set from the
environment if present); default: ;
--undefok (comma-separated list of flag names that it is okay to specify on
the command line even if the program does not define a flag with that
name); default: ;
Flags from verible/verilog/parser/verilog-parser.cc:
--verilog_trace_parser (Trace verilog parser); default: false;
Flags from verible/verilog/tools/obfuscator/verilog-obfuscate.cc:
--decode (If true, when used with --load_map, apply the translation
dictionary in reverse to de-obfuscate the source code, and do not
obfuscate any unseen identifiers. There is no need to --save_map with this
option, because no new substitutions are established.); default: false;
--load_map (If provided, pre-load an existing translation dictionary
(written by --save_map). This is useful for applying pre-existing
transforms.); default: "";
--preserve_builtin_functions (If true, preserve built-in function names such
as sin(), ceil()..); default: true;
--preserve_interface (If true, module name, port names and parameter names
will be preserved. The translation map saved with --save_map will have
identity mappings for these identifiers. When used with --load_map, the
mapping explicitly specified in the map file will have higher priority
than this option.); default: false;
--save_map (If provided, save the translation to a dictionary for reuse in a
future obfuscation with --load_map.); default: "";
Try --helpfull to get a list of all flags or --help=substring shows help for
flags which include specified substring in either in the name, or description or
path.
- Verible 混淆 ≠ 加密,不防专业逆向分析,只是去掉可读语义,适合低敏感场景
- Vivado 、Quartus 和 Microchip Libero SoC 本身都不内置 Verilog 源代码"混淆器(Obfuscator)"。它们自带IEEE P1735加密(加密后不可读,不是混淆)和 网表/DCP 黑盒交付。
| Flag | 作用 |
|---|---|
--save_map | 保存「原名字 → 混淆名字」映射表 |
--load_map | 用已有的映射表混淆 |
--decode | 反混淆(还原) |
--preserve_interface | 保留 module / port / parameter 名字 |
--preserve_builtin_functions | 保留 $sin、$ceil 等系统函数 |
verible-verilog-obfuscate < design.sv > design_obf.sv // 基础混淆

- 删除注释可以使用 :
sed -i 's/\/\/.*$//' test.sv
verible-verilog-obfuscate --save_map=map.txt < design.sv > design_obf.sv // 保存映射表

verible-verilog-obfuscate --load_map=map.txt < fifo.sv > fifo_obf.sv // 可用同一个映射表混淆多个文件
verible-verilog-obfuscate --load_map=map.txt --decode < design_obf.sv > design_recovered.sv // 反混淆(还原代码)
verible-verilog-obfuscate --preserve_interface --save_map=map.txt < ip_top.sv > ip_top_obf.sv // 保留接口(对外 IP 交付常用)
使用AI反混淆(也可正常编译):
module uart_rs232 (
input clk, // 20MHz
input rst_n, // 低有效复位
output txd, // RS232 TX
input rxd, // RS232 RX
input tx_req, // 发送请求
input [7:0] tx_data, // 待发送数据
output tx_busy, // 发送忙
output rx_valid, // 接收数据有效
output [7:0] rx_data // 接收数据
);
//==================== 参数 ====================
parameter BAUD_CNT_MAX = 12'd278; // 115200 @20MHz
parameter BAUD_HALF = 12'd139;
//==================== 内部信号 ====================
reg [11:0] baud_cnt;
reg baud_tick;
reg [9:0] tx_shift_reg;
reg tx_state;
reg [3:0] tx_bit_cnt;
reg rxd_sync_0;
reg rxd_sync_1;
wire rxd_negedge;
reg [1:0] rx_state;
reg [11:0] rx_baud_cnt;
reg [6:0] rx_shift_reg;
reg [2:0] rx_bit_cnt;
reg tx_busy;
reg txd;
reg rx_valid;
reg [7:0] rx_data;
//==================== TX 波特率生成 ====================
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
baud_cnt <= 0;
baud_tick <= 0;
end else if (baud_cnt == BAUD_CNT_MAX) begin
baud_cnt <= 0;
baud_tick <= 1'b1;
end else begin
baud_cnt <= baud_cnt + 1;
baud_tick <= 1'b0;
end
end
//==================== TX 发送逻辑 ====================
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
tx_state <= 0;
tx_busy <= 0;
txd <= 1'b1;
tx_bit_cnt <= 0;
end else begin
case (tx_state)
1'b0: begin
txd <= 1'b1;
tx_busy <= 0;
if (tx_req) begin
tx_state <= 1'b1;
tx_busy <= 1'b1;
tx_shift_reg <= {1'b1, tx_data, 1'b0};
tx_bit_cnt <= 0;
end
end
1'b1: begin
if (baud_tick) begin
txd <= tx_shift_reg[0];
tx_shift_reg <= {1'b1, tx_shift_reg[9:1]};
tx_bit_cnt <= tx_bit_cnt + 1;
if (tx_bit_cnt == 4'd9)
tx_state <= 1'b0;
end
end
endcase
end
end
//==================== RX 同步 & 下降沿 ====================
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
rxd_sync_0 <= 0;
rxd_sync_1 <= 0;
end else begin
rxd_sync_0 <= rxd;
rxd_sync_1 <= rxd_sync_0;
end
end
assign rxd_negedge = rxd_sync_1 && !rxd_sync_0;
//==================== RX 波特率计数 ====================
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
rx_baud_cnt <= 0;
else if (rx_state == 0)
rx_baud_cnt <= 0;
else if (rx_baud_cnt == BAUD_CNT_MAX)
rx_baud_cnt <= 0;
else
rx_baud_cnt <= rx_baud_cnt + 1;
end
//==================== RX 接收状态机 ====================
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
rx_state <= 0;
rx_bit_cnt <= 0;
rx_valid <= 0;
rx_shift_reg <= 0;
rx_data <= 0;
end else begin
case (rx_state)
2'd0: begin
rx_valid <= 0;
if (rxd_negedge)
rx_state <= 2'd1;
end
2'd1: begin
if (rx_baud_cnt == BAUD_HALF)
rx_state <= 2'd2;
end
2'd2: begin
if (rx_baud_cnt == BAUD_HALF) begin
if (rx_bit_cnt == 3'd7) begin
rx_data <= {rxd_sync_0, rx_shift_reg};
rx_valid <= 1;
rx_state <= 2'd3;
end else begin
rx_shift_reg <= {rxd_sync_0, rx_shift_reg[6:1]};
rx_bit_cnt <= rx_bit_cnt + 1;
end
end
end
2'd3: begin
rx_valid <= 0;
rx_state <= 0;
end
endcase
end
end
endmodule
Verible插件



356

被折叠的 条评论
为什么被折叠?



