一、設(shè)計(jì)需求
設(shè)計(jì)一個(gè)可以顯示分、秒的電子鐘模塊并在紅色颶風(fēng)E45開(kāi)發(fā)板的四個(gè)的數(shù)碼管進(jìn)行顯示。
二、設(shè)計(jì)思路
首先,我們得了解板上四個(gè)八段數(shù)碼管的特性進(jìn)行了解。圖1所示為數(shù)碼管的原理圖,從中可以知道數(shù)碼是共陰的,即當(dāng)LED_AN0~LED_AN3為高電平時(shí)三極管導(dǎo)通,LED_S0~LED_S3為低電平,數(shù)碼管被選中,其中LED_AN0~LED_AN3、LED_A~LED_G和LED_DP是直接連接到FPGA管腳上的。
圖1 數(shù)碼管原理圖
其次,根據(jù)數(shù)碼管的原理圖給出數(shù)碼管的編碼列表,如表1所示。其中的點(diǎn)號(hào)DP根據(jù)需要進(jìn)行亮與滅的選擇。
表1 數(shù)碼管編碼對(duì)應(yīng)表
接著,我們要對(duì)設(shè)計(jì)的功能進(jìn)行合理的劃分。根據(jù)需求電子鐘的功能包括計(jì)數(shù)和編碼顯示兩部分,故本設(shè)計(jì)的功能模塊組成如圖2所示。
圖2 定時(shí)器設(shè)計(jì)框架
最后,再補(bǔ)充一點(diǎn),由于數(shù)碼管是動(dòng)態(tài)掃描顯示的,利用的人眼的視覺(jué)暫留效應(yīng)及發(fā)光二極管的余暉效應(yīng),只要使掃描速度足夠快(低于0.1秒),就不會(huì)看到由于數(shù)碼管切換顯示時(shí)的閃爍感。
三、設(shè)計(jì)實(shí)現(xiàn)
timer.v:
/**********************************************版權(quán)申明************************************************* ** **--------------------------------------------文件信息-------------------------------------------------- ** 文件名: timer.v ** 創(chuàng)建者: CrazyBird ** 創(chuàng)建日期: 2015-7-26 ** 版本號(hào): 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; // 時(shí)鐘周期,單位ns parameter T0 = 1000_000; // 1ms延時(shí) // 修改以上參數(shù)以滿足需求 //****************************************************************************** // 端口定義 //****************************************************************************** input rst_n; // 全局復(fù)位,低電平有效 input clk; // 全局時(shí)鐘,50MHz output [7:0] seg; // 編碼后的數(shù)碼管輸出 output [3:0] sel; // 數(shù)碼管的位選 //****************************************************************************** // 變量定義 //****************************************************************************** wire [2:0] min_h; // 分的十位數(shù) wire [3:0] min_l; // 分的個(gè)位數(shù) wire [2:0] sec_h; // 秒的十位數(shù) wire [3:0] sec_l; // 秒的個(gè)位數(shù) wire display_flag; // 數(shù)碼管動(dòng)態(tài)顯示標(biāo)志位 //****************************************************************************** // 模塊例化 //****************************************************************************** // 例化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ù)應(yīng)用網(wǎng)站, CrazyBird ** **--------------------------------------------文件信息-------------------------------------------------- ** 文件名: time_counter.v ** 創(chuàng)建者: CrazyBird ** 創(chuàng)建日期: 2015-7-26 ** 版本號(hào): v1.0 ** 功能描述: 時(shí)間計(jì)數(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; // 時(shí)鐘周期,單位ns parameter T0 = 1000_000; // 1ms延時(shí) // 修改以上參數(shù)以滿足需求 // 不要修改以下參數(shù) parameter T0_VAL = T0/CLK_CYCLE-1; // 1ms延時(shí) // 不要修改以上參數(shù) //****************************************************************************** // 端口定義 //****************************************************************************** input rst_n; // 全局復(fù)位,低電平有效 input clk; // 全局時(shí)鐘,50MHz output reg [2:0] min_h; // 分的十位數(shù) output reg [3:0] min_l; // 分的個(gè)位數(shù) output reg [2:0] sec_h; // 秒的十位數(shù) output reg [3:0] sec_l; // 秒的個(gè)位數(shù) output display_flag; // 數(shù)碼管動(dòng)態(tài)掃描標(biāo)志位 //****************************************************************************** // 1ms延時(shí) //****************************************************************************** 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延時(shí)完成標(biāo)志位 assign display_flag = delay_1ms; // 數(shù)碼管動(dòng)態(tài)掃描標(biāo)志位 //****************************************************************************** // 1s延時(shí) //****************************************************************************** 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í)完成標(biāo)志位 //****************************************************************************** // 秒計(jì)數(shù)實(shí)現(xiàn) //****************************************************************************** // 秒個(gè)位數(shù)計(jì)數(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)); // 秒個(gè)位數(shù)進(jìn)位標(biāo)志位 // 秒十位數(shù)計(jì)數(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ù)進(jìn)位標(biāo)志位 //****************************************************************************** // 分計(jì)數(shù)實(shí)現(xiàn) //****************************************************************************** // 分個(gè)位數(shù)計(jì)數(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)); // 分個(gè)位數(shù)進(jìn)位標(biāo)志位 // 分十位數(shù)計(jì)數(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 ** 版本號(hào): 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; // 全局復(fù)位,低電平有效 input clk; // 全局時(shí)鐘,50MHz input [2:0] min_h; // 分的十位數(shù) input [3:0] min_l; // 分的個(gè)位數(shù) input [2:0] sec_h; // 秒的十位數(shù) input [3:0] sec_l; // 秒的個(gè)位數(shù) input display_flag; // 數(shù)碼管動(dòng)態(tài)顯示標(biāo)志位 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ù)碼管點(diǎn)號(hào)是否點(diǎn)亮,1為點(diǎn)亮 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ù)碼管動(dòng)態(tài)顯示的計(jì)數(shù)器 //****************************************************************************** reg [1:0] cnt; // 由于只有四個(gè)數(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 : // 顯示秒個(gè)位數(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 : // 顯示分個(gè)位數(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所示。其中,為了減少仿真時(shí)間以及可以在較短時(shí)間內(nèi)驗(yàn)證功能的正確性,將設(shè)計(jì)中的延時(shí)參數(shù)改小。
圖3

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