440 likes | 607 Views
第 七 張 行為模型 (Behavoral Modeling). 7.1 結構化程序 (Structured Procedures) 在 verilog 中有兩個結構化程序: always 和 initial 兩個敘述,這是最基本的敘述, verilog 是並行程式語言,執行流也是並行執行的,而且不能有巢狀結構。. 7.1.1 initial 要把將執行的敘述放在 initiial 敘述,行程 initiial 區塊,一個區塊啟動程式啟動模擬時間零,且執行一次多個區塊,就要同時啟動模擬時間零,但各自執行。. 範例 7-1 initial 敘述.
E N D
第 七 張 行為模型 (Behavoral Modeling)
7.1 結構化程序(Structured Procedures) 在verilog中有兩個結構化程序:always和initial兩個敘述,這是最基本的敘述,verilog是並行程式語言,執行流也是並行執行的,而且不能有巢狀結構。 7.1.1 initial 要把將執行的敘述放在initiial敘述,行程initiial區塊,一個區塊啟動程式啟動模擬時間零,且執行一次多個區塊,就要同時啟動模擬時間零,但各自執行。
範例7-1initial敘述 module stimulues; reg x,y,a,b,m; initial m=1’b0; //單一敘述,不需要被群聚。 initial begin #5 a=1’b1; //多個敘述,需要被群聚。 #25 b=1’b0; end
範例7-1initial敘述(續) initial begin #10 x =1’b0; #25 y =1’b1; end initial #50 $finish; endmudule
7.2 程式指定(Procedural Assignments) 程式指定可用來更新暫存器(reg)、整數(integer)、實數(real)或時間(time)變數的值,變數上的值會一直保持到被更新為止。 範例 簡單的程式指定 assignment::=variable_lvalue=[delay_or_event_control] expression 等號右手邊可以是任何一個可求出值的運算式,在行為模式中的運算子,皆能用來當行為模式的運算式。 程式指定有兩種型態:阻礙指定(Blocking)與 無阻礙指定(Nonblocking)。
7.2.1 阻礙指定(Blocking Assignments) 阻礙指定的運算符號是 “=”。 範例7-6 阻礙指定 regx, y, z; reg[15:0] reg_a,reg_b; integer count; //所有行為模式敘述,必須在initial或always區塊內。 initial begin x=0;y=1;z=1; //純量指定 count=0; //指定變數至整數變數
reg_a=16’b0;reg_b=reg_a; //設定向量初始 #15 reg_a[2]=1’b1: //在延遲後選擇位元指定 #10 reg_b[15:13]={x,y,z} //指定連結的結果至向量部分指定 count=count+1; //指定至一個整數(遞增) end
7.2.2 無阻礙指定(Nonblocking Assignments) 無阻礙指定的運算符號是“<=”。 範例7-7 無限定指定 reg x,y,z; reg [15:0]reg_a,reg_b; integer count; //所有行為模式敘述,必須在initial或always區塊內。 initial begin x=0;y=1;z=1; //純量指定 count=0; //指定變數至整數變數
reg_a=16’b0;reg_b=reg_a; //設定向量初始 reg_a[2] <=#15 1’b1; //在延遲後選擇位元指定 reg_b[15:13]<=#10 {x,y,z}; //指定連結的結果,至向量部分指定。 count<=count+1; //指定至一個整數(遞增) end
7.3 時序控制(Timing Controls) 7.3.1 延遲基礎時間控制(Delay-Based Timing Control) 延遲基礎時序控制是用來指定遇到某個運算式,到實際執行它之間所需的時間。延遲是以符號“#”來表示,其語法如下: delay3::=# delay_value │# (delay_value [,delay_ value [,delay_value ] ] ) delay2 ::=# delay_value │# (delay_value [,delay_ value [,delay_value ] ) delay_value::= unsigned_number │parameter_identifier │specparam_identifier │mintypmax_expression
正規延遲控制(Regular Delay Control) 正規延遲控制是在延遲時間非零的時候,使用在程序指定敘述的左邊。 範例7-10 正規延遲控制 //定義參數 parameter latency = 20; parameter delta = 2 ; //定義暫存器變數 reg x, y, z, p, q; initial begin x = 0; // 無延遲 #10 y = 1; //使用數值控制延遲,延遲執行 y=1,10個時間單位。
#latency z = 0; //使用識別字控制延遲,延遲20個時間單位。 #(latency + delta) p = 1; //使用一個運算式控制延遲。 #y x=x+1; //使用識別字控制延遲,從變數y取得延遲值。 #(4:5:6) q =0; //最大、典型、最小延遲值。 //這在邏輯閘層次模型的章節裡討論過了。 end
指定內部延遲控制(Intra-Assignment Dalay Control) 不同於正規延遲控制,指定內部延遲控制是用在指定程序中,指定運算子(Assignment Operator)右邊的延遲時間。 在範例7-11中將正規控制,和指定內部延遲控制作一個比較。 範例7-11 指定內部延遲 //定義暫存器變數 reg x, y, z; //指定內部延遲 initial begin x = 0; z = 0; y =#5x+z ; //在time=0讀取x和z的值並執行x+z,直到時間單位5再指定 //至y。 end
//使用暫時變數與正規延遲得到相同的結果 initial begin x=0; z=0; temp_xz =x+z; #5 y=temp_xz; //在目前的時間讀取x+z的值,並儲存至暫時變數。即 //使時間0至5間x和z的值改變了,也不影響單位時間 //5被指定至y的值。 end
7.3.2 事件基礎時序控制(Event-Based Timing Control) • 正規事件控制 事件控制的符號是@,當信號產生正緣、負緣的轉換,或者數值的改變時,敘述會被執行。表示正緣轉換的關鍵字是posedge,如範例7-13所示。 範例7-13 正規事件控制 @(clock) q=d; //當clock的值改變,q=d被執行。 @(posedge clock) q=d; //當clock正緣觸發(0 to 1,x or z, // x to 1,z to 1),q=d被執行。 @(negedge clock) q=d; //當clock負緣觸發(1 to 0,x or z, // x to 0,z to 0),q=d被執行。 q= @(posedge clock) d; //d立刻被執行,等到clock正緣觸發 //再指定至q 。
命名事件控制 Verilog可以宣告一個事件,然後觸發和識別這個事件(範例7-14),事件並不會包含任何資料。一個被命名的事件是用關鍵字event來宣告,並使用符號 “->”來觸發,一個觸發的事件是用“@”來識別。 範例7-14 命名事件控制 //當最後的封裝packet資料被接收時,儲存四個封裝資料至資//料緩衝器。 event recieved_ data; //定義一個事件recieved_ data always @(posedge clock) //在正緣觸發時做檢查 begin if(last_data_packet) //如果是最後的封裝資料 -> recieved_ data; //觸發事件recieved_ data
end always @(recieved_ data) //直到recieved_ data事件被觸 //發,儲存四個封裝資料至資料 //緩衝器。 data_buf={data_pkt[0], data_pkt[1], data_pkt[2], data_pkt[3]};
事件或控制 當有多個訊號或事件中,任一個都能觸發某個敘述或多敘述區塊執行,就好像這些訊號或事件做或(OR)的邏輯運算。這些事件或訊號的列表,也稱為感測列表(Sensitivity List),這多個觸發是用關鍵字or來區隔(範例7-15)。 範例7-15 事件或控制 //非同步重設位準感測閂 always @(reset or clock or d) //等待reset、clock或d的數值改變。 begin if(reset) //如果reset是高電位,設定q為0。 q=1’b0; else if(clock) //如果clock是高電位,鎖住輸入資料。 q=d; end
7.3.3 位準感測時序控制(Level-Sensitive Timing Control) Verilog也允許位準感測時序控制,亦即等到某一個條件變成真(true)值,才執行某個敘述或區塊。位準感測時序控制用關鍵字wait做指定。 always wait (count_enable) #20 count = count +1; 範例中,count_enable的值是一直被監控的。 如果count_enable是0,這個敘述將不會被執行。 如果是1,敘述將在20個時間單位後執行。 如果count_enable停在1的位準,則每隔20個間,單位count都會加1。
7.4 條件敘述(Condition Statements) 條件敘述依照條件成立與否,決定是否執行某敘述或執行其他敘述,其關鍵字為if和else。 //型1條件敘述,無else敘述,敘述可能被執行,或不被執行。 if (<expression), true_statement ; //型2條件敘述,一個else敘述, //true_statement 或 false_statement 其中一個會被執行。 If (<expression), true_statement;else false_statement; //型3條件敘述,巢狀 if-else-if。 //多個敘述擇一,僅有一個敘述被執行。 if (<expression1) true_statement1 ; else if (<expression2>), true_statement2 ; else if (<expression3>), true_statement3 ; else default_statement ;
7.5 多路徑分支(Multiway Branching) 這種巢狀結構的 if-else-if,在過多的選擇時會變的很難處理。此時可以用case敘述來完成相同的結果。 7.5.1 case敘述(case Statements) 其關鍵字為case、endcase和default。 case (expression) alternative1:statement1; alternative2:statement2; alternative3:statement3; …. …. default:default_statement; endcase
7.6 迴圈(Loops) 在Verilng中有四種迴圈敘述: while、for、repeat和forever。 迴圈的語法是與C程式語言相當類似的,而所有的迴圈敘述皆僅能在initial或always的區塊中,其能包含延遲的敘述。 7.6.1 while 迴圈 關鍵字為while,while迴圈會一直執行到while條件運算式 (While Expression)成假的時候。 若一進入while迴圈時,其條件運算式即是假時,這迴圈就不會執行。每一個條件運算式包含之運算子(Operators),若有多個敘述要在迴圈中執行,它們必須被群聚起來,通常上是使用關鍵字begin和end。
7.6.2 for 迴圈 • 其關鍵字為for。 • for迴圈包含了三個部份: • 初始條件。 • 判斷終止條件是否為真。 • 一個可改變控制變數的程序指定。 • 初始狀態和累增程序指定,是包含在for迴圈之中,不需另外去定義它們,所以for迴圈要比while迴圈簡潔。但while迴圈有較廣的用途,for迴圈並不能取代所有的while迴圈。 • for迴圈一般使用在有固定起始和結束的迴圈,如果迴圈是在某一條件下的簡單迴圈,最好使用while迴圈。
7.6.3 Repeat 迴圈 關鍵字式repeat,其功用為指定一個固定次數的迴圈。repeat迴圈必須帶一個數值,可以是一個常數、變數或訊號值,而不能是一個邏輯表示式。若其為變數或訊號值時,僅在迴圈剛開始時才被讀取,在迴圈執行期間並不會再去讀取。 7.6.4 forever迴圈 其關鍵字為forever,forever迴圈並未包含任何條件運算式(Expression),會一直執行到遇到$finish,就好像while迴圈的條件運算式永遠為真,例:while(1)。 forever迴圈亦可用disable敘述跳出。一般forever迴圈會與時序控制合用,若沒有使用時序控制,則會一直執行迴圈中的敘述,而其他的敘述將都不會被執行到。
7.7 循序和平行區塊(Sequential and Parallel Blocks) • 區塊是為了群眾多個敘述使其一起動作。在前面幾個範例中,我們使用關鍵字begin和end。 • 來群聚多個敘述,這樣所得的是循序區塊,其內部的敘述將會一個接一個執行。在這一節中我們將討論到循序和並行兩種區塊,和三種特殊區塊:命名區塊、關閉命名區塊和巢狀區塊。 • 7.7.1區塊型態 • 有兩種型態的區塊:循序區塊和平行區塊。 • 循序區塊 • 其關鍵字為begin和end,其有下列特性: • 每一個敘述會依照其順序執行,且要等到前一個敘述執行完才能開始執行(除了包含指定內部延遲控制的無阻礙指定)。 • 每一個相對延遲控制或事件控制的敘述,其需等到前一個敘述執行完成,再依相對延遲時間或事件執行。
範例7-26 循序區塊 //說明1:不含延遲的循序區塊 reg x, y; reg[1:0] z, w; initial begin x = 1’b0; y = 1’b1; z = {x,y}; w = {y,x}; end //說明2:含延遲的循序區塊
範例7-26 循序區塊(續) reg x, y; rge[1:0]z,w; initial begin x = 1’b0; //完成執行在模擬時間0 #5 y=1’b1; //完成執行在模擬時間5 #10 z={x,y}; //完成執行在模擬時間15 #20 w={y,x}; //完成執行在模擬時間35 end
平行區塊 • 其關鍵字為fork和join,在用特殊的模擬功能,其有以下之特性: • 在平行區塊中的所有敘述會同時執行。 • 在平行區塊中,敘述的執行順序是依照延遲控制與事件控 • 制。 • 所有時序控制與事件驅動的時間,都相對進入區塊的模擬時 • 間。 • 循序區塊與平行區塊最大的不同是,所有在平行區塊中的敘述皆執行於區塊啟動時,因此順序是不重要的,除了每一個敘述皆起始模擬時間0之外,結果皆相同,所以區塊結束會在模擬時間20而非35。
範例7-27 平行區塊 //範例1:包含延遲的平行區塊 reg x, y; reg [1:0] z, w; initial fork x=1’b0; //完成執行在模擬時間0 #5 y=1’b1; //完成執行在模擬時間5 #10 z={x,y}; //完成執行在模擬時間10 #20 w={y,x}; //完成執行在模擬時間20 join
//會產生競爭情況的平行區塊 reg x, y; reg [1:0] z,w; initial fork x=1’b0; y=1’b1; z={x,y}; w={y,x}; join
7.7.2區塊的特殊特性(Special Features of Blocks) 我們討論三種區塊敘述的特殊功能:巢狀區塊(Nasted Blocks)、命名區塊(Named Blocks)與禁能命名區塊(Disabling of Named Blocks)。 巢狀區塊(Nasted Blocks) 區塊可以巢狀使用,循序區塊和並行區塊是可以混合在一起的。
範例7-28 巢狀區塊 //巢狀區塊 initial begin x = 1’b0; fork #5 y=1’b1; #10 z= {x,y}; join #20 w = {y,x}; end
命名區塊(Named Blocks) • 區塊是可以命名的: • 命名區塊中可宣告區域變數。 • 命名區塊是設計階層的一部份,在命名區塊中的變數可用階 • 層化命名參照存取。 • 可以禁能一個命名區塊,也就是停止這區塊的執行。
範例7-29 命名區塊 //命名區塊 module top; initial begin:block1 //循序區塊命名為block1 integer i; //整數i是區塊block1的靜態區塊區域變數 //可以用以下的階層化命名來取得 //top.block1.i … … end
範例7-29 命名區塊(續) initial fork:block2 //平行區塊命名為block2 reg i; //暫存器i是block2的靜態區域變數 //可以用以下的階層化命名來取得, //top.block2.i … … join
禁能命名區塊(Disabling of Named Blocks) 關鍵字disable提供一個方法來結束一個命名區塊的執行。 範例7-30 禁止命名區塊 //說明:尋找flag(向量變數)中第一個1的位元 reg[15:0] flag; integer i; //整數持續計數 initial begin flag = 16’b 0010_0000_0000_0000; i=0; begin :block1 //將while迴圈內的主要區控命名為 //block1。
範例7-30 禁止命名區塊(續) while(i <16 ) begin if (flag [i] ) begin $display(“Encountered a TRUE bit at element number %d”,i); disable block1; //因發現“1”位元所以禁能block1。 end i=i+1; end end end
7.8 產生區塊(Generate Blocks) • 在模擬開始之前動態產生所需的區塊。這樣的產生方式,很適合開發參數化的設計模型,針對多位元的訊號所需的重複動 • 作,可以產生出對應的模組;針對不同的模擬條件,產生出對應的模組。產生的敘述方式可以針對訊號的宣告、功能的宣告,工作的宣告以及別名模組的產生來做控制。由關鍵字generate開始,到endgenerate結束。可以產生的對象可以分成底下幾類: • 模組。 • 使用者自訂的原生模組。 • Verilog中邏輯閘模組。 • 連續指定敘述。 • initial與always區塊。
7.8.2 條件化產生(Generate Conditional) • 條件化產生使用if-else-if的方式,依不同條件產生不同的Verilog語法。與迴圈化產生類似,可針對底下的資料型態使用。 • 模組。 • 使用者自訂原生邏輯閘,或是基本邏輯閘。 • 連續指定區塊。 • initial與always區塊。 7.8.3 組合條件化產生(Generate Case) • 組合條件化產生應用,在模擬開始之前,選取最適合的一組組合來做產生的動作,適合的資料型態如下: • 模組。 • 使用者自訂原生邏輯閘,或是基本邏輯閘。 • 連續指定區塊。 • initial與always區塊。
7.9 範例(Examples) 7.9.1 4對1多工器(4-to-1 Multiplexer) 範例7-35是行為模型4對1的多工器 範例7-35 行為模型4對1的多工器 //4-to-1 多工器 module mux4_to_1 (out, i0, i1, i2, i3, s1,s0); //宣告輸出入埠 output out; input i0, i1, i2, i3; input s1, s0; //宣告輸出為暫存器變數 reg out;
//當有任何輸入改變,重新計算輸出信號。 always @ (s1 or s0 or i0 or i1 or i2 or i3) begin case ({s1, s0}) 2‘b00: out = i0; 2‘b01: out = i1; 2‘b10: out = i2; 2‘b11: out = i3; default : out = 1‘bx; endcase end endmodule
7.9.3 紅綠燈控制器(Traffic Signal Controller) 我們將使用一個有限狀態機FSM來設計一個紅綠燈控制器。 規格說明 有一個紅綠燈在主要幹道(Main Highway)和郊道(Country Road)交叉口。 Main Highway Country Road
紅綠燈的規格如下: • 因為在主幹道上,時常有車在上面行駛,所以有較高優先順 • 序。其紅綠燈預設會保持綠燈。 • 偶爾會有車從郊道行駛到交叉口,郊道的紅綠燈應該轉為綠 • 燈,且有足夠時間讓郊道的車子通過。 • 若郊道上已無車輛,郊道的紅綠燈應轉為黃燈再轉為紅燈, • 主幹道的紅綠燈應由紅轉綠。 • 所以郊道上應有一個車子的感應器,其產生的信號(X),是紅 • 綠燈控制的輸入,X=1代表有車子在郊道上,反之為0。 • 狀態由S1到S2,由S2到S3和由S4到S0需要有延遲,延遲的 • 數值必須可以控制。 • 圖7-1表示紅綠燈的狀態圖。
State Signals S0 Hwy=G Cuntry=R S1 Hwy=Y Cuntry=R S2 Hwy=R Cuntry=R S3 Hwy=R Cuntry=G S4 Hwy=G Cuntry=Y 圖7-1 FSM應用於交通訊號控制器