文章目录

1、核心概念

1.1 四种逻辑值与线网强度

SystemVerilog 使用 4 态逻辑值系统:

含义 说明
0 逻辑低 低电平、假
1 逻辑高 高电平、真
x 未知 未初始化或多驱动冲突
z 高阻 三态、无驱动悬空

线网(net)类型支持驱动强度,多驱动时强度高者胜出,强度从高到低:

supply > strong > pull > large > weak > medium > small > highz
  • 连续赋值 assign 默认:strong 强度
  • supply0 / supply1supply 最高强度
  • 变量(variable)不支持强度模型

1.2 net(线网)与 variable(变量)本质区别

特性 net(线网) variable(变量)
存储特性 不存储值(trireg 除外) 赋值后保持值,直到下次赋值
驱动方式 支持多驱动,自动决议 单驱动,禁止多驱动
赋值方式 连续赋值 / 门驱动 / 端口驱动 过程赋值(initial/always
默认值 ztrireg 默认 x 4 态=x,2 态=0
强度支持 支持驱动/电荷强度 不支持强度

net 与 variable 分属不同命名空间,同名不冲突,但工程中不建议同名

1.3 4 态类型与 2 态类型

  • 4 态类型logic / reg / integer / time,含 0/1/x/z,适合设计建模
  • 2 态类型bit / byte / shortint / int / longint,仅 0/1,仿真更快,适合验证平台

1.4 单一类型与聚合类型

  • 单一类型(singular):基础类型、打包类型、string、句柄(单个值)
  • 聚合类型(aggregate):非打包数组/结构体/联合体(值集合)

2、内建线网(net)类型

线网类型速查表

类型 功能说明
wire / tri 通用线网,多驱动自动决议
uwire 单驱动线网,多驱动直接报错
wand / triand 线与逻辑,任一驱动 0 则输出 0
wor / trior 线或逻辑,任一驱动 1 则输出 1
trireg 电容存储,无驱动保持最后值
tri0 无驱动默认输出 0
tri1 无驱动默认输出 1
supply0 / supply1 电源/地,最高强度
interconnect 无类型连接,自动推导类型

下面详细解释 SystemVerilog中各种线网(net)类型的功能、行为特点和典型使用场景。

2.1 wire / tri

  • 功能:标准线网类型,支持多个驱动源,通过线网决议函数计算最终值。

  • 决议规则
    在这里插入图片描述

  • wiretri:功能完全等价,tri 强调可能被多个三态驱动。

  • 使用场景:模块间连接、组合逻辑输出。

  • 赋值限制:只能通过 assign、门输出、模块端口驱动,禁止在 initial/always 中直接赋值

示例:

wire w1, w2;
assign w1 = 1'b1;
assign w1 = 1'b0;   // 冲突 → x
assign w2 = 1'b1;
assign w2 = 1'bz;   // 1 与 z → 1

tri t1, t2;
assign t1 = 1'b1;
assign t1 = 1'b0;   // 冲突 → x
assign t2 = 1'b0;
assign t2 = 1'bz;   // 0 与 z → 0

2.2 uwire

  • 功能:单驱动线网,强制要求只有一个驱动源
  • 用途:在编译/详细设计阶段发现意外的多驱动错误。
  • 注意uwire 是 SystemVerilog 引入的特性。

示例:

uwire u1;
assign u1 = 1'b1;
// assign u1 = 1'b0;    // 错误!多驱动报错

2.3 wand / triand

  • 功能:线与逻辑,最终值为所有驱动值的逻辑与。
  • 决议规则
    在这里插入图片描述
    示例:
wand w_and;
assign w_and = 1'b1;
assign w_and = 1'b1;    // 1 & 1 = 1
assign w_and = 1'bz;    // 高阻忽略

triand t_and;
assign t_and = 1'b1;
assign t_and = 1'b0;    // 0 & 1 = 0

2.4 wor / trior

  • 功能:线或逻辑,最终值为所有驱动值的逻辑或。
  • 决议规则
    在这里插入图片描述

示例:

wor w_or;
assign w_or = 1'b0;
assign w_or = 1'b0;     // 0 | 0 = 0
assign w_or = 1'bz;     // 高阻忽略

trior t_or;
assign t_or = 1'b0;
assign t_or = 1'b1;     // 1 | 0 = 1

2.5 trireg

  • 功能:电容存储线网。当所有驱动为 z 时,保持上一个有效逻辑值。
  • 电荷强度:可指定 (small)(medium)(large) 表示衰减时间,默认无限保持。
  • 使用场景:建模动态节点、总线保持电路,主要用于模拟/混合信号仿真。

示例:

trireg (large) cap_node;
reg driver_en, data_val;

assign cap_node = driver_en ? data_val : 1'bz;

initial begin
    driver_en = 1; data_val = 1; #10;   // cap_node = 1
    driver_en = 0;                      // 驱动关闭,cap_node 保持 1
    #10 $display("%b", cap_node);       // 输出 1
end

2.6 tri0

  • 功能:弱下拉线网。所有驱动为 z 时,输出 0(内置弱下拉电阻)。
  • 使用场景:确保总线未驱动时有确定值。
    在这里插入图片描述

示例:

tri0 t0;
assign t0 = 1'b1;       // 强驱动 1,结果为 1
// assign t0 = 1'bz;    // 若所有驱动为 z,结果为 0

2.7 tri1

  • 功能:弱上拉线网。所有驱动为 z 时,输出 1
  • 使用场景:模拟上拉电阻。
    在这里插入图片描述

示例:

tri1 t1;
assign t1 = 1'b0;       // 强驱动 0,结果为 0
// assign t1 = 1'bz;    // 若所有驱动为 z,结果为 1

2.8 supply0 / supply1

  • 功能:电源/地线网,恒定输出 0/1,具有最高 supply 强度。
  • 使用场景:门级仿真中的 VSS/VDD 网络,测试平台中强制覆盖信号。

示例 1:supply0 覆盖 strong 驱动

supply0 gnd;
supply1 vcc;

wire sig;
assign sig = 1'b1;      // strong 强度,值 1
assign sig = gnd;       // supply 强度,值 0 → 结果 0

示例 2:supply1 覆盖 strong 驱动

supply1 vcc;
wire sig;
assign sig = vcc;       // supply 强度,值 1
assign sig = 1'b0;      // strong 强度,值 0 → 结果 1

示例 3:两个 supply 级驱动冲突

supply1 vcc;
supply0 gnd;
wire sig;
assign sig = vcc;       // supply 强度,值 1
assign sig = gnd;       // supply 强度,值 0
// 强度相同,值不同 → 结果为 x

2.9 interconnect

  • 功能:无类型连接线网,类型由连接的信号自动推导。
  • 限制:不能用于连续赋值右侧或门级输出,仅用于连接。
  • 注意:需工具支持 IEEE 1800-2012 或更新标准。

示例:

module top;
    logic a;
    wire  b;
    interconnect ic1, ic2;

    sub u_sub (.port_a(ic1), .port_b(ic2));
    assign ic1 = a;     // ic1 获得 logic 类型
    assign ic2 = b;     // ic2 获得 wire 类型
    // assign ic1 = 1'b1;  // 错误!
endmodule

3、变量定义

3.1 变量概述

变量是数据存储元素的抽象,用于在两次赋值之间保持其值。过程内的赋值语句会触发变量值的更新。

3.2 变量声明方式

3.2.1 传统形式

直接使用数据类型后跟变量名。

int i;
logic [7:0] data;
shortint s1, s2[0:9];

已为您优化如下:


3.2.2 var 关键字形式

var 开头,数据类型可选,省略时默认为 logic

var byte my_byte;           // 等价于 byte my_byte;
var v;                      // var logic v;
var [15:0] vw;              // var logic [15:0] vw;
var enum bit {clear, error} status;
input var logic data_in;    // 模块端口中使用
var reg r;                  // 合法但不推荐

3.3 数据类型分类

类别 包含类型
2 态整型向量 bit
4 态整型向量 logic, reg
2 态整型原子 byte, shortint, int, longint
4 态整型原子 integer, time
非整型 shortreal, real, realtime
特殊类型 void, chandle, string, event, 虚接口, 类句柄
枚举 enum

3.4 标量与向量

3.4.1 打包 vs 非打包
  • 打包维度(左侧):数据连续紧凑存储,可综合、支持位选/部分选,等价于 Verilog 向量
  • 非打包维度(右侧):数据独立分段存储,仿真易用,部分可综合
bit [7:0] a;        // 打包:8 位向量(硬件标准写法)
bit b [7:0];        // 非打包:8 个独立 1bit(数组)
bit [7:0] c [3:0];  // 4 个 8 位向量的数组(最常用)
3.4.2 向量范围指定
  • 格式:[msb_constant_expression : lsb_constant_expression]
  • msb 和 lsb 必须是常量整数表达式,可为任意整数值(正、负、零)。
  • lsb 值可以大于、等于或小于 msb 值。
  • 禁止包含 xz 位。

示例:

logic [3:0] v;          // 4 位,v[3] 最高位,v[0] 最低位
logic [-1:4] b;         // 6 位,有效索引 -1、0、1、2、3、4
logic [4:0] x, y, z;    // 三个 5 位向量
3.4.3 向量算术规则
  • 向量遵循模 2 n 2^n 2n 的算术规则, n n n 为向量位数。
  • 默认视为无符号量,除非用 signed 显式声明或连接到有符号端口。
3.4.4 向量长度限制
  • 工具对向量最大长度的限制至少为 65536 2 16 2^{16} 216)位。
