久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

阻塞賦值和非阻塞賦值深度解析——仿真事件的調(diào)度

 畢杰lb7q1kq7pr 2020-12-15

來源:EETOP BLOG   作者:acgoal

http://www./blog/html/46/553746-51456.html

下面有一段verilog代碼和仿真文件,,用的是VCS仿真和編譯工具。我們來研究一下不同的驅(qū)動(dòng)賦值方式對(duì)仿真結(jié)果的影響,。下面我把我做的例子和大家分享一下,。

設(shè)計(jì)源代碼如下:


`timescale 1ns/1ps
module 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;
input rst_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;
  end
end
always @(posedge clk) begin
  if(!rst_n) begin
    data_out1 <= 4'd0;
  end
  else begin
    data_out1 <= data_in1;
  end
end
endmodule


這里有兩段,分別表示帶異步復(fù)位和帶同步復(fù)位的,。

測(cè)試程序如下:


`timescale 1ns/1ps
module 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;
end
always begin
  #3 clk=~clk;
end
initial begin
  rst_n = 1'b1;
  #15 rst_n = 1'b0;
  #180 rst_n = 1'b1;
  #200 $finish;
end

initial 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;
end

initial 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;
end

initial begin
  $vcdpluson();
end
endmodule


注意這里紅色的部分,,data0和data1的驅(qū)動(dòng)都用非阻塞賦值,。得到的仿真波形圖如下:


下面我把非阻塞賦值改成阻塞賦值,改動(dòng)部分如下:initial 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;
end

initial 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;
end



這樣的代碼,,仿真波形圖如下:


和上面的不一樣,,為什么呢,為什么這次的flop行為沒有了呢,?直接給結(jié)論吧,。

根據(jù)verilog/system verilog的standard。我這里以system verilog的standard為例,,STD 1800-2009版本,,第四章“Scheduling Semantics”,這一章關(guān)于仿真的調(diào)度描述,。

simulation的event大體分為:Active event -> Inactive event -> NBA event -> Overserved event -> Reactive -> Re-Inactive -> Re-NBA 

一般的,,阻塞賦值發(fā)生在active/inactive event,而NBA( Non-blocking assignment update)從字面意思就能看出來是做非阻塞賦值的,。

再結(jié)合上面的例子,,如果data_in0是阻塞賦值出去的話,因?yàn)槔永锏膁ut是在時(shí)鐘上升延來的時(shí)候進(jìn)行非阻塞賦值(data_out0 <= data_in0),,這句話屬于NBA event,,而阻塞賦值data_in0 = 1 (或者2,4,,8)是Active event,,他比NBA要先執(zhí)行,所以我們看到data_out0在當(dāng)前的cycle就被采樣到了,。這就是后面一個(gè)波形圖的樣子,,看起來就像flop沒有用一樣。實(shí)際上是我們driver寫的有問題,。

如果data_in0在testbench里面用阻塞賦值就是 data_in0 <= 1 (或者2,,4,8,,見例子),,那么data_out0 <= data_in0, 和data_in0 <= 1同屬于NBA event。這樣子這兩句話同時(shí)執(zhí)行,,這樣就和實(shí)際電路中的flop行為一致了(就是并行執(zhí)行),。

結(jié)論:做驅(qū)動(dòng)的接口信號(hào)最好是非阻塞賦值出去。

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多