阻塞赋值与非阻塞赋值

合集下载

阻塞赋值和非阻塞赋值的用法

阻塞赋值和非阻塞赋值的用法

阻塞赋值和非阻塞赋值的用法说到Verilog编程里的阻塞赋值和非阻塞赋值,哎呀,简直就是两个“冤家”。

你可能听说过它们,但是可能还没有搞清楚到底哪个是“王者”,哪个又是“二把手”。

阻塞赋值和非阻塞赋值就像是两种性格截然不同的人,碰到的情况不同,做的事也不一样,它们互不干涉,但又相互影响。

来聊聊阻塞赋值吧。

阻塞赋值就像你在厨房做饭时,先把锅里的菜炒熟,等菜完全做好了,你才能开始准备下一道菜。

明白了吧?它的特点就是按顺序执行,你要做完当前的事,下一件事才会开始,完全不会“跳过”什么。

比如在Verilog代码里,如果你写了一个“=`赋值语句”,那这个赋值语句就会“阻塞”当前进程,必须等这个赋值完成后,才会继续执行后面的操作。

所以,如果你把多个赋值语句写在一起,执行的顺序是很重要的!有时候你会发现,哎,这个赋值好像搞得我有点儿“慢慢吞吞”了。

对,没错,它就是这么不急不躁。

比方说你要计算一个信号值时,必须等上一个信号的值被计算出来,再处理下一个,这种“循序渐进”的方式就是阻塞赋值的代表作。

但是,说到非阻塞赋值,它就完全不一样了。

非阻塞赋值好像一个特别会multitasking(多任务处理)的家伙,啥事都不急,做得也不慢,反正一心二用,顾得了这边又能管得了那边。

在Verilog中,非阻塞赋值就是用“<=”来表示的。

它和阻塞赋值最大的区别就是:它不会等前一个赋值操作完成后才去做下一个,而是直接“放手一搏”,按自己的节奏走。

就好像你炒菜的时候,一边看着锅里的菜,另一边手里已经开始切别的蔬菜了。

这种“同步进行”的方式让你的代码看起来很高效,也能避免在一些需要并行执行的场景下,出现拖沓的情况。

你会发现非阻塞赋值让代码看起来好像更“灵活”一些。

因为它可以在同一时刻进行多个赋值操作,减少了等待的时间,所以特别适合那些需要并行处理的复杂设计。

想象一下,当你在做一台计算机模拟的设计时,非阻塞赋值就好比是一个多线程的系统,不停地切换工作,任何时候都能看似同时处理多个任务,而不会因为一个赋值的完成而停顿下来。

用一个例子来学习阻塞赋值和非阻塞赋值

用一个例子来学习阻塞赋值和非阻塞赋值

⽤⼀个例⼦来学习阻塞赋值和⾮阻塞赋值阻塞赋值与⾮阻塞赋值阻塞赋值的⼀般表达式为:⽬标变量名=驱动表达式 阻塞赋值是⼀种理想化的数据传输,赋值⽴即发⽣,不存在延时⾏为⾮阻塞赋值⼀般表达式为:⽬标变量名<=驱动表达式 ⾮阻塞赋值⽐较接近真实的电路⼯作状态,应为他从综合的⾓度考虑到了延时和并⾏性。

在过程启动中,⾮阻塞赋值使三条语句同时运⾏,⽽阻塞赋值是按顺序⽅式完成更新的数据的。

新建⼯程,编写⽰例代码module block_nonblock(clk,rst_n,a,b,c,out );input clk,rst_n,a,b,c;output reg [1:0]out;//out=a+b+c>2,所以out 应该为2位reg [1:0] d;//定义⼀个中间变量//d=a+b ;//out=d+calways @(posedge clk or negedge rst_n)if (!rst_n)out =2'b0;else begind =a+b;out =d+c;endendmodule从RTL 视图可以看出整个运⾏过程是顺序执⾏的。

改变d=a+b;out=d+c;的赋值顺序,再观察RTL视图,会发现两者之间是有区别的,这说明顺序决定着输出的结果。

将赋值语句改为⾮阻塞赋值。

观察RTL视图,会发现两者是有明显不同。

同样的改变d<=a+b;out<=d+c;的赋值顺序,再观察RTL视图,会发现两者之间是没有区别的,这说明顺序并没有决定输出的结果。

由RTL图理论上可以看出两种赋值语句的不同,下⾯编写testbench进⾏仿真。

`timescale 1ns/1nsmodule block_nonblock_tb;`define clock_period 20reg clock,rst_n,a,b,c;wire [1:0] out ;block_nonblock block_nonblock0(clock,rst_n,a,b,c,out );//这⾥采⽤⼀⼀对应的调⽤⽅式initial clock=1'b0;always#(`clock_period/2) clock=~clock;//产⽣时钟信号initial beginrst_n=1'b0;a=0;b=0;c=0; //赋值激励信号#(`clock_period*200+1)rst_n=1'b1;a=0;b=0;c=1;#(`clock_period*200)a=0;b=1;c=0;#(`clock_period*200)a=0;b=1;c=1;#(`clock_period*200)a=1;b=0;c=0;#(`clock_period*200)a=1;b=0;c=1;#(`clock_period*200)a=1;b=1;c=0;#(`clock_period*200)a=1;b=1;c=1;#(`clock_period*200)#(`clock_period*200)$stop;endendmodule设定⽂件路径后按前⾯的四个程序进⾏前仿。

EDA

EDA

一、填空1、阻塞和非阻塞的区别阻塞性赋值“=”仅适用于过程结构含义:在当前的赋值操作完成前阻塞,或停止语句的执行顺序赋值的特点非阻塞性赋值“<=”同步赋值操作,具有并行执行的特点举例:课本172页2、always 和initial语句,reg和wire的区分initial语句不可综合,主要用于仿真程序中的初始化always 语句属于可综合语句,主要引导行为描述语句initial过程语句结构没有敏感信号列表,即不带触发条件always 过程语句要求将过程语句中的所有输入信号都放在敏感信号列表中initial过程中的块语句沿时间方向轴只执行一次always 可以自动执行无限次3、设计流程系统级描述(C语言,MATLAB语言)|行为级/RTL(HDL语言描述)|综合工具→结构级描述/网表←元件库|自动化工具电路/MOS管|物理版图4、未声明的信号,默认为wire;多bit信号必须声明wire5、多bit数据,wire [3:0]6、标识符(信号名,模块符)首字母不能是数字7、并行语句(assign,initial);串行语句(case,if else)8、FPGA(LET)和CPLD(与非阵列)如何实现可编程FPGA的编程是基于SRAM查找表的编程单元;掉电后编程信息立即丢失。

