verilog語法實例學習(6)

函數和任務

函數

https://wenku.baidu.com/view/d31d1ba8dd3383c4bb4cd283.htmlhtml

verilog中函數的目的是容許代碼寫成模塊的方式而不是定義獨立的模塊。函數一般用於計算或描述組合邏輯。若是在模塊內定義一個函數,則既能夠用連續賦值語句,也能夠用過程賦值語句調用。函數能夠有不僅一個輸入,但只能有一個輸出,由於函數名自己就充當輸出變量。web

verilog中函數還有如下幾個特色:dom

1.函數必須在module塊內調用。模塊化

2.函數內不能聲明wire,全部輸入輸出都是局部寄存器(reg, integer)函數

3.函數執行完成後,才返回結果。工具

4.函數內不能包含任什麼時候序控制語句。ui

5.函數內部能夠調用其它函數,但不能調用任務。spa

函數的定義以下:操作系統

function [range|integer] function_name; //返回值類型和寬度,函數名命令行

[input declaration]  //輸入端口說明

[parameter, reg, integer declaration]  //局部變量或常量聲明

begin

  statement; //行爲語句

end

endfunction

下面是一個16選1電路模塊代碼,代碼中使用了函數。

//16選1電路,演示function的用法
module function1(W,S16,f);
   input [15:0] W;
	input [3:0] S16;
	output reg f;
	reg [3:0] M;

	function mux4to1;
	  input [3:0] W;
	  input [1:0] S;

	  if(S==2'b00) mux4to1 = W[0];
	  else if(S==2'b01) mux4to1 = W[1];
	  else if(S==2'b10) mux4to1 = W[2];
	  else if(S==2'b11) mux4to1 = W[3];
	endfunction

   always @(W,S16)
   begin
	   M[0] = mux4to1(W[3:0],S16[1:0]);
		M[1] = mux4to1(W[7:4],S16[1:0]);
		M[2] = mux4to1(W[11:8],S16[1:0]);
		M[3] = mux4to1(W[15:12],S16[1:0]);
		f = mux4to1(M[3:0],S16[3:2]);
   end

endmodule
`timescale 1ns/1ns
`define clock_period 20

module function1_tb;

  reg clk;
  reg [15:0] W;
  reg [3:0]  S;
  wire f;

  function1 function1_0(.W(W),.S16(S),.f(f));
  always #(`clock_period/2) clk=~clk;
  initial
  begin
    clk = 1'b0;
	 W = 16'b1011_1100_1001_0110;
	 S = 4'b0000;
	 #(`clock_period)
	 S = 4'b0001;
	 #(`clock_period)
	 S = 4'b0010;
	 #(`clock_period)
	 S = 4'b0011;
	 #(`clock_period)
	 S = 4'b0100;
	 #(`clock_period)
	 S = 4'b0101;
	 #(`clock_period)
	 S = 4'b0110;
	 #(`clock_period)
	 S = 4'b0111;
	 #(`clock_period)
	 S = 4'b1000;
	 #(`clock_period)
	 S = 4'b1001;
	 #(`clock_period)
	 S = 4'b1010;
	 #(`clock_period)
	 S = 4'b1011;
	 #(`clock_period)
	 S = 4'b1100;
	 #(`clock_period)
	 S = 4'b1101;
	 #(`clock_period)
	 S = 4'b1110;
	 #(`clock_period)
	 S = 4'b1111;
	 #(`clock_period)
    $stop;
  end


endmodule


image


任務

任務具備輸入輸出變量,但沒有返回值,更像一個模塊。任務具備如下特色

1.任務只能自always(initial)塊內調用。

2.任務能夠具備任意個輸入、輸出以及雙向端口(包括0個)。

3.在任務中可使用延時、事件和時序控制結構,能夠自定義時鐘。

4.任務中能夠調用其它函數和任務。

5.任務中不能出現過程塊(always, initial)。

任務的定義;

task <任務名>;

  <端口及數據類型聲明語句>

  <語句1>

  ...

  <語句n>

endtask

下面是用task實現16選1模塊的代碼。

//16選1電路,演示task的用法
module task1(W,S16,f);
   input [15:0] W;
	input [3:0] S16;
	output reg f;
	reg [3:0] M;

	task mux4to1;
	  input [3:0] W;
	  input [1:0] S;
	  output Result;

	  if(S==2'b00) Result = W[0];
	  else if(S==2'b01) Result = W[1];
	  else if(S==2'b10) Result = W[2];
	  else if(S==2'b11) Result = W[3];
	endtask

   always @(W,S16)
   begin
	   mux4to1(W[3:0],S16[1:0],M[0]);
		mux4to1(W[7:4],S16[1:0],M[1]);
		mux4to1(W[11:8],S16[1:0],M[2]);
		mux4to1(W[15:12],S16[1:0],M[3]);
		mux4to1(M[3:0],S16[3:2],f);
   end

endmodule
`timescale 1ns/1ns
`define clock_period 20

module task1_tb;

  reg clk;
  reg [15:0] W;
  reg [3:0]  S;
  wire f;

  task1 task1_0(.W(W),.S16(S),.f(f));
  always #(`clock_period/2) clk=~clk;
  initial
  begin
    clk = 1'b0;
	 W = 16'b1011_1100_1001_0110;
	 S = 4'b0000;
	 #(`clock_period)
	 S = 4'b0001;
	 #(`clock_period)
	 S = 4'b0010;
	 #(`clock_period)
	 S = 4'b0011;
	 #(`clock_period)
	 S = 4'b0100;
	 #(`clock_period)
	 S = 4'b0101;
	 #(`clock_period)
	 S = 4'b0110;
	 #(`clock_period)
	 S = 4'b0111;
	 #(`clock_period)
	 S = 4'b1000;
	 #(`clock_period)
	 S = 4'b1001;
	 #(`clock_period)
	 S = 4'b1010;
	 #(`clock_period)
	 S = 4'b1011;
	 #(`clock_period)
	 S = 4'b1100;
	 #(`clock_period)
	 S = 4'b1101;
	 #(`clock_period)
	 S = 4'b1110;
	 #(`clock_period)
	 S = 4'b1111;
	 #(`clock_period)
    $stop;
  end


endmodule

image

      函數和任務對於設計verilog代碼不重要,但能夠大大方便模塊化設計。使用函數和任務的一個好處是它們能夠從一個always塊中調用,而這些塊中不容許包含例化語句。隨着代碼量的增多,verilog的這些特色顯得尤爲重要。

系統函數和任務總結

爲了仿真控制和對仿真結果進行比較,verilog中提供了大量的系統功能調用。這些調用分爲兩類:系統任務和系統函數。

verilog中系統函數和系統任務都是以$開頭的標識符。通常在initial和always語句中調用系統函數和系統任務。

系統函數和系統任務的主要區別:

系統任務能夠沒有返回值或者有多個返回值,系統函數只有一個返回值;系統任務能夠帶延遲,而系統函數不能夠,在0時刻當即執行。

依照功能不一樣,能夠分爲如下幾類:

顯示任務

$display 和 $write 任務

格式:

$display (<format>,signal0,signal1,…);

$write ((<format>,signal0,signal0,…);

     這兩個系統任務做用是用來輸出信息,format是雙引號括起來的字符串,用來定義後面要顯示信號的顯示格式,後面是逗號隔開的若干個信號。這兩個任務語法和c語言的printf函數很類似。

     這兩個系統任務的區別:$display自動的在輸出後進行換行,而$write不會自動換行。

format能夠包含如下兩種信息:

1)格式說明,由「%」和格式字符組成。它的做用是將輸出的數據轉換成指定的格式輸出。格式說明老是從%開始的。常見的幾種輸出格式

輸出格式 說明 輸出格式 說明
%h或%H 以十六進制形式輸出 %d或%D 以十進制形式輸出
%o或%O 以八進制形式輸出 %b或%B 以二進制形式輸出
%c或%C 以ASCII碼形式輸出 %v或%V 輸出網格型數據信號輕度
%m或%M 輸出等級層次名字 %s或%S 以字符串的形式輸出
%e或%E 以指數形式輸出實型數 %f或%F 以十進制的形式輸出實型數
%g或%G

以指數或者十進制數輸出實型數,可是

不管何種格式都以較短的結果輸出

%t或%T 輸出當前的時間格式

2)普通字符,即須要原樣輸出的字符。其中一些特殊的字符能夠經過轉換序列來輸出:

換碼序列 功能 換碼序列 功能
\n 換行 \'' 雙引號字符"
\t 橫向跳格 \o 1-3位八進制數表明的字符
\\ 反斜槓字符 %% 百分符號%

下面是代碼示例:

`timescale 1ns/1ns
`define clock_period 20

module vdisplay_tb;

   reg [7:0] a;
   reg [31:0] b;
   reg [15:0] c;

   initial
   begin
	   a = 8'b00101010;
	   b = 32'h12345678;
	   c = 16'hf01f;
	   #(`clock_period);
	   //normal char
	   $display("hello word,");
	   $display(" gkd");
	   $write("hello word,");
	   $write(" gkd");
	   //display simulation time
	   $display("\nsim time is %d",$time);
	   $display("hex: a=%h, oct: a=%o, bin: a=%b",a, a, a);
	   $display("hex: a=%h, oct: a=%o, bin: a=%0b",a, a, a);//not show high bits 0
	   $display("\\\t%%\n\"\123\"");
	   #(`clock_period);
	   $finish;

   end

endmodule

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Jan  3 10:25 2019
hello word,
  gkd
hello word, gkd
sim time is                   20
hex: a=2a, oct: a=052, bin: a=00101010
hex: a=2a, oct: a=052, bin: a=101010
\       %
"S"
$finish called from file "vdisplay.v", line 27.

若是在輸出列表中表達式的值包含不肯定的值或高阻值,其結果遵循如下規則:

輸出爲十進制的狀況下:

a)若是表達式值的全部位均爲不定值,則輸出結果爲小寫的x;

b)若是表達式中全部的位均爲高阻值,則輸出結果爲小寫的z;

c)若是表達式值的部分位爲不定值,則輸出結果爲大寫的X;

d)若是表達式值的部分爲高阻值,則輸出的結果位大寫的Z;

輸出爲十六進制和八進制的狀況下:

a)每4位二進制數爲一組表明一位十六進制數,每3位二進制數爲一組表明一位八進制數。

b)若是表達式值相對應的某進制的全部位均爲不定值,則輸出爲小寫的x;

c)若是表達式值相對應的某進制數的全部位均爲高阻值,則輸出小寫的z;

