天天看點

【FPGA實驗】數位管靜态顯示

開拓者FPGA開發闆上有六個共陽極八段數位管,本實驗将完成數位管靜态顯示。

功能描述

控制六位數位管以0.5秒的頻率同時顯示0-F 16個數字。

分頻子產品

開發闆本身的時鐘頻率為50kHz,對應時鐘周期為20ns,而本實驗需要0.5s讓數字變化一次,是以需要對時鐘進行分頻,使其0.5s輸出一個脈沖信号flag。

module time_count(
    input           clk     ,   // 時鐘信号
    input           rst_n   ,   // 複位信号

    output   reg    flag        // 一個時鐘周期的脈沖信号
);

//parameter define
parameter  MAX_NUM = 25000_000; // 計數器最大計數值

//reg define
reg [24:0] cnt;                 // 時鐘分頻計數器

//*****************************************************
//**                    main code
//*****************************************************

//計數器對時鐘計數,每計時到0.5s,輸出一個時鐘周期的脈沖信号
always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        flag <= 1'b0;
        cnt  <= 24'b0;
    end
    else if(cnt < MAX_NUM - 1'b1) begin
        cnt  <= cnt +1'b1;
        flag <= 1'b0;
    end
    else begin
        cnt  <= 24'b0;
        flag <= 1'b1;      

數位管靜态顯示子產品

首先需清楚兩個概念:

位選信号(sel)——控制哪個數位管顯示

段選信号(seg_led)–控制數位管顯示内容

數位管顯示具體數值可參考真值表:

【FPGA實驗】數位管靜态顯示

共陽極二極管,常理來說應當0才是點亮,而這裡是相反的。

原因可以看下面的原理圖,輸入信号并不是給到二極管的負級,而是給到了三級管的基極,三極管在這裡起到開關的作用,是以相反。

【FPGA實驗】數位管靜态顯示

子產品代碼:

module seg_led_static (
    input               clk     ,   // 時鐘信号
    input               rst_n   ,   // 複位信号(低有效)

    input               add_flag,   // 數位管變化的通知信号
    output  reg  [5:0]  sel     ,   // 數位管位選
    output  reg  [7:0]  seg_led     // 數位管段選
);

//reg define
reg [3:0] num;                      // 數位管顯示的十六進制數

//*****************************************************
//**                    main code
//*****************************************************

//控制數位管位選信号(低電平有效),選中所有的數位管
always @ (posedge clk or negedge rst_n) begin
    if (!rst_n)
        sel <= 6'b111111;
    else
        sel <= 6'b000000;
end

//每次通知信号到達時,數位管顯示的十六進制數值加1
always @ (posedge clk or negedge rst_n) begin
    if (!rst_n)
        num <= 4'h0;
    else if(add_flag) begin
        if (num < 4'hf)
            num <= num + 1'b1;
        else
            num <= 4'h0;
    end
    else
        num <= num;
end

//根據數位管顯示的數值,控制段選信号
always @ (posedge clk or negedge rst_n) begin
    if (!rst_n)
        seg_led <= 8'b0;
    else begin
        case (num)
            4'h0 :    seg_led <= 8'b1100_0000;
            4'h1 :    seg_led <= 8'b1111_1001;
            4'h2 :    seg_led <= 8'b1010_0100;
            4'h3 :    seg_led <= 8'b1011_0000;
            4'h4 :    seg_led <= 8'b1001_1001;
            4'h5 :    seg_led <= 8'b1001_0010;
            4'h6 :    seg_led <= 8'b1000_0010;
            4'h7 :    seg_led <= 8'b1111_1000;
            4'h8 :    seg_led <= 8'b1000_0000;
            4'h9 :    seg_led <= 8'b1001_0000;
            4'ha :    seg_led <= 8'b1000_1000;
            4'hb :    seg_led <= 8'b1000_0011;
            4'hc :    seg_led <= 8'b1100_0110;
            4'hd :    seg_led <= 8'b1010_0001;
            4'he :    seg_led <= 8'b1000_0110;
            4'hf :    seg_led <= 8'b1000_1110;
            default : seg_led <= 8'b1100_0000;      

頂層子產品

module seg_led_static_top (
    input               sys_clk  ,       // 系統時鐘
    input               sys_rst_n,       // 系統複位信号(低有效)

    output    [5:0]     sel      ,       // 數位管位選
    output    [7:0]     seg_led          // 數位管段選

);

//parameter define
parameter  TIME_SHOW = 25'd25000_000;    // 數位管變化的時間間隔0.5s

//wire define
wire       add_flag;                     // 數位管變化的通知信号

//*****************************************************
//**                    main code
//*****************************************************

//每隔0.5s産生一個時鐘周期的脈沖信号
time_count #(
    .MAX_NUM    (TIME_SHOW)
) u_time_count(
    .clk        (sys_clk  ),
    .rst_n      (sys_rst_n),
    
    .flag       (add_flag )
);

//每當脈沖信号到達時,使數位管顯示的數值加1
seg_led_static u_seg_led_static (
    .clk        (sys_clk  ), 
    .rst_n      (sys_rst_n),

    .add_flag   (add_flag ), 
    .sel        (sel      ),
    .seg_led    (seg_led  )
);      

管腳配置設定