3.4.5 vectored 与 scalared 关键字
  • 可选关键字,仅用于向量线网声明。
  • vectored:可能禁止位选/部分选,PLI 视为未展开。
  • scalared:允许位选/部分选,PLI 视为已展开。
tri1 scalared [63:0] bus64;     // 展开的总线
tri vectored [31:0] data;       // 可能不展开

3.5 变量生命周期(static / automatic)

  • static:静态存储,全局/模块级变量默认,仿真全程存在。
  • automatic:自动存储,函数/任务内变量默认,调用时创建、退出时销毁。
function automatic int calc(input int a);
    int temp = a * 2;    // 每次调用重新初始化
    return temp;
endfunction

3.6 变量初始化

3.6.1 显式初始化

声明时使用 = 初始值,初始值可以是运行时表达式。

int i = 0;
static mailbox mbx = new();
static int rand_val = $urandom;
3.6.2 初始化时机
  • 静态变量的初始化发生在所有 initialalways 过程启动之前
3.6.3 默认初始值
类型 默认初始值
4 态整型 (logic, reg, integer, time) 'x
2 态整型 (bit, byte, shortint, int, longint) '0
real, shortreal 0.0
string ""(空字符串)
event 新事件对象
类句柄 / chandle / 虚接口 null
枚举 基类型的默认初始值

