2009年8月17日 星期一

Verilog筆記...

記錄...
一些關於Verilog撰寫方面的筆記...

1. TestBench的module宣告不用宣告input port和output ports
ex:
電路設計檔的module宣告:
test.v
----------
module test (in1, in2, out); <= 有宣告所需的input和output ports
其TestBench檔的module宣告:
test_tb.v
----------
module test_tb; <= 不需要宣告test.v中所需的input和output ports

2. TestBench通常input ports會改宣告成reg型態 / output ports會改宣告成wire型態
ex:
電路設計檔的input / output ports宣告:
test.v
----------
module test (i0, i1, i2, out);
input i0, i1, i2;
output out;
reg out;

其TestBench檔的input / output ports宣告:
test_tb.v
----------
module test_tb;
reg i0, i1, i2; <= input ports改宣告成reg型態
wire out; <= output ports改宣告成wire型態

3. 這是發生在撰寫4 Bits Up-Down Counter時發生的邏輯錯誤:

4 Bits Up-Down Counter電路設計檔:
Four_Bits_Up_Down_Counter.v
----------
// 4 Bits Up-Down Counter with reset and control signal
module Four_Bits_Up_Down_Counter (control, reset, clk, out);
input control, reset, clk;
output [3:0] out;
reg [3:0] out;

always @(posedge clk)
begin
if (~reset) // When reset = 0: zero the value of out
begin
out <= 4'b0;
end
else if (control) // If control = 1: Up-count the number
begin
// Only Up-count while the number not reach 4'b1111
if (out != 4'b1111)
begin
out <= out + 1;
end
end
else // Else if control = 0: Down-count the number
begin
// Only Down-count while the number not reach 4'b0000
if (out != 4'b0000)
begin
out <= out - 1;
end
end
end
endmodule

其TestBench檔:
Four_Bits_Up_Down_Counter_tb.v
----------
// 4 Bits Up-Down Counter with reset and control signal Test Bench
module Four_Bits_Up_Down_Counter_tb;
reg control, reset, clk;
wire [3:0] out;

Four_Bits_Up_Down_Counter tb (.control(control), .reset(reset), .clk(clk), .out(out));

initial
begin
control = 1'b1;
reset = 1'b0;
clk = 1'b0;
#10 reset = 1'b1;
#500 $finish;
end

always
begin
#10 clk = !clk;
end
endmodule

其模擬出來的out都會是Unknown的訊號:


其原因在於...
當clk由負緣拉為正緣時:
always @(posedge clk)

程式才會進入下面的if / else判斷式

但由於在clk由負緣拉為正緣前:
always
begin
#10 clk = !clk;
end

reset就已經由0改設成為1了:
#5 reset = 1'b1;

也因此導致out沒有初始值 = Unknow
如此之後不論判斷式再怎麼加 / 減
其值均會為Unknown,導致錯誤的結果


解決方法:
將進入判斷式的條件多加:always @(posedge clk or negedge reset)
將reset也加入進入判斷式的條件中...
如此當reset由正緣拉為負緣時
就會一併將out初始為0000了


原本一直以為是自己Verilog有寫錯...
在問過學長後才發現原來有這麼一個隱藏的問題!!
果然有經驗的一看到就可以很快的發現問題出在哪...