Verilog HDL項(xiàng)目式教程 課件 項(xiàng)目1、2 Verilog HDL綜述;數(shù)據(jù)流建模_第1頁(yè)
Verilog HDL項(xiàng)目式教程 課件 項(xiàng)目1、2 Verilog HDL綜述;數(shù)據(jù)流建模_第2頁(yè)
Verilog HDL項(xiàng)目式教程 課件 項(xiàng)目1、2 Verilog HDL綜述;數(shù)據(jù)流建模_第3頁(yè)
Verilog HDL項(xiàng)目式教程 課件 項(xiàng)目1、2 Verilog HDL綜述;數(shù)據(jù)流建模_第4頁(yè)
Verilog HDL項(xiàng)目式教程 課件 項(xiàng)目1、2 Verilog HDL綜述;數(shù)據(jù)流建模_第5頁(yè)
已閱讀5頁(yè),還剩118頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

任務(wù)1.1

VerilogHDL標(biāo)準(zhǔn)

任務(wù)1.2電路設(shè)計(jì)

任務(wù)1.3電路仿真任務(wù)1.1

VerilogHDL標(biāo)準(zhǔn)VerilogHDL目前有三個(gè)標(biāo)準(zhǔn):IEEE1364-1995、IEEE1364-2001和IEEE1364-2005。這三個(gè)標(biāo)準(zhǔn)分別發(fā)布于1995年、2001年、2005年,相應(yīng)的標(biāo)準(zhǔn)可簡(jiǎn)稱為Verilog-1995、Verilog-2001和Verilog-2005。VerilogHDL語(yǔ)言最初是于1983年由GatewayDesignAutomation公司為其模擬器產(chǎn)品開(kāi)發(fā)的硬件建模語(yǔ)言。由于該公司的模擬、仿真器產(chǎn)品廣泛使用VerilogHDL,因此該語(yǔ)言作為一種便于使用且實(shí)用的語(yǔ)言逐漸為眾多設(shè)計(jì)者所接受。開(kāi)放Verilog國(guó)際組織是促進(jìn)VerilogHDL發(fā)展的國(guó)際性組織。1992年OVI決定致力于推廣Verilog標(biāo)準(zhǔn)成為IEEE標(biāo)準(zhǔn)并于1995年獲得成功(稱之為IEEE1364-1995)。與Verilog-1995相比,Verilog-2001加入了很多有用的特性,這些特性可以提高設(shè)計(jì)的生產(chǎn)效率、綜合能力和驗(yàn)證效率。新特性包括:增加generate語(yǔ)句,簡(jiǎn)化模塊多次實(shí)例化或者選擇實(shí)例化;增強(qiáng)對(duì)多維數(shù)組的支持;增強(qiáng)文件I/O的操作;增加對(duì)task和function重入的支持;增加always@(*);增加新的端口聲明方式;等等。與Verilog-2001相比,Verilog-2005增加了Verilog-AMS,支持對(duì)集成的模擬和混合信號(hào)系統(tǒng)的建模,把寄存器類型改名為變量類型。2009年,IEEE1364-2005和IEEE1800-2005兩個(gè)部分合并成IEEE1800-2009。IEEE1800-2005和IEEE1800-2009都是SystemVerilog語(yǔ)言標(biāo)準(zhǔn)。SystemVerilog是硬件描述驗(yàn)證語(yǔ)言,是硬件描述語(yǔ)言和硬件驗(yàn)證語(yǔ)言的一個(gè)集成。本書所有代碼均符合VerilogHDL的IEEE1364-2001標(biāo)準(zhǔn)。關(guān)于VerilogHDL標(biāo)準(zhǔn)更多的內(nèi)容和細(xì)節(jié),請(qǐng)讀者自行查閱上述VerilogHDL標(biāo)準(zhǔn)。任務(wù)1.2?電

設(shè)

計(jì)HDL,全稱硬件描述語(yǔ)言,用來(lái)描述電路。采用HDL編寫電路描述文件時(shí),可用綜合工具生成電路網(wǎng)表文件。電路設(shè)計(jì)完成后,通常需要查看綜合后的電路。本書使用的綜合工具軟件是Vivado14。該版本支持VerilogHDL的IEEE1364-2001標(biāo)準(zhǔn)。另外,本書部分項(xiàng)目也用到了QuartusⅡ13軟件。關(guān)于Vivado14和QuartusⅡ13軟件的安裝和詳細(xì)使用說(shuō)明,本書不展開(kāi)介紹,感興趣的讀者可自行查閱相關(guān)資料。在電路設(shè)計(jì)過(guò)程中,可能會(huì)結(jié)合使用HDL和C語(yǔ)言。HDL與C語(yǔ)言兩者有本質(zhì)區(qū)別,如圖1-1所示。C語(yǔ)言是軟件語(yǔ)言,編譯后生成機(jī)器語(yǔ)言程序(機(jī)器語(yǔ)言程序是一系列指令),并使CPU執(zhí)行,并不生成硬件電路,CPU處理軟件指令需要取址、譯碼、執(zhí)行,代碼是串行執(zhí)行的。HDL是硬件描述語(yǔ)言,綜合后生成硬件電路,代碼是并行執(zhí)行的。在電路設(shè)計(jì)過(guò)程中,通常將C語(yǔ)言和HDL語(yǔ)言結(jié)合使用,具體表現(xiàn)在:(1)在電路設(shè)計(jì)中,C語(yǔ)言可以進(jìn)行先期的算法驗(yàn)證,待算法驗(yàn)證后再使用HDL語(yǔ)言來(lái)實(shí)現(xiàn),也就是使用C語(yǔ)言輔助硬件設(shè)計(jì)。(2)?C語(yǔ)言與VerilogHDL硬件描述語(yǔ)言相似,在完全理解了兩種語(yǔ)言的語(yǔ)法和功能,并具備了軟件思維和硬件思維之后,很容易將C語(yǔ)言的程序轉(zhuǎn)成VerilogHDL語(yǔ)言的程序。一、設(shè)計(jì)舉例【例1-1】

使用HDL語(yǔ)言描述一個(gè)非門。上述代碼中,將輸出Y描述為輸入A取反,可以使用綜合工具查看生成的電路。綜合的電路如圖1-2所示?!纠?-2】

使用HDL語(yǔ)言描述一個(gè)D觸發(fā)器。上述代碼中,復(fù)位時(shí)將q的值賦為0,在clk上升沿將d賦值給q。綜合的電路如圖1-3所示。上述電路設(shè)計(jì)涉及的知識(shí)點(diǎn)有:module結(jié)構(gòu)及其相關(guān)知識(shí)點(diǎn)、assign連續(xù)賦值語(yǔ)句、always過(guò)程語(yǔ)句。(1)?module結(jié)構(gòu)。module和endmodule是VerilogHDL的關(guān)鍵字,用來(lái)說(shuō)明模塊。每個(gè)模塊都可以理解為一顆特定功能的芯片。VerilogHDL程序是由模塊構(gòu)成的,每個(gè)模塊的內(nèi)容都嵌在module和endmodule兩個(gè)語(yǔ)句之間。每個(gè)模塊可實(shí)現(xiàn)特定的功能,且可進(jìn)行層次嵌套。因此,可將大型的數(shù)字電路設(shè)計(jì)分割成不同的小模塊來(lái)實(shí)現(xiàn)特定的功能,最后通過(guò)頂層模塊調(diào)用子模塊來(lái)實(shí)現(xiàn)整體功能。(2)端口屬性。每個(gè)模塊需進(jìn)行端口列表聲明,說(shuō)明輸入/輸出端口屬性,并對(duì)模塊的功能進(jìn)行描述。input和output是VerilogHDL的關(guān)鍵字,用來(lái)說(shuō)明模塊的端口屬性。端口屬性分別為input(輸入)、output(輸出)和inout(輸入/輸出)。另外,每個(gè)模塊需進(jìn)行端口列表聲明,說(shuō)明這些端口的輸入、輸出屬性。(3)信號(hào)類型。wire、reg是VerilogHDL語(yǔ)言的關(guān)鍵字,用來(lái)說(shuō)明模塊內(nèi)部信號(hào)的屬性,包括線網(wǎng)類型、寄存器類型等。在設(shè)計(jì)過(guò)程中,需要注意的是,wire通常用來(lái)說(shuō)明在assign語(yǔ)句中被賦值的變量;reg通常用來(lái)說(shuō)明在initial語(yǔ)句或always語(yǔ)句中被賦值的變量。(4)注釋語(yǔ)句??梢杂?*…*/和//…對(duì)VerilogHDL程序的任何部分作注釋。一個(gè)有使用價(jià)值的源程序都應(yīng)當(dāng)加上必要的注釋,以增強(qiáng)程序的可讀性和可維護(hù)性。(5)書寫格式。VerilogHDL程序的書寫格式自由,一行可以寫幾個(gè)語(yǔ)句,也可以一個(gè)語(yǔ)句分寫多行。除了endmodule語(yǔ)句外,VerilogHDL程序中每個(gè)語(yǔ)句和數(shù)據(jù)定義的最后必須有分號(hào)。(6)?assign連續(xù)賦值語(yǔ)句。assign是VerilogHDL語(yǔ)言的關(guān)鍵字,用來(lái)說(shuō)明模塊內(nèi)部信號(hào)的連接關(guān)系。語(yǔ)句“assignY?=?~A;”的功能是:當(dāng)A?=?1時(shí),Y?=?0;當(dāng)A?=?0時(shí),Y?=?1。assign語(yǔ)句常用于實(shí)現(xiàn)簡(jiǎn)單的組合邏輯電路。(7)?always過(guò)程語(yǔ)句。always是VerilogHDL語(yǔ)言的關(guān)鍵字,用來(lái)說(shuō)明模塊的行為。always語(yǔ)句常用于實(shí)現(xiàn)時(shí)序邏輯電路和復(fù)雜的組合邏輯電路。二、查看電路圖代碼設(shè)計(jì)完成后,可以使用綜合工具查看電路圖。例如,QuartusⅡ、Vivado、DesignCompiler等都可用于查看綜合后的電路圖。Vivado設(shè)計(jì)套件是FPGA廠商Xilinx公司2012年發(fā)布的集成設(shè)計(jì)環(huán)境,包括高度集成的設(shè)計(jì)環(huán)境和新一代從系統(tǒng)到IC級(jí)的工具。本書使用的集成開(kāi)發(fā)環(huán)境是Vivado2014.4。QuartusⅡ是Altera公司的綜合性PLD/FPGA開(kāi)發(fā)軟件。本書使用的集成開(kāi)發(fā)環(huán)境是QuartusⅡ13.1。Vivado和QuartusⅡ均支持原理圖、VHDL、VerilogHDL等多種設(shè)計(jì)輸入形式,內(nèi)嵌自有的綜合器以及仿真器,可完成從設(shè)計(jì)輸入到硬件配置的完整設(shè)計(jì)流程。下面以Vivado為例來(lái)說(shuō)明查看綜合后的電路圖的步驟。1.創(chuàng)建新工程(1)打開(kāi)“Vivado2014.4”設(shè)計(jì)開(kāi)發(fā)軟件,選擇“CreateNewProject”,如圖1-4所示。(2)在彈出的創(chuàng)建新工程的界面中,點(diǎn)擊“Next”按鈕,開(kāi)始創(chuàng)建新工程,如圖1-5所示。(3)在“ProjectName”界面中,將工程名稱修改為“sw_led_vavido”,并設(shè)置好工程存放路徑。同時(shí)勾選上創(chuàng)建工程子目錄的選項(xiàng)。這樣整個(gè)工程文件都將存放在創(chuàng)建的“sw_led_vavido”子目錄中。然后,點(diǎn)擊“Next”按鈕,如圖1-6所示。(4)在選擇工程類型的界面中,選擇RTL工程。由于本工程需要?jiǎng)?chuàng)建源文件,因此,無(wú)須將“Donotspecifysourcesatthistime”(不指定添加源文件)勾選上。然后,點(diǎn)擊“Next”按鈕,如圖1-7所示。(5)在創(chuàng)建或添加Verilog源文件界面中,暫時(shí)先不新建或添加源文件。點(diǎn)擊“Next”按鈕,如圖1-8所示。(6)在創(chuàng)建或添加約束文件界面中,暫時(shí)先不新建或添加約束文件。點(diǎn)擊“Next”按鈕,如圖1-9所示。(7)在器件板卡選型界面中,不選擇任何器件,直接點(diǎn)擊“Next”按鈕。(8)在新工程總結(jié)界面中,檢查工程創(chuàng)建是否有誤。沒(méi)有問(wèn)題,則點(diǎn)擊“Finish”按鈕,完成新工程的創(chuàng)建。2.添加和編輯源文件(1)點(diǎn)擊“ProjectManager”目錄下的“AddSources”,如圖1-10所示。(2)選擇添加源文件。點(diǎn)擊“Next”按鈕,如圖1-11所示。(3)點(diǎn)擊“CreateFile…”,創(chuàng)建新文件。在彈出的對(duì)話框中輸入文件名“sw_led_vivado”,點(diǎn)擊“OK”按鈕進(jìn)行新建,如圖1-12所示。(4)在彈出的模塊定義對(duì)話框中,保持默認(rèn),點(diǎn)擊“OK”按鈕后,在彈出的模塊保存對(duì)話框中點(diǎn)擊“Yes”按鈕,完成源文件的創(chuàng)建。(5)雙擊“sw_led_vivado.v”,在出現(xiàn)的源文件編輯框中完成源文件的編輯,如圖1-13所示。3.查看RTL電路圖RTL原理圖不是設(shè)計(jì)開(kāi)發(fā)描述工具,而是綜合器輸出的一個(gè)結(jié)果。在FPGA應(yīng)用開(kāi)發(fā)過(guò)程中,可以通過(guò)“RTLANALYSIS→Schematic”查看電路圖,如圖1-14所示。圖1-3就是通過(guò)這種方法查看D觸發(fā)器的電路圖。

