首页 > 其他分享 >组合逻辑电路描述中采用阻塞赋值,时序逻辑用非阻塞赋值方式赋值

组合逻辑电路描述中采用阻塞赋值,时序逻辑用非阻塞赋值方式赋值

时间:2022-08-23 15:55:41浏览次数:90  
标签:p0 p1 用非 always 阻塞 描述 赋值

  对于VerilogHDL语言中,经常在always模块中,面临两种赋值方式:阻塞赋值和非阻塞赋值。

  对于初学者,往往非常迷惑这两种赋值方式的用法,本章节主要介绍这两种文章的用法。其实,有时候概念稍微不清楚,Bug就会找到我们,下面一文扫清阻塞赋值和非阻塞赋值所有的障碍。

 

 

基本概念

阻塞赋值(Blocking Assignment)

  阻塞赋值的基本描述格式为:[变量] = [逻辑表达式];

  阻塞赋值在执行的时候,右端表达式执行并赋值到左边变量,不会受任何情况打断。所以在本次赋值结束之前他“阻塞”了当前其他的赋值任务,阻塞赋值的操作和C语言中的变量赋值非常相似。

非阻塞赋值(Nonblocking assignment)

  非阻塞赋值的基本描述格式为:[变量] <= [逻辑表达式];

  非阻塞赋值行为有些细微之处比较难以理解。我们最好从硬件角度来理解,always模块可以被认为是纯硬件模块,当always模块被激活时,非阻塞赋值的右侧表达式就开始执行;当always模块所有表达式执行结束之后,所有执行结果才赋值到左侧变量当中。之所以称为“非阻塞”就是在本条赋值语句执行的过程中,其他赋值语句也可以执行。

 

在组合逻辑电路描述中采用阻塞赋值

  阻塞赋值和非阻塞赋值虽然都可以用来描述同一电路,以1位比较器举例来解释这种差别。

阻塞赋值实现1bit比较器

module eq1_block(input wire i0, i1,output reg ,eq);

  reg p0, p1;

  always @(i0,i1) // i0 和i1 在敏感量列表当中

          // 语句描述的顺序非常关键

  begin

    p0 = ~i0 & ~i1;

    p1 = i0 & i1;

  eq = p0 | p1;

  end

endmodule

  分析:程序中,敏感量列表中包含i0和i1,只要这两个变量有一个发生改变,都会激活always语句,那么p0、p1和eq就会顺序赋值,最终eq赋值就会被更新,所以这三条语句的描述顺序非常关键,假如将最后一条语句提前:

always @(i0,i1)

begin

  eq = p0 | p1;

  p0 = ~i0 & ~i1;

  p1 = i0 & i1;

end

  在第一条描述中,由于p0和p1还没有被赋予新值,所以p0和p1依然保持原来的赋值,这样得到的最终结果显然是错误的。

 

非阻塞赋值实现1bit比较器

module eq1_non_block(input wire i0, i1,output reg ,eq);

  reg p0, p1;

  always @(i0,i1,p0,p1) // p0, p1依然在敏感量列表中

              // 描述顺序无关紧要

  begin

    p0 <= ~i0 & ~i1;

    p1 <= i0 & i1;

    eq <= p0 | p1;

  end

endmodule

  分析:p0和p1包含在敏感量列表当中,当i0 或者 i1有所变化,always模块被激活,p0和p1在第一个时钟节拍结束时赋值,由于eq值为基于p0和p1原来保持值的赋值,所以eq不变,当前赋值结束时,always模块重新被激活,由于p0和p1被改变(这就是p0和p1放在敏感量列表中的原因),eq变量在第二个时钟节拍赋予了新值。从以上分析,即使将以上语句的顺序发生改变,也不会影响最终结果,因为eq的赋值以及always模块的激活与这些语句的顺序并没关系。

  总结:虽然两种描述方法都可以描述同一电路,但是两个电路的结果是有区别的,采用非阻塞赋值法描述仿真的时候花的时间更长一些,电路输出结果在时序上也有微弱差别,鉴于此,我们有这么一条原则“在组合逻辑电路描述中采用阻塞赋值”。

时序逻辑描述,采用非阻塞赋值方式赋值

  就单独一个寄存器来说,阻塞赋值和非阻塞赋值都可以描述存储单元,如DFF可以描述为