3.7 有符号/无符号规则

默认有符号类型 默认无符号类型
byte, shortint, int, longint bit, logic, reg
integer time
  • 可使用 signedunsigned 显式覆盖。
bit signed [7:0] signed_byte;
logic unsigned [31:0] u32;

3.8 整数类型速查表

3.8.1 2 态整数类型
类型 位宽 默认符号
bit 自定义 无符号
byte 8 bit 有符号
shortint 16 bit 有符号
int 32 bit 有符号
longint 64 bit 有符号
3.8.2 4 态整数类型
类型 位宽 默认符号
logic / reg 自定义 无符号
integer 32 bit 有符号
time 64 bit 无符号

3.9 特殊变量类型

类型 说明
void 无数据类型,仅用于函数返回值
chandle DPI-C 接口中传递 C 指针的不透明句柄,默认 null
虚接口 (virtual interface) 验证平台中连接 DUT 的接口句柄
类句柄 指向 class 对象的引用,默认 null

3.10 类型转换

3.10.1 静态转换

编译时检查,语法 type'(expr)

int i = 10;
real r = real'(i);          // int → real
logic [3:0] b = 4'(8'hFF);  // 截断高位,b = 4'hF
3.10.2 动态转换

运行时检查,语法 $cast(target, source),主要用于类句柄转换。

