找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 6794|回復: 0
收起左側(cè)

FPGA應用—電子鐘程序+原理圖+制作詳解

[復制鏈接]
ID:91350 發(fā)表于 2015-11-1 17:00 | 顯示全部樓層 |閱讀模式

一、設計需求

設計一個可以顯示分、秒的電子鐘模塊并在紅色颶風E45開發(fā)板的四個的數(shù)碼管進行顯示。

二、設計思路

首先,我們得了解板上四個八段數(shù)碼管的特性進行了解。圖1所示為數(shù)碼管的原理圖,從中可以知道數(shù)碼是共陰的,即當LED_AN0~LED_AN3為高電平時三極管導通,LED_S0~LED_S3為低電平,數(shù)碼管被選中,其中LED_AN0~LED_AN3、LED_A~LED_G和LED_DP是直接連接到FPGA管腳上的。

598835886159.jpg

圖1 數(shù)碼管原理圖

其次,根據(jù)數(shù)碼管的原理圖給出數(shù)碼管的編碼列表,如表1所示。其中的點號DP根據(jù)需要進行亮與滅的選擇。

表1 數(shù)碼管編碼對應表

598844462119.jpg

接著,我們要對設計的功能進行合理的劃分。根據(jù)需求電子鐘的功能包括計數(shù)和編碼顯示兩部分,故本設計的功能模塊組成如圖2所示。

598850862022.jpg

圖2 定時器設計框架

最后,再補充一點,由于數(shù)碼管是動態(tài)掃描顯示的,利用的人眼的視覺暫留效應及發(fā)光二極管的余暉效應,只要使掃描速度足夠快(低于0.1秒),就不會看到由于數(shù)碼管切換顯示時的閃爍感。

三、設計實現(xiàn)

timer.v:

