1,要實現的是如下的一個“產生佔空比不同的分頻時鐘”:
(1)、建模:
module fdivision_module(clock,d_clock,reset,j);
input clock,reset;
output d_clock,j;
reg d_clock;
reg [2:0]j;
always @(posedge clock)
begin
if(!reset)
//初始化過程
begin
d_clock<=0;
j<=0;
end
else
begin
if(j==4)
j<=0;
else if(j==1)
begin
d_clock=1;
j<=j+1;
end
else
begin
d_clock=0;
j<=j+1;
end
end
end
endmodule
(2)testbench:
`include "fdivision_module.v"
module fdivision_stimulus;
reg clock,reset;
wire d_clock;
wire [2:0]j;
fdivision_module fd(clock,d_clock,reset,j);
initial
begin
clock=0;
forever #5 clock=~clock;
end
initial
begin
reset=0;
#20 reset=1;
#100 reset=1;
#5 reset=1;
end
(3)、正確仿真波形:
2、出現的問題及解決辦法:
(1)、第一次的仿真結果如下:由圖可見,在reset置0的時候,d_clock並沒有置0,沒有初始化;
(2)、爲了調試程序,我將局部變量j也作爲輸出變量,得到下面的仿真結果:局部起到計數的變量一直爲未知量x。
(3)、改動程序,將reset也放入always的敏感列表中,寫成always @(posedge clock,negedge reset),得到下面的結果:很顯然,儘管仿真出結果,但是佔空比錯誤,這個錯歸根結底還是在於計數器的設定,開始我寫成(j==5)時,j<=0;(j==2)時,d_clock=1;特別很明顯0~5總共經歷了6個時鐘。所以,建模過程中,要特別注意計數器j的設定。
(4),現在回過頭來想想最開始的建模有什麼錯誤,在2.3中,將reset置於敏感列表中,寫成always @(posedge clock,negedge reset),這相當於異步置0 ,reset的置0信號是不受時鐘控制的,只要reset=0,就能將d_clock和j置0。但是在最開始錯誤的2.1中,敏感列表爲always @(posedge clock),再在後面過程塊中寫,reset=0時,j=0,d_clock=0;那麼這時的reset置0爲同步置0,只有當上升沿出現時,才生效,給j和d_clock賦值。但是,我在testbench模塊中,給reset的賦值如下圖:很顯然,在0~5ns時,reset=0,#5ns之後reset=1,則當#10ns,上升沿到來時,reset已經爲1,不能再給j和d_clock賦值了,所以造成了2.1的錯誤。特別值得注意的是,在異步置0時,reset=0的保持時間可以任意,但同步置0時,reset=0的保持時間需要大於一個時鐘,否則就會出現上面上升沿還沒到來,reset就爲1,不能賦值的錯誤。