parent_class p;
child_class c;
if ($cast(c, p)) begin
    // 转换成功
end
3.10.3 类型兼容性规则
  • 2 态 → 4 态:自动转换,0/1 保持。
  • 4 态 → 2 态:x/z 自动转为 0
  • 位宽不匹配:赋值时自动截断或补零。

3.11 示例汇总

// 标量声明
logic a;

// 向量声明
tri [15:0] busa;
logic [3:0] v;
logic signed [3:0] signed_reg;
logic [-1:4] b;

// 批量声明
wire w1, w2;
logic [4:0] x, y, z;

// 变量初始化
int i = 0;
string msg = "Hello";

4、常用数据类型扩展

4.1 string 类型常用方法

方法 功能说明
s.len() 返回字符串长度
s[i] / s.getc(i) 获取第 i 个字符
s.putc(i, c) 修改第 i 个字符
s.toupper() 转换为大写
s.tolower() 转换为小写
s.atoi() 字符串转整数
s.atoreal() 字符串转实数

示例:

module string_example;
    initial begin
        string s = "Hello";
        $display("s[1] = %c", s[1]);   // 输出 'e'
        s.putc(1, "a");                // s 变为 "Hallo"
        $display("upper: %s", s.toupper()); // "HALLO"
    end
endmodule

4.2 event 事件基本用法

语法 功能说明
event e; 声明事件
-> e; 触发事件
@e; 等待事件在后续时间步触发(边缘敏感)
wait(e.triggered); 等待事件在当前时间步已触发(电平敏感)

@ewait(e.triggered) 区别

  • @e:若事件在等待前已触发,会错过。
  • wait(e.triggered):只要当前时间步曾触发即满足。

示例:

event e;
initial begin
    #10 -> e;
    $display("e triggered");
end

initial begin
    @e $display("received via @");
end

initial begin
    #5;
    wait(e.triggered) $display("received via wait");
end

4.3 typedef 自定义类型

typedef 为现有类型创建别名,提高可读性。

typedef int my_type;
typedef logic [31:0] addr_t;

typedef enum {IDLE, READ, WRITE} state_t;

typedef struct packed {
    addr_t addr;
    my_type data;
} transaction_t;

4.4 枚举类型(enum)

枚举定义一组命名的常量。

// 基础枚举
enum {IDLE, READ, WRITE} state;

// 显式指定基类型和值
enum bit [1:0] {
    RED   = 2'b00,
    GREEN = 2'b01,
    BLUE  = 2'b10
} color;

// 类型安全枚举
typedef enum logic [2:0] {
    S_IDLE  = 3'b001,
    S_START = 3'b010,
    S_WAIT  = 3'b100
} state_t;

state_t curr = S_IDLE;
$display("State: %s", curr.name());   // 输出 "S_IDLE"

// 枚举内置方法
curr = curr.first();  // 首个枚举值
curr = curr.last();   // 最后一个枚举值
curr = curr.next();   // 下一个值(循环)
curr = curr.prev();   // 上一个值(循环)

4.5 ref 参数传递

ref 用于任务/函数中按引用传递参数,避免大数组拷贝。

// 按值传递(拷贝整个数组)
function int sum_copy(int arr[10]);
    // arr 是副本
endfunction

// 按引用传递(不拷贝)
function int sum_ref(ref int arr[10]);
    arr[0] = 0;   // 影响外部实参
endfunction

// const ref:只读引用
function void print(const ref int arr[10]);
    foreach (arr[i]) $display("%0d", arr[i]);
endfunction

5、工程常见易错点与编码建议