d)若是表達式值相對應的某進制數的部分位爲不定值,則該位輸出的結果爲大寫的X;

e)若是表達式值相對性的某進制數的部分位位高阻值,則該位輸出的結果爲大寫的Z;

3)對於二進制的狀況:表達式的值每一位的輸出結果都用0,1,x,z表示。

verilog中還有幾種標準輸出格式,用來輸出固定格式:

$displayb/$writeb  //輸出2進制格式

$displayo/$writeo //輸出8進制格式

$displayh/$writeh //輸出16進制格式

%m用來輸出module的層次結構,好比下面的代碼:


`timescale 1ns/1ns
`define clock_period 20

module test;
  initial
    $display("displaying in %m");
endmodule
module vtop_tb;

   test test1();
   test test2();
   test test3();
   initial
   begin
	   #(`clock_period);
	   $finish;

   end

endmodule


Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Jan  3 10:40 2019
displaying in vtop_tb.test1
displaying in vtop_tb.test2
displaying in vtop_tb.test3
$finish called from file "vtop.v", line 16.

探測任務

     $strobe屬於探測監控任務,用來在某時刻全部的事件都執行完畢後,在時間步的末尾將數據輸出。更多用來顯示用非阻塞賦值的變量的值。

     探測任務和顯示任務的區別是,顯示任務遇到語句開始執行,而探測任務要等到時間步的末尾才執行。

