SystemVerilog:告别锁存器,优雅驾驭FPGA设计

System Verilog 约束技巧 文章目录System Verilog的约束与随机约束 System Verilog的约束与随机 约束 简单表达式:一个表达式中最多只能使用一个关系操作符,约束块里只能包含表达式,所以在约束块里不能进行赋值。 权重分布:dist src dist {0:40,[1:3]:=60}; //权重和不用等于100,值和权重可以是常数或者变量 集合(set)和inside c inside {[lo:hi]} ; c inside {[$:4],[20:$]} //可以使用$取位宽范围内的最大或者最 阅读详情

SystemVerilog避坑指南:告别锁存器,优雅驾驭FPGA设计

在ASIC/FPGA开发中,锁存器(Latch)往往是设计师最不想看到的“不速之客”,而SystemVerilog提供了一套优雅的语法工具,让我们能够从根本上规避这类问题。

引言:被锁存器困扰的FPGA开发者们

作为一个FPGA开发者,你一定经历过这样的情况:综合报告中出现意外的锁存器警告,时序分析变得复杂,设计性能下降,甚至出现难以调试的功能错误。这些问题的根源往往是我们不经意间在代码中创建的锁存器。

传统Verilog中,不完整的条件判断很容易导致锁存器的意外产生。但幸运的是,SystemVerilog通过引入更强大的语法特性,为我们提供了一套完整的解决方案。

锁存器的本质与危害

什么是锁存器?

锁存器是一种电平敏感的基本存储单元,与边沿触发的触发器不同,它在使能信号有效期间会持续透明地传递数据。在组合逻辑中意外产生锁存器通常是一个设计错误。

锁存器带来的三大问题:

  1. 时序分析困难 :锁存器的透明特性使得静态时序分析变得复杂
  2. 毛刺敏感 :电平敏感特性使其更容易受到毛刺影响
  3. 测试难度增加 :锁存器在可测试性设计(DFT)中往往带来额外挑战

SystemVerilog的“锁存器免疫”语法

1. always_comb:专为组合逻辑而生

SystemVerilog引入的 always_comb 块是避免锁存器的第一道防线。

verilog

// 传统Verilog中容易产生锁存器的代码
always @(*) begin
    if (enable) begin
        data_out = data_in;
    end
    // 缺少else分支,当enable=0时,data_out保持原值
    // 这将推断出一个锁存器!
end

// SystemVerilog的解决方案
always_comb begin
    if (enable) begin
        data_out = data_in;
    end else begin
        data_out = '0;  // 明确指定所有条件分支
    end
end

关键优势 :always_comb 会在编译时检查代码的完整性,确保所有可能的输入组合都有对应的输出赋值,从而从根本上避免锁存器产生。

2. unique/priority 条件判断修饰符

SystemVerilog提供了 unique 和 priority 修饰符,使条件判断更加明确和安全。

verilog

// 使用unique修饰符
always_comb begin
    unique case (state)
        IDLE:   next_state = (start) ? WORK : IDLE;
        WORK:   next_state = (done) ? IDLE : WORK;
        default: next_state = IDLE;  // 明确的默认情况
    endcase
end

// 使用priority修饰符
always_comb begin
    priority if (high_priority) begin
        grant = 3'b100;
    end else if (medium_priority) begin
        grant = 3'b010;
    end else begin
        grant = 3'b001;  // 所有条件都已覆盖
    end
end

语法优势 :

  • unique:确保条件互斥,如果没有条件匹配且无default,会报告运行时警告
  • priority:确保条件按顺序评估,至少有一个条件会被执行
  • 两者都会在综合时帮助识别不完整的条件判断

3. 完整的case语句与default赋值

SystemVerilog强化了case语句的完整性检查:

verilog

// 传统Verilog的不完整case语句
always @(*) begin
    case (sel)
        2'b00: out = a;
        2'b01: out = b;
        // 缺少sel=2'b10和2'b11的情况,会生成锁存器!
    endcase
end

