本文爲明德揚原創及錄用文章,轉載請註明出處!
作者:一條鹹魚
個人感想:
本文首先分析了至簡設計法案例—4位閃爍燈,然後通過該案例舉一反三,實現了一個交通燈的功能。通過修改最重要的2個計數器cnt0、cnt1的代碼,並且僅修改了1個數字和信號變化條件,就實現了交通燈案例。案例代碼的模塊化與規範化爲代碼的移植與修改提供了很大的便利,節省了大量的時間。
設計目標:
使用4個LED燈—LED1~LED4,實現一個呼吸燈的功能。這4個燈具體的變化情況爲:第一個燈隔1秒,亮1秒後變暗;然後第2個燈隔1秒,亮2秒後變暗;然後第3個燈隔1秒,亮3秒後變暗;最後第4個燈隔1秒,亮4秒後變暗。之後循環往復。
信號設計:
對於LED0,復位後,先滅1秒,亮1秒,然後再滅12秒;對於LED1,復位後,先滅3秒,亮2秒,然後再滅9秒,循環往復;對於LED2,復位後,先滅6秒,亮3秒,然後再滅5秒,循環往復;對於LED3,先滅10秒,亮4秒,循環往復。(注:設計目標中的LED1~ LED4指的是開發板上的4個LED燈,信號設計中的LED0~ LED3指的是設計輸出的4個信號。)
波形圖:
工程實現思想:
本工程需要2個計數器,一個cnt0用於計算1秒鐘,一個cnt1用於計算一個週期14秒鐘。計數器的設計與本書的第1個案例的計數器設計相同,這裏不再贅述。輸出信號LED0,LED1,LED2,LED3根據2個計數器計數的狀態來判定是變0還是變1。這裏以led0爲例,led0有兩種變化點:變0和變1。變0的原因都是計數到1秒的時間,也就是add_cnt1&&cnt11-1時,led0變0.變1的原因,則是數到2秒時間時,即add_cnt1&&cnt12-1時,led0變1。其餘信號變換以此類推。
案例擴展:
還可以對本案例進行擴展,例如交通燈。假設一個十字路口的交通燈,分爲東西南北四個方向。每個方向紅燈持續10秒,綠燈持續7秒,黃燈持續3秒。這裏便可套用本案例的思想與框架。每個方向的紅、綠、黃的三個燈的變化可以看作一組3位閃爍燈的變化。
交通燈波形圖:
注:南北方向的信號相同,東西方向的信號相同。這裏設南北方向的紅綠燈信號爲red_led0、yellow_led0、green_led0;東西方向的紅綠燈信號爲red_led1、yellow_led1、green_led1。
案例擴展代碼:
modulejiaotongled(
clk,
rst_n,
red_led0,
yellow_led0,
green_led0,
red_led1,
yellow_led1,
green_led1
);
input clk;
input rst_n;
output red_led0;
output yellow_led0;
output green_led0;
output red_led1;
output yellow_led1;
output green_led1;
reg[28:0] cnt0;
reg[4:0] cnt1;
wire add_cnt0;
wire end_cnt0;
wire add_cnt1;
wire end_cnt1;
reg red_led0;
reg yellow_led0;
reg green_led0;
reg red_led1;
reg yellow_led1;
reg green_led1;
always @(posedgeclkor negedgerst_n)begin
if (!rst_n)begin
cnt0 <= 0;
end
else if(add_cnt0)begin
if(end_cnt0)
cnt0 <= 0;
else
cnt0 <= cnt0 + 1;
end
end
assignadd_cnt0 = 1;
assignend_cnt0 = add_cnt0 && cnt0 == 50_000_000-1;
always@(posedgeclk or negedgerst_n)begin
if (!rst_n)begin
cnt1 <= 0;
end
else if(add_cnt1)begin
if(end_cnt1)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end
assignadd_cnt1 = end_cnt0;
assignend_cnt1 = add_cnt1 && cnt1 == 20-1;
always @(posedgeclk or negedgerst_n)begin //南北方向紅燈
if(rst_n==1'b0)begin
red_led0 <= 1;
end
else if(add_cnt0 && cnt1==1-1)begin
red_led0 <= 0;
end
else if(add_cnt1 && cnt1==10-1)begin
red_led0 <= 1;
end
end
always @(posedgeclk or negedgerst_n)begin //南北方向黃燈
if(rst_n==1'b0)begin
yellow_led0 <= 1;
end
else if(add_cnt1 && cnt1==17-1)begin
yellow_led0 <= 0;
end
else if(end_cnt1) begin
yellow_led0 <= 1;
end
end
always @(posedgeclk or negedgerst_n)begin //南北方向綠燈
if(rst_n==1'b0)begin
green_led0 <= 1;
end
elseif(add_cnt1 && cnt1==10-1) begin
green_led0 <= 0;
end
else if(add_cnt1 && cnt1==17-1)begin
green_led0 <= 1;
end
end
always @(posedgeclk or negedgerst_n)begin //東西方向紅燈
if(rst_n==1'b0)begin
red_led1 <= 1;
end
else if(add_cnt1 && cnt1==10-1)begin
red_led1 <= 0;
end
else if(end_cnt1) begin
red_led1 <= 1;
end
end
always @(posedgeclk or negedgerst_n)begin //東西方向黃燈
if(rst_n==1'b0)begin
yellow_led1 <= 1;
end
else if(add_cnt1 && cnt1==7-1)begin
yellow_led1 <= 0;
end
else if(add_cnt1 && cnt1==10-1)begin
yellow_led1 <= 1;
end
end
always @(posedgeclk or negedgerst_n)begin //東西方向綠燈
if(rst_n==1'b0)begin
green_led1 <= 1;
end
else if(add_cnt0 && cnt1==1-1)begin
green_led1 <= 0;
end
else if(add_cnt1 && cnt1==7-1)begin
green_led1 <= 1;
end
end
endmodule
交通燈仿真結果:
個人感想:
交通燈的代碼基本繼承於4位閃爍燈的代碼,其中最重要的2個計數器cnt0、cnt1的代碼也只是改了1個數字,其它也只是修改了一下信號變化的條件。案例的代碼的模塊化與規範化爲代碼的移植與修改提供了很大的便利,節省了大量的時間。