CPLD是基于电可擦除存储单元的EEPROM或Flash技术。

9、触发器和锁存器的区别触发器是边沿触发锁存器是电平触发10、触发器没有复位,初始状态为X11、同步和异步的区别及电路图12、timescale`timescale 1ns/1ps 1ns属于仿真时间单位 1ps属于精度13、什么是寄存器传输级设计14、综合的概念15、什么情况会综合出锁存器参考50页不完整的条件分支和不完整的输出赋值会导致综合出锁存器(解决办法:保证任何情况所有变量都被赋值cas语句不能覆盖所有取值)16、查找表电路的工作原理17、速度优化和面积(资源)优化举例速度优化:1.流水线2.寄存器配平3.关键路径法4.乒乓操作面积优化:1.资源共享2.逻辑优化3.串行化二、程序题(3道挖空,6道自己写,其中4道需写tb.v)1、半加器118页2、全加器119页ain 加数bin 被加数cin 进位输入sum 值输出cout 进位输出3、二选一多位选择器(assign描述,if-else描述,case描述)if语句52页5、计数器(4位十进制计数器)加法计数器47页 60页6、移位寄存器(左右移,带同步置位功能)116页 62页8、状态机(给状态转移图)212页9、同步(清零,置位)触发器;异步(清零,置位)触发器设计56/57知识点:⏹基本方式:模块名调用名(端口名表项)➢调用方式一:位置对应调用,位置关联module h_adder(a, b, so, co);h_adder u1(ain, bin, e, d );➢调用方式二:端口名对应调用,端口名关联h_adder u1(.a(ain), .so(e), .b(bin), .co(d));使用层次式方法,用VerilogHDL描述一个完整的全加器电路。

阻塞赋值和非阻塞赋值深度解析——仿真事件的调度

阻塞赋值和非阻塞赋值深度解析——仿真事件的调度

阻塞赋值和⾮阻塞赋值深度解析——仿真事件的调度来源:EETOP BLOG 作者:acgoal/blog/html/46/553746-51456.html下⾯有⼀段verilog代码和仿真⽂件,⽤的是VCS仿真和编译⼯具。

我们来研究⼀下不同的驱动赋值⽅式对仿真结果的影响。

下⾯我把我做的例⼦和⼤家分享⼀下。

设计源代码如下:`timescale 1ns/1psmodule counter (data_out0, data_out1,clk,rst_n, data_in0, data_in1);output[3:0] data_out0;output [3:0] data_out1;input [3:0] data_in0;input [3:0] data_in1;input clk;inputrst_n;reg [3:0] data_out0;reg [3:0] data_out1;always @(posedge clk or negedge rst_n)begin if(!rst_n) begin data_out0 <= 4'd0; end else begin data_out0 <=data_in0; endendalways @(posedge clk) begin if(!rst_n) begin data_out1 <= 4'd0; end elsebegin data_out1 <= data_in1; endendendmodule这⾥有两段,分别表⽰带异步复位和带同步复位的。