// SystemVerilog的安全写法
always_comb begin
    case (sel)
        2'b00: out = a;
        2'b01: out = b;
        2'b10: out = c;
        2'b11: out = d;
        default: out = '0;  // 即使所有情况已覆盖,也建议保留default
    endcase
end

4. 初始化赋值与完整赋值策略

SystemVerilog鼓励在always块开始处对所有输出进行初始化:

verilog

always_comb begin
    // 首先为所有输出设置默认值
    data_out = '0;
    valid = 1'b0;
    ready = 1'b1;
  
    // 然后根据条件覆盖这些默认值
    if (condition1) begin
        data_out = data_a;
        valid = 1'b1;
    end else if (condition2) begin
        data_out = data_b;
        ready = 1'b0;
    end
  
    // 所有可能的执行路径都已经为输出赋值
end

这种方法确保在任何条件下,输出都有明确的值,彻底杜绝锁存器产生。

实战:FSM设计中的锁存器规避

让我们看一个状态机设计的对比示例:

verilog

// 传统Verilog中易出错的状态机
module risky_fsm (
    input logic clk, rst, input_a, input_b,
    output logic out
);
    typedef enum {S0, S1, S2} state_t;
    state_t current_state, next_state;
  
    // 状态转移逻辑 - 容易产生锁存器
    always @(*) begin
        case (current_state)
            S0: if (input_a) next_state = S1;
            S1: if (input_b) next_state = S2;
            S2: next_state = S0;
            // 问题:没有default分支!
        endcase
    end
  
    // 省略其他代码...
endmodule