always@(posedge clk)

  q <= d;

也可以描述为

always@(posedge clk)

  q = d;

 

  但是当设计中存在多个寄存器描述单元的时候,就会有细微的查别,假设有两个寄存器在每个时钟的上升沿进行数据交换,采用阻塞赋值描述如下:

always@(posedge clk)

  a = b;

always@(posedge clk)

  b = a;

 

  在时钟的上升沿,两个always语句同时被激活并且并行执行,一个时钟节拍后两条语句执行结束,按照verilog语法标准,两个always语句执行结果时间顺序上谁都有可能在前面,这样一来,如果第一个always语句执行在前面,由于阻塞赋值,所以变量a立即得到b的赋值,那么当第二个always块执行之后,变量b得到a的赋值,由于刚才第一个always执行的时候b值赋予了a,所以现在b的值会维持不变,还是原来的值。

  同样的道理,如果第二个always模块先执行了,那么a就会保持自身值不变,从Verilog语法角度来看,两种结果都是有效的。但是从数字电路的角度来说,明显引起了竞争。

  下面我们将阻塞赋值修改为非阻塞赋值,以上代码修改为:

always@(posedge clk)

  a <= b;

always@(posedge clk)

  b <= a;

  采用非阻塞赋值,由于原始信号在赋值语句中使用,所以a和b都会得到正确的值,而与顺序没有关系。所以在时序逻辑描述中,阻塞赋值往往会引起条件竞争,所以要采用非阻塞赋值方式赋值。

总结一下

① 在组合逻辑电路描述中采用阻塞赋值

② 时序逻辑描述,采用非阻塞赋值方式赋值

标签:p0,p1,用非,always,阻塞,描述,赋值
From: https://www.cnblogs.com/6666y/p/16616545.html

相关文章

  • es6 class类中可以直接写赋值语句
    -classCar{//类中考科一直接写赋值语句,如下代码的含义是:给Car的实例对象添加一个属性,名为a,值为1a=1;b}console.log(Car);letc=newCar()console.log......
  • 阻塞非阻塞与同步异步的区别
    阻塞非阻塞与同步异步的区别同步/异步关注的是消息通知的机制,而阻塞/非阻塞关注的是程序(线程)等待消息通知时的状态。以小明下载文件打个比方,同步阻塞:小明一直盯着下载......
  • 2022.8.21 读写锁与阻塞队列
    9、读写锁   自定义的缓存,没有加锁,就会出现一个没有写入完成,另一个突然插进来的情况 packagecom.xing.rw; ​ importjava.util.HashMap; importjava.util.......
  • 日常学习(2)sv赋值、寻址方式、正则
    sv赋值方式sv的赋值方式可以采用.形参(参数)的方式,更清晰功能https://gitee.com/bai-mengwei/my_uart_tb/blob/11126a220e740ea070c128f1949078daaaf5cad7/uvm_tb/registe......
  • 阻塞和非阻塞
    阻塞和非阻塞阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关。也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的状态角度来说的。......
  • TSS结构赋值
    在进程切换过程中,需要一个结构体,在保护模式中,称为TSS.。在MenuetOS32系统中,加载应用,也就是进程时,用了如下的方式:;TSSmoveax,cr3......
  • 赋值运算符
    python中等号=是赋值运算符,而不是数学意义上的等于号。注意python解释器会先计算=右边的表达式,然后将结果赋值给=左边的变量。请始终记住这一点,初学者很容易理解错误。>>......
  • PYTHON错误——”赋值“ 和 ”拷贝“
    #关于自己写的代码有个逻辑没有问题,但是代码有问题的错误。本质上是关于“拷贝”和“赋值”的错误。#我想将每次大循环后x["x1"]的结果保存到a中。#即:a:[[0,1],[0......
  • 使用反射对实体类赋值
    JSON字符串{"data":{ "PD01":{ "KEY1":"1", "KEY2":"2", "KEY3":"3" }, "PD02":{ "KEY4":"4", "KEY5":"5&qu......
  • python3:面向对象之成员变量(成员变量赋值为元组、字典)
    python3:面向对象之成员变量(成员变量赋值为元组、字典)    一、python3源码  1#!/usr/bin/python323classdata:45#python是“弱类型......