精华内容
下载资源
问答
  • 在写testbench时,经常会用到文件的读取,下面示例了文件读取和写入的方法: 文件读取 图中第一行定义一个文件句柄。由于打开的文件中一行中有两个10bit的十进制数据,所以定义了2个reg变量。...

    在写testbench时,经常会用到文件的读取,下面示例了文件读取和写入的方法:

    文件读取

    图中第一行定义一个文件句柄。由于打开的文件中一行中有两个10bit的十进制数据,所以定义了2个reg变量。

    第6行到12行就是文件的读取过程。

    使用的系统函数$fopen打开文件;

    使用$feof判断文件是否读完;

    使用$fscanf读取文件内容。

    在实际验证中,仿真一段时间后,仿真会结束,注意在仿真结束时,要使用$fclose(dti_fid)关闭文件。

     

    文件写入

    在写文件时,首先要建一个文件句柄如15行;

    17-18行,声明2个10bit的输出数据dto_i和dto_r;

    20-22行,建立一个文件;

    24-27行,写文件。dto_vld是dto_i和dto_r数据的有效指示。

    还是要注意在仿真结束时,要用$fclose(dto_fid)关闭文件句柄。

     

    展开全文
  • 二、$fopen,$fwrite,$fclose 三、仿真验证 四、参考 一、$readmemb/$readmemh $readmemb和$readmemh用来从文件中读取数据到存储器中。读取的内容只包括:空白位置(空格、换行、制表格(tab和form-feeds),注释...

    目录

     

    一、$readmemb/$readmemh

    二、$fopen,$fwrite,$fclose

    三、仿真验证

    四、参考


    一、$readmemb/$readmemh

    $readmemb和$readmemh用来从文件中读取数据到存储器中。读取的内容只包括:空白位置(空格、换行、制表格(tab和form-feeds),注释行、二进制或十六进制的数字。

    数字中不能包含位宽说明和格式说明,其中readmemb要求每个数字是二进制数,readmemh要求每个数字必须是十六进制数字。数字中不定值x或X,高阻值z或Z,和下划线(_)的使用方法和代表意义与一般Verilog HDL程序中的用法一致。

    在Verilog语法中,一共有以下六种用法:

    • (1)$readmemb("<数据文件名>",<存储器名>);
    • (2)$readmemb("<数据文件名>",<存储器名>,<起始地址>);
    • (3)$readmemb("<数据文件名>",<存储器名>,<起始地址>,<终止地址>);
    • (4)$readmemh("<数据文件名>",<存储器名>);
    • (5)$readmemh("<数据文件名>",<存储器名>,<起始地址>);
    • (6)$readmemh("<数据文件名>",<存储器名>,<起始地址>,<终止地址>);

    二、$fopen,$fwrite,$fclose

    $fwrite用来向文件中写入数据。与文件读取不同,文件写入需要打开文件,写入,最后关闭文件。操作流程如下:

    handle = $fopen("D:/file.txt","w");//按照写操作打开文件,得到对应的句柄,作为文件操作标识;其中,文件路径间隔为“/”而不是“\”

    $fwrite(handle,"%d\n",data);//按照十进制格式写入数据到handle对应文件中,只能逐个写入(即data不能是数组)

    $fclose(handle);//关闭文件,至此文件操作结束

    三、仿真验证

    验证流程:

    新建文件num.txt,存入0-10共11个二进制数;

    测试文件中,将num.txt中的数据按照二进制格式读入到寄存器;

    再将寄存器中的数据反序按照10进制存入num2.txt。

    测试文件如下:

    `timescale 1ns / 1ps
    
    module file_test(
    
        );
    reg [3:0]data[0:15];
    reg [3:0]data2[0:15];
    integer handle1;
    integer i=0;
    initial
    begin
        $readmemb("F:/vivado_files/num.txt",data);
    
        handle1 = $fopen("F:/vivado_files/num2.txt","w");
        repeat(16)
        begin
            $fwrite(handle1,"%d\n",data[15-i]);
            i = i+1;
        end
        $fclose(handle1);
    end
    endmodule
    

    num.txt文件如下:

     

    读取结果如下:

    num2.txt文件如下:  

     

    四、参考

    verilog中$readmemb和$readmemh的使用

    展开全文
  • 除了看波型圖外,在寫Testbench時還可搭配Verilog本身所帶的一些函數做驗證,如$display()、$strobe()、$monitor()與$fwrite()等,這些函數在遇到blocking與nonblocking時,該如何使用才正確呢?它與Debussy / Verdi...

    Abstract
    除了看波型圖外,在寫Testbench時還可搭配Verilog本身所帶的一些函數做驗證,如$display()、$strobe()、$monitor()與$fwrite()等,這些函數在遇到blocking與nonblocking時,該如何使用才正確呢?它與Debussy / Verdi的nWave又有什麼關係呢?

    Introduction
    使用環境:ModelSim SE 6.3e + Debussy 5.4 v9

    本文將討論以下主題:

    1.Verilog的『stratified event queue』

    2.blocking / nonblocking與$display()、$strobe()、$monitor()、$fwrite()的執行順序

    3.Debussy / Verdi的nWave與blocking / nonblocking的關係

    4.Conclusion

    先來看一下摘自[1] Clifford E. Cummings 2000, Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kills, Sunburst Design, Inc.這篇paper的一段範例,我稍加修改,另外加上了常用的$fwrite()與Debussy的$fsdbDumpvars()與$fsdbDumpvars()一起測試。

    nb_schedule1.v / Verilog

    复制代码
    1 module nb_schedule1; 2 3  reg a, b; 4 integer fp; 5 6 initial begin 7 fp = $fopen("log.txt","w"); 8 a = 0; 9 b = 0; 10 #1; 11 a = 0; 12 b = 1; 13 a <= b; 14 b <= a; 15 16 $monitor("%0dns :\$monitor: a=%b b=%b" , $stime, a, b); 17 $display("%0dns :\$display: a=%b b=%b" , $stime, a, b); 18 $strobe ("%0dns :\$strobe : a=%b b=%b\n", $stime, a, b); 19 $fwrite(fp, "%0dns :\$fwrite : a=%b b=%b\n", $stime, a, b); 20 #0 $display("%0dns :#0 : a=%b b=%b" , $stime, a, b); 21 22 23 #1 $monitor("%0dns :\$monitor: a=%b b=%b" , $stime, a, b); 24 $display("%0dns :\$display: a=%b b=%b" , $stime, a, b); 25 $strobe ("%0dns :\$strobe : a=%b b=%b\n", $stime, a, b); 26 $fwrite(fp, "%0dns :\$fwrite : a=%b b=%b\n", $stime, a, b); 27 #0 $display("%0dns :#0 : a=%b b=%b" , $stime, a, b); 28 29 30 $fclose(fp); 31 end 32 33 initial begin 34 $fsdbDumpfile("nb_schedule1.fsdb"); 35 $fsdbDumpvars(0, nb_schedule1); 36 end 37 38 endmodule
    复制代码

    執行結果

    复制代码
    # 1ns :$display: a=0 b=1 # 1ns :#0 : a=0 b=1 # 1ns :$monitor: a=1 b=0 # 1ns :$strobe : a=1 b=0 # # 2ns :$display: a=1 b=0 # 2ns :#0 : a=1 b=0 # 2ns :$monitor: a=1 b=0 # 2ns :$strobe : a=1 b=0
    复制代码
    文字檔部份
    1ns :$fwrite : a=0 b=1 2ns :$fwrite : a=1 b=0

    Debussy的nWave

    strobe00

    假如結果如你預期,恭喜你,那表示你的觀念非常清楚,如果不是,請你繼續往下看,我將會解釋這段範例程式。

    Verilog的『stratified event queue』

    我在(原創) 深入探討blocking與nonblocking (SOC) (Verilog)曾經討論過Verilog在Simulator內實際的運行方式,這裡再稍為提一下。

    在軟體的世界,程式碼基本上是一行一行地執行,也就是再同一個時間點,只有一件事情會發生;但在硬體的世界裡,電路卻可以平行執行,也就是在同一個時間點,有很多事情可以同時發生。我們現在要在一個只能『循序處理』的軟體去『模擬』能『平行處理』的硬體,勢必有些特殊的機制才行。

    在Simulator內,為了要模擬出硬體的平行處理機制,時間軸是個虛擬的時間軸,另外搭配了5個event queue,也就是說,當一個時間點的5個event queue內的所有程式碼都執行過後,時間軸才會自動加1,如此就很巧妙的『看起來』好像在同一個時間點作了很多事情,不過事實上對於軟體與CPU來說,依然是同一時間點只發生了一件事情。

    strobe01

    在IEEE Verilog Standard中定義了這5個Event Queue,依序討論如下:

    1.Active Events:

    大部分的Verilog程式碼都在此執行,其中包括以綠色字表示的blocking asignments以及continuous assignments (也就是用assign寫的),至於nonblocking部分,只執行RHS (Right Hand Side),也就是只執行nonblocking右測的部分,唯一用紅色表示的是本文所要討論的$display()與$fwrite(),也是屬於Active Events,值的注意的是,在Active Events中的程式碼,若是同一個時間點,且在同一個sequential block,程式碼是依序執行,但是IEEE Verilog Standard並不保證在同一個時間點,不同的sequential block內的程式碼誰先執行,也就是說若你寫的程式碼都屬於Active Events所執行,但分屬不同的sequential block,且彼此互相依賴,就可能出現Race Condition的情形發生

    當在Active Events的程式碼執行完後,會自動移出Active Events。

    2.Inactive Events

    當Active Events執行完後,Inactive Events的程式碼會依序變成Active Events而執行之。

    Inactive Events執行的是blocking assignments且帶#0 delay,因為是#0,所以理論上還是屬於同一個時間點,只是執行順序略晚於正常的blocking assignments,這也是為什麼遇到Race Condition時,常常加上#0就會正常,這就是因為#0是屬於Inactive Events,執行順序很明顯的在Active Events之後,因此不會有在Active Events內不保證誰先誰後執行,而造成Race Condition發生。

    很多人認為#0會在每個時間點的最後執行,這是個錯誤的觀念,事實上,#0只是在Inactive Events,比Nonblocking Events還要早。

    3.Nonblocking Events

    當Inactive Events執行完後,接著Nonblocking Event的程式碼會依序變成Active Events而執行之。

    Nonblocking Events執行的是nonblocking的LHS(Left Hand Side)部分,在此我們可以明確地發現,blocking發生在Active Events,而nonblocking雖然在Active Events已經執行了RHS,但真正完成LHS是在Nonblocking Events,也就是blocking會在nonblocking之前先完成。這也是為什麼同一個時間點,nonblocking可以讀到blocking所做的改變,但是blocking卻無法讀到nonblocking的改變,因為blocking已經先執行,必須要等到下一個clk edge才能讀到nonblocking所做的改變。

    除此之外,還有一個常見的迷思也可在此澄清,我們都知道寫sequential logic時要用nonblocking寫,事實上用blocking也是可以寫,只是blocking寫很容易造成Race Condition,要很小心注意其先後順序,但為什麼用nonblocking寫就不會有Race Condition呢?

    理由就在於nonblocking的RHS是在Active Events,而LHS是在Nonblocking Events,儘管彼此互相依賴,但Nonblocking Events很明顯地在Active Events之後,所以執行順序可以明確地確定,不像用blocking寫時,因為在Active Events內執行順序不確定,造成結果不可預期而產生Race Condition。

    4.Monitor Events

    當Nonblocking Events執行完後,接著Monitor Events的程式碼會依序變成Active Events而執行之。

    我們都知道$display()無法觀察nonblocking所改變的結果,必須要使用$strobe()才可以,這是為什麼呢?因為$display()是屬於Active Events,而nonblocking完成於Nonblocking Events,明顯在Active Events之後,所以$display()跟本欄不到nonblocking所造成的改變,必須使用比Nonblocking Events更晚執行的Monitor Events中的$strobe()才可以觀察到nonblocking所改變的結果。

    5.Verilog PLI Events

    當Monitor Events執行完後,接著Verilog PLI Events的程式碼會依序變成Active Events而執行之。

    Verilog PLI是允許你用C語言去寫一些Simulator的擴充功能,如Debussy / Verdi的$fsdbDumpfile()、$fsdbDumpvars()就是透過Verilog PLI,以前我ㄧ直搞不懂為什麼我用$display()與$fwrite()所dump的值與在Debussy / Verdi的nWave所看到的值不一樣,後來才發現原來$display()與$fwrite()是屬於Active Events,而$fsdbDumpfile()與$fsdbDumpvars是屬於Verilog PLI Events,比Nonblocking Events晚執行,這也是為什麼Debussy / Verdi可以顯示每個時間點nonblocking的值,而$display()與$fwrite()卻無法dump每個時間點的nonblocking,彼此的結果會差1個clock。

    blocking / nonblocking與$display()、$strobe()、$monitor()、$fwrite()的執行順序

    了解Verilog Simulator的『stratified event queue』之後,為了解釋nb_schedule1為什麼會有這樣的執行結果,我們將所有程式依照其在Event Queue的執行順序重新排列如下圖所示:

    strobe02 

    我們可以發現,儘管nonblocking與$monitor()、$strobe()寫在$display()與$fwrite()前面,但真正在執行時,Verilog Simulator還是會把它放在該放的Event Queue內,因為$display()與$fwrite()是放在Active Events,所以會印出a=0, b=1,接下來是Inactive Events的#0 $display(),也是顯示a=0, b=1,再過來是Nonblocking Events,執行 a <= b與b<=a,最後才是Monitor Events的$monitor()與$strobe(),因為nonblocking已經執行過,a與b的值已經改變,所以a=1, b=0,接下來因為a與b的值都不再改變,所以印出的值都不會再變。

    Debussy / Verdi的nWave與blocking / nonblocking的關係

    strobe03

    在nWave內,1 ns時,所顯示的是a=1, b=0,若你是用$display()與$fwrite()去dump資料時,會得到a=0, b=1,也就是說,$display()與$fwrite()看到的是blocking的值,而nWave看到的是nonblocking的值,因為$fsdbDumpfile()與$fsdbDumpvars()是在Verilog PLI Events,執行點是在Nonblocking Events之後。

    這也是為什麼有些工程師在寫sequential logic時,會在nonblocking加上#1,為的就是在Debussy / Verdi下看波形圖時比較好看,而Synthesizer會自動忽略nonblocking的#1,所以結果不會受影響。

    Conclusion
    1.因為blocking與nonblocking的關係,所以程式碼執行的順序不見的會依照我們所寫的順序,而是要依照『stratified event queue』的執行順序執行。

    2.若皆屬Active Events的程式碼,在同一個時間點,在同一個sequential block內會依序執行,但在不同的sequential block內就無法保證誰會先執行,若彼此依賴有相關,就有可能造成Race Condition。

    3.#0的blocking會比較晚一點執行,可以暫時解決Race Condition所造成的問題,不過這不是一個推薦的coding style,建議找出Race Condition的真正原因,而改用nonblocking去解決。

    4.#0並不是最後執行,只是在Inactive Events而已,比Active Events稍晚,但還是比Nonblocking Events早。

    5.Sequential logic也是可以用blocking寫,只是很容易造成Race Condition,必須很小心的安排blocking的執行順序,不是一個推薦的coding style。

    6.$display()只能觀察到blocking,無法觀察到nonblocking,若要觀察nonblocking,要使用$strobe()與$monitor()。

    7.$fsdbDumpfile()與$fsdbDumpvars()比$strobe()與$monitor()還晚執行,所以在Debussy / Verdi總是觀察到nonblocking的值,會比使用$display()與$fwrite()早1個clock。

    展开全文
  • 原链接: http://www.cnblogs.com/oomusou/archive/2011/06/25/verilog_strobe.html ...(筆記) $dispaly()、$strobe()、$monitor() 、$fwrite()與blocking / nonblocking的關係 (SOC) (Verilog) (Debussy) (V

    原链接: http://www.cnblogs.com/oomusou/archive/2011/06/25/verilog_strobe.html

        ---向博主 致敬!!!

    (筆記) $dispaly()、$strobe()、$monitor() 、$fwrite()與blocking / nonblocking的關係 (SOC) (Verilog) (Debussy) (Verdi)

    Abstract
    除了看波型圖外,在寫Testbench時還可搭配Verilog本身所帶的一些函數做驗證,如$display()、$strobe()、$monitor()與$fwrite()等,這些函數在遇到blocking與nonblocking時,該如何使用才正確呢?它與Debussy / Verdi的nWave又有什麼關係呢?

    Introduction
    使用環境:ModelSim SE 6.3e + Debussy 5.4 v9

    本文將討論以下主題:

    1.Verilog的『stratified event queue』

    2.blocking / nonblocking與$display()、$strobe()、$monitor()、$fwrite()的執行順序

    3.Debussy / Verdi的nWave與blocking / nonblocking的關係

    4.Conclusion

    先來看一下摘自[1] Clifford E. Cummings 2000, Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kills, Sunburst Design, Inc.這篇paper的一段範例,我稍加修改,另外加上了常用的$fwrite()與Debussy的$fsdbDumpvars()與$fsdbDumpvars()一起測試。

    nb_schedule1.v / Verilog

    复制代码
    1 module nb_schedule1; 2 3  reg a, b; 4 integer fp; 5 6 initial begin 7 fp = $fopen("log.txt","w"); 8 a = 0; 9 b = 0; 10 #1; 11 a = 0; 12 b = 1; 13 a <= b; 14 b <= a; 15 16 $monitor("%0dns :\$monitor: a=%b b=%b" , $stime, a, b); 17 $display("%0dns :\$display: a=%b b=%b" , $stime, a, b); 18 $strobe ("%0dns :\$strobe : a=%b b=%b\n", $stime, a, b); 19 $fwrite(fp, "%0dns :\$fwrite : a=%b b=%b\n", $stime, a, b); 20 #0 $display("%0dns :#0 : a=%b b=%b" , $stime, a, b); 21 22 23 #1 $monitor("%0dns :\$monitor: a=%b b=%b" , $stime, a, b); 24 $display("%0dns :\$display: a=%b b=%b" , $stime, a, b); 25 $strobe ("%0dns :\$strobe : a=%b b=%b\n", $stime, a, b); 26 $fwrite(fp, "%0dns :\$fwrite : a=%b b=%b\n", $stime, a, b); 27 #0 $display("%0dns :#0 : a=%b b=%b" , $stime, a, b); 28 29 30 $fclose(fp); 31 end 32 33 initial begin 34 $fsdbDumpfile("nb_schedule1.fsdb"); 35 $fsdbDumpvars(0, nb_schedule1); 36 end 37 38 endmodule
    复制代码

    執行結果

    复制代码
    # 1ns :$display: a=0 b=1 # 1ns :#0 : a=0 b=1 # 1ns :$monitor: a=1 b=0 # 1ns :$strobe : a=1 b=0 # # 2ns :$display: a=1 b=0 # 2ns :#0 : a=1 b=0 # 2ns :$monitor: a=1 b=0 # 2ns :$strobe : a=1 b=0
    复制代码
    文字檔部份
    1ns :$fwrite : a=0 b=1 2ns :$fwrite : a=1 b=0

    Debussy的nWave

    strobe00

    假如結果如你預期,恭喜你,那表示你的觀念非常清楚,如果不是,請你繼續往下看,我將會解釋這段範例程式。

    Verilog的『stratified event queue』

    我在(原創) 深入探討blocking與nonblocking (SOC) (Verilog)曾經討論過Verilog在Simulator內實際的運行方式,這裡再稍為提一下。

    在軟體的世界,程式碼基本上是一行一行地執行,也就是再同一個時間點,只有一件事情會發生;但在硬體的世界裡,電路卻可以平行執行,也就是在同一個時間點,有很多事情可以同時發生。我們現在要在一個只能『循序處理』的軟體去『模擬』能『平行處理』的硬體,勢必有些特殊的機制才行。

    在Simulator內,為了要模擬出硬體的平行處理機制,時間軸是個虛擬的時間軸,另外搭配了5個event queue,也就是說,當一個時間點的5個event queue內的所有程式碼都執行過後,時間軸才會自動加1,如此就很巧妙的『看起來』好像在同一個時間點作了很多事情,不過事實上對於軟體與CPU來說,依然是同一時間點只發生了一件事情。

    strobe01

    在IEEE Verilog Standard中定義了這5個Event Queue,依序討論如下:

    1.Active Events:

    大部分的Verilog程式碼都在此執行,其中包括以綠色字表示的blocking asignments以及continuous assignments (也就是用assign寫的),至於nonblocking部分,只執行RHS (Right Hand Side),也就是只執行nonblocking右測的部分,唯一用紅色表示的是本文所要討論的$display()與$fwrite(),也是屬於Active Events,值的注意的是,在Active Events中的程式碼,若是同一個時間點,且在同一個sequential block,程式碼是依序執行,但是IEEE Verilog Standard並不保證在同一個時間點,不同的sequential block內的程式碼誰先執行,也就是說若你寫的程式碼都屬於Active Events所執行,但分屬不同的sequential block,且彼此互相依賴,就可能出現Race Condition的情形發生

    當在Active Events的程式碼執行完後,會自動移出Active Events。

    2.Inactive Events

    當Active Events執行完後,Inactive Events的程式碼會依序變成Active Events而執行之。

    Inactive Events執行的是blocking assignments且帶#0 delay,因為是#0,所以理論上還是屬於同一個時間點,只是執行順序略晚於正常的blocking assignments,這也是為什麼遇到Race Condition時,常常加上#0就會正常,這就是因為#0是屬於Inactive Events,執行順序很明顯的在Active Events之後,因此不會有在Active Events內不保證誰先誰後執行,而造成Race Condition發生。

    很多人認為#0會在每個時間點的最後執行,這是個錯誤的觀念,事實上,#0只是在Inactive Events,比Nonblocking Events還要早。

    3.Nonblocking Events

    當Inactive Events執行完後,接著Nonblocking Event的程式碼會依序變成Active Events而執行之。

    Nonblocking Events執行的是nonblocking的LHS(Left Hand Side)部分,在此我們可以明確地發現,blocking發生在Active Events,而nonblocking雖然在Active Events已經執行了RHS,但真正完成LHS是在Nonblocking Events,也就是blocking會在nonblocking之前先完成。這也是為什麼同一個時間點,nonblocking可以讀到blocking所做的改變,但是blocking卻無法讀到nonblocking的改變,因為blocking已經先執行,必須要等到下一個clk edge才能讀到nonblocking所做的改變。

    除此之外,還有一個常見的迷思也可在此澄清,我們都知道寫sequential logic時要用nonblocking寫,事實上用blocking也是可以寫,只是blocking寫很容易造成Race Condition,要很小心注意其先後順序,但為什麼用nonblocking寫就不會有Race Condition呢?

    理由就在於nonblocking的RHS是在Active Events,而LHS是在Nonblocking Events,儘管彼此互相依賴,但Nonblocking Events很明顯地在Active Events之後,所以執行順序可以明確地確定,不像用blocking寫時,因為在Active Events內執行順序不確定,造成結果不可預期而產生Race Condition。

    4.Monitor Events

    當Nonblocking Events執行完後,接著Monitor Events的程式碼會依序變成Active Events而執行之。

    我們都知道$display()無法觀察nonblocking所改變的結果,必須要使用$strobe()才可以,這是為什麼呢?因為$display()是屬於Active Events,而nonblocking完成於Nonblocking Events,明顯在Active Events之後,所以$display()跟本欄不到nonblocking所造成的改變,必須使用比Nonblocking Events更晚執行的Monitor Events中的$strobe()才可以觀察到nonblocking所改變的結果。

    5.Verilog PLI Events

    當Monitor Events執行完後,接著Verilog PLI Events的程式碼會依序變成Active Events而執行之。

    Verilog PLI是允許你用C語言去寫一些Simulator的擴充功能,如Debussy / Verdi的$fsdbDumpfile()、$fsdbDumpvars()就是透過Verilog PLI,以前我ㄧ直搞不懂為什麼我用$display()與$fwrite()所dump的值與在Debussy / Verdi的nWave所看到的值不一樣,後來才發現原來$display()與$fwrite()是屬於Active Events,而$fsdbDumpfile()與$fsdbDumpvars是屬於Verilog PLI Events,比Nonblocking Events晚執行,這也是為什麼Debussy / Verdi可以顯示每個時間點nonblocking的值,而$display()與$fwrite()卻無法dump每個時間點的nonblocking,彼此的結果會差1個clock。

    blocking / nonblocking與$display()、$strobe()、$monitor()、$fwrite()的執行順序

    了解Verilog Simulator的『stratified event queue』之後,為了解釋nb_schedule1為什麼會有這樣的執行結果,我們將所有程式依照其在Event Queue的執行順序重新排列如下圖所示:

    strobe02 

    我們可以發現,儘管nonblocking與$monitor()、$strobe()寫在$display()與$fwrite()前面,但真正在執行時,Verilog Simulator還是會把它放在該放的Event Queue內,因為$display()與$fwrite()是放在Active Events,所以會印出a=0, b=1,接下來是Inactive Events的#0 $display(),也是顯示a=0, b=1,再過來是Nonblocking Events,執行 a <= b與b<=a,最後才是Monitor Events的$monitor()與$strobe(),因為nonblocking已經執行過,a與b的值已經改變,所以a=1, b=0,接下來因為a與b的值都不再改變,所以印出的值都不會再變。

    Debussy / Verdi的nWave與blocking / nonblocking的關係

    strobe03

    在nWave內,1 ns時,所顯示的是a=1, b=0,若你是用$display()與$fwrite()去dump資料時,會得到a=0, b=1,也就是說,$display()與$fwrite()看到的是blocking的值,而nWave看到的是nonblocking的值,因為$fsdbDumpfile()與$fsdbDumpvars()是在Verilog PLI Events,執行點是在Nonblocking Events之後。

    這也是為什麼有些工程師在寫sequential logic時,會在nonblocking加上#1,為的就是在Debussy / Verdi下看波形圖時比較好看,而Synthesizer會自動忽略nonblocking的#1,所以結果不會受影響。

    Conclusion
    1.因為blocking與nonblocking的關係,所以程式碼執行的順序不見的會依照我們所寫的順序,而是要依照『stratified event queue』的執行順序執行。

    2.若皆屬Active Events的程式碼,在同一個時間點,在同一個sequential block內會依序執行,但在不同的sequential block內就無法保證誰會先執行,若彼此依賴有相關,就有可能造成Race Condition。

    3.#0的blocking會比較晚一點執行,可以暫時解決Race Condition所造成的問題,不過這不是一個推薦的coding style,建議找出Race Condition的真正原因,而改用nonblocking去解決。

    4.#0並不是最後執行,只是在Inactive Events而已,比Active Events稍晚,但還是比Nonblocking Events早。

    5.Sequential logic也是可以用blocking寫,只是很容易造成Race Condition,必須很小心的安排blocking的執行順序,不是一個推薦的coding style。

    6.$display()只能觀察到blocking,無法觀察到nonblocking,若要觀察nonblocking,要使用$strobe()與$monitor()。

    7.$fsdbDumpfile()與$fsdbDumpvars()比$strobe()與$monitor()還晚執行,所以在Debussy / Verdi總是觀察到nonblocking的值,會比使用$display()與$fwrite()早1個clock。

    完整程式碼下載
    nb_schedule1.7z

    See Also
    (筆記)如何使用blocking與nonblocking assignment? (SOC) (Verilog)
    (原創) 深入探討blocking與nonblocking (SOC) (Verilog)

    Reference
    [1] Clifford E. Cummings 2000, Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kills, Sunburst Design, Inc.

    全文完。

    展开全文
  • Verilog行为仿真

    2020-08-30 13:57:14
    系统函数 显示 $display $strobe $monitor 仿真控制 ...对Verilog中用于验证的常用函数进行总结,方便以后使用。 2.系统函数 系统任务和系统函数的名字都是用字符"$"开头。 2.1 显示 $display 用于.
  • verilog语言中的文件读写原创: IC控 IC控 2月22日在Verilog语言中,对文件的读写一般用在编写testbench,而用到的系统函数大概有以下几种,首先是$fopen,然后是对文件的读或写$fread$fwrite,最后是关闭文件 $...
  • verilog系统函数用法

    2014-09-22 19:54:00
    1、$fwrite 向文件写入数据 $fdisplay 格式:$fwrite(fid,"%h%h\n",dout_r1,dout_r2); (1)fwrite是需要触发条件的,在一次触发条件之后也不会自动发生换行,所以要求手动添加换行。 (2)如果写放文件的格式为...
  • verilog常用系统函数

    2019-05-17 11:18:18
    1.打开文件  integer file_id;  file_id = fopen(...2.写入文件:$fmonitor,$fwrite,$fdisplay,$fstrobe  //$fmonitor只要有变化就一直记录  $fmonitor(file_id, "%format_char", parameter);  $fmonit...
  • verilog读取txt文件

    千次阅读 2018-11-12 10:42:50
    以前我一般常用到的系统函数只有几个:$readmemb,$readmemh,$display,$fmonitor,$fwrite,$fopen,$fclose等。通常需要对文件作预处理,才能用于Testbench读取。今天又尝试了几个其他的文件输入输出函数,不需要...
  • Verilog 中的fscanf函数的使用

    千次阅读 2019-08-31 19:51:05
    Verilog编写testbench时,系统函数比较常用的一般为display、display、display、fopen、fclose、fclose、fclose、fwrite、$fmonitor。但是关于对于读取文件中的数据所采用的fread、fscanf、fgets使用频率相对较少。...
  • verilog常用系统函数以及例子   1.打开文件  integer file_id;  file_id = fopen("file_path/file_name"); 2.写入文件:$fmonitor,$fwrite,$fdisplay,$fstrobe  //$fmonitor只要有...
  • 串并转换 1. 复习verilog语法 【选做题】 - 文件操作fopen fdisplay fwrite fclose ...这几个我真没用过,先给一个优秀的链接:FPGA篇(四)Verilog系统函数介绍($display,$fopen,$fscanf,$fwrite($fdispl...
  • Verilog系统函数(一) $display

    千次阅读 2019-05-03 23:48:21
    参考:FPGA篇(四)Verilog系统函数介绍($display,$fopen,$fscanf,$fwrite($fdisplay),$fclose,$random,$stop) 下面代码截自仿真文件部分: reg flag; //---------------------------------------...
  • 标签:verilog $fdisplay $fwrite 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://lihaichuan.blog.51cto.com/498079/981084 $fopen(...
  • 本次分享的主题是Verilog的语法中用fscanf函数读取txt文本文件中的数据,用fscanf函数读取txt文本文件中的数据,用fscanf函数读取txt文本文件中的数据,用fwrite函数将计算出的数据输出到txt文本文件。因为只是借鉴...
  • 1.打开文件  integer file_id;  file_id = fopen("file_...2.写入文件:$fmonitor,$fwrite,$fdisplay,$fstrobe  //$fmonitor只要有变化就一直记录  $fmonitor(file_id, "%format_char", parameter);  $f...
  • verilog读写文件(整理)

    万次阅读 2014-11-15 15:47:57
    以前我一般常用到的系统函数只有几个:$readmemb,$readmemh,$display,$fmonitor,$fwrite,$fopen,$fclose等。通常需要对文件作预处理,才能用于Testbench读取。今天又尝试了几个其他的文件输入输出函数,不需要...
  • SystemVerilog/Verilog提供的文件写入读取方法并不多,主要有两类。 第一类是writememb/writememh/readmemb/readmemh,第二类是$fscanf/$fwrite。第一类用法简单,但是功能弱,文件读取也不支持多维数组;第二类...
  • 要想同时输出到屏幕只要将打开文件得到的fd的最低位置1即可 integer fd; initial begin ... $fwrite(fd,"hello\n"); end 转载于:https://www.cnblogs.com/fbi888/archive/2013/06/...
  • VerilogModelsim文件操作($fopen,$fwrite,$fscanf,$fclose)使用While循环,如不是最后一行,则一直读取,类似c语言的while(!foef(fp_r)){}。转:系统函数$fopen用于打开一个文件,并还回一个整数指针.然后,$...
  • 2.写入文件:$fmonitor,$fwrite,$fdisplay,$fstrobe  //$fmonitor只要有变化就一直记录  $fmonitor(file_id, "%format_char", parameter);  $fmonitor(file_id, "%m: %t in1=%d o1=%h", $time, in1, o1); //$
  • $readmemb,$readmemh~读取...$fdisplay ,$fwrite ~只有当调用时,才会将数据写入“Dump”文件,二者的区别是,fdisplay自动加入回车换行; $fmonitor ~只要“检测”reg 的内容发生变化,就自动写入“Dump”文件;
  • 推荐一篇很不错的博文,对理解blocking 与 nonblocking等有很大帮助: ...http://www.cnblogs.com/oomusou/archive/2011/06/25/verilog_strobe.html 转载于:https://www.cnblogs.com/socquan/p/3310010.html...

空空如也

空空如也

1 2
收藏数 28
精华内容 11
关键字:

fwriteverilog