/**********************************************版權(quán)申明*************************************************
**
**--------------------------------------------文件信息--------------------------------------------------
** 文件名:          timer.v
** 創(chuàng)建者:          CrazyBird
** 創(chuàng)建日期:        2015-7-26
** 版本號:           v1.0
** 功能描述:        電子鐘頂層模塊
**                   
********************************************************************************************************/
// synopsys translate_off
`timescale 1 ns / 1 ps
// synopsys translate_on
module timer(
    rst_n,
    clk,
    seg,
    sel
    );
    //******************************************************************************
    //                                  參數(shù)定義
    //******************************************************************************
    //  修改以下參數(shù)以滿足需求
    parameter   CLK_CYCLE = 20;                                        //   時鐘周期,單位ns
    parameter   T0        = 1000_000;                                  //   1ms延時
    //  修改以上參數(shù)以滿足需求
    
    //******************************************************************************
    //                                 端口定義
    //******************************************************************************
    input                   rst_n;                                     //   全局復位,低電平有效
    input                   clk;                                       //   全局時鐘,50MHz
    output      [7:0]       seg;                                       //   編碼后的數(shù)碼管輸出
    output      [3:0]       sel;                                       //   數(shù)碼管的位選
    
    //******************************************************************************
    //                                 變量定義
    //******************************************************************************
    wire        [2:0]       min_h;                                     //   分的十位數(shù)
    wire        [3:0]       min_l;                                     //   分的個位數(shù)
    wire        [2:0]       sec_h;                                     //   秒的十位數(shù)
    wire        [3:0]       sec_l;                                     //   秒的個位數(shù)
    wire                    display_flag;                              //   數(shù)碼管動態(tài)顯示標志位
    
    //******************************************************************************
    //                                 模塊例化
    //******************************************************************************
    //  例化time_counter模塊
    time_counter #(
        .CLK_CYCLE  (   CLK_CYCLE   ),
        .T0         (   T0          )
    )
    u_time_counter (
        .rst_n          (   rst_n       ),
        .clk            (   clk         ),
        .min_h          (   min_h       ),
        .min_l          (   min_l       ),
        .sec_h          (   sec_h       ),
        .sec_l          (   sec_l       ),
        .display_flag   (   display_flag)
    );
    
    //  例化display模塊
    display u_display(
        .rst_n          (   rst_n       ),
        .clk            (   clk         ),
        .min_h          (   min_h       ),      
        .min_l          (   min_l       ),
        .sec_h          (   sec_h       ),      
        .sec_l          (   sec_l       ),
        .display_flag   (   display_flag),
        .seg            (   seg         ),
        .sel            (   sel         )
    );
    
    //******************************************************************************

endmodule
//*********************************************文件結(jié)束*****************************************************

time_counter.v:

/**********************************************版權(quán)申明*************************************************
**                                   電子技術(shù)應用網(wǎng)站, CrazyBird
**
**--------------------------------------------文件信息--------------------------------------------------
** 文件名:          time_counter.v
** 創(chuàng)建者:          CrazyBird
** 創(chuàng)建日期:        2015-7-26
** 版本號:           v1.0
** 功能描述:        時間計數(shù)
**                   
********************************************************************************************************/
// synopsys translate_off
`timescale 1 ns / 1 ps
// synopsys translate_on
module time_counter(
    rst_n,
    clk,        
    min_h,      
    min_l,
    sec_h,      
    sec_l,
    display_flag
    );
    //******************************************************************************
    //                                  參數(shù)定義
    //******************************************************************************
    //  修改以下參數(shù)以滿足需求
    parameter   CLK_CYCLE = 20;                                        //   時鐘周期,單位ns
    parameter   T0        = 1000_000;                                  //   1ms延時
    //  修改以上參數(shù)以滿足需求
    
    //  不要修改以下參數(shù)
    parameter   T0_VAL    = T0/CLK_CYCLE-1;                            //   1ms延時
    //  不要修改以上參數(shù)
    
    //******************************************************************************
    //                                  端口定義
    //******************************************************************************
    input                   rst_n;                                     //   全局復位,低電平有效
    input                   clk;                                       //   全局時鐘,50MHz
    output reg  [2:0]       min_h;                                     //   分的十位數(shù)
    output reg  [3:0]       min_l;                                     //   分的個位數(shù)
    output reg  [2:0]       sec_h;                                     //   秒的十位數(shù)
    output reg  [3:0]       sec_l;                                     //   秒的個位數(shù)
    output                  display_flag;                              //   數(shù)碼管動態(tài)掃描標志位
    
    //******************************************************************************
    //                                  1ms延時
    //******************************************************************************
    reg [15:0]  cnt;
    always@(posedge clk or negedge rst_n)
    begin
        if(rst_n == 1'b0)
            cnt <= (0);
        else if(cnt < T0_VAL)
            cnt <= cnt + 1'b1;
        else
            cnt <= (0);
    end
    assign  delay_1ms = (cnt == T0_VAL);                               //   1ms延時完成標志位
    assign  display_flag = delay_1ms;                                  //   數(shù)碼管動態(tài)掃描標志位
    
    //******************************************************************************
    //                                 1s延時
    //******************************************************************************
    reg         [9:0]       mse;
    always@(posedge clk or  negedge rst_n)
    begin
        if(rst_n == 1'b0)
            mse <= (0);
        else
        begin
            if(delay_1ms == 1'b1)
            begin
                if(mse < 10'd9)
                    mse <= mse + 1'b1;
                else
                    mse <= (0);
            end
        end
    end
    wire    sec_l_flag = ((mse == 10'd9) && (delay_1ms == 1'b1));      //  1s延時完成標志位
    
    //******************************************************************************
    //                                 秒計數(shù)實現(xiàn)
    //******************************************************************************
    //  秒個位數(shù)計數(shù)
    always@(posedge clk or  negedge rst_n)
    begin
        if(rst_n == 1'b0)
            sec_l <= 0;
        else
        begin
            if(sec_l_flag == 1'b1)
            begin
                if(sec_l < 4'd9)
                    sec_l <= sec_l + 1'b1;
                else
                    sec_l <= 0;
            end
        end
    end
    wire    sec_h_flag = ((sec_l == 4'd9) && (sec_l_flag == 1'b1));    //  秒個位數(shù)進位標志位
    
    //  秒十位數(shù)計數(shù)
    always@(posedge clk or  negedge rst_n)
    begin
        if(rst_n == 1'b0)
            sec_h <= 0;
        else
        begin
            if(sec_h_flag == 1'b1)
            begin
                if(sec_h < 3'd5)
                    sec_h <= sec_h + 1'b1;
                else
                    sec_h <= 0;
                end
        end
    end
    wire    min_l_flag = ((sec_h == 3'd5) && (sec_h_flag == 1'b1));    //  秒十位數(shù)進位標志位
    
    //******************************************************************************
    //                                  分計數(shù)實現(xiàn)
    //******************************************************************************
    //  分個位數(shù)計數(shù)
    always@(posedge clk or  negedge rst_n)
    begin
        if(rst_n == 1'b0)
            min_l <= 0;
        else
        begin
            if(min_l_flag == 1'b1)
            begin
                if(min_l < 4'd9)
                    min_l <= min_l + 1'b1;
                else
                    min_l <= 0;
            end
        end
    end
    wire    min_h_flag = ((min_l == 4'd9) && (min_l_flag == 1'b1));    //  分個位數(shù)進位標志位
    
    //  分十位數(shù)計數(shù)
    always@(posedge clk or  negedge rst_n)
    begin
        if(rst_n == 1'b0)
            min_h <= 0;
        else
        begin
            if(min_h_flag == 1'b1)
            begin
                if(min_h < 3'd5)
                    min_h <= min_h + 1'b1;
                else
                    min_h <= 0;
            end
        end
    end
    //******************************************************************************

endmodule
//*********************************************文件結(jié)束*****************************************************

display.v:

/**********************************************版權(quán)申明*************************************************


**
**--------------------------------------------文件信息--------------------------------------------------
** 文件名:          display.v
** 創(chuàng)建者:          CrazyBird
** 創(chuàng)建日期:        2015-7-26
** 版本號:           v1.0
** 功能描述:        編碼顯示
**                   
********************************************************************************************************/
// synopsys translate_off
`timescale 1 ns / 1 ps
// synopsys translate_on
module display(
    rst_n,
    clk,
    min_h,      
    min_l,
    sec_h,      
    sec_l,
    display_flag,
    seg,
    sel
    );
    //******************************************************************************
    //                                 端口定義
    //******************************************************************************
    input                   rst_n;                                     //   全局復位,低電平有效
    input                   clk;                                       //   全局時鐘,50MHz
    input       [2:0]       min_h;                                     //   分的十位數(shù)
    input       [3:0]       min_l;                                     //   分的個位數(shù)
    input       [2:0]       sec_h;                                     //   秒的十位數(shù)
    input       [3:0]       sec_l;                                     //   秒的個位數(shù)
    input                   display_flag;                              //   數(shù)碼管動態(tài)顯示標志位
    output reg  [7:0]       seg;                                       //   編碼后的數(shù)碼管輸出
    output reg  [3:0]       sel;                                       //   數(shù)碼管的位選
    
    //******************************************************************************
    //                                  編碼函數(shù)
    //******************************************************************************
    function [7:0]  seg_data;
        input   [3:0]       din;                                       //   待編碼數(shù)據(jù)
        input               dp;                                        //   決定數(shù)碼管點號是否點亮,1為點亮
        
        begin
            case(din)
            4'd0 : seg_data = {7'b1111110,dp};
            4'd1 : seg_data = {7'b0110000,dp};
            4'd2 : seg_data = {7'b1101101,dp};
            4'd3 : seg_data = {7'b1111001,dp};
            4'd4 : seg_data = {7'b0110011,dp};
            4'd5 : seg_data = {7'b1011011,dp};
            4'd6 : seg_data = {7'b1011111,dp};
            4'd7 : seg_data = {7'b1110000,dp};
            4'd8 : seg_data = {7'b1111111,dp};
            4'd9 : seg_data = {7'b1111011,dp};
            endcase
        end
    endfunction
    
    //******************************************************************************
    //                          數(shù)碼管動態(tài)顯示的計數(shù)器
    //******************************************************************************
    reg         [1:0]       cnt;                                       //   由于只有四個數(shù)碼管,故只需兩位
    always @(posedge clk or negedge rst_n)
    begin
        if(rst_n == 1'b0)
            cnt <= (0);
        else if(display_flag == 1'b1)
            cnt <= cnt + 1'b1;
        else
            cnt <= cnt;
    end
    
    //******************************************************************************
    //                                 編碼輸出 
    //******************************************************************************
    always @(posedge clk or negedge rst_n)
    begin
        if(rst_n == 1'b0)
        begin
            seg <= (0);
            sel <= (0);
        end
        else
        begin
            case(cnt)
            2'b00 :                                                    //   顯示秒個位數(shù)
            begin
                seg <= seg_data(sec_l,1'b0);
                sel <= 4'b0001;
            end
            
            2'b01 :                                                    //   顯示秒十位數(shù)
            begin
                seg <= seg_data({1'b0,sec_h},1'b0);
                sel <= 4'b0010;
            end
            
            2'b10 :                                                    //   顯示分個位數(shù)
            begin
                seg <= seg_data(min_l,1'b1);
                sel <= 4'b0100;
            end
            
            2'b11 :                                                    //   顯示分十位數(shù)
            begin
                seg <= seg_data({1'b0,min_h},1'b0);
                sel <= 4'b1000;
            end
            endcase
        end
    end
    
    //******************************************************************************

endmodule
//*********************************************文件結(jié)束*****************************************************

電子鐘的modelsim仿真結(jié)果如圖3~圖8所示。其中,為了減少仿真時間以及可以在較短時間內(nèi)驗證功能的正確性,將設計中的延時參數(shù)改小。

598858198549.jpg

圖3

598864907207.jpg

圖4

598872085301.jpg

圖5

598878794186.jpg

圖6

598885493297.jpg

圖7

598893148579.jpg

圖8

最后,經(jīng)過綜合、實現(xiàn)、生成bit流文件以及下載到板子上,便可以在數(shù)碼管上看到電子鐘的效果。


回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表