基於EP4CE6F17C8的FPGA流水燈例項

fxzq發表於2024-03-09

一、電路模組

1、LED

開發闆闆載了4個使用者LED發光二極體。4 個使用者LED部分的原理圖如下圖所示,當 FPGA的引腳輸出為邏輯 0時,LED會熄滅。輸出為邏輯1時,LED被點亮。

其實物圖如下所示。

LED的引腳分配見下表。

2、時鐘晶振

開發闆闆載了一個50MHz的有源晶振,為系統提供時鐘。

其實物圖如下所示。

時鐘輸出引腳分配見下表。

3、按鍵

開發闆闆載了4個獨立按鍵,其中有3個使用者按鍵(KEY1~KEY3),1個功能按鍵(RESET)。按鍵按下為低電平(0),釋放為高電平(1),4個按鍵的原理圖如下圖所示。本例中只使用了RESET鍵。

其實物圖如下所示。

按鍵的引腳分配見下表。

二、實驗程式碼

本例實現4位LED的流水燈,輸出使用4個發光管led1~led4。程式碼使用Verilog編寫,如下。

module led4_shift ( 
    input    clk,            //板載50HMz系統時鐘
    input rst_n,             //復位按鍵
    output reg[3:0] led      //4個LED
 );
 
reg [27:0] timer;            //定義時鐘計數器
    
//4秒迴圈計數
always@(posedge clk or negedge rst_n)    //敏感訊號為時鐘上沿或復位下沿
begin
    if (rst_n == 1'b0)                     //低電平復位
    timer <= 28'd0;                        //復位時時鐘計數器清零
    else if (timer == 28'd199_999_999)     //時鐘計數器到達4秒時
        timer <= 28'd0;                    //時鐘計數器清零
    else
        timer <= timer + 28'd1;            //時鐘計數器加1,即來一次時鐘脈衝加一次
end

//LED控制
always@(posedge clk or negedge rst_n)    //敏感訊號為時鐘上沿或復位下沿
begin
    if (rst_n == 1'b0)                    //低電平復位時LED全滅
        led <= 4'b0000;
    else if (timer == 28'd49_999_999)     //時鐘到1秒時,LED0點亮
        led <= 4'b0001; 
    else if (timer == 28'd99_999_999)     //時鐘到2秒時,LED1點亮
        led <= 4'b0010;
    else if (timer == 28'd149_999_999)    //時鐘到3秒時,LED2點亮
        led <= 4'b0100; 
    else if (timer == 28'd199_999_999)    //時鐘到4秒時,LED3點亮
        led <= 4'b1000;
end
endmodule

程式碼也可以寫成如下的方式。

module led4_shift ( 
    input    clk,            //板載50HMz系統時鐘
    input rst_n,             //復位按鍵
    output reg[3:0] led      //4個LED
 );
 
reg [25:0] timer;            //定義時鐘計數器
reg [2:0] sec;               //定義秒計數器
    
//4秒迴圈計數
always@(posedge clk or negedge rst_n)    //敏感訊號為時鐘上沿或復位下沿
begin
    if (rst_n == 1'b0)                      //低電平復位
    begin
        timer <= 26'd0;                     //復位時時鐘計數器及秒計數器清零
        sec <= 3'd0;
    end
     else if (timer == 26'd49_999_999)      //時鐘計數器到達1秒時
     begin
        timer <= 26'd0;                     //時鐘計數器清零
        sec <= sec + 3'd1;                  //秒計數器加1
    end
     else if(sec == 3'd4)                   //秒計數器加到4時恢復零
        sec <= 3'd0;
    else
        timer <= timer + 26'd1;             //時鐘計數器加1,即來一次時鐘脈衝加一次
end

//LED控制
always@(posedge clk or negedge rst_n)    //敏感訊號為時鐘上沿或復位下沿
begin
    if (rst_n == 1'b0)                      //低電平復位時LED全滅
        led <= 4'b0000;
    else if (sec == 3'd1)                   //時鐘到1秒時,LED0點亮
        led <= 4'b0001; 
    else if (sec == 3'd2)                   //時鐘到2秒時,LED1點亮
        led <= 4'b0010;
    else if (sec == 3'd3)                   //時鐘到3秒時,LED2點亮
        led <= 4'b0100; 
    else if (sec == 3'd4)                   //時鐘到4秒時,LED3點亮
        led <= 4'b1000;
end
endmodule

三、實驗步驟

FPGA開發的詳細步驟請參見“基於EP4CE6F17C8的FPGA開發流程(以半加器為例)”一文,本例只對一同之處進行說明。

本例工程放在D:\EDA_FPGA\Exam_2資料夾下,工程名稱為Exam_2。模組檔名稱為led4_shift.v,並設定為頂層實體。其餘步驟與“基於EP4CE6F17C8的FPGA開發流程”中的一樣。

接下來看管腳約束,本例中不僅使用了4個LED,還引入了時鐘晶振和復位按鈕,具體的埠分配如下圖所示。

對於未用到的引腳設定為三態輸入方式,多用用途引腳全部做為普通I/O埠,電壓設定為3.3-V LVTTL(與”基於EP4CE6F17C8的FPGA開發流程“中的一樣)。需要注意,程式中的每個埠都必須為其分配管腳,如果系統中存在未分配的I/O,軟體可能會進行隨機分配,這將造成不可預料的後果,存在燒壞FPGA晶片的風險。

接下來對工程進行編譯,編譯完成後,可檢視一下邏輯器件的消耗情況,第一種程式碼的消耗如下圖所示。

第二種程式碼的消耗如下圖所示。

可以看到,第二種方式要消耗掉更多的器件。另外,還可以點選選單Tools->Netlist Viewers->RTL Viewer,檢視一下生成的RTL電路圖。

最後進行程式下載,並檢視結果。

根據前面的程式,初始化時4個led均為熄滅狀態,1秒後led0點亮其餘熄滅,再過1秒後led1點亮其餘熄滅,再過1秒後led2點亮其餘熄滅,再過1秒後led3點亮其餘熄滅, 再過1秒後led0再次被點亮其餘熄滅,如此迴圈,如下面4張圖片所示。

當按下RESET鍵時,所示LED均熄滅。如下圖所示。

相關文章