首页 > 其他分享 >Verilog连续赋值、过程赋值、过程连续赋值总结

Verilog连续赋值、过程赋值、过程连续赋值总结

时间:2024-07-28 21:17:10浏览次数:14  
标签:Verilog always 阻塞 连续 time 赋值 d2 d1

最近总是遇到systemverilog的赋值问题,查看了一下手册发现SV的赋值方式总的还是继承了verilog的赋值方式,而且verilog赋值方面的资料比较多,所以就写了先写一篇关于verilog的赋值总结。

连续赋值

连续赋值就是一旦赋值,输出将随输入改变而变化,一旦修改输入则立刻体现在输出上。

input a,b;
wire out;

assign out = a & b;
  • 要求赋值左侧必须为net型
  • 关键词assign
  • 赋值过程类似于物理场景的导线连接,out将跟随a异或b的电路变化而变化,一旦a或b有修改则立刻体现在输出上。
  • 连续赋值属于并发执行,与书写顺序无关,不论在何时赋值都会在一开始执行。
  • 对于同一参数多次赋值,视情况和强度而定,但不要进行该操作。
  • 常用于组合逻辑

过程赋值

过程赋值只会在赋值时刻进行改变,其余时间保持不变,而且根据使用的赋值符号=<=,分为阻塞赋值和非阻塞赋值。

阻塞赋值 =

//例1
initial begin
      ai            = 4'd1 ; 	  	//(1)
      ai            = 4'd2 ;   		//(2)
      //ai 最此刻为 2
      #20 ;                    		//(3)
      ai            = 4'd3 ;     	//(4)
      bi            = 4'd4 ;     	//(5)
      value_blk     = ai + bi ;  	//(6)
      //value_blk 最终为7
        #40;
    end
  • 要求赋值左侧必须为reg、integer, real, time-variable, or memory(等非net型);
  • 赋值过程在initial或always块中;
  • 阻塞赋值类似于C语言的赋值方式,后面的赋值会覆盖掉前面的赋值,执行顺序为1->2->...->6,类似软件编程的赋值方式,随时赋值随时开始。
  • 最终结果与书写顺序相关.
  • 常用于testbench测试用例/组合逻辑.

非阻塞赋值 =>

//例1
initial begin
      ai            = 4'd1 ; 	  	//(1)
      bi            = 4'd2 ;   		//(2)
      //ai和bi的初始值分别为1,2
      #20 ;                    		//(3)
      //非阻塞赋值
      ai            <= 4'd3 ;     	//(4)
      bi            <= 4'd4 ;     	//(5)
      value_nonblk     <= ai + bi ;  	//(6)
      #40;
      //value_blk 最终为3
end

image

  • 要求赋值左侧必须为reg型
  • 关键词为initial或always
  • 非阻塞赋值类似于物理电路中的时序电路,其中可以这样理解代码执行顺序,1->2->3之后其他的非阻塞赋值(4)(5)(6)不着急执行,而是列入到"事件队列"中,一直存到#40需要被执行前,即下一个时刻需要执行前,(4)(5)(6)将会被同时执行,此时对于value_nonblk而言其对应的ai和bi依旧是1和2,因此结果为3,可用于时序电路建模。
  • 最终结果与书写顺序相关
  • 常用于时序逻辑

下面使用阻塞赋值和非阻塞分别描述构成的组合逻辑和时序逻辑。

module top_module(
input a, output reg out1, output reg out2);
always@(*)	begin
		out1 = a;       //a的值直接到out1
    out2 = out1;    //当前out1直接赋给out2
end                 //也就是说a的值直接out2
endmodule

阻塞赋值在always(*)块下,直接综合时形成了如下的组合逻辑电路。
image

module top_module(
input a, input clk, output reg out1, output reg out2);
always@(posedge clk)	begin
		out1 <= a;       //a的值赋给out1
    out2 <= out1;    //此时左侧的out1并不是a的大小,而是上一周期的值,因此这时是将上一周期的out1的值赋给out2
end                                                  
endmodule           

而非阻塞赋值在always(posedge clk)块下,在综合时形成了如下时序电路。
image