测试程序如下:`timescale 1ns/1psmodule tb_top;reg clk;reg rst_n;wire [3:0] data_out0;wire [3:0] data_out1;reg[3:0] data_in0;reg [3:0] data_in1;counter u_counter0(.clk(clk), .rst_n(rst_n),.data_out0(data_out0), .data_out1(data_out1), .data_in0(data_in0),.data_in1(data_in1));initial begin clk=1'b0;endalways begin #3 clk=~clk;endinitial begin rst_n= 1'b1; #15 rst_n = 1'b0; #180 rst_n = 1'b1; #200 $finish;endinitial begin data_in0 <= 0;wait(!rst_n); wait(rst_n); @(posedge clk); data_in0 <= 1; @(posedge clk); data_in0 <= 2;@(posedge clk); data_in0 <= 4; @(posedge clk); data_in0 <= 8; @(posedge clk); data_in0<= 0;endinitial begin data_in1 <= 0; wait(!rst_n); wait(rst_n); @(posedge clk); data_in1 <= 1;@(posedge clk); data_in1 <= 2; @(posedge clk); data_in1 <= 4; @(posedge clk); data_in1<= 8; @(posedge clk); data_in1 <= 0;endinitial begin $vcdpluson();endendmodule注意这⾥红⾊的部分,data0和data1的驱动都⽤⾮阻塞赋值。

Verilog_HDL中阻塞赋值与非阻塞赋值的区别与应用

Verilog_HDL中阻塞赋值与非阻塞赋值的区别与应用

Verilog HDL中阻塞赋值与非阻塞赋值的区别与应用张文波摘要:Verilog HDL语言是世界上应用最广泛的硬件描述语言之一。

在Verilog HDL语言中最容易混淆的概念之一就是阻塞赋值与非阻塞赋值,甚至一些非常有经验的Verilog HDL设计师也不能完全理解为什么和什么时候使用阻塞赋值和非阻塞赋值。

本文详细阐述了阻塞赋值与非阻塞赋值的概念和区别,通过仿真和举例进一步解释了阻塞赋值与非阻塞赋值在工程中的典型应用和技巧。

本文中的所有程序代码,在ISE10.1应用软件中均测试通过,可以直接引用。

关键词:阻塞赋值;非阻塞赋值;仿真中图分类号:TP368文献标识码:The Difference and Application of Blocking assignment and Nonblocking assignment in Verilog HDLZHANG Wen-bo(China Airboren Missile Academy, Henan Luoyang 471000, China)ABSTRACT:In the world,one of the most extensive hardware description language is Verilog HDL.One of the most misunderstood constructs in the Verilog language is the blocking assignment and nonblocking assignment,even very experienced Verilog designers do not understand when and why blocking assignment and nonblocking assignment should be used.This paper details the difference and the constructs of the blocking assignment and nonblocking assignment,and makes a further explanation about the typical application and skills whit the simulation and examples.In this paper,all of the code were validated by ISE10.1.KEYWORDS:blocking assignment; nonblocking assignment; simulation1 引言Verilog HDL语言是目前世界上最流行的硬件描述语言之一,被广泛的应用于基于可编程逻辑器件的项目开发。

VHDL非阻塞赋值理解(转载)

VHDL非阻塞赋值理解(转载)

在always语句块中,verilog语言支持两种类型的赋值:阻塞赋值和非阻塞赋值。

阻塞赋值使用“=”语句;非阻塞赋值使用“<=”语句。

注意,千万不要将这两种赋值方法与assign赋值语句混淆起来,assign赋值语句根本不允许出现在always语句块中。

位于begin/end块内的多条阻塞赋值语句是串行执行的,这一点同标准的程序设计语言是相同的。

但是多条非阻塞赋值语句却是并行执行的,这些非阻塞赋值语句都会在其中任何一条语句执行完成之前开始执行。

这正是硬件电路的特点,因为实际的逻辑门电路都是独立运转的,而不是等到其他门电路运转结束之后自己才开始运转。

下面我们以描述移位寄存器的两种方法为例来讲述两种赋值类型的区别。

在下面的这种描述中,第一个触发器中的数据被移到第二个触发器中,第二个触发器中的数据被移到第三个触发器中……如此继续下去,直到最后一个触发器中的数据被移出该寄存器为止。

1module shiftreg (input clk,2input sin,3outout reg [3:0]q);//这是正确使用非阻塞赋值的实例4a lways @(posedge clk)5b egin6q[0] <= sin;//非阻塞赋值:<=7q[1] <= q[0];8q[2] <= q[1]9q[3] <= q[2];10//这里写作q <= {q[2:0],sin};更简单更好一些11e nd12endmodule非阻塞赋值语句的功能是使得所有语句右侧变量的值都同时被赋给左侧的变量。

因此,在上面的实例中,q[1]得到的是q[0]的原始值,而非sin的值(在第一条语句中,sin的值被赋给了q[0])。

这正是我们期望得到的实际硬件电路。

当然,我们可以把上边的四条语句合并写成一条简短的语句:q<={q[2:0],sin}。

阻塞赋值语句的功能更接近于传统的程序设计语言,但是阻塞赋值语句并不是准确的硬件工作模型。

阻塞和非阻塞赋值语句的用法

阻塞和非阻塞赋值语句的用法

例1和例2的RTL Viewer
例1和例2的仿真波形
非阻塞赋值语句也是出现在initial和always块语 句中,赋值符号是“<=”,格式为 赋值变量 <= 表达式;
在非阻塞赋值语句中,赋值号“<=”左边的赋值 变量也必须是reg型变量,其值不象在过程赋值 语句那样,语句结束时即刻得到,而在该块语句 结束才可得到。
建议:在时序逻辑电路的设计中,采用非阻塞型 赋值语句
always @(posedge clock)
m = 3;
n = 75;
ቤተ መጻሕፍቲ ባይዱ
n <= m;
r = n; 语句执行结束后,r的值是75,而不是3,因为第3行 是非阻塞赋值语句“n <= m”,该语句要等到本块语 句结束时,n的值才能改变。
2016/12/5 5
非阻塞式赋值语句与阻塞式赋值语句
例 1: module DDF3(clk,D,Q); input clk,D; output reg Q; reg a,b; always@(posedge clk) begin a<=D; b<=a; Q<=b; end endmodule 例 2: module DFF3(clk,D,Q); input clk,D; output reg Q; reg a,b; always@(posedge clk) begin a=D; b=a; Q=b; end endmodule
非阻塞式赋值
在过程语句中,比较接近真实的电路赋值 和输出。 有一个特殊的延时操作,而且在赋值过程 中不影响其它同类语句的赋值操作。 同阻塞式赋值一样,允许对同一目标信号 多次赋值或驱动。Verilog规定,被赋值 的目标变量接受最接近过程结束的那一个 驱动源的数据。

Verilog中阻塞与非阻塞的区别

Verilog中阻塞与非阻塞的区别

从上面的例子中,我们可以看出,在阻塞赋值语句中,赋值的次序非常重要,而在非阻塞赋值语句中,赋值的次序并不重要。

下面我们具体分析一下阻塞和非阻塞赋值的语义本质:阻塞:在本语句中“右式计算”和“左式更新”完全完成之后,才开始执行下一条语句;非阻塞:当前语句的执行不会阻塞下一语句的执行。

先看阻塞赋值的情况:我们来看这段代码:always @(posedge Clk)beginQ1 = D;Q2 = Q1;Q3 = Q2;endalways语句块对Clk的上升沿敏感,当发生Clk 0~1的跳变时,执行该always语句。

在begin...end语句块中所有语句是顺序执行的,而且最关键的是,阻塞赋值是在本语句中“右式计算”和“左式更新”完全完成之后,才开始执行下一条语句的。

在本例中,D的值赋给Q1以后,再执行Q2 = Q1;同样在Q2的值更新以后,才执行Q 3 = Q2。

这样,最终的计算结果就是Q3 = D。

所有的语句执行完以后,该always语句等待Clk的上升沿,从而再一次触发begin...end 语句。

接下来,再看看非阻塞赋值的情况。

所谓非阻塞赋值,顾名思义,就是指当前语句的执行不会阻塞下一语句的执行。

always @(posedge Clk)beginQ1 <= D;Q2 <= Q1;Q3 <= Q2;end首先执行Q1 <= D,产生一个更新事件,将D的当前值赋给Q1,但是这个赋值过程并没有立刻执行,而是在事件队列中处于等待状态。

然后执行Q2 <= Q1,同样产生一个更新事件,将Q1的当前值(注意上一语句中将D值赋给Q1的过程并没有完成,Q1还是旧值)赋给Q2,这个赋值事件也将在事件队列中处于等待状态。

再执行Q3 <= Q2,产生一个更新事件,将Q2的当前值赋给Q3,这个赋值事件也将在事件队列中等待执行。

这时always语句块执行完成,开始对下一个Clk上升沿敏感。

FPGA学习系列:5.阻塞赋值与非阻塞赋值

FPGA学习系列:5.阻塞赋值与非阻塞赋值
8
9 always @ (posedge clk)
10 begin
11 if(!rst_n) //复位时用非阻塞给寄存器输出赋初值
12 begin
13 q1 <= 0;
14 q <= 0;
15 end
16 else //非阻塞语句进行赋值
17 begin
18 q1 <= d;
19 q <= q1;
20 end
1
2 module tb;
3
4 reg clk;
5 reg rst_n;
6 reg [1:0] d;
7 wire [1:0] q;
8
9 initial begin
10 clk = 1;
11 rst_n = 0;
12 d = 0;
13
14 #200.1 rst_n = 1;
15
16 #100 d = 2;
1 //输入输出端口
2 input clk;
3 input rst_n;
4 input [1:0] d;
5 output reg [1:0] q;
6
7 reg [1:0] q1; //定义一个寄存器
8
9 always @ (posedge clk)
10 begin
11 if(!rst_n) //复位时用阻塞给寄存器输出赋初值
17 #100 d = 0;
18
19 end
20
21 always #10 clk = ~clk;
22
23 study_4 dut(
24 .clk(clk),
25 .rst_n(rst_n),
26 .d(d),

EDA练习题

EDA练习题

1. 用EDA技术进行电子系统设计的目标是最终完成专用集成电路(asic)或印制电路板(pcb)的设计与实现。

2. 可编程器件分为简单PLD 和复杂PLD 。

3. 简要说明仿真时阻塞赋值与非阻塞赋值的区别。

答:阻塞式赋值:是一种理想化的数据传输,是立即发生的,不存在任何的延时行为。

表述方式目标变量名=驱动表达式;非阻塞式赋值:是比较真实的电路赋值和输出,因为它从综合的角度考虑到了延时和并行性。

表述方式目标变量名<=驱动表达式;4. 试用Verilog HDL描述一个带进位输入、输出的8位全加器。

端口:A、B为加数,CI为进位输入,S为和,CO为进位输出。

module ADDER8B (A,B,CI,CO,S);output [7:0] S; output CO;input [7:0]A,B; input CI;assign {CO,S} = A + B + CI;endmodule1. 随着EDA技术的不断完善与成熟,自顶向下的设计方法更多的被应用于Verilog HDL 设计当中。

2.写出下列缩写的中文含义:ASIC:专用集成电路RTL:寄存器传送FPGA:现场可编程门阵列CPLD:复杂可编程逻辑器件EDA:电子设计自动化IP:知识产权核3. module AAA( a ,b );input [6:0] b ;定义七位二进制b为输入端口output a ;定义一位二进制a为输入端口reg[2:0] sum; 定义三位二进制sum为寄存器类型integer i; 定义一位二进制i为整数类型reg a 定义一位二进制a为寄存器类型always @ (b) 定义以b为敏感信号的过程语句begin 开始块语句sum = 0; 给sum赋值为0for(i = 0;i<=6;i = i+1) 次数为7的for循环语句if(b[i]) sum = sum+1; 查询并记录二进制数b中含1的数目并赋值给sumif(sum[2]) a = 1; 当sum值大于等于4时a赋值为1else a = 0; 当不满足上述情况时a赋值为0end 结束块语句endmodule 模块结束语句本程序的逻辑功能是:7人投票表决器4. 编写一个带异步清零、异步置位的D触发器。

深入理解阻塞和非阻塞赋值

深入理解阻塞和非阻塞赋值
在阻塞赋值中,赋值操作是顺序执行 的,即先计算等号右边的表达式,再 将结果赋值给左边的变量。
阻塞赋值的特点
顺序执行
阻塞赋值是顺序执行的,先计算等号右边的表达式,再将结果赋 值给左边的变量。
等待完成
阻塞赋值会等待赋值操作完成后再继续执行后续的代码。
适合简单赋值场景
阻塞赋值适用于简单的赋值场景,如将一个常量赋值给变量。
非阻塞赋值的含义
01
非阻塞赋值是指在进行赋值操作时,不会阻塞程序的执行流程,赋值操作会在 后台异步进行。
02
在非阻塞赋值中,赋值语句的执行不会等待赋值操作完成,而是立即返回,继 续执行后续的代码。
03
非阻塞赋值通常用于需要同时进行多个操作的情况,例如在多线程编程中,多 个线程同时进行数据更新时,可以使用非阻塞赋值来避免线程间的竞争和死锁 。
适用场景比较
阻塞赋值
阻塞赋值适用于需要保护共享变量免受并发修改影响的场景。例如,当多个线程需要同时读取共享变量,但只有 特定线程需要写入时,阻塞赋值可以确保数据的一致性和完整性。
非阻塞赋值
非阻塞赋值适用于需要最大化并发性能的场景。例如,在高性能计算或实时系统中,非阻塞赋值可以减少线程之 间的竞争和上下文切换,从而提高整体性能。
06
总结与展望
对阻塞赋值和非阻塞赋值的总结
01 02
阻塞赋值
在阻塞赋值中,当一个线程对共享变量进行写操作时,其 他线程必须等待直到该线程完成写操作,才能对共享变量 进行读或写操作。这确保了数据的一致性和同步性,但可 能导致线程阻塞和性能下降。
非阻塞赋值
非阻塞赋值允许线程在不等待其他线程完成写操作的情况 下对共享变量进行读或写操作。这样可以提高并发性能, 但可能导致数据不一致或竞争条件。

modelsim 阻塞赋值 非阻塞赋值

modelsim 阻塞赋值 非阻塞赋值

modelsim 阻塞赋值非阻塞赋值摘要:1.模型仿真(ModelSim)概述2.阻塞赋值与非阻塞赋值的概念3.阻塞赋值的应用场景与实例4.非阻塞赋值的应用场景与实例5.阻塞赋值与非阻塞赋值的优缺点比较6.结论正文:一、模型仿真(ModelSim)概述模型仿真(ModelSim)是一种针对数字系统、嵌入式系统及混合信号系统进行验证、仿真和测试的工具。

它能够对硬件描述语言(HDL)进行编译,生成可在仿真环境中运行的模型,从而对设计进行功能验证和性能分析。

在ModelSim 中,赋值操作是模型仿真过程中的基本操作之一,它用于将一个值赋给一个变量。

根据赋值操作的执行方式,我们可以将其分为阻塞赋值和非阻塞赋值两种。

二、阻塞赋值与非阻塞赋值的概念1.阻塞赋值:阻塞赋值是指在赋值操作执行过程中,程序将暂停执行其他任务,直至赋值操作完成。

在阻塞赋值期间,程序不会响应其他事件,也不会执行其他任务。

2.非阻塞赋值:非阻塞赋值是指在赋值操作执行过程中,程序不会暂停执行其他任务。

非阻塞赋值允许程序在赋值操作进行的同时,执行其他任务。

当赋值操作完成后,程序会继续执行原先的任务。

三、阻塞赋值的应用场景与实例阻塞赋值通常用于对变量的初始化以及对敏感元件的赋值等场景。

以下是一个阻塞赋值的实例:```verilogreg a = 0;initial begina = 5;end```在这个例子中,变量a 被声明为寄存器类型,并初始化为0。

在initial 块中,将a 赋值为5。

在这个过程中,程序将暂停执行其他任务,直至赋值操作完成。

四、非阻塞赋值的应用场景与实例非阻塞赋值通常用于在循环过程中对变量进行更新,或在需要实时响应的事件中进行赋值等场景。

以下是一个非阻塞赋值的实例:```verilogreg a = 0;always @(posedge clk) begina <= a + 1;end```在这个例子中,变量a 被声明为寄存器类型。

非阻塞赋值和阻塞赋值

非阻塞赋值和阻塞赋值

非阻塞赋值和阻塞赋值非阻塞赋值和阻塞赋值,听起来像个程序员的外星语,别担心,咱们慢慢来聊聊,保证让你明白得通透透。

想象一下,你在厨房忙得不可开交,家里一堆事情等着你去做。

这个时候,非阻塞赋值就像一个聪明的助手,你给了他一个任务,他就会立刻去做,根本不管你有没有空。

你可以继续切菜,煮汤,甚至顺便打个电话,反正这位助手会自动完成他的工作,等他做好了再告诉你。

就这么简单。

你心里想着,哎,这个助手真不错,我可以省出好多时间来。

再说说阻塞赋值,这就有点儿像你的亲戚来访,非得跟你聊个痛快,才能离开。

你一边听着他滔滔不绝,心里想着还有一大堆事情没做,完全无法分身。

这个过程就像程序里的阻塞赋值,你要等到这个亲戚说完,才能继续做自己的事。

可能你心里已经默念无数遍“快点吧,赶紧聊完”,可是他就是不知好歹,唠唠叨叨。

哦,生活就是这样,有些时候你只能耐心等待,没办法。

我们再深入聊聊,非阻塞赋值在实际应用中就像你在跑步机上健身。

你可以同时做很多事情,放歌、看视频,甚至吃零食,根本不影响你跑步的节奏。

程序执行的时候,可以同时进行多个操作,效率极高,简直像飞一样。

那种爽快感,仿佛自己是个超人,可以处理无数任务而不觉得累。

但是,前提是你得有个好心态,不然就容易分心了,这时候就得小心了,跑步机可不会等你。

反观阻塞赋值,咱们就得把这比作在电影院看电影。

你得等着前面的广告结束,才能看到你想看的剧情,心里那种着急感,简直要炸了。

好不容易等到广告结束,你才终于能看到精彩的片段。

就像程序里,某个任务必须完成,才能进行下一个,这个时候你就得耐心等待。

虽然有时候觉得无聊,但也好比是人生的一种沉淀,等到对的时机,所有的努力都能水到渠成。

聊到这儿,有趣的是,非阻塞和阻塞赋值在实际编程中其实是相辅相成的。

你可以选择在合适的时候用非阻塞赋值,让自己轻松应对更多任务;又能在某些关键时刻用阻塞赋值,确保数据的一致性。

两者之间的平衡,就像生活中的甜与咸,缺一不可。

阻塞赋值与非阻塞赋值

阻塞赋值与非阻塞赋值

阻塞赋值与⾮阻塞赋值内容阻塞赋值VS⾮阻塞赋值有两种赋值语句被⽤在always块内:阻塞赋值与⾮阻塞赋值。

关于阻塞与⾮阻塞复制有3条简单的准则:将电路分为两部分:寄存器电路和组合电路在寄存器电路中使⽤⾮阻塞赋值在组合电路中使⽤阻塞赋值1 概览阻塞赋值基本语法如下:1[var] = [expression];当该条语句被执⾏时,右⼿边的表达式将被赋给左⼿边的变量,期间不允许其他语句的⼲扰。

因此,就阻塞了其他语句,直到该条语句执⾏完毕为⽌。

阻塞赋值的⾏为与C语⾔中的变量赋值类似。

⾮阻塞赋值基本语法如下:1[var] <= [expression];⾮阻塞赋值的⾏为⾮常令⼈难以琢磨。

当always块被激活(在time step的开始),右⼿边的表达式被赋初值。

当运⾏到always块的结尾(即time step的结尾),运算所得的值被赋给左⼿边的变量。

以x变量执⾏⾮阻塞赋值为例。

因为Verilog模型的实际流程⽐较复杂,我们将⾮阻塞赋值的⾏为翻译成⼀下⼏个步骤:在alway块的开始,x值传递给x_entry;右⼿边的变量x的值被x_entry取代;左⼿边变量x的值被x_exit取代;在always块的结束,x_exit的值传递给x。

在下⾯的代码⽚段内,上述四个步骤被呈现在代码的注释中。

1 2 3 4 5always@*begin// x_entry = xy <= x & ... // y = x_entry & ... x <= ... // x_exit = ...end// x = x_exit范例为了了解阻塞赋值和⾮阻塞赋值的区别,我们⽤三输⼊的的电路来做讨论。

代码1 使⽤阻塞赋值的电路12 3 4 5 6 7 8 9 10 11 12 13 14 15module and_blocking (input a,input b,input c,output reg y);always@*beginy = a;y = y & b;y = y & c;endendmodule1516阻塞赋值的欣慰类似于C语⾔中的顺序赋值。

verilog赋值原则之阻塞赋值与非阻塞赋值

verilog赋值原则之阻塞赋值与非阻塞赋值

verilog赋值原则之阻塞赋值与⾮阻塞赋值⼀. 阻塞赋值与⾮阻塞赋值的区别阻塞赋值(Blocking)符号为“ = ”,如:b = a ;可以认为是只有⼀个步骤的操作,计算RHS(等号右边)并更新LHS(等号左边),和C语⾔的赋值很类似。

其中“阻塞”⼆字的意思是在同⼀个块语句中,后⾯的赋值语句是在前⼀个语句赋值结束后才开始赋值的。

⾮阻塞赋值(Non_blocking)符号为“ <= ”,如:b <= a ;当⼀个块语句中有多条赋值语句时,同时计算RHS,计算完成后同时更新LHS。

举⼀个例⼦:`timescale 1ns/1nsmodule blocking ();reg[1:0] a,b,c;initial begina = 2'd1;b = 2'd2;c = 2'd3;#10a = 2'd0;b = a;c = b;$display("a=%d b=%d c=%d ",a,b,c);endendmodule运⾏结果为:若将上述代码的阻塞赋值都改为⾮阻塞赋值,则运⾏结果为:⼆. 赋值原则1. ⾮阻塞赋值只能⽤于寄存器型变量,只能在initial块和always块中使⽤。