5.1 reg / logic / bit 核心区别

类型 推荐度 说明
reg 不推荐 Verilog 遗留,无语法优势,建议用 logic 替代
logic 强烈推荐 4 态标准类型,支持变量和线网(单驱动),替代 reg
bit 推荐 2 态类型,仿真更快,适合复位/控制信号,注意无 x/z

5.2 wire 与 logic 混用规则

场景 推荐类型
模块输入端口 wirelogic 均可
模块输出端口(单驱动) logic
模块输出端口(多驱动,如三态总线) wire
组合逻辑输出 优先 logic,避免多驱动

5.3 多驱动错误排查

  • 使用 uwire 替代 wire,编译器直接报错多驱动源。
  • 检查 assign、门输出、模块端口是否重复驱动同一信号。

5.4 隐式线网声明

  • 未声明的信号默认生成 wire
  • 可通过 `default_nettype uwire 强制单驱动,或 `default_nettype none 禁止隐式声明。

5.5 初始化差异

  • 仿真:变量默认值按类型,net 默认 z
  • 综合:忽略声明时的初始化值,仅复位信号有效。

5.6 向量范围

  • 允许 lsb > msb(如 logic [0:7] a),位序仅影响位选索引,不改变实际硬件位宽。

5.7 编码规范推荐

  1. 设计代码:单驱动信号用 logic,多驱动三态总线用 wire
  2. 验证代码:优先 bit(2 态)提升仿真速度
  3. 状态机强烈推荐enum 定义,避免硬编码数字。enum 可提高可读性、可维护性,支持类型检查与调试显示状态名;硬编码语法上允许,但团队协作时不推荐。
  4. 跨模块信号:一律显式声明类型,禁止依赖隐式线网。

6、仿真验证示例

为验证前文所述的线网(net)类型决议规则以及字符串(string)常用方法,本章提供两个独立的 SystemVerilog Testbench,可直接用 VCS 仿真验证。

6.1 线网类型仿真验证

6.1.1 Testbench 代码
// filename: net_types_tb.sv
// 功能: 验证 SystemVerilog 线网决议规则