⚠️注意
虽然阻塞赋值always@(*) out_block = a & b;和连续赋值assign out = a & b;赋值方式不同,而且左侧采用的分别为reg类型和net类型,但最终综合出来却是一样的组合逻辑电路,都不会出现寄存器,这说明声明的类型与合成的硬件无关。
同样赋值过程并完全等同于硬件实现过程 always@(posedge clk) a <= 1;always@(posedge clk) a = 1; 两者也并没有区别,a作为输出都有寄存器的出现,也就是赋值方式与硬件实现过程并不相同这主要是Verilog语法的历史遗留问题, 只采用声明的类型和赋值方式很难区分,而systemverilog干脆直接用logic代替了wire和reg两种类型,对声明的类型不做区分【难办,难办就别办了~~】,因此了解综合后的硬件电路,要重点关注语法本身是组合还是时序。

因此作为一个ICer,不能为了炫技而采用各种花里胡哨的技巧,而是采用一些原则来保证自己的代码可以更便于观察。因此为了更清晰的描述出确定的电路, 在使用非阻塞与阻塞赋值时最好遵循以下原则:

  1. 时序电路建模时,使用非阻塞赋值 ;
  2. 锁存器电路建模时,使用非阻塞赋值 ;
  3. 使用always块写组合逻辑电路时,采用阻塞赋值;
  4. 在同一个always块中同时建立时序和组合逻辑电路时,用非阻塞赋值 ;
  5. 在同一个always块中不要同时使用非阻塞赋值和阻塞赋值 ;
  6. 不要在多个always块中,为一个变量赋值;
  7. 用$strobe系统任务来显示用非阻塞赋值的变量值;
  8. 在赋值时不要使用#0延迟【有时间了再去聊原因】;

遵循以上逻辑可以消除90%-100%的在仿真中产生的竞争冒险现象,有助于正确编写可综合硬件。
image


过程连续赋值

连续赋值通过assign语句驱动net类型变量,而过程赋值通过initial和always块驱动reg类型的变量。这两种驱动方式基本上可以构成常用的电路,但verilog又给出了一种赋值方式,即过程连续赋值,可以通过覆盖现有的赋值,并在一定时期内驱动net、reg数据变量。
主要有两对过程连续赋值:assign-deassignforce-release。但这种赋值方式最好不要用于设计,会使得代码难以理解,更多用于testbench,在测试时,为出现对应结果,将设计中某些必要的信号强制赋为期待值。

assign-deassign

assign通过在有一段时间内覆盖掉现有的过程赋值控制的reg变量的值。并在执行deassign之后,就会释放掉过程连续赋值,但可以保持一段时间,直到其他赋值进行修改。

module assign_deassign_ex;
  reg [3:0] d1;
  initial begin
    $monitor("At time T = %0t: d1 = %0d", $time, d1);
    d1 = 5;
    #20 d1 = 7;
  end
  
  initial begin
    #5;
    assign d1 = 3;	//直接覆盖掉d1从5->3
    #5 deassign d1; //d1释放之后,d1维持一段时间,在#20时刻从5变为7
    $display("At time T = %0t: deassign d1", $time);
  end
endmodule

//输出结果
At time T = 0: d1 = 5
At time T = 5: d1 = 3
At time T = 10: deassign d1
At time T = 20: d1 = 7

force-release

force 和 release 语句通过在一段时间内覆盖现有的过程、连续或过程连续赋值来控制 net 和 reg 数据类型变量值,force的权限比assign要高,可以覆盖掉其他的赋值方式。release同deassign一样,可以释放掉赋值,但对于过程赋值和过程连续赋值前可以保持前一个值。而对于net类型,直接恢复到前一个连续赋值的值。

module assign_deassign_ex;
  reg [3:0] d1;
  wire [3:0] d2;
  
  assign d2 = 2;
  initial begin
    $monitor("At time T = %0t: d1 = %0d, d2 = %0d", $time, d1, d2);
    d1 = 5;
    #20 d1 = 7;
  end
  
  initial begin
    #5;
    $display("At time T = %0t: force d1 and d2", $time);
    force d1 = 3;		//强制将d1赋值为3
    force d2 = 4;		//d2赋值为4
    #5 release d1;	//d1可以保持为3,一直到#20恢复为7
    release d2;			//d2一旦释放则恢复到2
    $display("At time T = %0t: release d1 and d2", $time);
  end
endmodule

//输出
At time T = 0: d1 = 5, d2 = 2
At time T = 5: force d1 and d2
At time T = 5: d1 = 3, d2 = 4
At time T = 10: release d1 and d2
At time T = 10: d1 = 3, d2 = 2
At time T = 20: d1 = 7, d2 = 2