代碼示例:

`timescale 1ns/1ns
`define clock_period 20

module vtrobe_tb;
   reg [7:0] a;
   reg [7:0] b;

   initial
   begin
	   a = 8'b01010101;
	   $strobe("strobe,a = %b",a);
	   $display("display,a = %b",a);
	   a = 8'b11110000;
	   #(`clock_period*2);
	   $finish;
   end
   initial
   begin
      b <= 8'h11;
      $strobe("strobe,b = %b",b);
      $display("display1,b = %b",b);
      #(`clock_period);
      $strobe("strobe,b = %b",b);
      $display("display2,b = %b",b);
      b <= 8'h22;
   end

endmodule

注意如下的輸出順序:

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Jan  3 10:54 2019
display,a = 01010101
display1,b = xxxxxxxx
strobe,b = 00010001
strobe,a = 11110000
display2,b = 00010001
strobe,b = 00100010
$finish called from file "vstrobe.v", line 15

監控任務

      $monitor, 一旦調用後,將隨時對輸出變量名錶項中列出的各個變量進行監控,若是其中任何一個發生變化,就會啓動$monitor任務,在時間步結束時候,按既定的格式輸出全部變量。若是在同一時刻,多個變量或表達式發生變化,則該時刻只輸出顯示一次。能夠經過$monitoron,$monitoroff打開和關閉監控任務。在多模塊調試時,能夠有多個模塊調用$monitor,但任意時刻只有一個monitor被啓動。缺省狀態下,監控任務是打開的。