阻塞赋值既可以⽤于寄存器型变量,也可以⽤于线⽹型变量。

2. 通常在设计可综合的RTL代码时,描述组合逻辑⽤阻塞赋值,描述时序逻辑⽤⾮阻塞赋值。

3. 在同⼀个块语句中描述组合逻辑和时序逻辑的混合逻辑时,⽤⾮阻塞赋值。

4. 尽量不要在同⼀个always块中同时使⽤阻塞赋值和⾮阻塞赋值。

5. 不能在多个always块中对同⼀个变量进⾏赋值(如果⽤两个always块对同⼀个变量赋值,⽆论其中经过了怎样的条件判断,最终都相当于将两个触发信号连在同⼀个寄存器的CLK端,这显然不合符数字逻辑电路的规则,这样的代码在综合时会报错)。

区分阻塞赋值与非阻塞赋值

区分阻塞赋值与非阻塞赋值

区分阻塞赋值与非阻塞赋值阻塞赋值与非阻塞赋值的区别1.阻塞型过程赋值语句:用“=”标识;在顺序块中(begin-end语句块)内的各条阻塞型赋值语句将以它们在顺序块中的排列先后次序得到执行,在并行块中(fork-join块)内的各条阻塞过程赋值语句则是同时得到执行的;阻塞型过程赋值语句的执行过程是:首先计算右边赋值表达式的取值,然后立即将计算结果赋值给“=”左端的赋值变量。