// SystemVerilog安全状态机
module safe_fsm (
    input logic clk, rst, input_a, input_b,
    output logic out
);
    typedef enum logic [1:0] {S0 = 2'b00, S1 = 2'b01, S2 = 2'b10} state_t;
    state_t current_state, next_state;
  
    // 使用always_comb和完整case
    always_comb begin
        // 设置默认值
        next_state = current_state;
        out = 1'b0;
      
        // 明确的状态转移
        unique case (current_state)
            S0: begin
                out = 1'b1;
                if (input_a) next_state = S1;
            end
            S1: begin
                if (input_b) next_state = S2;
                else         next_state = S0;
            end
            S2: begin
                next_state = S0;
            end
            default: next_state = S0;  // 安全回退
        endcase
    end
  
    // 状态寄存器
    always_ff @(posedge clk or posedge rst) begin
        if (rst) begin
            current_state <= S0;
        end else begin
            current_state <= next_state;
        end
    end
endmodule

SystemVerilog的其他实用特性

1. always_ff和always_latch

SystemVerilog明确区分了三种always块:

  • always_comb:用于组合逻辑
  • always_ff:用于时序逻辑(触发器)
  • always_latch:用于明确的锁存器设计

verilog

// 明确意图的锁存器设计(在确实需要时)
always_latch begin
    if (enable) begin
        data_latched <= data_in;  // 明确的锁存器
    end
end

2. 断言(Assertions)辅助检查

SystemVerilog断言可以在仿真时检查设计假设:

verilog

always_comb begin
    // 功能代码...
  
    // 添加断言检查
    assert_final_value: assert (
        !$isunknown(data_out)
    ) else $warning("data_out has unknown bits!");
  
    // 检查是否可能产生锁存器
    assert_complete_assignment: assert (
        condition_a || condition_b || condition_c
    ) else $warning("Incomplete condition may cause latch!");
end

最佳实践总结

  1. 始终使用 always_comb代替 always @(*) 进行组合逻辑设计
  2. 为所有输出变量在每个执行路径中都提供赋值 ,包括默认值
  3. 在case语句中总是包含default分支 ,即使你认为所有情况都已覆盖
  4. 使用 unique或 priority修饰符明确条件判断的预期行为
  5. 在always_comb开始处初始化所有输出 ,确保完整赋值
  6. 使用SystemVerilog的枚举类型增强状态机的可读性和安全性
  7. 利用断言验证设计假设 ,在仿真阶段捕捉潜在问题

结语:拥抱SystemVerilog,写出更可靠的RTL代码

锁存器问题只是SystemVerilog解决的众多FPGA/ASIC设计难题之一。通过采用SystemVerilog的现代语法特性,我们不仅能避免意外的锁存器产生,还能提高代码的可读性、可维护性和可靠性。

作为当代数字设计工程师,掌握SystemVerilog不再是一种选择,而是一种必要。它不仅是语言的升级,更是设计思维的升级。从今天开始,让我们用SystemVerilog写出更优雅、更安全、更高效的硬件设计代码!


让锁存器成为设计选择,而不是代码意外。拥抱SystemVerilog,掌控你的硬件设计!

你在FPGA设计中还遇到过哪些因锁存器导致的棘手问题?或者你有自己的SystemVerilog避坑技巧?欢迎在评论区分享交流!

Systemverilog断言介绍(二) 阅读详情

相关推荐

systemverilog语法(六)

十六、随机化 通过随机化可以通过利用CPU的时间来换取人工检查的时间,提高效率,提供足够的激励。 采用受约束的随机测试法(CRT)产生测试集:使用随机的数据流为DUT产生输入的测试代码。改变伪随机数发生器(PRNG)的种子(seed)。 一般会在测试设计时考虑设计规范的边界处,甚至测试设计规范之外的行为。 1、 简单的随机变量的简单类 例: Randc表示周期随机性,即所有的

南国之邱 3万+

SystemVerilog学习笔记(六):控制流

条件语句用于检查块中的语句是否被执行。条件语句创建语句块。如果给出的表达式是 true,执行块中的语句集,如果表达式为 false,则 else 块语句将最后执行。

qq_38156104的博客 1073

#systemverilog# 关于随机约束之 randcase/endcase关键字

前言: 有时,我们遇到一些情况,我们希望求解器从众多语句中随机选择一个。 关键字randcase引入了一个case语句,该语句随机选择其分支之一。 案例项目表达式是正整数值,代表与每个项目相关的权重。 选择某项商品的可能性由该商品的权重除以所有权重之和得出。 语法: randcase item : statement; ... endcase 例1: 所有权重的总和为9,因此选择第一个分支的概率为1/9或11.11%,选择第二个分支的概率为5/9或55.56%,选择最后一个分支

那么菜的博客 3403

Verilog基础语法(13)之case语句

case语句的功能是:在某个信号(本例中的sel)取不同的值时,给另一个信号(本例中的q)赋不同的值。在括弧内的表达式将被精确地评估一次,并按其编写顺序与备选方案列表进行比较,与给定表达式匹配的备选方案的语句将被执行。Verilog HDL针对电路的特性提供了case语句的其它两种形式用来处理case语句比较过程中的不必考虑的情况( don’t care condition )。如果所有的case项都不符合给定的表达式,则执行缺省项内的语句,缺省语句是可选的,在case语句中只能有一条缺省语句。

m0_51965113的博客 2万+

systemverilog设计: assert 应用的例子(ncverilog测试过的)代码

systemverilog设计: assert 应用的例子(ncverilog测试过的)代码 测试 , 设计

VirtualBox安装Win10虚拟机超详细教程(附微软官方镜像下载)

本文提供了一份详细的VirtualBox安装Win10虚拟机教程,涵盖从环境准备、工具下载到系统安装与初始配置的全过程。特别推荐使用微软官方镜像下载,确保系统纯净安全。此外,还分享了性能优化技巧和常见问题解决方案,帮助用户高效搭建稳定的Windows测试环境。

weixin_29243279的博客 916

SystemVerilog-决策语句-case语句

数字硬件建模SystemVerilog-决策语句-case语句经过几周的更新,SV核心部分用户自定义类型和包内容已更新完毕,接下来就是RTL表达式和运算符。马上HDLBits-SystemVerilog版本也开始准备了,基本这一部分完成后就开始更新~决策语句(Decision statements)允许程序块的执行流程根据设计中信号的当前值分支到特定语句。SystemVerilog有两个主要的决策...

OpenFPGA的博客 6796

算法竞赛入门到进阶 --- 完整学习路线(含知识点讲解)

前言: 咳咳,接触算法竞赛也有一年了,却从来都没有进行过一次系统的学习,稀里糊涂的就这么搞了半年,如今,我决定认认真真的进行一次系统的复盘。嗯嗯,先把大体路线列出来,然后往后每天搞几篇,可能大三能完成,可能永远也不能写完这些,我只能慢慢来,一起共勉吧。冲了!(主要是太菜了,不系统学习下,怕是铜牌都拿不到呀!) 算法竞赛入门到进阶一、sort函数自定义排序二、c++容器的使用1.vector动态数组2.stack栈3.queue队列4.list链表5.set集合6.map映射三、二进制子集生成四、bfs.

qq_43514659的博客 2万+

sv中的三种case

精确匹配用case​ - 最安全,首选需要通配符用casez​ - 谨慎使用,用?明确标记Testbench用casex​ - 避免在RTL中使用总是添加uniquepriority​ - 提高代码可读性和安全性必须要有default​ - 除非使用且已覆盖所有情况。

baidu_38316985的博客 574

从Unitree B2W到四足机器人:用Isaac Lab构建强化学习奖励函数的5个实战技巧

本文分享了在Isaac Lab仿真环境中,为Unitree B2W等四足机器人设计强化学习奖励函数的5个核心实战技巧。内容涵盖奖励函数的结构化组合、轮腿混合机器人的适配策略、课程学习的动态调整、域随机化增强鲁棒性以及高效的调试可视化方法,旨在帮助开发者构建更稳定、高效的机器人运动策略。

lg888的博客 1065

dxf-viewer 查看器

dxf-viewer SDK 的示例,它是一个基于 Three.js 和 Vue3 构建的基于 WebGL 的 BIM 模型查看器。它用于查看 DWG/DXF/PDF 文件。面积测量 - 角度测量 -标记。

qq_25547755的博客 862

SystemVerilog如何优雅的提升FPGA开发效率

在传统 Verilog 中,always @(*) 是组合逻辑的标准写法,always @(posedge clk) 是时序逻辑的写法,但这些语句本身并不能明确表达“这段代码是组合逻辑”还是“时序逻辑”,综合工具必须猜测工程师的意图,可能导致不符合预期的综合结果。类似下面的代码,WAIT和DONE的值是相同的,显然这是错误的,但是verilog是无法检测出的,而使用enum,在编译时或者通过语法检查工具能立刻检查出来。• 其他赋值操作是非法的:除了上述规定的情况,任何其他的赋值操作都是非法的。

OpenFPGA的博客 556

ComfyUI-Impact-Subpack插件安装避坑指南:为什么你的UltralyticsDetectorProvider节点还是找不到?

本文深入解析了ComfyUI-Impact-Subpack插件的安装与排障问题,特别是针对UltralyticsDetectorProvider节点缺失的常见问题提供了详细的解决方案。从底层机制到高阶应用,涵盖了手动安装、模型配置、性能优化等关键步骤,帮助用户彻底解决插件依赖关系断裂问题。

Jerry的专栏 1150

FPGA中状态机实现:深度剖析三段式编码技巧

深入解析FPGA中状态机的三段式编码方法,结合数字电路与逻辑设计原理,提升代码可读性与综合效率,是掌握数字电路与逻辑设计的关键实践技巧。

weixin_30765637的博客 358

两层板如何做阻抗控制呢

两层板如何做阻抗控制呢? 这个问题可能很多人都会碰到,有的人在此等需要做阻抗控制的情况都选择做多层板。诚然,多层板在阻抗控制,EMC等等方面都有着天然的优势。然而,在价格上和周期上,两层板就有着绝对优势了。 对于成本非常敏感而又不是太复杂的产品,尽管对于我们硬件工程师而言,有一堆的理由要求使用多层板。然而在面对毛都不懂的老板“别人能做,你为什么不能做?”这个问题时只得低下我们高傲的头颅。 好...

weixin_42005993的博客 2万+

【TC3xx芯片】TC3xx芯片UCB详解

TC3xx芯片UCB详解

qq_36056498的博客 1万+

systemVerilog中case语句

always_comb begin x='0; y='0; z='0; case (1'b1) s1: begin x='1; y='1; z='1; end s2: begin x='2; y='2; z='2; end s3: begin x='3; y='3; z='3; end default: begin x='0; y='0; .