代碼示例:

`timescale 1ns/1ns
`define clock_period 20

module vmonitor_tb;
   integer a, b;
   initial
   begin
	   a = 2;
	   b = 4;
	   forever begin
		   #(`clock_period) a = a + b;
		   #(`clock_period) b = a - 1;
	   end

   end
   initial
   begin
     $monitor($time," a=%d,b=%d",a,b);
   end
   initial
   begin
	   #(`clock_period*10)
	   $finish;
   end

endmodule




Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Jan  3 13:22 2019
                    0 a=          2,b=          4
                   20 a=          6,b=          4
                   40 a=          6,b=          5
                   60 a=         11,b=          5
                   80 a=         11,b=         10
                  100 a=         21,b=         10
                  120 a=         21,b=         20
                  140 a=         41,b=         20
                  160 a=         41,b=         40
                  180 a=         81,b=         40
$finish called from file "vmonitor.v", line 23.

控制類系統任務

格式:$finish;$finish(n);

系統任務$finish的做用是退出仿真器,返回主操做系統,也就是結束仿真過程。根據參數的值輸出不一樣的特徵信息。若是不帶參數,默認其值爲1;

格式:$stop;$stop(n);

$stop任務的做用是將EDA工具設置爲暫停模式,在仿真環境下給出一個交互式的命令,將控制權交給用戶。

n的取值以下:

0 不輸出任何信息。

1 輸出當前的仿真時間和模擬文件的位置;

2 輸出當前的仿真時間、模擬文件位置和仿真過程當中所用memory和CPU的時間統計。


代碼例子:

`timescale 1ns/1ns
`define clock_period 20

module vfinish_tb;
   initial
   begin
	   #(`clock_period*10)
	   $display("time = %d",$time);
	   $stop;
	   #(`clock_period*10)
	   $finish;
   end

endmodule


好比上面代碼用vcs編譯後,運行simv,程序將暫停在ucli界面,咱們輸入quit,則退出simulation。

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Jan  3 13:44 2019
time =                  200
$stop at time 200 Scope: vfinish_tb File: vfinish.v Line: 9
ucli%
ucli% quit
            V C S   S i m u l a t i o n   R e p o r t
Time: 200 ns
CPU Time:      0.560 seconds;       Data structure size:   0.0Mb
Thu Jan  3 13:44:57 2019

仿真時間

在Verilog HDL中有兩類型的時間系統函數,$time和$realtime。用這兩個系統函數能夠獲得當前的仿真時間。