module net_types_tb;

    // ========== 1. wire / tri 静态决议 ==========
    wire w1, w2;
    tri  t1, t2;
    assign w1 = 1'b1;
    assign w1 = 1'b0;      // 1 与 0 -> x
    assign w2 = 1'b1;
    assign w2 = 1'bz;      // 1 与 z -> 1
    assign t1 = 1'b1;
    assign t1 = 1'b0;      // 1 与 0 -> x
    assign t2 = 1'b0;
    assign t2 = 1'bz;      // 0 与 z -> 0

    // ========== 2. wand / triand (线与) ==========
    wand wand_sig;
    assign wand_sig = 1'b1;
    assign wand_sig = 1'b1;  // 1 & 1 -> 1
    wand wand2;
    assign wand2 = 1'b0;
    assign wand2 = 1'b1;     // 0 & 1 -> 0
    wand wand3;
    assign wand3 = 1'bz;
    assign wand3 = 1'b1;     // z & 1 -> 1

    // ========== 3. wor / trior (线或) ==========
    wor wor_sig;
    assign wor_sig = 1'b0;
    assign wor_sig = 1'b0;   // 0 | 0 -> 0
    wor wor2;
    assign wor2 = 1'b1;
    assign wor2 = 1'b0;      // 1 | 0 -> 1
    wor wor3;
    assign wor3 = 1'bz;
    assign wor3 = 1'b0;      // z | 0 -> 0

    // ========== 4. trireg (电容存储) ==========
    trireg (large) cap_node;

    // ========== 5. tri0 / tri1 ==========
    tri0 tri0_sig;   // 弱下拉,默认 0
    tri1 tri1_sig;   // 弱上拉,默认 1

    // ========== 6. supply0 / supply1 强度测试 ==========
    supply0 gnd;
    supply1 vcc;
    
    // 6.1 顺序 force 演示覆盖关系
    wire test_strong, test_supply;
    
    // 6.2 静态多 assign 演示同时冲突 (两个 supply 驱动同一线网)
    wire test_both;
    assign test_both = gnd;
    assign test_both = vcc;

    // 测试控制 (initial 块)
    initial begin
        $display("==========================================");
        $display("  SystemVerilog Net Types Testbench");
        $display("  (Static assign + dynamic force/release)");
        $display("==========================================\n");

        // ----- 1. wire / tri (静态决议) -----
        $display("--- 1. wire / tri (static multiple assign) ---");
        #1;
        $display("wire w1 (1 and 0) = %b (expect x)", w1);
        $display("wire w2 (1 and z) = %b (expect 1)", w2);
        $display("tri  t1 (1 and 0) = %b (expect x)", t1);
        $display("tri  t2 (0 and z) = %b (expect 0)\n", t2);

        // ----- 2. wand / triand -----
        $display("--- 2. wand / triand (static multiple assign) ---");
        $display("wand (1 & 1) = %b (expect 1)", wand_sig);
        $display("wand (0 & 1) = %b (expect 0)", wand2);
        $display("wand (z & 1) = %b (expect 1)\n", wand3);

        // ----- 3. wor / trior -----
        $display("--- 3. wor / trior (static multiple assign) ---");
        $display("wor  (0 | 0) = %b (expect 0)", wor_sig);
        $display("wor  (1 | 0) = %b (expect 1)", wor2);
        $display("wor  (z | 0) = %b (expect 0)\n", wor3);

        // ----- 4. trireg (电容存储, 使用 force/release) -----
        $display("--- 4. trireg (force/release) ---");
        force cap_node = 1'b1;
        #1;
        $display("trireg forced to 1 = %b", cap_node);
        release cap_node;          // 释放后应保持之前的值(电容特性)
        #1;
        $display("trireg after release (hold) = %b (expect 1)", cap_node);
        force cap_node = 1'b0;
        #1;
        $display("trireg forced to 0 = %b", cap_node);
        release cap_node;
        #1;
        $display("trireg after release again = %b (expect 0)\n", cap_node);

        // ----- 5. tri0 / tri1 (弱上/下拉, 使用 force/release) -----
        $display("--- 5. tri0 / tri1 (force/release) ---");
        // tri0: 强1驱动覆盖弱下拉
        force tri0_sig = 1'b1;
        #1;
        $display("tri0 forced to strong 1 = %b (expect 1)", tri0_sig);
        release tri0_sig;          // 释放后弱下拉生效 -> 0
        #1;
        $display("tri0 after release (pull-down) = %b (expect 0)", tri0_sig);

        // tri1: 强0驱动覆盖弱上拉
        force tri1_sig = 1'b0;
        #1;
        $display("tri1 forced to strong 0 = %b (expect 0)", tri1_sig);
        release tri1_sig;          // 释放后弱上拉生效 -> 1
        #1;
        $display("tri1 after release (pull-up) = %b (expect 1)\n", tri1_sig);

        // ----- 6. supply0 / supply1 强度测试 -----
        $display("--- 6. supply0 / supply1 strength ---");
        
        // 6.1 顺序 force 演示覆盖关系
        $display("--- 6.1 Sequential force override ---");
        // supply0 覆盖 strong1
        force test_strong = 1'b1;
        #1;
        $display("After strong1 alone: test_strong = %b", test_strong);
        force test_strong = gnd;   // supply0 覆盖
        #1;
        $display("After supply0 overrides strong1: test_strong = %b (expect 0)", test_strong);
        release test_strong;
        
        // supply1 覆盖 strong0
        force test_supply = 1'b0;
        #1;
        $display("After strong0 alone: test_supply = %b", test_supply);
        force test_supply = vcc;   // supply1 覆盖
        #1;
        $display("After supply1 overrides strong0: test_supply = %b (expect 1)", test_supply);
        release test_supply;
        
        // 6.2 静态多 assign 演示同时冲突
        $display("--- 6.2 Simultaneous multiple assign (supply0 vs supply1) ---");
        #1;
        $display("supply0 vs supply1 (static) = %b (expect x)", test_both);

        $display("\n==========================================");
        $display("  Testbench completed.");
        $display("==========================================");
        $finish;
    end

