🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 时序电路中 ## 只有一级时 ### 非阻塞赋值 ``` module t( input clk, input din, output reg a ); always@(posedge clk) a <= din; endmodule ``` 综合后的RTL: ![](https://img.kancloud.cn/0e/4f/0e4f94b5a8ae5bd6539381dee712337d_631x310.png) ### 阻塞赋值 ``` module t( input clk, input din, output reg a ); always@(posedge clk) a = din; endmodule ``` 综合后的RTL: ![](https://img.kancloud.cn/ea/a3/eaa32f1e5a747524602a27ca1c46af33_723x384.png) ### 小结 ` `可以看到在这种情况下两者综合出来的是一样的,都是一个触发器,但是我们在使用的时候尽量还是保证时序电路用`<=`,组合电路用`=`,大多数情况用`<=`的原则。 ## 多级连接 ### 非阻塞赋值 ``` module t ( input clk, input din, output reg a, output reg b, output reg c ); always@(posedge clk) begin a <= din; b <= a; c <= b; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/a2/d3/a2d3da5e887ce07416cda52e96c7c28d_927x550.png) ### 阻塞赋值 ``` module t ( input clk, input din, output reg a, output reg b, output reg c ); always@(posedge clk) begin a = din; b = a; c = b; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/42/a4/42a43fff61aa0e44359dbce8e0999daf_706x606.png) ### 混合使用 ``` module t ( input clk, input din, output reg a, output reg b, output reg c ); always@(posedge clk) begin a <= din; b = a; c <= b; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/13/29/13298b15d470b31fb75b32286025956f_831x483.png) ` `可看到<=赋值影响的是后面的部分,前面的没有受到影响。由此我们推测到下面这种和上面的综合结果将会是一样的。 ``` module t ( input clk, input din, output reg a, output reg b, output reg c ); always@(posedge clk) begin a <= din; b = a; c = b; end endmodule ``` ![](https://img.kancloud.cn/7b/61/7b61791b2bf4c8eceeaefa7233511bc8_864x496.png) ` `结果证明上述猜测是对的。 ` `上面的都是放在同一个always中,那么我们将其放在两个always中会怎样? ``` module t ( input clk, input din, output reg a, output reg b, output reg c ); always@(posedge clk) begin a <= din; b = a; end always@(posedge clk) begin c = b; end endmodule ``` ![](https://img.kancloud.cn/18/d0/18d06357440033a1bf5e5b6b428d1206_860x508.png) ` `发现相当于就是三个模块都按非阻塞复制连接的。 ``` module t ( input clk, input din, output reg a, output reg b, output reg c ); always@(posedge clk) begin a <= din; b = a; end always@(posedge clk) begin c <= b; end endmodule ``` 综合结果和上一种情况一样: ![](https://img.kancloud.cn/70/7a/707abe3a51e3f3d1a6d03abd5f54e643_956x567.png) ### 看看其他组合的情况 ``` module t ( input clk, input din, output reg a, output reg b, output reg c ); always@(posedge clk) begin a <= din; b <= a; end always@(posedge clk) begin c <= b; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/1f/90/1f902fb57fdb947d0686b8b6c57a15c8_1051x594.png) ``` module t ( input clk, input din, output reg a, output reg b, output reg c ); always@(posedge clk) begin a = din; b = a; end always@(posedge clk) begin c <= b; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/43/a0/43a0995beb0dede971942d53ada6c15b_1049x591.png) ### 小结 ` `可以看到,阻塞赋值相当于几个并联起来,而非阻塞赋值相当于几个串联起来,因此串联起来的模块在时序电路中,后一级的数据要晚于前一级的数据一个始终的时间。 # 在组合电路中 ## 只有一级时 ### 阻塞赋值 ``` module t ( input clk, input din, output reg a ); always@(clk) begin a = din; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/05/31/05319e8f695b31fecc33655f7782e385_603x325.png) ### 非阻塞赋值 ``` module t ( input clk, input din, output reg a ); always@(clk) begin a <= din; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/55/33/55333c9f780a39fcc57b0de502f8bf76_724x361.png) ## 多级连接 ### 阻塞赋值 ``` module t ( input clk, input din, output reg a output reg b, output reg c ); always@(*) begin a = din; b = a; c = b; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/6e/24/6e24b592fa17cf1c8e09167bbd072e85_585x363.png) ### 非阻塞赋值 ``` module t ( input clk, input din, output reg a output reg b, output reg c ); always@(*) begin a <= din; b <= a; c <= b; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/56/e7/56e7c15eae9e48407f97eecc067dd8f3_828x454.png) ### 其他情况 ``` module t ( input clk, input din, output reg a, output reg b, output reg c ); always@(*) begin a <= din; end always@(a) begin b <= a; end always@(b) begin c <= b; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/ec/0a/ec0a6de0bdbca510a79d290169eabbc0_841x467.png) ` `上面的结果你可能还没理解,我们结合下一个你再看看,就明白了。就好像c中的函数一样,上一个的结果做为下一个的输入! ``` module t ( input clk, input [7:0]din, output reg[7:0]a, output reg[7:0] b, output reg[7:0]c ); always@(*) begin a <= din+1; end always@(a) begin b <= a + 2; end always@(b) begin c <= b + 5; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/ec/70/ec70a4ffa0c7b8e06ea461b6f2126bae_1036x349.png) ``` module t ( input clk, input [7:0]din, output reg[7:0]a, output reg[7:0] b, output reg[7:0]c ); always@(*) begin a = din+1; end always@(a) begin b = a + 2; end always@(b) begin c = b + 5; end endmodule ``` 综合结果: ![](https://img.kancloud.cn/9d/01/9d01093dfb586dc0976c54986729a663_1048x331.png) ### 小结 ` `能发现在组合逻辑下,`=和<=`没有区别。 # 总结 ` `综上所述,我们需要注意的是在时序电路下,多级连接时选择阻塞赋值爱是非阻塞赋值,其他的基本没有什么问题,组合逻辑下不区分`=和<=`。 ` `阻塞赋值:阻塞赋值语句是在这句之后所有语句执行之前执行的,即后边的语句必须在这句执行完毕才能执行,所以称为阻塞,实际上就是顺序执行。 ` `非阻塞赋值:非阻塞赋值就是与后边相关语句同时执行,即就是并行执行。 ` `所以一般时序电路使用非阻塞赋值,assign语句一般使用=阻塞赋值; ` `组合逻辑电路使用阻塞赋值;