$time能夠返回一個64位的整數來表示當前仿真時刻值,該時刻是以模塊的仿真時間尺度爲基準的。

$realtime返回的時間數字是一個實型數。該數也是以時間尺度爲基準的。

`timescale 1ns/1ns
`define clock_period 20

module vtime_tb;
   integer i;
   initial
   begin
	   $monitor("time = %d,%f, i=%d",$time,$realtime,i);
	   #(2.6)
	   i = 0;
	   #(3.2)
	   i = 1;
	   #(4.6)
	   i = 3;
	   #(1)
	   $finish;
   end

endmodule
輸出結果爲:

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Jan  3 14:07 2019
time =                    0,0.000000, i=          x
time =                    3,3.000000, i=          0
time =                    6,6.000000, i=          1
time =                   11,11.000000, i=          3
$finish called from file "vtime.v", line 16.

修改`timescale 爲 1ns/100ps,則realtime時間單位能夠精確到0.1ns。

Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11;  Jan  3 14:10 2019
time =                    0,0.000000, i=          x
time =                    3,2.600000, i=          0
time =                    6,5.800000, i=          1
time =                   10,10.400000, i=          3
$finish called from file "vtime.v", line 16.

系統任務$random(隨機函數)

這個系統函數提供了一個產生隨機數的手段。當函數被調用時返回一個32位的隨機數。這是一個帶符號的整型數。

$random的通常用法是:$random%b,其中b>0.他給出了一個範圍在(-b+1):(b-1)中的隨機數。下面給出例子:

reg [23:0]rand;

rand=$random%60;            //生成-59~59之間的隨機數

rand={$random}%60;       //生成0~59之間的隨機數

一般咱們在testbench當中,用$random來產生隨機激勵。

文件輸入輸出任務

1)打開文件:

文件能夠用系統任務$fopen打開,用法:

文件句柄=$fopen("文件名",mode);//mode能夠省略

      任務$fopen返回一個被稱做多通道描述符(multichannel descriptor)的32位值。mode爲w/w+/a/a+。

      w:打開文件並從文件頭開始寫,文件不存在,則建立文件。

     w+:打開文件並從文件頭開始讀寫,文件不存在,則建立文件。

      a:打開文件並從文件尾開始寫,文件不存在,則建立文件。

     a+:打開文件並從文件尾開始讀寫,文件不存在,則建立文件。

2)寫文件:

監控,顯示,寫入,探測任務都有相應的寫文件版本,$fmonitor,$fdisplay、$fwrite,$strobe等。用法:

$fdisplay(文件描述符,p1,p2,..pn)

$fmonitor(文件描述符,p1,p2,...pn)

p1,p2,…pn能夠是變量,信號名或者帶引號的字符串。文件描述符是一個多通道描述符,他能夠是一個文件句柄或者多個文件句柄的按位組合。Verilog會把輸出寫到與文件描述符中值爲1 的文件中。

3)關閉文件

文件能夠用系統任務$fclose來關閉。用法:

$fclose(文件描述符);  如:$fclose(handle1);文件一旦被關閉,多通道描述符中的相應位被設置爲0,下一次的fopen的調用能夠重用這一位。


系統任務$readmemb $readmemh

在Verilog中有兩個系統任務$readmemb和$readmemh,並用來從文件中讀取數據到存儲器中。這兩個系統任務能夠在仿真的任什麼時候刻都被執行使用。

(1)$readmemb("<數據文件名>",<存儲器名>);

(2)$readmemb("<數據文件名>",<存儲器名>,<起始地址>);

(3)$readmemb("<數據文件名>",<存儲器名>,<起始地址>,<結束地址>);

(4)$readmemh("<數據文件名>",<存儲器名>);

(5)$readmemh("<數據文件名>",<存儲器名>,<起始地址>);

(6)$readmemh("<數據文件名>",<存儲器名>,<起始地址>,<結束地址>);

在這兩個系統函數中,被讀取的數據文件的內容只能包括:空白字符(空格換行和製表格) 註釋行(//和/**/) 二進制和十六進制數字。當地址出如今數據文件中時,其格式爲@FF...F。

在上面6種系統任務格式,需補充說明一下幾點:

(1)若是系統任務和數據文件都沒有說明地址。則從默認的存儲器地址開始寫入數據,直至數據寫完或者存儲器存滿。

(2)若是系統任務說明了起始地址,沒有說明結束地址,則數據從起始地址開始存放,直至存儲器的結束地址爲止。

(3)若是系統任務說明了起始地址和結束地址。那麼久按章任務說明中的地址進行存儲,不考慮存儲器的默認起始地址。

(4)若是系統任務和數據文件都說明了地址。那麼數據文件中的地址說明必須包含在任務地址說明語句中,不然將出現錯誤信息,而且中止存儲。

(5)若是數據文件中的數據個數和系統任務中起始地址和結束地址暗示的數據個數不一樣,也會報錯。

verilog文件讀寫的例子參照:

https://www.cnblogs.com/mikewolf2002/p/10158575.html

值變存儲文件

  $dumpfile(「dump.vcd」); //把信號寫入vcd格式波形文件dump.vcd

  $dumpvars;   //沒有參數dump全部信號

  $dumpvars(level,start_module); //要記錄的信號,level=0表示記錄全部信號

  $dumpflush; //將VCD數據保存到磁盤

  $dumpoff; //中止記錄

  $dumpon; //從新開始記錄

  $dumplimit(size); //限制VCD文件的大小(以字節爲單位)

  $dumpall;  //記錄全部指定的信號值

下面的示例代碼,將會把全部的信號dump到dump.vcd文件中。

module adder4(cout, sum, ina, inb, cin,clk);
output [3:0] sum;
output cout;
input [3:0] ina, inb;
input cin,clk;
reg[3:0] tempa, tempb, sum;
reg cout;
reg tempc;

always @(posedge clk)
begin
	tempa = ina;
	tempb = inb;
	tempc = cin;
end

always @(posedge clk)
begin
 {cout, sum} = tempa+ tempb + tempc;
end
endmodule


`timescale 1ns/10ps
`include "adder4.v"

module adder_tp;
reg[3:0] ina,inb;
reg cin;
reg clk = 0;
wire[3:0] sum;
wire cout;

always #10 clk =~ clk;

initial
begin
	ina=0;
	repeat(20)
	#20 ina = $random;
end

initial
begin
	inb=0;
	repeat(10)
	#40 inb = $random;
end

initial
begin
	cin=0;
	repeat(2)
	#200 cin = {$random} % 16;
end

adder4 adder_te(
	       .clk(clk),
	       .sum(sum),
	       .cout(cout),
	       .ina(ina),
	       .inb(inb),
	       .cin(cin)
       );
initial
begin
	$monitor($time,,,"%b + %b + %b = {%b,%b}", ina, inb, cin,cout,sum);
	#400 $finish;
end

initial
begin
	 $dumpfile("dump.vcd");
	 $dumpvars;
end
endmodule




編譯指令

     Verilog HDL語言和C語言同樣也提供編譯預處理的功能。在Verilog中爲了和通常的語句相區別,這些預處理語句以符號"`"開頭,注意,這個字符位於主鍵盤的左上角,其對應的上鍵盤字符爲"~",這個符號並非單引號"'".這裏簡單介紹最經常使用的`define `include `timescale.