2.非阻塞型过程赋值语句:用“<=”标识;在(begin-end)顺序块中,一条非阻塞型过程赋值语句的执行不会阻塞下一条语句的执行,即在本条非阻塞型过程赋值语句对应的赋值操作执行完毕之前,下一条语句也可以开始执行;非阻塞赋值过程赋值语句首先计算其右端赋值表达式的值,然后要等到当前仿真时间结束再将该计算结果赋值给被赋值变量,即非阻塞过程赋值语句的赋值操作是在同一仿真时刻上的其他普通操作结束之后才得到执行的。

例:module nonblocking_assignment_test;reg a;initialbegina<=0;a<=#51;a<=#100;a<=#151;a<=#300;a<=#101;endendmodule所示的延时操作都是在确定的仿真时刻执行。

“非阻塞过程赋值语句”经典例题:module multiple1;reg a;initial a=0;initialbegina<=#100;//在t=10时刻,给变量a赋值0a<=#101;//在t=10时刻,给变量a赋值1end//在t=10时刻,变量a的最终取值为1endmodule说明:如果在同一个过程块内使用多条非阻塞型过程赋值语句对同一变量赋值(时间延迟相同),则被赋值变量的最终取值是确定的,且由过程块的最后一条非阻塞型过程赋值语句决定。