“RTLANALYSIS→Schematic”功能在自頂向下的層級(jí)設(shè)計(jì)中,常用于檢查模塊端口間的連接是否正確,是一個(gè)比較實(shí)用的工具。在本書的后續(xù)章節(jié)中會(huì)使用這一工具給出電路原理圖,說(shuō)明模塊間的連接關(guān)系;同時(shí),在電路圖的設(shè)計(jì)過(guò)程中,也常用這個(gè)工具來(lái)排查錯(cuò)誤,尤其是模塊間的連接錯(cuò)誤。另外,使用其他綜合工具也可以查看電路圖,如QuartusⅡ、DesignCompiler等。但在其他綜合工具中查看的電路圖與Vivado中的電路圖在外觀上不太一致,如例1-2,在QuartusⅡ中查看到的電路圖如圖1-15所示。任務(wù)1.3?電

仿

真HDL語(yǔ)言描述的電路功能是否正常,可以使用仿真來(lái)驗(yàn)證。本書中的項(xiàng)目使用的仿真工具軟件是ModelSim10.0,該版本支持VerilogHDL的IEEE1364-2001標(biāo)準(zhǔn)。本任務(wù)詳細(xì)介紹了Verilog的仿真技術(shù)。因?yàn)榭删C合的語(yǔ)法是Verilog語(yǔ)法的一個(gè)子集,所以讀者要全面了解VerilogHDL的強(qiáng)大功能,就必須詳細(xì)全面地了解VerilogHDL語(yǔ)法,且為了配合對(duì)各種語(yǔ)法進(jìn)行仿真分析,還需要借助ModelSim軟件。ModelSim是一種功能強(qiáng)大的仿真軟件,不僅支持向量波形文件的仿真,還支持文本文件的仿真。一、仿真舉例【例1-3】

使用HDL語(yǔ)言對(duì)非門進(jìn)行驗(yàn)證。//顯示輸出,aa或yy有變化時(shí)才打印信息上述代碼可以實(shí)現(xiàn)對(duì)非門的仿真,仿真圖形如圖1-16所示?!纠?-4】

使用HDL語(yǔ)言對(duì)D觸發(fā)器進(jìn)行驗(yàn)證。上述代碼可以實(shí)現(xiàn)對(duì)D觸發(fā)器的仿真,仿真圖形如圖1-18所示。上述電路仿真涉及的知識(shí)點(diǎn)有testbench、模塊例化、initial過(guò)程語(yǔ)句、延時(shí)仿真、多變量處理、循環(huán)語(yǔ)句、系統(tǒng)函數(shù)、仿真軟件force功能等。下面對(duì)這些知識(shí)點(diǎn)進(jìn)行說(shuō)明。(1)?testbench。testbench是一種驗(yàn)證手段。任何設(shè)計(jì)都會(huì)有輸入/輸出,但是在軟環(huán)境中沒(méi)有激勵(lì)輸入,也不會(huì)對(duì)設(shè)計(jì)的輸出的正確性進(jìn)行評(píng)估,因此testbench就應(yīng)運(yùn)而生了。testbench是一種“虛擬平臺(tái)”,俗稱測(cè)試臺(tái),模擬實(shí)際環(huán)境的輸入激勵(lì)和輸出校驗(yàn)的產(chǎn)生,可以對(duì)設(shè)計(jì)從軟件層面上進(jìn)行分析和校驗(yàn)。測(cè)試臺(tái)mynot_tb的主要功能是為mynot模塊提供輸入激勵(lì)信號(hào);測(cè)試模塊mydff_tb的主要功能是為mydff模塊提供輸入激勵(lì)信號(hào)。(2)模塊例化。測(cè)試臺(tái)調(diào)用設(shè)計(jì)代碼稱為例化。非門測(cè)試的例化語(yǔ)句形式為其中,A和Y為設(shè)計(jì)代碼中的端口信號(hào)名,aa和yy為測(cè)試代碼中相對(duì)應(yīng)的信號(hào)名。通過(guò)為aa增加激勵(lì),可以觀察輸出yy的響應(yīng)。這種例化方式稱為名稱關(guān)聯(lián)例化。D觸發(fā)器測(cè)試的例化語(yǔ)句形式為mydffUU(clk,rst,d,q);其中,clk、rst、d、q均為測(cè)試模塊中的信號(hào),而沒(méi)有出現(xiàn)設(shè)計(jì)模塊中的信號(hào)名,這種例化的信號(hào)傳遞是由信號(hào)在端口中的位置決定的。這種例化方式稱為位置關(guān)聯(lián)例化。應(yīng)注意測(cè)試臺(tái)中的變量聲明與被例化的設(shè)計(jì)模塊中的端口類型說(shuō)明。例如,測(cè)試模塊mynot_tb中aa為reg類型,而在設(shè)計(jì)模塊mynot中A為wire類型。測(cè)試模塊mydff_tb和設(shè)計(jì)模塊mydff,其中的端口類型也是類似的,測(cè)試模塊mydff_tb中的clk、rst、d等變量均定義成了reg類型,而在設(shè)計(jì)模塊中這些相應(yīng)的端口均為wire類型。(3)?initial過(guò)程語(yǔ)句。initial是VerilogHDL語(yǔ)言的關(guān)鍵字,用來(lái)為輸入信號(hào)添加激勵(lì)。在測(cè)試臺(tái)mynot_tb中,為aa賦值20次,每次間隔10個(gè)時(shí)間單位,所賦的值是隨機(jī)產(chǎn)生的。(4)延時(shí)仿真。#N表示的是延時(shí)N個(gè)時(shí)間單位。時(shí)間單位通過(guò)?'timescale進(jìn)行說(shuō)明。在測(cè)試臺(tái)mynot_tb中,repeat(20)#10aa=($random)%2;就是重復(fù)20次操作,每次操作的間隔為10個(gè)時(shí)間單位。(5)多變量處理。當(dāng)需要為多個(gè)變量設(shè)置激勵(lì)時(shí),雖然可以將所有激勵(lì)寫在一個(gè)initial語(yǔ)句塊或一個(gè)always語(yǔ)句塊中,但當(dāng)設(shè)計(jì)輸入信號(hào)多且變化情況也多時(shí),則信號(hào)激勵(lì)的產(chǎn)生會(huì)不太清晰,甚至?xí)斐蛇壿嫽靵y。因此,建議為每個(gè)變量單獨(dú)設(shè)置激勵(lì),即一個(gè)變量的激勵(lì)設(shè)置僅在一個(gè)initial語(yǔ)句塊或一個(gè)always語(yǔ)句塊中處理。在測(cè)試臺(tái)mydff_tb中,clk、rst、d都是進(jìn)行單獨(dú)設(shè)置激勵(lì)的。(6)循環(huán)語(yǔ)句。forever和repeat用于執(zhí)行循環(huán),前者表示循環(huán)次數(shù)無(wú)限;后者表示循環(huán)次數(shù)有限,且在其后括號(hào)中說(shuō)明循環(huán)次數(shù)。循環(huán)語(yǔ)句在仿真中較常用,使用循環(huán)語(yǔ)句設(shè)置激勵(lì)比較高效實(shí)用。(7)系統(tǒng)函數(shù)。調(diào)用系統(tǒng)函數(shù)時(shí)應(yīng)在函數(shù)名前加?$。下面對(duì)例中的系統(tǒng)函數(shù)的作用進(jìn)行說(shuō)明。stop函數(shù)用來(lái)停止仿真。monitor和display函數(shù)用來(lái)顯示當(dāng)前變量值。monitor與display的區(qū)別是:前者是待顯示變量有變化時(shí)就會(huì)顯示該變量的值,而display只顯示一次。realtime函數(shù)用于顯示當(dāng)前仿真時(shí)間。(8)仿真軟件force功能。對(duì)于初學(xué)者,在ModelSim軟件中,除了編寫測(cè)試臺(tái)仿真外,也可以直接使用軟件中的force按鈕產(chǎn)生激勵(lì)進(jìn)行仿真。使用force按鈕產(chǎn)生激勵(lì)的優(yōu)點(diǎn)是不用寫測(cè)試臺(tái)程序,可以直接針對(duì)設(shè)計(jì)的輸入設(shè)置相應(yīng)的激勵(lì),然后直接觀察設(shè)計(jì)的仿真結(jié)果。這種方法在一些簡(jiǎn)單設(shè)計(jì)中比較直觀,減少了初學(xué)者編寫測(cè)試臺(tái)的干擾,對(duì)初學(xué)者學(xué)習(xí)語(yǔ)法和理解設(shè)計(jì)代碼有一定的幫助。但對(duì)于熟悉HDL語(yǔ)言的開(kāi)發(fā)者來(lái)說(shuō),建議在測(cè)試臺(tái)上進(jìn)行仿真。二、基于ModelSim的仿真步驟1.創(chuàng)造ModelSim工程(1)點(diǎn)擊“開(kāi)始→程序→ModelSimSE-6410.0c”或雙擊桌面上的快捷方式,打開(kāi)ModelSim軟件。(2)點(diǎn)擊“File→New→Project”,出現(xiàn)如圖1-19所示的界面,在“ProjectName”中輸入建立的工程名字“MyPrj”,在“ProjectLocation”中輸入工程保存的路徑為“D:/BOOK_HDL”。注意:ModelSim不能為一個(gè)工程自動(dòng)建立一個(gè)目錄,創(chuàng)建者應(yīng)自己在ProjectLocation中輸入路徑來(lái)為工程建立目錄,使用自己創(chuàng)建的目錄;在“DefaultLibraryName”中設(shè)置設(shè)計(jì)編譯后存放的目標(biāo)庫(kù),使用默認(rèn)值。(3)編譯設(shè)計(jì)文件后,在Workspace窗口的Library中會(huì)出現(xiàn)work庫(kù)。完成各項(xiàng)設(shè)置后,點(diǎn)擊“OK”按鈕。2.添加工程文件在如圖1-20所示的界面中,可以點(diǎn)擊不同的圖標(biāo)來(lái)為工程添加不同的項(xiàng)目。點(diǎn)擊“CreateNewFile”可以為工程添加新建的文件,點(diǎn)擊“AddExistingFile”為工程添加已經(jīng)存在的文件,點(diǎn)擊“CreateSimulation”為工程添加仿真,點(diǎn)擊“CreateNewFolder”可以為工程添加新的目錄。這里我們點(diǎn)擊“CreateNewFile”。(1)點(diǎn)擊“CreateNewFile”,出現(xiàn)如圖1-21所示的界面。(2)在“FileName”框中輸入“MyFile”。在“Addfileastype”下拉框中選擇“Verilog”,如圖1-21所示,點(diǎn)擊“OK”按鈕。(3)打開(kāi)“MyFile.v”文件,錄入設(shè)計(jì)代碼和測(cè)試代碼,代碼文件如下所示?!纠?-5】

