加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

阻塞与非阻塞赋值(深度理解)

(2013-03-13 22:48:34)
标签:

fpga

verilog

it

分类: Verilog

作者:李秋凤,华清远见嵌入式学院讲师。

稍微接触过Verilog HDL的都对阻塞与非阻塞赋值略知一二,也是我们经常强调的重点之一,在课堂上还是有学员问什么不一样呢,为什么我用阻塞赋值也能得出正确的结果呢?

在编写可综合代码的时候,建议大家不要忘了打开RTL网表查看器看看我们自己综合出来的电路是不是自己想要的逻辑。

我就阻塞与非阻塞赋值这个问题详细说明一下。

1、连续赋值

连续赋值语句的硬件实现是:从赋值语句(=)右边提取出的逻辑,用于驱动赋值语句左边的线网(net)

连续赋值语句

module continousassignment(a,b,c);
    input a,b;
    output c;
    assign c=a&b; 
    endmodule

http://www.embedu.org/Column/images/Column86-1.jpg

综合以后,通过网表查看器为上图的结果,线网c由赋值语句的右边的逻辑是组合逻辑a&b简单驱动

2、过程赋值

过程赋值语句的硬件实现是,从赋值语句的(=或<=)右边提取出的逻辑用于驱动赋值语句左边的变量(必需是reg类型)。必须注意的是虽然过程赋值语句是可以出现在initial语句中(仅用于仿真),也可以出现在“always”块语句中,但是只有“always”中的过程赋值语句才能被综合

有两种类型的过程赋值语句:阻塞赋值语句(Blocking Assignment statement)、非阻塞赋值语句(non-Blocking Assignment statement)

2.1、阻塞赋值语句

阻塞赋值语句可以简单描述为,在一个always块中,语句按照从上到下的顺序执行

module blockingassignment (clk ,q1,q2);
    input clk;
    output [2:0] q1,q2;
    reg[2:0] q1,q2;
    always @ (posedge clk)
    begin
    q1=q1+3'b1;
    q2=q1;
    end
    endmodule

http://www.embedu.org/Column/images/Column86-2.jpg

综合后的RTL视图如上图所示,每个时钟上升沿触发后,变量q2、q1的值是同步的,q2被赋予了q1更新后的值

2.2、非阻塞赋值语句

非阻塞赋值语句简述为:在一个always 块中,语句是并行执行的

module nonblockingassignment (clk ,q1,q2);
    input clk;
    output [2:0] q1,q2;
    reg[2:0] q1,q2;
    always @ (posedge clk)
    begin
    q1<=q1+3'b1;
    q2<=q1;
    end
    endmodule

http://www.embedu.org/Column/images/Column86-3.jpg

从综合结果的RTL查看器可以看到如上图所示,每个时钟触发后,q2被赋予的q1值时上个时钟周期生成的值

从上面可以看出,第一条语句综合出来的结果是一样的,阻塞与非阻塞不同在于它们会影响到后面引用该条语句的逻辑

3、阻塞与非阻塞建模建模原则

1)、组合逻辑使用阻塞语句、时序逻辑使用非阻塞语句;

2)、在同一个模块里,同一个变量不能既有阻塞赋值,又有非阻塞赋值

 

例如:
always@(posedge clk)
begin
    a=a+1;
    b=a-c;
end

always@(posedge clk)
begin
    c=a;
end

endmodule 

b的结果为2。因为b取a赋值后的值,但取c赋值之前的值。
打开Tool->Netlist Viewer->RTL Viever查看综合出的电路如图:
http://blog.chinaunix.net/attachment/201111/30/24203478_1322658645WHMk.png
实际上a、b、c触发器的赋值仍然是同时进行的,只不过b会与a同时赋a+1的值。
如改为非阻塞语句:
always@(posedge clk)
begin
    a<=a+1;
    b<=a-c;
end

always@(posedge clk)
 
begin
    c<=a;
end

endmodule 

结果b=1,则综合出电路如下:
http://blog.chinaunix.net/attachment/201111/30/24203478_1322659099Rubs.png
区别仅在于b赋a而上面是b赋a+1。
弄了很久,,,
如果是组合逻辑中的阻塞语句:
always@(posedge clk)
begin
    a<=a+1;
end

always@(a)
begin
    b=a+3;
    c=b+7;
end

则综合结束如下:
http://blog.chinaunix.net/attachment/201111/30/24203478_1322660247nP7L.png
b、c全由组合逻辑电路实现。
若使用非阻塞语句:
always@(posedge clk)
begin
    a<=a+1;
end

always@(a)
 
begin
    b<=a+3;
    c<=b+7;
end
则综合出的电路和上面一样。因此似乎在组合逻辑中使用非阻塞语句没有意义。因此一般的在组合逻辑中就直接使用阻塞语句。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有