module multiple2;reg a;initial a=1;initial#8a<=#81;//语句S1,在t=8时刻执行该语句,在t=16时刻给变量a赋值1initial#12a<=#40;//语句S2,在t=12时刻执行该语句,在t=16时刻给变量a赋值0endmodule说明:语句S1和S2在t=16时刻都对变量a进行赋值操作,但是由于语句S2的执行时间晚于语句S1,所以变量a的最终取值由语句S2决定。

sv阻塞赋值和非阻塞赋值

sv阻塞赋值和非阻塞赋值

sv阻塞赋值和非阻塞赋值1. 引言在硬件描述语言(HDL)中,阻塞赋值和非阻塞赋值是两种常见的赋值方式。

这两种方式在行为和实现上有一些区别,对于设计和模拟电路的工程师来说,理解它们的差异非常重要。

本文将详细介绍sv阻塞赋值和非阻塞赋值的概念、用法以及它们之间的区别。

2. sv阻塞赋值2.1 概念sv阻塞赋值是一种顺序执行的赋值方式,它在执行过程中会阻塞后续的代码执行,直到当前赋值完成。

在sv中,阻塞赋值使用“=”符号进行赋值操作。

2.2 用法sv阻塞赋值通常用于描述组合逻辑电路,其中信号的赋值会立即生效。

下面是一个简单的例子,展示了sv阻塞赋值的用法:module blocking_assignment;reg a, b;wire c;always @(a or b)beginc = a & b;// 其他代码endendmodule在上述代码中,当输入信号a或b发生变化时,阻塞赋值语句c = a & b;会被执行,并立即将结果赋值给信号c。

在阻塞赋值语句执行期间,其他代码会被阻塞,直到赋值完成。

2.3 特点sv阻塞赋值具有以下特点:•执行顺序:阻塞赋值按照代码的顺序执行,每次只能执行一个赋值语句。

•顺序执行:阻塞赋值是顺序执行的,每次只处理一个赋值语句,不会并行执行多个赋值操作。

