1. 程式人生 > 實用技巧 >LED流水燈設計-ISE操作工具

LED流水燈設計-ISE操作工具

本系列將帶來FPGA的系統性學習,從最基本的數位電路基礎開始,最詳細操作步驟,最直白的言語描述,手把手的“傻瓜式”講解,讓電子、資訊、通訊類專業學生、初入職場小白及打算進階提升的職業開發者都可以有系統性學習的機會。

系統性的掌握技術開發以及相關要求,對個人就業以及職業發展都有著潛在的幫助,希望對大家有所幫助。後續會陸續更新 Xilinx 的 Vivado、ISE 及相關操作軟體的開發的相關內容,學習FPGA設計方法及設計思想的同時,實操結合各類操作軟體,會讓你在技術學習道路上無比的順暢,告別技術學習小BUG卡破腦殼,告別目前忽悠性的培訓誘導,真正的去學習去實戰應用。話不多說,上貨。

LED流水燈設計-ISE操作工具

作者:李西銳校對:陸輝

在軟體設計時,第一個例程總是“hello world!”,那麼學習硬體時,也會有硬體的“hello world”------流水燈。

在FPGA開發板上有四個LED,我們要做的流水燈,顧名思義就是要LED像流水一樣的點亮熄滅。直白點說就是,點亮第一個一段時間,然後熄滅第一個的同時,點亮第二個·····。在此,我們設定每一個LED點亮的時間為1秒鐘。

  • 硬體介紹

在我們的開發板上有四個LED,設計邏輯為:FPGA輸出高電平時,LED點亮;FPGA輸出低電平時,LED熄滅。

  • 架構設計和訊號說明

本設計的模組名稱為ledrun。

建立工程、新建檔案等步驟在之前的篇章中已經明確羅列,以後將不再敘述。

  • 設計程式碼
module ledrun (  input      wire          clk,// 50MHz  input      wire      rst_n, // low valid  output    reg    [3:0]    led   // high valid);  parameter    T_1s    =    50_000_000;   reg          [25:0]  cnt;  always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0) cnt <= 26'd0; else if (cnt < T_1s - 1'b1) cnt <= cnt + 1'b1; else cnt <= 26'd0; end always @ (posedge clk, negedge rst_n) begin if (rst_n == 1'b0) led <= 4'b0001; else if (cnt == T_1s - 1'b1) led <= {led[2:0], led[3]}; else led <= led; endendmodule

parameter可以定義一個引數(預設是32位)。在寫程式碼時,對於某些數字,設計者經常利用定義引數的方式進行編寫,方便修改,也方便閱讀。

在硬體電路中,使用計數器當做計時器,每記錄一個數字等於過去一個時鐘週期。由於本設計中採用的clk為50MHz,所以經過50_000_000(在verilog中,如果是描述數字,中間的下劃線只起到分隔的作用,不影響數值的大小)個週期正好為1秒鐘。由於計數器是從0開始計數,所以計數器只需要記錄到50_000_000-1即可。

為了能夠記錄到50_000_000-1這麼大的數字,所以定義了一個26位的計數器cnt(參考附錄1:設計中位寬的概念和計算位寬的小技巧)。

在verilog中,“{}”( 大括號)的第一個特殊作用為位拼接。{a,b}相當於將a和b拼接為一個整體,並且是高位為a,低位為b。

當led輸出為4’b0001時,第一個led點亮;經過1秒鐘,輸出4’b0010時,第二個led點亮;經過1秒鐘,輸出4’b0100時,第三個led點亮;經過1秒鐘,輸出4’b1000時,第四個led點亮;經過1秒鐘,輸出4’b0001時,第一個led點亮······按照上述的過程周而復始,就形成了流水燈。

不難發現,led的輸出,一直為3個0,1個1。並且1的位置每1秒鐘移動一次,從頭到尾,然後又到頭。這種現象可以利用移位的思想進行實現。即:led[3]<=led[2]; led[2]<=led[1]; led[1]<=led[0]; led[0]<=led[3];如果將被賦值的組成一個整體,那就是led,賦值的組成一個整體就是{led[2:0], led[3]}。

  • 模擬程式碼
`timescale 1ns/1ps     //定義時間單位和精度module ledrun_tb;  reg               clk;  reg               rst_n;  wire    [3:0]     led;  ledrun ledrun_inst(      .clk        (clk),// 50MHz      .rst_n      (rst_n), // low valid      .led        (led)   // high valid    );  initial clk = 1'b0;      // 50MHz  always # 10 clk = ~clk;  initial begin    rst_n = 1'b0;    # 201            // reset     rst_n = 1'b1;    # 2000;    $stop;  endendmodule

$stop是一個系統任務,功能為將Isim的模擬停止。

執行分析綜合後,開啟RTL模擬。

  • 波形分析

在Isim中的Instances and Processes中,點開ledrun_tb,可以看到ledrun_inst,選中之後再Objects視窗中就會看到程式碼中的所有變數。我們選中cnt右鍵,選擇Add to wave window。

返回到wave視窗中,cnt訊號已經新增到wave視窗中。由於新新增進來,沒有資料(no data)。

點選restart。

restart按鈕為重新執行波形,點選後,波形全部消失,wave視窗中所有的波形都處於no data 狀態。點選run –all按鈕,開始執行波形。

執行後,會自動停止。停止在tb檔案中的$stop處。

返回wave視窗,各個訊號都會有波形。

設定cnt的訊號進製為無符號的十進位制:右擊cnt訊號,選擇radix中的unsigned Decimal。

把游標放到復位結束時,選擇放大波形。

放大按鈕的右側第二個按鈕為全域性縮放,功能為將所有執行波形,顯示到目前的窗口裡;左側第二個為縮小。最右邊的按鈕是顯示到游標位置。

可以看到,在復位結束後,cnt訊號每一個時鐘週期都會增加1。

由於我們設計的流水燈是每1秒鐘流動一個,在上述的模擬中,led數值是不會變化的。如果模擬幾秒鐘的話,模擬的時間會比較長。在此不建議模擬幾秒鐘的時長,有可能會導致電腦卡住。

模擬時,可以將T_1s的值,改成一個較小值。例如:5。然後在此編譯模擬。

在ISE的編譯器中,修改完後。進行綜合分析,保證沒有任何語法錯誤。點選Re-launch。

能夠清楚的看到,led在進行移位,並且都是5個週期移動一次。

模擬通過後,關閉ISIM。回到ISE中,將引數修改成為50_000_000,綜合分析後,分配管腳。佈局佈線,生成配置檔案,進行下板測試。

開發板上的四個LED開始做流水狀點亮。

- End -

【福利】:QQ交流群173560979,進群備註名字+學校/企業。淘寶店鋪:https://shop588964188.taobao.com
論壇網址:www.sxznfpga.com
郝旭帥團隊製作

往期推薦