計(jì)數(shù)器的設(shè)計(jì)代碼和測(cè)試代碼。上述設(shè)計(jì)代碼和測(cè)試代碼均寫在一個(gè)文件中。實(shí)際開(kāi)發(fā)過(guò)程中,也可以將設(shè)計(jì)代碼和測(cè)試代碼分別寫入兩個(gè)不同名稱的文件。錄入代碼后,如圖1-22所示。3.編譯工程通過(guò)圖1-23可以看出,在Workspace窗口中的“Project”選項(xiàng)卡里,“MyFile.v”文件狀態(tài)欄有問(wèn)號(hào),這表示該文件未曾編譯或者編譯后又進(jìn)行了修改。對(duì)文件的編譯過(guò)程如下:(1)選擇“Compile→CompileSelected”或者“Compile→CompileAll”,如圖1-23所示。(2)在命令窗口中將出現(xiàn)“#CompileofMyfile.vwassuccessful.”,且在狀態(tài)欄后有一對(duì)號(hào),表示編譯成功,如圖1-24所示。如果編譯出錯(cuò),則可以雙擊錯(cuò)誤彈出錯(cuò)誤的提示信息,然后根據(jù)提示進(jìn)行排錯(cuò)。排錯(cuò)后再次編譯,如果編譯還出錯(cuò),就繼續(xù)排錯(cuò),直到編譯成功為止。4.仿真(1)選擇“Library”標(biāo)簽,出現(xiàn)如圖1-25所示的界面。(2)展開(kāi)“work”庫(kù),并選中其中的“counter_tb”,即頂層測(cè)試模塊,也是所要仿真的對(duì)象。選中后單擊右鍵,選擇“Simulationwithoutoptimization”后,彈出如圖1-26所示的界面,在該界面中可以看到sim標(biāo)簽頁(yè)和Wave標(biāo)簽頁(yè),表明仿真設(shè)置成功。(3)為了觀察波形窗口,需要為該窗口添加需要觀察的對(duì)象,首先,在主窗口勾選“View→debugWindows→Objects”,打開(kāi)信號(hào)列表窗口如圖1-27所示,在該窗口中點(diǎn)擊“Add→ToWave→SignalsinRegion”,在波形窗口中就可以看到clk、rst和cnt信號(hào)。(4)在主窗口中輸入“run1μs”后回車,表示運(yùn)行仿真1μs,仿真時(shí)CPU的利用率一直為100%,如果仿真較慢,則還可以觀察狀態(tài)欄里的當(dāng)前仿真時(shí)間。(5)仿真完成后,點(diǎn)擊Wave標(biāo)簽頁(yè),可以看到仿真波形。5.功能仿真結(jié)果分析首先,給Wave窗口增加一個(gè)cnt,并將其中一個(gè)cnt設(shè)置成無(wú)符號(hào)十進(jìn)制,即“unsigned”,另一個(gè)cnt設(shè)置成模擬信號(hào)輸出,即“Analog”,設(shè)置界面如圖1-28所示。按圖1-28所示,將“Radix”設(shè)置為“unsigned”,將“Format”設(shè)置為“Analog”。設(shè)置完成后,仿真波形如圖1-29所示。根據(jù)仿真結(jié)果可知,該設(shè)計(jì)實(shí)現(xiàn)了一個(gè)0~15的計(jì)數(shù)器。如果外加DAC器件將數(shù)字量變成模擬量,該設(shè)計(jì)則很容易產(chǎn)生一個(gè)鋸齒波。三、結(jié)構(gòu)化過(guò)程語(yǔ)句InitialInitial語(yǔ)句通常用于仿真過(guò)程中對(duì)輸入信號(hào)執(zhí)行一次添加激勵(lì)的操作。所有在initial語(yǔ)句內(nèi)的語(yǔ)句構(gòu)成了一個(gè)initial塊。initial塊從仿真0時(shí)刻開(kāi)始執(zhí)行,在整個(gè)仿真過(guò)程中只執(zhí)行一次。如果一個(gè)模塊中包括了若干個(gè)initial塊,則這些initial塊從仿真0時(shí)刻開(kāi)始并發(fā)執(zhí)行,且每個(gè)initial塊的執(zhí)行是各自獨(dú)立的。initial塊的使用類似于always塊(always語(yǔ)句將在“任務(wù)4.1”中進(jìn)行詳細(xì)描述),塊內(nèi)使用的語(yǔ)句必須是行為語(yǔ)句,應(yīng)用于always塊內(nèi)的語(yǔ)句均可應(yīng)用于initial塊。在一個(gè)模塊內(nèi),可同時(shí)包括若干個(gè)initial塊和若干個(gè)always塊,所有這些塊均從仿真0時(shí)刻開(kāi)始并發(fā)執(zhí)行,且每個(gè)塊的執(zhí)行是各自獨(dú)立的。如果在initial塊內(nèi)包含了多條行為語(yǔ)句,則需要將這些語(yǔ)句組成一組,使用關(guān)鍵字begin和end(或者fork和join)將它們組合為一個(gè)塊語(yǔ)句;如果塊內(nèi)只有一條語(yǔ)句,則無(wú)須使用關(guān)鍵字begin和end(或者fork和join)。這一點(diǎn)類似于C語(yǔ)言中的復(fù)合語(yǔ)句{}。initial語(yǔ)句的格式如下:由于initial塊語(yǔ)句在整個(gè)仿真期間只能執(zhí)行一次,因此,它一般用于初始化、信號(hào)監(jiān)視、生成仿真波形等。下面舉例說(shuō)明initial語(yǔ)句的使用?!纠?-6】initial塊語(yǔ)句舉例。程序說(shuō)明:(1)程序中各變量的波形圖如圖1-30所示。從圖1-30中的仿真波形可以看出,多個(gè)initial塊都是從仿真0時(shí)刻開(kāi)始并發(fā)執(zhí)行的。(2)程序中,一個(gè)initial語(yǔ)句僅對(duì)應(yīng)著一個(gè)變量的賦值,使程序簡(jiǎn)潔易懂。(3)塊內(nèi)的語(yǔ)句按順序執(zhí)行,即只有上面一條語(yǔ)句執(zhí)行完后,下面的語(yǔ)句才能執(zhí)行。(4)每條語(yǔ)句的延時(shí)時(shí)間是相對(duì)于前一條語(yǔ)句的仿真時(shí)間而言的。(5)直到最后一條語(yǔ)句執(zhí)行完,程序流程控制才跳出該initial語(yǔ)句塊。(6)在仿真過(guò)程中,如果某條語(yǔ)句前面存在延時(shí),那么對(duì)這條語(yǔ)句的仿真將會(huì)停頓下來(lái),經(jīng)過(guò)指定的延時(shí)時(shí)間之后再繼續(xù)執(zhí)行(可結(jié)合代碼和波形圖進(jìn)行理解)。(7)在程序的for語(yǔ)句中加入延時(shí),是為了看清楚初始化過(guò)程。(8)在VerilogHDL中,可以給每個(gè)順序塊和并行塊取一個(gè)名字,只需將名字加在關(guān)鍵詞begin或fork后面即可。這樣做的原因有以下幾點(diǎn):①

可以在塊內(nèi)定義局部變量,即只在塊內(nèi)使用的變量,本例為變量t。②

可以允許塊被其他語(yǔ)句調(diào)用,如被disable語(yǔ)句調(diào)用。③