参考文献
[1] Procedural continuous assignments - VLSI Verify-教程类
[2] Verilog Assignments-教程类
[3] Verilog 过程连续赋值-教程类
[4] How does SystemVerilog force work? -问答类

标签:Verilog,always,阻塞,连续,time,赋值,d2,d1
From: https://www.cnblogs.com/nullbeer/p/18196655

相关文章

  • c语言中给int类型变量赋值double型数值; 给double型变量赋值int型数据
      001、给int型变量赋值double型数据[root@PC1test]#lstest.c[root@PC1test]#cattest.c##测试程序#include<stdio.h>intmain(void){inti;i=8.583;printf("i=%d\n",i);//......
  • 通配连续性题目解法小结
    把所有经常写到的连续力扣罗列在这,对这种看上去比较复杂的题目总结一个普适性强的解法LeetCode603连续空余座位连续可用座位查找电影院所有连续可用座位,返回值按seat_id升序排列思路:WITHcinema_valid_seatAS(SELECTseat_id,seat_id+1ASnext_num,--5的......
  • Modelsim仿真实现Verilog HDL频率检测器
     检测输入信号的频率,输出8位数码显示,十进制。可以用于八段式数码管显示屏。1clk产生1Hz的方波,这是个很低的频率,被检测的频率都比这个高,因此,1个周期(即1s)内,可以有很多很多个signal的上升沿,只需要统计signal上升沿的数量,就可以算出signal的频率。在clk第1个上升沿发生后,令......
  • tableau如何计算一段连续时间的环比
    需求描述:如何用tableau计算一段连续时间的环比1、如图所示新建参数《开始时间》 2、如图所示新建参数《结束时间》 3、新建计算字段《本期金额》IF[订单日期]>=[开始时间]AND[订单日期]<=[结束时间]THEN[销售额]END 4、新建计算字段《上期金额》IF[订单日期......
  • 15 赋值、浅拷贝和深拷贝区别_is和==的区别
     欢迎来到@一夜看尽长安花博客,您的点赞和收藏是我持续发文的动力对于文章中出现的任何错误请大家批评指出,一定及时修改。有任何想要讨论的问题可联系我:[email protected]。发布文章的风格因专栏而异,均自成体系,不足之处请大家指正。   专栏:java全栈C&C++PythonAIP......
  • Verilog编程学习之—呼吸灯
    Verilog编程-呼吸灯1.设计目标用FPGA产生占空比变化的PWM波,控制LED灯由暗变亮的变化。2.设计思路设置PWM波的步长为2us,周期为2ms,每个周期内LED亮的时间由0增加至999,再从999减少至0,依次循环,就可以看到LED灯由暗变亮再由亮变暗的循环过程。可以设置一个占空比寄存器duty_r和一个......
  • 2024-07-27:用go语言,给定一个正整数数组,最开始可以对数组中的元素进行增加操作,每个元素
    2024-07-27:用go语言,给定一个正整数数组,最开始可以对数组中的元素进行增加操作,每个元素最多加1。然后从修改后的数组中选出一个或多个元素,使得这些元素排序后是连续的。要求找出最多可以选出的元素数量。输入:nums=[2,1,5,1,1]。输出:3。解释:我们将下标0和3处的元素增加1......
  • 水泥去铬剂在线给料失重秤连续计量喂料
    #水泥去铬添加剂在线给料失重秤连续计量喂料系统###引言在现代工业生产中,环境保护和生产效率是企业发展的关键因素。水泥生产过程中,去除有害重金属铬(Cr)是至关重要的一环,因为铬是一种致癌物质,对环境和人体健康有着极大的危害。为此,水泥去铬添加剂在线给料失重秤连续计量喂料......
  • 【Django】 js实现动态赋值、显示show隐藏hide效果
    文章目录需要达到的前端效果预览:实现步骤复制bootstrp代码(buttons)复制bootstrp代码(Alert警告框)写js测试效果需要达到的前端效果预览:{%loadstatic%}<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="......
  • 一下午连续故障两次,谁把我们接口堵死了?!
    唉。。。大家好,我是程序员鱼皮。又来跟着鱼皮学习线上事故的处理经验了喔!事故现场周一下午,我们的编程导航网站连续出现了两次故障,每次持续半小时左右,现象是用户无法正常加载网站,一直转圈圈。用户很快就在群里炸开锅了,甚至有用户表示“我提前进去了,都不敢刷新。。”看到......