在這個階層中,我們只需考慮電路模組的功能,而不需考慮其硬體的詳細內容. Verilog 的時序控制為以事件為基礎的時序控制:
always 敘述:
always 敘述的觀念有如監督程式一般,隨時監看著輸出入埠訊號的變化,然後告知模組內部 進行相關的處理. 語法如下:
- // Style1
- always
- statement
- // Style2
- always@(event_expression)
- statement
- // Style3
- always
- begin
- statements
- end
- // Style4
- always@(event_expression)
- begin
- statements
- end
always@(…) 括弧內的運算式稱之為事件運算式 (event expression),其可以是:
接著來看 單一訊號範例:
- module test(in, out);
- input in;
- output out;
- reg out;
- always@(in)
- out = ~ in;
- endmodule
接著來看 多個訊號的範例:
- module test(a, b, out);
- input a, b;
- output out;
- reg out;
- always@(a or b)
- begin
- out = a | b;
- end
- endmodule
接著來看 邊緣觸發之 "posedge" (在 clock cycle 的正緣觸發)
- module test(a, ck, out);
- input a, ck;
- output out;
- reg out;
- always@(posedge ck)
- begin
- out = ~ a;
- end
- endmodule
如果是負緣觸發, 則使用 always@(negedge ck), 輸出結果:
if 敘述:
可用來進行訊號值的判斷,後根據判斷結果執行相關處理. if 敘述能處理正準位與負準位觸發兩種訊號, 語法如下:
- // Style1
- if (expression)
- statement
- // Style2
- if (expression)
- begin
- statements
- end
- module test(reset, in, out);
- input reset, in;
- output out;
- reg out;
- always
- begin
- if (reset == 1’b1) // 正
- out = 0;
- if (reset == 1’b0) // 負
- out = in;
- end
- endmodule
if-else 敘述:
語法如下:
- // Style1
- if (expression)
- statement
- else statement
- // Style2
- if (expression)
- begin
- statements
- end
- else
- begin
- statements
- end
- always@(X, Y, Z)
- begin
- if (Z) // highest
- out = result4;
- else if (Y)
- out = result3;
- else if (X)
- out = result2;
- else out = result1; // lowest
- end
case 敘述為一多路分支選擇的敘述, 如果電路中所有可能的分支判別條件都被指定了,則稱為 full case. 語法如下:
- case (expression)
- alter_1, alter_2: stm_1;
- alter_3: stm_2;
- …
- default: default_stm;
- endcase
- module mux21(in1, in2, sl, out);
- input in1, in2, sl;
- output out;
- reg out;
- always@(in1 or in2 or sl)
- begin
- case (sl)
- 1’b0: out = in1;
- 1’b1: out = in2;
- endcase
- end
- endmodule
接著來考慮一個優先編碼模組:
- module priencoder(X, Y, Z, out);
- input [1:0] X, Y, Z;
- output [2:0] out;
- reg [2:0] out;
- always@(X or Y or Z)
- begin
- case (2'b11)
- X: out = 3'b001;
- Y: out = 3'b010;
- Z: out = 3'b100;
- default: out = 3'b000;
- endcase
- end
- endmodule
- `timescale 1ns / 1ns
- module priencoder_tb;
- reg [1:0] X,Y,Z;
- wire [2:0] out;
- priencoder ENCODER(X,Y,Z,out);
- initial
- begin
- X <= 2'b00;
- Y <= 2'b00;
- Z <= 2'b00;
- #1 $display("out=%b", out);
- X <= 2'b11;
- Y <= 2'b00;
- Z <= 2'b00;
- #5 $display("out=%b", out);
- X <= 2'b00;
- Y <= 2'b11;
- Z <= 2'b00;
- #5 $display("out=%b", out);
- X <= 2'b00;
- Y <= 2'b00;
- Z <= 2'b11;
- #5 $display("out=%b", out);
- X <= 2'b11;
- Y <= 2'b11;
- Z <= 2'b11;
- #5 $display("out=%b", out);
- end
- endmodule
Verilog 中還有 casex 與 casez 兩種 case 敘述, 更多可以參考 Case Statement.
迴圈敘述 for:
Verilog 提供有 for、while、repeat 和 forever 等迴圈敘述, 語法如下:
- for (statement; expression; statement)
- begin
- statements;
- end
接著來看一個範例:
- module forloop(a, b, out);
- parameter size=2;
- input [size-1:0] a, b;
- output [size-1:0] out;
- reg [size-1:0] out;
- integer i;
- always @(a or b)
- begin
- for (i = 0;i < size; i = i + 1)
- out[i] = a[i] & b[i];
- end
- endmodule
- `timescale 1ns / 1ns
- module forloop_tb;
- reg [1:0] a, b;
- wire [1:0] out;
- forloop FL(a, b, out);
- initial
- begin
- a <= 2'b00;
- b <= 2'b00;
- #1 $display("a=%b; b=%b; out=%b", a, b, out);
- a <= 2'b01;
- b <= 2'b00;
- #1 $display("a=%b; b=%b; out=%b", a, b, out);
- a <= 2'b01;
- b <= 2'b01;
- #1 $display("a=%b; b=%b; out=%b", a, b, out);
- a <= 2'b10;
- b <= 2'b01;
- #1 $display("a=%b; b=%b; out=%b", a, b, out);
- a <= 2'b10;
- b <= 2'b10;
- #1 $display("a=%b; b=%b; out=%b", a, b, out);
- a <= 2'b11;
- b <= 2'b10;
- #1 $display("a=%b; b=%b; out=%b", a, b, out);
- a <= 2'b11;
- b <= 2'b11;
- #1 $display("a=%b; b=%b; out=%b", a, b, out);
- end
- endmodule
Supplement:
* Verilog online help > Loop Statements
* Bioelectromagnetics Lab > Verilog tutorial
沒有留言:
張貼留言