在Verilog語(yǔ)言里,所有的變量都是靜態(tài)的,即所有的變量都只有一個(gè)唯一的存儲(chǔ)地址,因此,進(jìn)入或跳出塊并不影響存儲(chǔ)在變量?jī)?nèi)的值?;谝陨显?,塊名就提供了一個(gè)可在任何仿真時(shí)刻確認(rèn)變量值的方法。(9)本例中,可使用fork…join替換begin…end,讀者可以學(xué)習(xí)體會(huì)兩者的區(qū)別。fork…join語(yǔ)句塊中,所有語(yǔ)句均是并行的,每條語(yǔ)句的執(zhí)行時(shí)刻僅與該語(yǔ)句前面的延時(shí)相關(guān),與其他語(yǔ)句的延時(shí)無(wú)關(guān)。(10)從本例可以看出,initial語(yǔ)句的用途之一,是初始化各變量;initial語(yǔ)句的另一用途,是用initial語(yǔ)句來(lái)生成激勵(lì)波形作為電路的測(cè)試仿真信號(hào),如圖1-30中的x即可用作電路的激勵(lì)信號(hào)。initial塊常用于測(cè)試文件的編寫,用來(lái)產(chǎn)生仿真測(cè)試信號(hào)和設(shè)置信號(hào)記錄等仿真環(huán)境。四、延時(shí)仿真設(shè)計(jì)電路時(shí),描述的電路都是無(wú)延時(shí)的。而在實(shí)際的電路中,任何一個(gè)邏輯門都具有延時(shí),Verilog允許用戶通過(guò)延時(shí)語(yǔ)句來(lái)說(shuō)明邏輯電路中的延時(shí)。通常,在測(cè)試激勵(lì)塊中都需要使用延時(shí),下面將對(duì)延時(shí)作進(jìn)一步說(shuō)明。信號(hào)在電路中傳輸會(huì)有傳播延時(shí),如線延時(shí)、器件延時(shí)等。所謂延時(shí)就是對(duì)延時(shí)特性的HDL描述,舉例如下:assign#2B=A;表示B信號(hào)在2個(gè)時(shí)間單位后得到A信號(hào)的值,如圖1-31所示。在VerilogHDL中,所有延時(shí)都必須根據(jù)時(shí)間單位進(jìn)行定義,定義的方法是在module前添加如下語(yǔ)句:`timescale1ns/100ps其中,`timescale是VerilogHDL提供的編譯預(yù)處理命令,1?ns表示時(shí)間單位是1?ns,100?ps表示時(shí)間精度是100ps。根據(jù)該命令,編譯工具才可以認(rèn)知?#2為2?ns。在VerilogHDL的IEEE標(biāo)準(zhǔn)中,沒(méi)有規(guī)定時(shí)間單位的缺省值,由各仿真工具確定。因此,在編寫代碼時(shí)必須確定時(shí)間單位。在Verilog中,時(shí)序控制起著非常重要的作用,它使得設(shè)計(jì)者可以指定賦值發(fā)生的時(shí)刻,進(jìn)而控制仿真時(shí)間的推進(jìn)過(guò)程?;谘訒r(shí)的時(shí)序控制出現(xiàn)在表達(dá)式中,它指定了語(yǔ)句開(kāi)始執(zhí)行到執(zhí)行完成之間的時(shí)間間隔。延時(shí)值可以是數(shù)字、標(biāo)識(shí)符或表達(dá)式,但需要在延時(shí)值加上關(guān)鍵字?#。`timescale命令用來(lái)說(shuō)明跟在該命令后的模塊的時(shí)間單位和時(shí)間精度。使用`timescale命令可以在同一個(gè)設(shè)計(jì)里包含采用了不同的時(shí)間單位的模塊。例如,一個(gè)設(shè)計(jì)中包含了兩個(gè)模塊,其中一個(gè)模塊的時(shí)間延時(shí)單位為ns,另一個(gè)模塊的時(shí)間延時(shí)單位為ps,EDA工具仍然可以對(duì)這個(gè)設(shè)計(jì)進(jìn)行仿真測(cè)試。`timescale命令的格式如下:`timescale<時(shí)間單位>/<時(shí)間精度>在這條命令中,時(shí)間單位參量用來(lái)定義模塊中仿真時(shí)間和延時(shí)時(shí)間的基準(zhǔn)單位。時(shí)間精度參量用來(lái)聲明該模塊的仿真時(shí)間的精確程度,該參量被用來(lái)對(duì)延時(shí)時(shí)間值進(jìn)行取整操作(仿真前),因此,該參量又被稱為取整精度。如果在同一個(gè)程序設(shè)計(jì)里,存在多個(gè)`timescale命令,則用最小的時(shí)間精度值來(lái)決定仿真的時(shí)間單位。另外,時(shí)間精度要和時(shí)間單位一樣精確,時(shí)間精度值不能大于時(shí)間單位值。在?`timescale命令中,用于說(shuō)明時(shí)間單位和時(shí)間精度參量值的數(shù)字必須是整數(shù),其有效數(shù)字為1、10、100,單位為秒(s)、毫秒(ms)、微秒(μs)、納秒(ns)、皮秒(ps)等。這幾種單位的意義見(jiàn)表1-1的說(shuō)明。下面舉例說(shuō)明`timescale命令的用法?!纠?-7】`timescale命令的用法舉例。程序運(yùn)行結(jié)果如圖1-32所示。程序說(shuō)明:(1)?`timescale命令定義了模塊test的時(shí)間單位為10?ns、時(shí)間精度為1?ns。在這個(gè)命令之后,模塊中所有的時(shí)間值都是10?ns的倍數(shù),并且可表達(dá)為帶一位小數(shù)的實(shí)型數(shù),這是因?yàn)?`timescale命令定義的時(shí)間精度為時(shí)間單位的1/10。(2)參數(shù)d?=?1.37,根據(jù)時(shí)間精度,d的值應(yīng)為1.4(四舍五入),再根據(jù)時(shí)間單位,d所代表的時(shí)間為14ns(即1.4?×?10?ns)。(3)?#dset?=?0;中,d為延時(shí)值,#d表示延時(shí)d秒,整個(gè)句子表達(dá)的意思是延時(shí)d秒后再將set賦值為0。延時(shí)值可以是數(shù)字、標(biāo)識(shí)符或表達(dá)式,表示延時(shí)時(shí)需要在延時(shí)值前加上關(guān)鍵字?#。(4)本例的仿真過(guò)程為:在仿真時(shí)刻為14?ns時(shí),寄存器set被賦值0;在仿真時(shí)刻為28ns時(shí),寄存器set被賦值1。五、仿真常用系統(tǒng)函數(shù)和任務(wù)VerilogHDL語(yǔ)言中有以下系統(tǒng)函數(shù)和任務(wù):$bitstoreal、$rtoi、$display、$setup、$finish、$skew、$hold、$setuphold、$itor、$strobe、$period、$time、$printtimescale、$timefoemat、$realtime、$width、$realtobits、$write、$recovery等。VerilogHDL語(yǔ)言中的每個(gè)系統(tǒng)函數(shù)和任務(wù)前面都應(yīng)用一個(gè)標(biāo)識(shí)符?$?來(lái)加以確認(rèn)。這些系統(tǒng)函數(shù)和任務(wù)提供了非常強(qiáng)大的功能,有興趣的讀者可以參閱相關(guān)書籍。下面僅對(duì)一些常用的系統(tǒng)函數(shù)和任務(wù)進(jìn)行介紹。1.系統(tǒng)任務(wù)$display、$write和$strobe格式:這三個(gè)函數(shù)和系統(tǒng)任務(wù)的作用是用來(lái)輸出信息,即將參數(shù)p2~pn按參數(shù)p1給定的格式輸出。參數(shù)p1通常稱為“格式控制”,參數(shù)p2~pn通常稱為“輸出表列”。這三個(gè)任務(wù)的作用基本相同。$display在輸出后自動(dòng)地進(jìn)行換行,$write則不是這樣,如果想在一行里輸出多個(gè)信息,可以使用$write;$strobe是在同一仿真時(shí)刻的其他語(yǔ)句執(zhí)行完成之后才執(zhí)行。在$display、$write和$strobe中,其輸出格式控制是用雙引號(hào)括起來(lái)的字符串,它包括兩種信息:格式說(shuō)明和普通字符。(1)格式說(shuō)明由“%”和格式字符組成,它的作用是將輸出的數(shù)據(jù)轉(zhuǎn)換成指定的格式輸出。格式說(shuō)明總是由“%”字符開(kāi)始的,對(duì)于不同類型的數(shù)據(jù)用不同的格式輸出。表1-2中給出了常用的幾種輸出格式。(2)普通字符即需要原樣輸出的字符。其中一些特殊的字符可以通過(guò)表1-3中的轉(zhuǎn)換序列來(lái)輸出。表1-3中的字符形式用于格式字符串參數(shù)中,用來(lái)顯示特殊的字符。在?$display和?$write的參數(shù)列表中,其“輸出表列”是需要輸出的一些數(shù)據(jù),可以是表達(dá)式。下面舉幾個(gè)示例進(jìn)行說(shuō)明?!纠?-8】$display應(yīng)用舉例。

其輸出結(jié)果如圖1-33所示。程序說(shuō)明:(1)使用?$display時(shí),輸出列表中數(shù)據(jù)的顯示寬度是自動(dòng)按照輸出格式進(jìn)行調(diào)整的。因此,在顯示輸出數(shù)據(jù)并經(jīng)過(guò)格式轉(zhuǎn)換以后,總是用表達(dá)式的最大可能值所占的位數(shù)來(lái)顯示表達(dá)式的當(dāng)前值。在用十進(jìn)制數(shù)格式輸出時(shí),輸出結(jié)果前面的0值用空格來(lái)代替。對(duì)于其他進(jìn)制,輸出結(jié)果前面的0仍然顯示出來(lái)。對(duì)于一個(gè)位寬為7位的值,如按照十六進(jìn)制數(shù)輸出,則輸出結(jié)果占2個(gè)字符的位置,如按照十進(jìn)制數(shù)輸出,則輸出結(jié)果占3個(gè)字符的位置。這是因?yàn)檫@個(gè)表達(dá)式的最大可能值為7F(十六進(jìn)制)或127(十進(jìn)制)。因此,可以通過(guò)在%和表示進(jìn)制的字符中間插入一個(gè)0,自動(dòng)調(diào)整顯示輸出數(shù)據(jù)寬度的方式,使輸出時(shí)總是用最少的位數(shù)來(lái)顯示表達(dá)式的當(dāng)前值。例如:$display("hex:%0h,decimal:%0d",a,a);(2)如果輸出列表中表達(dá)式的值包含有不確定的值或高阻值時(shí),其結(jié)果輸出應(yīng)遵循一定的規(guī)則。下面分別針對(duì)十進(jìn)制、八進(jìn)制/十六進(jìn)制、二進(jìn)制進(jìn)行說(shuō)明。①

在輸出格式為十進(jìn)制的情況下:如果表達(dá)式值的所有位均為不定值,則輸出結(jié)果為小寫的x。如果表達(dá)式值的所有位均為高阻值,則輸出結(jié)果為小寫的z。如果表達(dá)式值的部分位為不定值,則輸出結(jié)果為大寫的X。如果表達(dá)式值的部分位為高阻值,則輸出結(jié)果為大寫的Z。②