•实时更新:阻塞赋值在赋值完成后立即更新信号的值,可以实时反映出信号的变化。

•代码简洁:阻塞赋值通常比非阻塞赋值的代码更简洁,易于理解和维护。

3. sv非阻塞赋值3.1 概念sv非阻塞赋值是一种并行执行的赋值方式,它不会阻塞后续的代码执行,而是在一个时钟周期结束后才会生效。

在sv中,非阻塞赋值使用“<=”符号进行赋值操作。

3.2 用法sv非阻塞赋值通常用于描述时序逻辑电路,其中信号的赋值会在时钟的上升沿或下降沿发生变化。

下面是一个简单的例子,展示了sv非阻塞赋值的用法:module nonblocking_assignment;reg clk, a, b;reg [3:0] count;always @(posedge clk)begina <= b;count <= count + 1;// 其他代码endendmodule在上述代码中,当时钟信号clk的上升沿到来时,非阻塞赋值语句a <= b;和count <= count + 1;会被执行,并在时钟周期结束后生效。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

阻塞赋值与非阻塞赋值作者:zhsj 日期:2015-7-27在Verilog语法中,阻塞赋值和非阻塞赋值是非常难理解的一个概念,尤其是对于初学者,往往搞不懂何时使用非阻塞赋值及何时使用阻塞赋值才能设计出符合要求的电路。

本文是笔者学习此概念时的学习笔记,主要分为概念解析和实例分析,并对一些编程要点进行总结分析,希望对各位初学者有所帮助。

在正式讲解之前先定义两个英文缩写字:RHS——赋值符合右边的表达式或变量;LHS——赋值符号左边的表达式或变量。

一、概念解析1.1 阻塞赋值阻塞赋值操作符为等号(即“=”),当采用阻塞赋值方式赋值时,需要先计算等号右手方向(RHS)部分的值,这时赋值语句不允许任何别的Verilog语句的干扰,直到现行的赋值完成时刻,即把RHS赋值给LHS的时刻,它才允许别的赋值语句的执行。

一般可综合的阻塞赋值操作在RHS不能设定有延迟,即使是零延迟也不允许。

若在RHS上加上延迟,则在延迟期间会阻止赋值语句的执行,延迟后才执行赋值,这种赋值语句是不可综合的,在需要综合的模块中不可使用这种风格的代码。

阻塞赋值的执行可以认为是只有一个步骤的操作,即计算RHS并更新LHS,此时不允许有来自任何其他Verilog语句的干扰。

所谓阻塞的概念是指在同一个always块中,其后面的赋值语句从概念上是前一句赋值语句结束后在开始赋值的,请注意,这只是概念上的先后,而无实质上的延迟。

在使用阻塞赋值时,如果在一个过程块中阻塞赋值的RHS变量正好是另一个过程块中阻塞赋值的LHS变量,这两个过程块又使用同一个时钟沿触发,这时阻塞赋值操作会出现问题,即如果阻塞赋值的顺序安排不好,就会出现竞争。

若这两个赋值操作用同一个时钟沿触发,则执行的顺序是无法确定的,在后面的例子中会看到这一问题。

1.2 非阻塞赋值非阻塞赋值操作符为小于等于号(即“<=”),当采用非阻塞赋值时,在赋值操作开始的时刻计算非阻塞赋值符RHS表达式,赋值操作结束的时刻才更新LHS。

在计算非阻塞赋值的RHS表达式和更新LHS期间,其他的Verilog语句,包括其他的Verilog非阻塞赋值语句都能同时计算RHS表达式和更新LHS。

非阻塞赋值允许其他的Verilog语句同时进行操作。

非阻塞赋值的操作过程可以看做两个步骤:(1)在赋值开始的时刻,计算非阻塞赋值RHS表达式;(2)在赋值结束的时刻,更新非阻塞赋值LHS表达式。

非阻塞赋值操作只能用于对寄存器类型变量进行赋值,因此只能使用在“initial”块和“always”块等过程块中,而且非阻塞赋值不允许用于连续赋值。

二、实例分析2.1 阻塞赋值与非阻塞赋值的执行顺序【例1】用阻塞赋值实现反馈振荡器module fbosc1(a, b, clk, rst_n);input clk;input rst_n;output reg a, b;always @(posedge clk or negedge rst_n)beginif (!rst_n)a = 0; //resetelsea = b;endalways @(posedge clk or negedge rst_n)beginif (!rst_n)b = 1; //resetelseb = a;endendmodule在本例中,两个always块是并行执行的,若复位信号已从0到1,且例1中的第一个always 块的有效时钟沿比第二个always块的有效时钟沿早几个皮秒(由时钟偏差造成)到达,则a和b 都会取为1;若第二个always块的有效时钟沿比第一个always块的有效时钟沿早几个皮秒到达,则a和b都会取为0。

这就清楚的说明这个Verilog模块是不稳定的,必定会产生冒险和竞争的情况。

【例2】用非阻塞赋值实现反馈振荡器同样在本例中,两个always 块是并行执行的,与前后顺序无关。

复位信号回到1后,无论哪一个always 块的有效沿先到,两个always 块中的非阻塞赋值都在赋值开始时刻计算RHS 表达式,而在结束时刻才更新LHS 表达式。

所以,复位信号从1回到0后,无论哪个always 块的有效时钟沿早到几个皮秒,a 为1且b 为0是确定的,因为实质上a 被赋的b 值是由rst_n 负跳变沿确定的,而b 被赋的a 值也是由rst_n 负跳变沿确定的。

从用户的角度看这两个非阻塞赋值好像是并行执行的。

2.2 移位寄存器模型如图2.1所示是一个简单的移位寄存器方框图。

图2.1 移位寄存器电路在接下来的例3~例5中介绍了三种用阻塞赋值实现图2.1移位寄存器电路的方式,其中有些是不正确的。

【例3】用阻塞赋值来描述移位寄存器(方式1,该方法不正确)例3中所描述的模块是错误的,因为按顺序进行的阻塞赋值将使得在下一个时钟上升沿时刻,所有的寄存器输出值都等于输入值d 。

在每个时钟的上升沿,输入值d 将无延时地直接输出到q3。

