目录
前言
本人承诺本专栏不会开启付费专栏,如觉得有帮助可以点点关注和打赏感谢,本文为专栏部分内容,完整部分请查看专栏!
我们在明晰assign语句与always语句中了解到了begin end语句,本文我们就来探讨一下他的奥秘。
一、什么是begin end?
我们在前文了解到如果always语句中如果有多条赋值语句必须由begin和end包裹,就像这样
这个模块可以实现一个全加器,我们可以看到这个全加器的赋值语句被框住了,在begin和end之间,也能看到他们被等号所连接,属于是阻塞赋值,其实他们之间还有另一种赋值方式--非阻塞赋值!
可以知道的是,begin end之间的赋值语句有阻塞赋值与非阻塞赋值之分!
二、什么是阻塞赋值和非阻塞赋值?
如果你接触过C语言这类的编程语言,你就会知道他是从main函数开始,一句一句的顺序执行(不考虑中断之类的),阻塞赋值也是这样的,语句顺序执行,前面的执行完才能执行后面的。
赋值符号 =
赋值目标1 = 表达式1;//只有赋值语句1完成
赋值目标2 = 表达式2;//才会完成赋值语句2
而非阻塞赋值相反,它不需要参考赋值语句1,所有语句并行执行。
赋值符号:<=
赋值目标1 <= 表达式1;//赋值语句1不会阻塞赋值语句2
赋值目标2 <= 表达式2;//赋值语句1和赋值语句2并行执行
不清楚什么是表达式的可以参考链接:
举例比较一下:
阻塞赋值:
begin
m=a*b;
y=m;
end
当 m=a*b 执行完才能执行 y=m 。
当 m 赋值完成后,才能执行 y 的赋值,y 得到的是 m 的新值。
非阻塞赋值:
begin
m <= a*b
y <= m;
end
m=a*b 和 y=m 并行执行 。
m 和 y 的赋值并行执行,y 得到的是 m 的旧值。
三、阻塞与非阻塞的实质
阻塞赋值的实质:右边表达式的计算和对左边寄存器变量的赋值是一个统一的原子操作中的两个动作,这两个动作之间不能再插入其他任何动作。
备注:原子操作:是指在多线程编程中,不会被线程调度机制打断的操作,一旦开始,就一直运行到结束。
举个栗子;
always @ (A,B) //设A、B同时由0变1,激活前:M1=0,M2=0,Q=0
begin //激活后:
M1=A; //先计算A=1,马上赋值给M1
M2=B&M1; //再计算B&M1=1,马上赋值给M2
Q=M1|M2; //再计算M1|M2=1,马上赋值给Q
end
非阻塞赋值的实质:首先按顺序计算右边表达式的值,但是并不马上赋值,而是要等到过程结束时再按顺序赋值。
举个栗子;
always @ (A,B) //设A、B同时由0变1,激活前:M1=0,M2=0,Q=0
begin //激活后:
M1 <= A; //先计算A=1,(等待,不赋值)
M2 <= B&M1; //再计算B&M1=0,(等待,不赋值)
Q <= M1|M2; //再计算M1M2=0,(等待,不赋值)
end //过程结束 先赋值给M1=1 再赋值给M2=0 再赋值给Q=0
四、使用说明和注意事项
-
设计组合电路时常用阻塞赋值;
-
设计时序电路时常用非阻塞赋值,但不是绝对的。
-
不建议在一个always块中混合使用阻塞赋值和非阻塞赋值
总结
以上就是今天要讲的内容,本文介绍了什么是begin end 还有什么是阻塞与非阻塞赋值,我们离数字的世界又进了一步。
标签:语句,begin,end,FPGA,阻塞,M1,06,赋值 From: https://blog.csdn.net/x2410369939/article/details/145259249