在輸出格式為十六進(jìn)制和八進(jìn)制的情況下:每4位二進(jìn)制數(shù)為一組,代表一位十六進(jìn)制數(shù);每3位二進(jìn)制數(shù)為一組,代表一位八進(jìn)制數(shù)。如果表達(dá)式值相對(duì)應(yīng)的一位八進(jìn)制(十六進(jìn)制)數(shù)的所有位均為不定值,則該位八進(jìn)制(十六進(jìn)制)數(shù)的輸出結(jié)果為小寫的x。如果表達(dá)式值相對(duì)應(yīng)的一位八進(jìn)制(十六進(jìn)制)數(shù)的所有位均為高阻值,則該位八進(jìn)制(十六進(jìn)制)數(shù)的輸出結(jié)果為小寫的z。如果表達(dá)式值相對(duì)應(yīng)的一位八進(jìn)制(十六進(jìn)制)數(shù)的部分位為不定值,則該位八進(jìn)制(十六進(jìn)制)數(shù)輸出結(jié)果為大寫的X。如果表達(dá)式值相對(duì)應(yīng)的一位八進(jìn)制(十六進(jìn)制)數(shù)的部分位為高阻值,則該位八進(jìn)制(十六進(jìn)制)數(shù)輸出結(jié)果為大寫的Z。③

對(duì)于二進(jìn)制輸出格式,表達(dá)式值的每一位的輸出結(jié)果為0、1、x、z。選通顯示($strobe)與?$display作用大同小異。如果許多其他語(yǔ)句與?$display任務(wù)在同一時(shí)刻執(zhí)行,那么,這些語(yǔ)句與?$display任務(wù)的執(zhí)行順序是不確定的。如果使用?$strobe,該語(yǔ)句總是在同一時(shí)刻的其他語(yǔ)句執(zhí)行完成之后才執(zhí)行。因此,它可以確保所有在同一時(shí)刻賦值的其他語(yǔ)句執(zhí)行完成后,才顯示數(shù)據(jù)?!纠?-9】$strobe應(yīng)用舉例。輸出結(jié)果如下:#$display:val=0#$strobe:val=1程序說(shuō)明:(1)由于val<=1;是非阻塞賦值,要在此仿真時(shí)刻最后才完成賦值,因此,非阻塞語(yǔ)句的賦值在所有的$display命令執(zhí)行以后才更新數(shù)值;由于$display在val=0;語(yǔ)句之后,所以顯示的val值,為此刻的值0。(2)?$strobe語(yǔ)句總是在同一時(shí)刻的其他語(yǔ)句執(zhí)行完成之后才執(zhí)行,它顯示val非阻塞賦值完成后的值1。因此,建議讀者用$strobe系統(tǒng)任務(wù)來(lái)顯示用非阻塞賦值的變量的值。2.系統(tǒng)任務(wù)?$monitor格式:任務(wù)?$monitor提供了監(jiān)控和輸出參數(shù)列表中的表達(dá)式或變量值的功能,其參數(shù)列表中輸出控制格式字符串和輸出表列的規(guī)則和?$display的一樣。當(dāng)啟動(dòng)一個(gè)帶有一個(gè)或多個(gè)參數(shù)的$monitor任務(wù)時(shí),仿真器則建立一個(gè)處理機(jī)制,使得每當(dāng)參數(shù)列表中的變量或表達(dá)式的值發(fā)生變化時(shí),整個(gè)參數(shù)列表中的變量或表達(dá)式的值都將輸出顯示。如果同一時(shí)刻,有多于一個(gè)的參數(shù)值發(fā)生變化,在該時(shí)刻也只輸出顯示一次。$monitoron和?$monitoroff任務(wù)是通過(guò)打開(kāi)和關(guān)閉監(jiān)控標(biāo)志來(lái)控制監(jiān)控任務(wù)?$monitor的啟動(dòng)和停止。其中,$monitoroff任務(wù)用于關(guān)閉監(jiān)控標(biāo)志,停止監(jiān)控任務(wù)?$monitor;$monitoron用于打開(kāi)監(jiān)控標(biāo)志,啟動(dòng)監(jiān)控任務(wù)?$monitor。通常在調(diào)用?$monitoron啟動(dòng)?$monitor時(shí),不管?$monitor參數(shù)列表中的值是否發(fā)生變化,總是立刻輸出顯示當(dāng)前時(shí)刻參數(shù)列表中的值,這些值可用于在監(jiān)控的初始時(shí)刻設(shè)定初始比較值。在缺省情況下,控制標(biāo)志在仿真的起始時(shí)刻就已經(jīng)打開(kāi)了。在多模塊調(diào)試的情況下,許多模塊中都調(diào)用了?$monitor,因?yàn)槿魏螘r(shí)刻只能有一個(gè)?$monitor起作用,因此,需配合?$monitoron與?$monitoroff使用,把需要監(jiān)視的模塊用?$monitoron打開(kāi),在監(jiān)視完畢后及時(shí)用?$monitoroff關(guān)閉,以便把?$monitor讓給其他模塊使用。$monitor與?$display的不同處還在于?$monitor往往在initial塊中被調(diào)用,只要不調(diào)用?$monitoroff,$monitor便可不間斷地對(duì)所設(shè)定的信號(hào)進(jìn)行監(jiān)視。3.時(shí)間度量系統(tǒng)函數(shù)$time在VerilogHDL中有兩種類型的時(shí)間系統(tǒng)函數(shù):$time和?$realtime。用這兩個(gè)時(shí)間系統(tǒng)函數(shù)可以得到當(dāng)前的仿真時(shí)刻。系統(tǒng)函數(shù)?$time可以返回一個(gè)用64比特整數(shù)表示的當(dāng)前仿真時(shí)刻值,該時(shí)刻以模塊的仿真時(shí)間尺度為基準(zhǔn)。$realtime和?$time的作用一樣,只是?$realtime返回的時(shí)間數(shù)字是一個(gè)實(shí)型數(shù),該數(shù)字也是以仿真時(shí)間尺度為基準(zhǔn)的。下面舉例說(shuō)明。【例1-10】$monitor和$time應(yīng)用舉例。輸出結(jié)果如下:程序說(shuō)明:(1)在這個(gè)例子中,模塊monit設(shè)置為在時(shí)刻為14?ns時(shí)設(shè)置寄存器data為0,在時(shí)刻為28?ns時(shí)設(shè)置寄存器data為1,在42ns時(shí)設(shè)置寄存器data為0,在56?ns時(shí)設(shè)置寄存器data為1。但是,由?$time記錄的data變化時(shí)刻卻和預(yù)想的不一樣。(2)?$time顯示時(shí)刻受時(shí)間尺度比例的影響。在本例中,時(shí)間單位是10?ns,因?yàn)?$time輸出的時(shí)刻是時(shí)間單位的倍數(shù),即14?ns、28?ns、42?ns和56?ns輸出為1.4、2.8、4.2和5.6。又因?yàn)?$time是輸出整數(shù),所以在將經(jīng)過(guò)尺度比例變換的數(shù)字輸出時(shí),需要先進(jìn)行取整。在本例中,1.4、2.8、4.2和5.6經(jīng)取整后為1、3、4和6。注意:時(shí)間精度并不影響數(shù)字的取整。(3)若將例子中?$monitor($time,"data=",data);?改為$monitor($realtime,"data=",data);,則輸出結(jié)果如下:從輸出結(jié)果可以看出,$realtime將仿真時(shí)刻經(jīng)過(guò)尺度變換以后輸出,不需進(jìn)行取整操作。所以,$realtime返回的時(shí)刻是實(shí)型數(shù)。(4)可以使用$monitor($time,"%0tdata=%0d",$time,data);?來(lái)去掉輸出中的空格,也可以在格式符中使用具體的數(shù)值來(lái)規(guī)定輸出占據(jù)的位寬。若讀者想了解更多格式符的使用方法,可自行查閱相關(guān)資料。4.系統(tǒng)任務(wù)$finish和$stop1)?$finish格式:系統(tǒng)任務(wù)$finish的作用是退出仿真器,返回主操作系統(tǒng),也就是結(jié)束仿真過(guò)程。任務(wù)$finish可以帶參數(shù),根據(jù)參數(shù)的值輸出不同的特征信息。如果不帶參數(shù),則默認(rèn)$finish的參數(shù)值為1。下面給出了對(duì)于不同的參數(shù)值,系統(tǒng)輸出的特征信息:0表示不輸出任何信息;1表示輸出當(dāng)前仿真時(shí)刻和位置;2表示輸出當(dāng)前仿真時(shí)刻、位置和在仿真過(guò)程中所用memory及CPU時(shí)間的統(tǒng)計(jì)。2)?$stop格式:$stop任務(wù)的作用是把EDA仿真器設(shè)置成暫停模式,在仿真環(huán)境下給出一個(gè)交互式的命令提示符,將控制權(quán)交給用戶。這個(gè)任務(wù)可以帶有參數(shù)表達(dá)式,根據(jù)參數(shù)值(0,1或2)的不同,輸出不同的信息,參數(shù)值越大,輸出的信息越多。5.系統(tǒng)任務(wù)$readmemb和$readmemh在VerilogHDL程序中有兩個(gè)系統(tǒng)任務(wù)$readmemb和$readmemh,用來(lái)從文件中讀取數(shù)據(jù)到存儲(chǔ)器中。這兩個(gè)系統(tǒng)任務(wù)可以在仿真的任何時(shí)刻執(zhí)行使用,其共有以下六種使用格式:(1)?$readmemb("<數(shù)據(jù)文件名>",<存儲(chǔ)器名>);(2)?$readmemb("<數(shù)據(jù)文件名>",<存儲(chǔ)器名>,<起始地址>);(3)?$readmemb("<數(shù)據(jù)文件名>",<存儲(chǔ)器名>,<起始地址>,<結(jié)束地址>);(4)?$readmemh("<數(shù)據(jù)文件名>",<存儲(chǔ)器名>);(5)?$readmemh("<數(shù)據(jù)文件名>",<存儲(chǔ)器名>,<起始地址>);(6)?$readmemh("<數(shù)據(jù)文件名>",<存儲(chǔ)器名>,<起始地址>,<結(jié)束地址>);規(guī)則如下:(1)第一個(gè)變量是一個(gè)ASCII文件的名字,這個(gè)文件可以只包含空白位置(空格、換行、制表格tab和form-feeds)、Verilog注釋(//形式的和/*…*/形式的都允許)、hex地址值以及二進(jìn)制或十六進(jìn)制數(shù)字。數(shù)字中不能包含位寬說(shuō)明和格式說(shuō)明,對(duì)于$readmemb系統(tǒng)任務(wù),每個(gè)數(shù)字必須是二進(jìn)制數(shù)字;對(duì)于$readmemh系統(tǒng)任務(wù),每個(gè)數(shù)字必須是十六進(jìn)制數(shù)字。數(shù)據(jù)值必須和存儲(chǔ)器數(shù)組的寬度相同,而且用空白分隔。(2)第二個(gè)變量是存儲(chǔ)器數(shù)組的名字。(3)當(dāng)數(shù)據(jù)文件被讀取時(shí),每一個(gè)被讀取的數(shù)字都被存放到地址連續(xù)的存儲(chǔ)器單元中。存儲(chǔ)器單元的存放地址范圍由系統(tǒng)任務(wù)聲明語(yǔ)句中的起始地址和結(jié)束地址來(lái)說(shuō)明,每個(gè)數(shù)據(jù)的存放地址在數(shù)據(jù)文件中進(jìn)行說(shuō)明。(4)地址值是帶前綴@的十六進(jìn)制且允許大寫和小寫的數(shù)字。在字符“@”和數(shù)字之間不允許存在空白位置??梢栽跀?shù)據(jù)文件里出現(xiàn)多個(gè)地址。當(dāng)系統(tǒng)任務(wù)遇到一個(gè)地址說(shuō)明時(shí),系統(tǒng)任務(wù)將該地址后的數(shù)據(jù)存放到存儲(chǔ)器中相應(yīng)的地址單元中。下面舉例說(shuō)明系統(tǒng)任務(wù)$readmemb和$readmemh的應(yīng)用。【例1-11】