1)宏定義`define

用一個指定的標識符(名字)來表明一個字符串,其的通常形式爲: `define 標識符(宏名) 字符串(宏內容) 如:`define  SIGNAL string

其做用是在後面程序中用SIGNAL替代全部的string字符串,在編譯預處理時,將程序中該命令後面全部的SIGNAL替換爲string。這種替代過程稱做宏展開。

說明:

a)宏名能夠是大寫字母,也能夠是小寫字母。通常用大寫字母,防止與後面的變量名重複。

b)`define能夠出如今模塊定義裏面,也能夠出如今外邊。其有效範圍是從該命令行開始至源文件結束。

c)在引用已定義的宏名時,必須在宏名的前面加上符號`,表示該名字是一個通過宏定義的名字。

d)宏定義是用宏名代替一個字符串,只作簡單替換不檢查語法。

e)宏定義不是Verilog HDL語句,沒必要在後面加分號。

f)在進行宏定義時,能夠引用已經定義的宏名,能夠層層替換。

g)宏名和宏內容必須在同一行進行聲明。若是在宏內容中包含有註釋行,註釋行不會做爲被置換的內容。

注意:組成宏內容的字符串不可以被如下的語句記號分隔開。註釋行+數字+字符串+確認符+關鍵詞+雙目或三目運算符

以下面的宏定義聲明和引用就是非法的:

`define first_half "start of string