endmodule
6.1.2 仿真输出

在这里插入图片描述


6.2 字符串类型使用示例

string 是 SystemVerilog 中常用的验证/仿真辅助类型,支持动态长度、内置方法。以下示例演示常用方法(长度访问、字符修改、大小写转换、类型转换等)。

6.2.1 Testbench 代码
// filename: string_demo.sv
// 功能: 演示 SystemVerilog string 类型常用方法
// 仿真命令: vcs -sverilog string_demo.sv -R

module string_demo;

    initial begin
        string s, t, u;
        int int_val;
        real real_val;

        $display("==========================================");
        $display("  SystemVerilog String Methods Demo");
        $display("==========================================\n");

        // ----- 1. 字符串基本操作 -----
        s = "Hello";
        $display("1. 原始字符串: \"%s\"", s);
        $display("   长度: %0d", s.len());
        $display("   第1个字符(s[1]): '%c'", s[1]);   // 注意索引从0开始?实际上s[0]='H', s[1]='e'
        // 更正: 索引从0开始,s[0]='H', s[1]='e'
        $display("   第0个字符(s[0]): '%c'", s[0]);

        // ----- 2. 修改字符 -----
        s.putc(1, "a");   // 将索引1的字符改为'a'
        $display("\n2. putc(1, 'a') 后: \"%s\" (期望 \"Hallo\")", s);

        // ----- 3. 大小写转换 -----
        s = "Hello World";
        $display("\n3. 原始: \"%s\"", s);
        $display("   toupper(): \"%s\"", s.toupper());
        $display("   tolower(): \"%s\"", s.tolower());

        // ----- 4. 字符串拼接与比较 -----
        t = "Hello";
        u = " World";
        s = {t, u};   // 拼接
        $display("\n4. 拼接 \"%s\" + \"%s\" = \"%s\"", t, u, s);
        $display("   compare(\"%s\", \"%s\") = %0d", t, u, t.compare(u));

        // ----- 5. 字符串转整数/实数 -----
        s = "123";
        int_val = s.atoi();
        $display("\n5. atoi(\"%s\") = %0d", s, int_val);

        s = "3.1415";
        real_val = s.atoreal();
        $display("   atoreal(\"%s\") = %0.4f", s, real_val);

        // ----- 6. 整数/实数转字符串 -----
        int_val = 456;
        s = $sformatf("%0d", int_val);
        $display("\n6. $sformatf(\"%%0d\", %0d) = \"%s\"", int_val, s);

        real_val = 2.71828;
        s = $sformatf("%0.3f", real_val);
        $display("   $sformatf(\"%%0.3f\", %0.5f) = \"%s\"", real_val, s);

        // ----- 7. 子串提取 -----
        s = "abcdefgh";
        t = s.substr(2, 5);   // 索引2到5,包含两端
        $display("\n7. substr(2,5) of \"%s\" = \"%s\" (期望 \"cdef\")", s, t);

        $display("\n==========================================");
        $display("  Demo completed.");
        $display("==========================================");
        $finish;
    end

endmodule
6.2.2 预期仿真输出日志

在这里插入图片描述

6.2.4 注意事项
  • string 索引从 0 开始(s[0] 是第一个字符)。
  • putc(i, c) 修改索引 i 处的字符,索引超出范围会导致运行时错误。
  • substr(i, j) 提取从索引 ij(含两端)的子串。
  • atoi()atoreal() 遇到非数字字符会停止转换,不会报错。
  • $sformatf() 是系统函数,返回格式化后的字符串,类似 C 的 sprintf仅用于仿真,不可综合。
  • string 类型不可综合,仅用于测试平台、验证环境。

📚 参考文档IEEE Standard for SystemVerilog

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