系統(tǒng)任務(wù)$readmemb和$readmemh應(yīng)用舉例。程序使用的文件“Mem.txt”如圖1-34所示。程序運(yùn)行結(jié)果如圖1-35所示。關(guān)于系統(tǒng)任務(wù)?$readmemb和?$readmemh的進(jìn)一步說(shuō)明:(1)如果系統(tǒng)任務(wù)聲明語(yǔ)句和數(shù)據(jù)文件中都沒(méi)有進(jìn)行地址說(shuō)明,則缺省的存放起始地址為該存儲(chǔ)器定義語(yǔ)句中的起始地址。數(shù)據(jù)文件里的數(shù)據(jù)被連續(xù)存放在該存儲(chǔ)器中,直到該存儲(chǔ)器單元存滿或數(shù)據(jù)文件里的數(shù)據(jù)存完為止。(2)如果系統(tǒng)任務(wù)中說(shuō)明了存放的起始地址,沒(méi)有說(shuō)明存放的結(jié)束地址,則數(shù)據(jù)從起始地址開(kāi)始存放,存放到該存儲(chǔ)器定義語(yǔ)句中的結(jié)束地址為止。(3)如果在系統(tǒng)任務(wù)聲明語(yǔ)句中,起始地址和結(jié)束地址都進(jìn)行了說(shuō)明,則數(shù)據(jù)文件里的數(shù)據(jù)按該起始地址開(kāi)始存放到存儲(chǔ)器單元中,直到該結(jié)束地址,而不考慮該存儲(chǔ)器的定義語(yǔ)句中的起始地址和結(jié)束地址。(4)如果地址信息在系統(tǒng)任務(wù)和數(shù)據(jù)文件里都進(jìn)行了說(shuō)明,那么數(shù)據(jù)文件里的地址必須在系統(tǒng)任務(wù)中地址參數(shù)聲明的范圍之內(nèi)。否則將提示錯(cuò)誤信息,并且裝載數(shù)據(jù)到存儲(chǔ)器中的操作被中斷。(5)如果數(shù)據(jù)文件里的數(shù)據(jù)個(gè)數(shù)和系統(tǒng)任務(wù)中起始地址及結(jié)束地址暗示的數(shù)據(jù)個(gè)數(shù)不相同,會(huì)提示錯(cuò)誤信息。6.系統(tǒng)任務(wù)?$fopen和?$fclose$fopen是打開(kāi)一個(gè)文件進(jìn)行寫操作的系統(tǒng)函數(shù),用?$fdisplay、$fmonitor等系統(tǒng)任務(wù)將文本寫入到文件。$fclose是關(guān)閉一個(gè)文件的系統(tǒng)任務(wù)。格式:規(guī)則:(1)當(dāng)調(diào)用?$fopen函數(shù)時(shí),它返回一個(gè)與文件關(guān)聯(lián)的32位的文件句柄或者是0(文件不能打開(kāi)時(shí))。若返回的是文件句柄,則該文件句柄只有1位被置成1,并且按照文件被打開(kāi)的順序,依次將位1,位2,位3,…,位31置位。(2)多通道描述符可以是一個(gè)文件句柄或者多個(gè)文件句柄按位的組合。多通道描述符為32位,可以認(rèn)為是32個(gè)標(biāo)志。每個(gè)標(biāo)志表示一個(gè)獨(dú)立的文件通道:位0和標(biāo)準(zhǔn)輸出關(guān)聯(lián);位1和第一個(gè)打開(kāi)的文件關(guān)聯(lián);位2和第二個(gè)打開(kāi)的文件關(guān)聯(lián),以此類推。(3)一次可以同時(shí)打開(kāi)32個(gè)文件,并且可以有選擇地同時(shí)寫多個(gè)文件。(4)當(dāng)一個(gè)文件的輸出系統(tǒng)任務(wù)(如?$fdisplay)被調(diào)用時(shí),第一個(gè)變量是一個(gè)多通道描述符,它表示在哪里寫文本,文本被寫在多通道描述符的標(biāo)志被置位的文件中。系統(tǒng)任務(wù)?$fdisplay、$fmonitor、$fwrite、$fstrobe都用于寫文件。下面舉例說(shuō)明?!纠?-12】

文件讀寫應(yīng)用舉例。程序說(shuō)明:(1)程序運(yùn)行后,在ModelSim命令窗口出現(xiàn)“#Startingsimulation...”信息,在文件“messages”和“result”中寫入如圖1-36所示的信息。(2)本例中,desc1的值為32'h0000_0002(位1被置成1),desc2的值為32'h0000_0004(位2被置成1)。AllFiles=desc1|desc2|1;執(zhí)行后,AllFiles的值為32'h0000_0007(最低3位均被置成1),也就是說(shuō)AllFiles包含了3個(gè)文件;AllFiles=desc1|desc2;執(zhí)行后,AllFiles的值為32'h0000_0006(位2和位3被置成1),也就是說(shuō)AllFiles包含了2個(gè)文件。(3)多通道描述符的優(yōu)點(diǎn)在于可以有選擇地同時(shí)寫多個(gè)文件。多通道描述符可以是一個(gè)文件句柄或者多個(gè)文件句柄按位的組合,Verilog會(huì)把輸出寫到與多通道描述符中值為1的位相關(guān)聯(lián)的所有文件中。例如,“#Startingsimulation...”信息被同時(shí)寫入了3個(gè)文件(包括標(biāo)準(zhǔn)輸出),“Importantinformation...”信息被同時(shí)寫入了2個(gè)文件。7.系統(tǒng)任務(wù)綜合應(yīng)用舉例下面再通過(guò)一個(gè)例子來(lái)說(shuō)明系統(tǒng)函數(shù)的使用。該例子是使用ModelSim讀出正弦波數(shù)據(jù)文件中的數(shù)據(jù),并生成正弦波。在實(shí)際的應(yīng)用中,可能需要較大的數(shù)據(jù)量,使用傳統(tǒng)的方法在測(cè)試文件中指定輸入數(shù)據(jù)不太現(xiàn)實(shí)。通常,用其他軟件(如C、MATLAB等軟件)生成所需的數(shù)據(jù),并保存在?*.dat文件中,然后在ModelSim中調(diào)用該文本文件,將文本中的數(shù)據(jù)讀出使用。同樣的,輸出數(shù)據(jù)量也較大時(shí),用傳統(tǒng)的方法去看輸出波形也是不可靠的,因此需要把結(jié)果也輸出到文本中,與行為模型所產(chǎn)生的標(biāo)準(zhǔn)輸出向量作對(duì)比,這樣就可以比較簡(jiǎn)單且準(zhǔn)確地指示結(jié)果是否正確。首先,使用C語(yǔ)言創(chuàng)建“sin.dat”文件,一共100個(gè)正弦波數(shù)據(jù),涵蓋了一個(gè)完整的周期,均以十六進(jìn)制格式存放,其內(nèi)容如圖1-37所示。【例1-13】

生成正弦波數(shù)據(jù)的C語(yǔ)言程序所示。該程序?qū)⒄也〝?shù)據(jù)通過(guò)取正弦后加1,然后再乘以100,這樣就使正弦波數(shù)據(jù)都位于0~200之間。然后,通過(guò)例1-14來(lái)說(shuō)明如何使用ModelSim讀該文件數(shù)據(jù)并輸出這些數(shù)據(jù),形成正弦波?!纠?-14】

使用ModelSim讀寫文件生成正弦波。程序說(shuō)明:(1)仿真波形如圖1-38所示。(2)命令窗口顯示結(jié)果。由于命令窗口顯示的仿真結(jié)果較長(zhǎng),所以僅摘抄一部分,供讀者分析程序使用,如圖1-39所示。(3)本程序中使用了?$display、$monitor、$fopen、$fclose、$fdisplayh、$readmemh、$finish等系統(tǒng)任務(wù),關(guān)于這些任務(wù)的用法與含義,可結(jié)合本書前面章節(jié)的內(nèi)容理解或自行查閱相關(guān)書籍學(xué)習(xí)。(4)實(shí)際開(kāi)發(fā)中,可以將任意波形數(shù)據(jù)存放在文件中,然后通過(guò)讀取文件的方式生成任意波形,也可以通過(guò)這種方式制作信號(hào)發(fā)生器。本節(jié)對(duì)一些常用的系統(tǒng)函數(shù)和任務(wù)逐一進(jìn)行了介紹,在此基礎(chǔ)上,讀者可以在ModelSim軟件中編寫功能強(qiáng)大的測(cè)試激勵(lì)塊,更好地使用ModelSim軟件的功能。通過(guò)本節(jié)的學(xué)習(xí),我們可以發(fā)現(xiàn)ModelSim不僅好用,而且易用。任務(wù)2.1連續(xù)賦值語(yǔ)句任務(wù)2.2運(yùn)算符類型任務(wù)2.3基本語(yǔ)法及其學(xué)習(xí)建議任務(wù)2.1連續(xù)賦值語(yǔ)句以關(guān)鍵詞assign開(kāi)始的語(yǔ)句為連續(xù)賦值語(yǔ)句。連續(xù)賦值語(yǔ)句是Verilog數(shù)據(jù)流建模的基本語(yǔ)句,用于對(duì)線網(wǎng)進(jìn)行賦值。assign語(yǔ)句對(duì)應(yīng)的電路通常都是組合邏輯電路。下面介紹3個(gè)電路設(shè)計(jì)案例:多路選擇器、奇偶校驗(yàn)器、加法器?!纠?-1】

二選一多路選擇器電路設(shè)計(jì)。

【例2-2】

二選一多路選擇器電路仿真。使用QuartusⅡ軟件可以對(duì)設(shè)計(jì)進(jìn)行綜合,綜合出來(lái)的電路圖如圖2-1所示。由圖2-1可以看出,該設(shè)計(jì)實(shí)現(xiàn)的是一個(gè)二選一選擇電路。奇/偶校驗(yàn)(ParityCheck)是數(shù)據(jù)傳送時(shí)采用的一種校正數(shù)據(jù)錯(cuò)誤的方式,根據(jù)被傳輸?shù)囊唤M二進(jìn)制代碼的數(shù)位中“1”的個(gè)數(shù)是奇數(shù)或偶數(shù)來(lái)進(jìn)行校驗(yàn)。【例2-3】