Leo ICer的博客 6959

汽车零部件产线实战:C#上位机+YOLO实现螺栓装配到位视觉检测

本项目基于C#上位机+YOLOv8实现汽车零部件产线螺栓装配到位视觉检测,全程贴合产线实际场景,从硬件选型、安装调试,到模型训练、上位机开发,再到项目联调、优化扩展,均提供手把手实操指导,代码可直接复制使用,规避了工业视觉产线检测的高频踩坑点。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1330

Verilog之case语句

verilog设计进阶 时间:2014年5月6日星期二   主要收获: 1.学会使用case语句; 2.学会使用随机函数$random。   $random: 1.函数说明:$random函数调用时返回一个32位的随机数,它是一个带符号的整形数。 2.产生0~59之间的随机数的例子: reg[23:0]rand; rand={$random}% 60; 3.产生一个在min

u012373020的专栏 8万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

【Arcanis the Omnipotent】从今天起弄明白case/casez/casex

还是来自一篇paper 分清楚case/casez/casex 在simulation/synthesis到底有什么不同 我基本就是照着翻译下来,基本没啥我总结的东西,因为消化的不好 首先,一般性的常识是使用casez,强烈的建议不要使用casex,(虽然我没有这个常识)。这是为啥呢?待续。 首先要明确的是'?'代表的不是don't care,而是'z'。这点一定要明确。 再有就是c...