所以例3中的模块综合后的结果如图2.2所示,这并不是当初想要设计的移位寄存器电路。

图2.2 综合后的电路图 【例4】用阻塞赋值来描述移位寄存器(方式2,该方法正确,但风格不好)例4中所描述的模块是正确的,即可以得到图2.1所示的移位寄存器,但本模块在设计中阻塞赋值的顺序是经过仔细安排的,如果不是按照这种顺序的话就不会得到预期的电路,因此不建议使用这种描述方式,因为对于比较复杂的电路,赋值顺序稍不注意的话就会出错。

【例5】用阻塞赋值来描述移位寄存器(方式3,该方法综合后结果正确,但仿真结果不定)在本例中,三个阻塞赋值被分别放在不同的always块里。

仿真时,这些块的先后顺序是随机的,因此可能会出现错误的结果,这是Verilog中的竞争冒险现象。

按不同的顺序执行这些块将导致不同的结果。

但是,这些代码的综合结果却是正确的流水线寄存器。

也就是说,前仿真和后仿真的结果可能会不一致。

所以,不要采用这种描述方式。

在接下来的例6~例8中介绍了三种用非阻塞赋值实现图2.1移位寄存器电路的方式,三个例子全部是正确的。

【例6】用非阻塞赋值来描述移位寄存器(方式1)【例7】用非阻塞赋值来描述移位寄存器(方式2)【例8】用非阻塞赋值来描述移位寄存器(方式3)以上的三个例子综合和仿真的结果全部正确,对比之前阻塞赋值的三个例子我们可以发现:(1)3种阻塞赋值设计方式中有1种可以保证仿真正确;(2)3种阻塞赋值设计方式中有2种可以保证综合正确;(3)3种非阻塞赋值设计方式中全部可以保证仿真正确;(4)3种非阻塞赋值设计方式中全部可以保证综合正确;虽然在一个always块中正确地安排赋值顺序,则用阻塞赋值的方式也可以实现移位寄存器时序流水线逻辑。

但是,采用非阻塞赋值实现同一时序逻辑要相对简单,而且,非阻塞赋值可以保证仿真和综合的结果都是一致和正确的。

因此建议大家在编写Verilog时序逻辑时必须要使用非阻塞赋值的方式。

2.3 时序反馈移位寄存器模型线性反馈移位寄存器(Linear Feedback Shift-Register,LFSR)是带反馈回路的时序逻辑。

如果采用阻塞赋值的方式描述反馈回路的话往往会存在很多麻烦。

【例9】用阻塞赋值实现的线性反馈移位寄存器,实际上并不具有LFSR的功能module lfsrb1(clk, pre_n, q3);input clk;input pre_n;output reg q3;reg q2, q1;wire n1;assign n1 = q1 ^ q2;always @(posedge clk or negedge pre_n)beginif (!pre_n)beginq3 = 1'b1;q2 = 1'b1;q3 = 1'b1;endelsebeginq3 = q2;上例中所描述的模块并不具有线性反馈移位寄存器的功能,可以使用中间变量来进行修改使其达到预期的电路,但那样的话就太麻烦了。

【例10】用阻塞赋值实现的线性反馈移位寄存器,可以实现但不推荐使用本例是将所有的赋值语句组成单行等式来避免使用中间变量,这种方法是可以实现的,但是如果逻辑比较复杂的话,单行等式是难以编写和调试的,因此不建议使用这种方法。

如果将例9和例10中的阻塞赋值用非阻塞赋值代替,则仿真结果都和LFSRs的功能相一致。

如例11和例12所示。

【例11】用非阻塞赋值实现的线性反馈移位寄存器,功能正确,可以综合成正确的电路【例12】用非阻塞赋值实现的线性反馈移位寄存器,功能正确,可以综合成正确的电路通过对前面一些例子的分析总结,我们可以得到以下两条原则:★原则1 时序电路建模时,采用非阻塞赋值。

★原则2 锁存器电路建模时,采用非阻塞赋值。

2.4 组合逻辑模型在Verilog中可以用多种方法来描述组合逻辑,但是当用always块来描述组合逻辑时,应该用阻塞赋值。

如果always块中只有一条赋值语句,使用阻塞赋值和非阻塞赋值语句都可以。

但是为了养成良好的编程习惯,应该尽量使用阻塞赋值语句来描述组合逻辑。

有些设计人员认为非阻塞赋值语句不仅可以用于时序逻辑,也可以用于组合逻辑的描述。

对于简单的组合always块是可以这样的,但是当always块中有多个赋值语句时,使用没有延时的非阻塞赋值可能导致仿真结果不正确。

有时需要在always块的入口附加敏感事件参数,才能使仿真结果正确,因而从仿真的时间效率角度看也不合算。

【例13】用非阻塞赋值语句来描述组合逻辑,综合后结果正确,仿真结果错误在上例中,输出y值由3个时序语句计算得到。

由于非阻塞赋值语句在LHS更新前计算RHS 的值,因此tmp1和tmp2仍是进入该always块时的值,而不是在该步仿真结束时将更新的数值。

输出y反映的是刚进入always块时的tmp1和tmp2的值,而不是在always块中经计算后得到的值,因此在仿真时会出错。

【例14】用非阻塞赋值语句来描述组合逻辑,综合后结果正确,仿真结果正确,但效率低例14与例13的唯一区别在于,tmp1和tmp2加入到了敏感列表中。

如前所描述,当非阻塞赋值的LHS数值更新时,always块将自动触发并用最新计算出的tmp1和tmp2值更新输出y 的值。

将tmp1和tmp2加入到敏感列表中后,现在输出y的值是正确的。

但是,一个always块中有多次参数传递,由此降低了仿真器的性能,只有在没有其他合理方法的情况下才考虑这样做。

【例15】用阻塞赋值语句来描述组合逻辑,综合后结果正确,仿真结果正确,推荐使用例15和例13的区别在于用阻塞赋值替代了非阻塞赋值,这样既保证了仿真时经过一次数据传递输出y的值是正确的,又提高了仿真效率。

在always块中使用阻塞赋值语句就可以实现组合逻辑,这样做既简单,且仿真效率又快又好,建议大家使用这种风格的Verilog代码。

相关文档
最新文档