奇校驗(yàn)電路設(shè)計(jì)。

【例2-4】

奇校驗(yàn)電路仿真。仿真輸出結(jié)果如圖2-2所示。在仿真結(jié)果中可直接觀察輸入數(shù)據(jù)以及其中1的個(gè)數(shù),并跟輸出的1的個(gè)數(shù)進(jìn)行對(duì)比。【例2-5】

使用數(shù)據(jù)流建模實(shí)現(xiàn)一位半加器。解題指引:半加器實(shí)現(xiàn)的是不帶進(jìn)位的兩個(gè)數(shù)的相加,若半加器的輸入為ain和bin,輸出為sum和co。其中,sum為和,co為進(jìn)位。半加器的真值表如表2-1所示。Verilog實(shí)現(xiàn)代碼如下:上面例2-3、例2-4和例2-5都是數(shù)據(jù)流建模,且都使用了assign語(yǔ)句,該語(yǔ)句通常使用連續(xù)賦值語(yǔ)句對(duì)變量進(jìn)行賦值,賦值語(yǔ)句通常會(huì)涉及大量的運(yùn)算符。上述電路設(shè)計(jì)和仿真涉及的知識(shí)點(diǎn)有:assign連續(xù)賦值語(yǔ)句、運(yùn)算符、系統(tǒng)函數(shù)、循環(huán)語(yǔ)句、延時(shí)等。下面對(duì)這些知識(shí)點(diǎn)進(jìn)行說(shuō)明。(1)?assign連續(xù)賦值語(yǔ)句。assign是VerilogHDL語(yǔ)言的關(guān)鍵字,是數(shù)據(jù)流建模的典型特征。連續(xù)賦值語(yǔ)句的基本元素是表達(dá)式、運(yùn)算符和操作數(shù)。連續(xù)賦值語(yǔ)句的功能是計(jì)算右側(cè)表達(dá)式的值,然后賦給左邊變量。表達(dá)式由運(yùn)算符和操作數(shù)構(gòu)成,根據(jù)運(yùn)算符界定的功能對(duì)操作數(shù)進(jìn)行運(yùn)算后,得出結(jié)果。數(shù)據(jù)流的強(qiáng)大建模能力體現(xiàn)在多種運(yùn)算符類型上。連續(xù)賦值語(yǔ)句總是處于激活狀態(tài),只要任意一個(gè)操作數(shù)發(fā)生變化,表達(dá)式就會(huì)立即被重新計(jì)算,并且將結(jié)果賦給等號(hào)左邊的線網(wǎng)型變量。assign{co,sum}=ain+bin;是一條連續(xù)賦值語(yǔ)句,它將ain和bin的和存放在{co,sum}中。該語(yǔ)句中,“{}”為位拼接符,其完成的功能是將co和sum拼接成一個(gè)兩位數(shù)。連續(xù)賦值語(yǔ)句的左邊必須是一個(gè)標(biāo)量或向量線網(wǎng),或者是標(biāo)量或向量線網(wǎng)的拼接,而不能是任何形式的寄存器。例如,下面的形式是非法的:操作數(shù)可以是線網(wǎng)型標(biāo)量或向量,也可以是寄存器型標(biāo)量或向量。(2)運(yùn)算符。語(yǔ)句assigny=s?b:a;使用了條件運(yùn)算符,其功能是:當(dāng)s?=?1時(shí),y?=?b;當(dāng)s?=?0時(shí),y?=?a。語(yǔ)句{a,b,s}={a,b,s}+1;使用了算術(shù)運(yùn)算符、拼接運(yùn)算符,{a,b,s}的功能是將三個(gè)1位數(shù)a、b、s拼接成一個(gè)三位數(shù);使用的算術(shù)運(yùn)算符是“+”。assign{co,sum}=ain+bin;?使用了算術(shù)運(yùn)算符、拼接運(yùn)算符。(3)系統(tǒng)函數(shù)。monitor和time都是VerilogHDL語(yǔ)言的系統(tǒng)函數(shù),monitor監(jiān)控變量值,當(dāng)要顯示的變量值發(fā)生變化時(shí)就會(huì)顯示;time用于顯示當(dāng)前仿真時(shí)刻。(4)循環(huán)語(yǔ)句和仿真延時(shí)。forever是VerilogHDL語(yǔ)言的關(guān)鍵字,用來(lái)一直產(chǎn)生信號(hào)。forever#5d_in=d_in+1;語(yǔ)句的含義是每5個(gè)時(shí)間單位,變量值加1。任務(wù)2.2?運(yùn)

型VerilogHDL語(yǔ)言提供了許多類型的運(yùn)算符,分別是算術(shù)、關(guān)系、邏輯、按位、縮減、條件、移位和位拼接運(yùn)算符。表2-2按運(yùn)算符類型列出了常用的運(yùn)算符。由表2-2可知,VerilogHDL語(yǔ)言中的運(yùn)算符所帶的操作數(shù)是不同的。只帶1個(gè)操作數(shù)的運(yùn)算符稱為單目運(yùn)算符,此時(shí)操作數(shù)需放在運(yùn)算符的右邊;帶2個(gè)操作數(shù)的運(yùn)算符稱為雙目運(yùn)算符,操作數(shù)需放在運(yùn)算符的兩邊;帶3個(gè)操作的運(yùn)算符稱為三目運(yùn)算符,這3個(gè)操作數(shù)用三目運(yùn)算符分隔開(kāi),如表2.2中的條件運(yùn)算符就是三目運(yùn)算符。表達(dá)式中的操作數(shù)可以是以下類型中的一種。(1)常數(shù)。(2)參數(shù)。(3)線網(wǎng)。(4)寄存器。(5)位選擇。(6)部分選擇。(7)存儲(chǔ)器單元。(8)函數(shù)調(diào)用。下面對(duì)表2-2中的運(yùn)算符分別進(jìn)行介紹。一、算術(shù)運(yùn)算符算術(shù)運(yùn)算符包括加(+)、減(-)、乘(×)、除(?/?)、取模(%)、乘方(**)。依據(jù)運(yùn)算的不同,算術(shù)運(yùn)算符分別對(duì)應(yīng)著加法器、減法器、乘法器、除法器、取余電路。電路設(shè)計(jì)中,加法器通常由基本的邏輯門實(shí)現(xiàn),乘法器則由加法器來(lái)實(shí)現(xiàn)。算術(shù)運(yùn)算符的具體示例說(shuō)明如表2-3所示。使用算術(shù)運(yùn)算符時(shí)需注意以下幾點(diǎn):(1)加(+)、減(-)、乘(×)、除(?/?)、取模(%)、乘方(**)均為雙目運(yùn)算符,要求運(yùn)算符兩側(cè)均有操作數(shù)。(2)在進(jìn)行整數(shù)除法運(yùn)算時(shí),結(jié)果值要略去小數(shù)部分,只取整數(shù)部分。(3)乘方運(yùn)算符要求冪是一個(gè)常量,不能為變量。(4)模運(yùn)算符又稱為求余運(yùn)算符,要求%兩側(cè)均為整型數(shù)據(jù)。(5)進(jìn)行取模運(yùn)算時(shí),結(jié)果值的符號(hào)位采用模運(yùn)算式里第一個(gè)操作數(shù)的符號(hào)位。表2-4中列舉了一些例子。二、關(guān)系運(yùn)算符關(guān)系運(yùn)算符包括大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(==)、不等于(!==)。關(guān)系運(yùn)算符對(duì)應(yīng)的實(shí)際電路是比較器。關(guān)系運(yùn)算符的具體示例說(shuō)明如表2-5所示。在進(jìn)行關(guān)系運(yùn)算時(shí),如果聲明的關(guān)系是假的(false),則返回值是0;如果聲明的關(guān)系是真的(true),則返回值是1。關(guān)系運(yùn)算符中大于、小于、大于等于、小于等于有著相同的優(yōu)先級(jí)別,等于、不等于有著相同的優(yōu)先級(jí)別,前者的優(yōu)先級(jí)別大于后者的優(yōu)先級(jí)別。關(guān)系運(yùn)算符的優(yōu)先級(jí)別低于算術(shù)運(yùn)算符的優(yōu)先級(jí)別。例如:從上面的例子可以看出這兩種不同運(yùn)算符的優(yōu)先級(jí)別。當(dāng)表達(dá)式size?-?(1?<?a)進(jìn)行運(yùn)算時(shí),關(guān)系表達(dá)式先運(yùn)算,然后返回結(jié)果值0或1被size減去;而當(dāng)表達(dá)式size?-?1?<?a進(jìn)行運(yùn)算時(shí),size先減去1,然后再同a相比。三、按位運(yùn)算符按位運(yùn)算符包括取反(?~?)、按位與(?&?)、按位或(?|?)、按位異或(?^?)、按位同或(~^?和?^~)。按位運(yùn)算符對(duì)應(yīng)的電路是基本的邏輯門,如&對(duì)應(yīng)與門,|?對(duì)應(yīng)或門,~對(duì)應(yīng)非門,^對(duì)應(yīng)異或門。按位運(yùn)算符的具體示例說(shuō)明如表2-6所示。位運(yùn)算符中除了~是單目運(yùn)算符以外,其余均為雙目運(yùn)算符。位運(yùn)算符中的雙目運(yùn)算符要求對(duì)兩個(gè)操作數(shù)的相應(yīng)位進(jìn)行運(yùn)算操作。表2-7所示為按位操作的邏輯規(guī)則。對(duì)按位運(yùn)算符的說(shuō)明如下:(1)兩個(gè)長(zhǎng)度不同的數(shù)據(jù)進(jìn)行位運(yùn)算時(shí),系統(tǒng)會(huì)自動(dòng)地將兩者按右端對(duì)齊。位數(shù)少的操作數(shù)會(huì)在相應(yīng)的高位用0填滿,以使兩個(gè)操作數(shù)按位進(jìn)行操作。(2)按位運(yùn)算符與邏輯運(yùn)算符雖然符號(hào)相近,但兩者完全不同。邏輯運(yùn)算符執(zhí)行邏輯操作,運(yùn)算的結(jié)果是一個(gè)邏輯值0或1;而按位運(yùn)算符則產(chǎn)生一個(gè)與較長(zhǎng)位寬操作數(shù)等寬的數(shù)值,該數(shù)值的每一位都是兩個(gè)操作數(shù)按位運(yùn)算的結(jié)果。四、縮減運(yùn)算符縮減運(yùn)算符包括縮減與(&)、縮減與非(~&)、縮減或(?|?)、縮減或非(~?|?)、縮減異或(?^?)、縮減同或(~^和^~)??s減運(yùn)算符對(duì)應(yīng)的電路是基本的邏輯門,如&對(duì)應(yīng)與門,|?對(duì)應(yīng)或門,~?對(duì)應(yīng)非門,^對(duì)應(yīng)異或門??s減運(yùn)算符的具體示例說(shuō)明如表2-8所示。位運(yùn)算符中除了?~?是單目運(yùn)算符以外,其余均為雙目運(yùn)算符;而縮減運(yùn)算符是單目運(yùn)算符,也有與、或、非運(yùn)算。其與、或、非運(yùn)算規(guī)則類似于位運(yùn)算符的與、或、非運(yùn)算規(guī)則,但運(yùn)算過(guò)程不同。位運(yùn)算是對(duì)操作數(shù)的相應(yīng)位進(jìn)行與或非運(yùn)算,操作數(shù)是幾位數(shù),則運(yùn)算結(jié)果也是幾位數(shù);而縮減運(yùn)算則不同,縮減運(yùn)算是對(duì)單個(gè)操作數(shù)進(jìn)行與或非遞推運(yùn)算,最后的運(yùn)算結(jié)果是一位的二進(jìn)制數(shù)。縮減運(yùn)算的具體運(yùn)算過(guò)程為:第一步,將操作數(shù)的第一位與第二位進(jìn)行與或非運(yùn)算;第二步,將運(yùn)算結(jié)果與第三位進(jìn)行或與非運(yùn)算;依次類推,直至最后一位。例如:上述代碼對(duì)應(yīng)的電路是一個(gè)4輸入的與門。由于邏輯運(yùn)算符、按位運(yùn)算符、縮減運(yùn)算符都使用相同的符號(hào)表示,因此容易混淆。區(qū)分這些運(yùn)算符的重點(diǎn)在于分清操作數(shù)的數(shù)目和運(yùn)算的規(guī)則。五、邏輯運(yùn)算符邏輯運(yùn)算符包括邏輯與(&&)、邏輯或(|?|)、邏輯非(!)。邏輯運(yùn)算符對(duì)應(yīng)的實(shí)際電路是基本的邏輯門。如果操作數(shù)是一位的,則邏輯運(yùn)算符直接對(duì)應(yīng)著邏輯門,與按位邏輯運(yùn)算符的功能相同;如果操作數(shù)是多位的,則對(duì)應(yīng)的電路就稍微復(fù)雜一些。邏輯運(yùn)算符的具體示例說(shuō)明如表2-9所示?!?&”和“|?|”是雙目運(yùn)算符,它們要求有兩個(gè)操作數(shù),如(a>b)&&(b>c),(a<b)||(b<c)。“!”是單目運(yùn)算符,只要求一個(gè)操作數(shù),如!(a>b)。表2-10為邏輯運(yùn)算的真值表,它表示當(dāng)a和b的值為不同的組合時(shí),各種邏輯運(yùn)算所得到的值。邏輯運(yùn)算符中“&&”和“||”的優(yōu)先級(jí)別低于關(guān)系運(yùn)算符,“!”高于算術(shù)運(yùn)算符。例如:六、條件運(yùn)算符條件運(yùn)算符(??:?)帶有三個(gè)操作數(shù):條件表達(dá)式???、真表達(dá)式?:?、假表達(dá)式?;?。條件運(yùn)算符與case語(yǔ)句、if語(yǔ)句對(duì)應(yīng)的電路都是多路選擇器。下面以case語(yǔ)句為例進(jìn)行說(shuō)明,如表2-11所示。執(zhí)行過(guò)程為:首先計(jì)算條件表達(dá)式,如果為真,則計(jì)算真表達(dá)式的值;如果為假,則計(jì)算假表達(dá)式的值。條件運(yùn)算符可以嵌套使用,每個(gè)真表達(dá)式或假表達(dá)式也可以是一個(gè)條件運(yùn)算符表達(dá)式。條件表達(dá)式的作用相當(dāng)于控制開(kāi)關(guān)。【例2-6】