weixin_30901729的博客 1266

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

第15章 SystemVerilog 断言示例

例1.  assert_nextstart_event是一个trigger,只有start_event成立,才会触发后面的sequence进行评估,等num_cks(常数)个clk后,test_expr得成立。例2.assert_no_underflowtest_expr等于最小值后一个时钟,test_expr&gt;=min(最小值),且小于某个极大值。例3.assert_bits判断bit[x...

XtremeDV 9812

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

芯片设计:verilog断言(SVA)语法

reference : http://blog.sina.com.cn/s/blog_4c270c730101f6mw.html     断言assertion被放在verilog设计中,方便在仿真时查看异常情况。当异常出现时,断言会报警。一般在数字电路设计中都要加入断言,断言占整个设计的比例应不少于30%。以下是断言的语法: 1. SVA的插入位置:在一个.v文件

limanjihe的专栏 2万+

FPGA学习(一)——LED点灯与开发流程

本文介绍了FPGA的基本概念及其在数字信号处理、通信、工业控制等领域的应用优势,强调其灵活性、并行性和集成性,同时指出其设计复杂度高、功耗较大等局限。随后以LED点灯为例,详细演示了基于Vivado的FPGA开发流程:创建工程、配置引脚约束、生成比特流文件,并通过仿真验证设计。重点展示了如何添加调试探针、连接硬件并实时观察信号,为初学者提供了完整的FPGA入门实践指南。

weixin_55136196的博客 82

FPGA与ASIC的区别详解:内部结构、开发成本与适用场景,项目选型到底该选哪个

FPGA与ASIC是数字芯片的两条根本路线:FPGA用可编程的LUT、触发器与布线网络在制造后还能改硬件,ASIC用标准单元把电路一次固化在硅上。本文讲清两者的内部结构、性能与功耗差距、NRE与单颗成本的交叉点,以及原型、小批量与大规模量产各自该选哪个,并回答GPU和CPU算不算ASIC这个常见问题。

sindwe的博客 334
上一篇: 握手协议在I2C中的应用
下一篇: 主流FPGA厂商对SystemVerilog的支持现状
GateWorld
博客等级 码龄2年 489粉丝 106原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值