$display(`first_half end of string")

2)文件包含處理`include

所謂文件包含是指處理一個源文件能夠將另外一個源文件的所有內容包含進來,即將另外文件包含到本文件之中。通常格式爲: `include"文件名"

在執行命令時,將被包含文件的所有內容複製插入到`include命令出現的地方,而後繼續進行下一步的編譯。關於文件包含的幾點說明:

1)一個文件包含命令只能制定一個被包含的文件,若是須要包含n個文件,要用n個`include命令。

2)`include命令能夠出如今Verilog程序的任何位置。被包含文件名能夠是相對路徑名,也能夠是絕對路徑名。

3)能夠將多個包含命令卸載同一行,能夠出現空格和註釋行。

4)若是文件1 包含文件2,文件2須要用到文件3的內容,能夠在文件一種用兩個`include命令分別將文件2和文件3包含進去,並且文件3要在文件2以前。

5)在一個被包含文件中又能夠包含其餘的文件,即文件的包含是能夠嵌套的。

3)時間尺度`timescale

`timescale命令用來講明跟在該命令後面的模塊的時間單位和精度。使用`timescale命令能夠在同一個設計中包含不一樣的時間單位的模塊。通常的命令格式以下:`timescale<時間單位>/<時間精度>

在這條命令中,時間單位參量是用來定義模塊中的仿真時間和延遲時間的基準單位的。時間精度是用來聲明該模塊的仿真時間的精確程度的,該參量被用來對延遲時間值進行取證操做,所以又能夠稱做是取整精度。若是在同一個程序設計裏,存在多個`timescale同樣的命令,則用最小的時間精度值來決定仿真的時間單位。另外時間精度不能大於時間單位值。

使用`timescale時應該注意,`timescale的有效區域爲`timescale語句處直至下一個`timescale命令或者`resetall語句爲止。當有多個`timescale命令時,只有最後一個才起做用,多以在同一個源文件中`timescale定義的不一樣的多個模塊最好分開編譯,不要包含在一塊兒以避免出錯。

`timescale 1ns/1ps         //時間值都爲1ns的整數倍,時間精度爲1ps,所以延遲時間能夠表達爲帶三位小數的實型數。

`timescale 10μs/100ns   //時間單位爲10μs的整數倍,時間精度位100ns,所以延遲時間能夠表達爲帶兩位小數的實型數。

時間尺度

1)根據時間精度,參數p的值從1.55取整爲1.6;

2)由於時間單位是10ns,時間精度爲1ns,因此延遲時間#p做爲事件單位的整數倍爲16ns;

3)能夠用$printtimescale函數來輸出顯示一個模塊的時間單位和時間精度。

4)條件編譯命令`ifdef `else `endif

通常狀況下,Verilog HDL源程序中全部的航都參加編譯。可是有時但願對其中的部份內容只有在知足編譯條件時才進行編譯。也就是對一部份內容指定編譯條件,即條件編譯。

條件編譯命令有如下幾種形式:

     `ifdef 宏名 (標識符)

      程序段1

    `else

      程序段2

    `endif

它的做用是當宏名已經被定義過(`define定義),則對程序1進行編譯,程序段2被忽略。其中else部分能夠沒有。注意:忽略掉的程序段也要符合語法規則

相關文章
相關標籤/搜索