【學習筆記】《FPGA至簡設計原理與應用》——4位閃爍燈設計

本文爲明德揚原創及錄用文章,轉載請註明出處!
作者:一條鹹魚

個人感想:

本文首先分析了至簡設計法案例—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個數字,其它也只是修改了一下信號變化的條件。案例的代碼的模塊化與規範化爲代碼的移植與修改提供了很大的便利,節省了大量的時間。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章