使用條件運(yùn)算符來(lái)實(shí)現(xiàn)一個(gè)四選一多路選擇器。程序說(shuō)明如下:(1)?assignout=(sel[1])?(sel[0]?in1:in2):(sel[0]?in3:in4);?在真表達(dá)式和假表達(dá)式中均嵌套了一個(gè)條件運(yùn)算符表達(dá)式。程序的運(yùn)算過(guò)程如下:首先判斷sel[1]是否為真,若為真則計(jì)算(sel[0]?in1:in2),否則計(jì)算(sel[0]?in3:in4);然后按照同樣的規(guī)則計(jì)算這兩個(gè)條件運(yùn)算符表達(dá)式。(2)本代碼實(shí)現(xiàn)了一個(gè)四選一多路選擇器,輸出由條件sel決定。當(dāng)sel為2'b11時(shí),選擇in1;當(dāng)sel為2'b10時(shí),選擇in3;當(dāng)sel為2'b01時(shí),選擇in2;當(dāng)sel為2'b00時(shí),選擇in4。(3)這段代碼可以很容易地使用case語(yǔ)句或者if語(yǔ)句來(lái)實(shí)現(xiàn)。例如:上面的代碼使用case語(yǔ)句來(lái)實(shí)現(xiàn)與例2-16完全相同的功能。七、移位運(yùn)算符移位運(yùn)算符包括左移位運(yùn)算符(<<)和右移位運(yùn)算符(>>)。移位運(yùn)算符對(duì)應(yīng)的實(shí)際電路是線的對(duì)應(yīng)連接關(guān)系,不消耗邏輯資源。移位運(yùn)算符的具體示例說(shuō)明如表2-12所示。移位運(yùn)算符的使用方法如下:a>>n或a<<na代表要進(jìn)行移位的操作數(shù),n代表要移幾位。這兩種移位運(yùn)算都用0來(lái)填補(bǔ)移出的空位,下面舉例說(shuō)明。【例2-7】

采用移位運(yùn)算符實(shí)現(xiàn)兩個(gè)3位數(shù)的乘法。解題指引如圖2-3所示,設(shè)a為3位乘數(shù),用a2a1a0表示,設(shè)b為3位被乘數(shù),用b2b1b0表示,乘法運(yùn)算過(guò)程如下:乘法的最后是把5列分別求和得到5位的積。根據(jù)以上運(yùn)算過(guò)程可以看出,乘法的最后也可以將最后3行代表的3個(gè)數(shù)相加,但第2行相對(duì)第1行要左移1位,第3行相對(duì)第1行要左移2位。Verilog實(shí)現(xiàn)代碼如下:程序說(shuō)明如下:(1)wire[5:0]m1,m2,m3;定義了3個(gè)中間變量,m1用于存放第1行的值,m2用于存放第2行的值,m3用于存放第3行的值。(2)本例為兩個(gè)3位數(shù)相乘,我們可以采用數(shù)據(jù)流建模方式來(lái)完成,如果位數(shù)較多,比如位數(shù)為64位,則采用數(shù)據(jù)流建模顯得煩瑣,此時(shí)可采用循環(huán)語(yǔ)句來(lái)完成此算法,即采用更高抽象級(jí)的行為建模。(3)進(jìn)行移位運(yùn)算時(shí)應(yīng)注意移位前后變量的位數(shù)。例如,4'b1001<<1=5'b10010,4'b1001<<2=6'b100100,1<<6=32'b1000000。(4)從本例中可看出,由于移位運(yùn)算符可以用來(lái)實(shí)現(xiàn)移位操作、乘法算法的移位相加以及其他許多有用的操作,因此它在具體設(shè)計(jì)中是很有用的。(5)本例這種采用移位操作將乘法轉(zhuǎn)換成加法的算法,可以通過(guò)流水線來(lái)提高系統(tǒng)的工作頻率。關(guān)于流水線的內(nèi)容可參見(jiàn)本書的后續(xù)章節(jié)。八、位拼接運(yùn)算符位拼接運(yùn)算符包括拼接運(yùn)算符({})、重復(fù)運(yùn)算符({{}})。位拼接運(yùn)算符對(duì)應(yīng)的實(shí)際電路是線的對(duì)應(yīng)連接關(guān)系,不消耗邏輯資源,可結(jié)合移位運(yùn)算符來(lái)理解。位拼接運(yùn)算符的具體示例說(shuō)明如表2-13所示。拼接運(yùn)算符{}可以把兩個(gè)或多個(gè)信號(hào)的某些位拼接起來(lái)進(jìn)行運(yùn)算操作。其使用方法如下:{信號(hào)1的某幾位,信號(hào)2的某幾位,…,信號(hào)n的某幾位}即把某些信號(hào)的某些位詳細(xì)地列出來(lái),中間用逗號(hào)分開(kāi),最后用大括號(hào)括起來(lái)表示一個(gè)整體信號(hào)。例如:{a,b[3:0],w,3'b101}//等價(jià)于{a,b[3],b[2],b[1],b[0],w,1'b1,1'b0,1'b1}在位拼接表達(dá)式中的每個(gè)信號(hào)均需指明位數(shù),這是因?yàn)樵谟?jì)算拼接信號(hào)的位寬大小時(shí)必須知道其中每個(gè)信號(hào)的位寬。對(duì)于未指明位數(shù)的數(shù)字,則按照默認(rèn)值32位進(jìn)行處理。例如:{1,1}//64位,從右邊數(shù)第0位為1,第32位為1,其余位均為0如果需要重復(fù)多次拼接同一個(gè)操作數(shù),則可以使用重復(fù)運(yùn)算符。重復(fù)拼接的次數(shù)用常數(shù)來(lái)表示,該常數(shù)指定了其后大括號(hào)內(nèi)變量的重復(fù)次數(shù)。例如:{4{w}}//等價(jià)于{w,w,w,w}位拼接還可以用嵌套的方式來(lái)表達(dá)。例如:

{b,{3{a,b}}}//等價(jià)于{b,a,b,a,b,a,b}用于表示重復(fù)的表達(dá)式(如上例中的4和3)必須是常數(shù)表達(dá)式。位拼接運(yùn)算符在有些場(chǎng)合非常有用。比如,在使用的函數(shù)中想返回幾個(gè)值的時(shí)候,可使用位拼接運(yùn)算符將幾個(gè)待返回的值拼接為一個(gè)值,作為函數(shù)值進(jìn)行返回。九、運(yùn)算符的優(yōu)先級(jí)下面討論運(yùn)算符之間的優(yōu)先級(jí)。如果不使用小括號(hào)將表達(dá)式的各個(gè)部分分開(kāi),則Verilog將根據(jù)運(yùn)算符之間的優(yōu)先級(jí)對(duì)表達(dá)式進(jìn)行計(jì)算。圖2-4列出了常用的幾種運(yùn)算符的優(yōu)先級(jí)別。下面通過(guò)一個(gè)例子來(lái)說(shuō)明運(yùn)算符優(yōu)先級(jí)別的應(yīng)用。若a、b、x、y均定義為wire[3:0]類型,且a=1,b=7,則(1)當(dāng)x=(a==2)?~a|b:b>>2;時(shí),可計(jì)算出x=1。該表達(dá)式用到了相等運(yùn)算符(==)、按位運(yùn)算符(~

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論