FPGA系统性学习笔记连载_Day17【打卡计数、数码管显示实验】

2021-04-08 11:03:45 浏览数 (1)

FPGA系统性学习笔记连载_Day17【打卡计数、数码管显示实验】之【Intel Cycle IV FPGA平台验证】

本系列为FPGA系统性学习学员学习笔记整理分享,如有学习或者购买开发板意向,可加交流群联系群主。

连载《叁芯智能fpga设计与研发-第17天》 【打卡计数、数码管显示实验】之【Intel Cycle IV FPGA平台验证】

原创作者:紫枫术河 转载请联系群主授权,否则追究责任

本实验做一个打卡计数器,用一个按键模拟打卡信号,按键每按一次数码管的数字加一。

实验要求,按键检测必须用状态机实现,按键的计数值,通过调用数码管显示模块实现,不能再一个模块实现所有功能,这个实验的模块是为了以后的实验能给直接复用现在的 按键检测模块、数码管模块。

一、按键检测模块FSM_key_fiter.v

代码语言:javascript复制
module  FSM_key_fiter(
    input           clk,
    input               rst_n,
    input           key,
     
    output  reg     flag_up,
    output  reg     flag_down
);
 
    parameter   WAIT_DOWN   = 3'b000;
    parameter   DOWN            = 3'b001;
    parameter   DOWN_Fiter  = 3'b010;
    parameter   WAIT_UP     = 3'b011;  
    parameter   UP              = 3'b100;  
    parameter   UP_Fiter        = 3'b101;      
    parameter   OK              = 3'b110;
     
    parameter   T_10ms      = 500_000;
     
    reg [19:0]  cnt;
     
    reg [2:0] status;
 
     
    wire        flag_up_r;
    wire        flag_down_r;
 
     
    edge_check edge_check_inst(
        .signal     (key),
        .clk            (clk),
        .rst_n      (rst_n),
 
        .flag_up        (flag_up_r),
        .flag_down  (flag_down_r)
    );
 
     
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            begin
                status <= WAIT_DOWN;
                cnt <= 20'd0;
                flag_down <= 1'b0;
                flag_up <= 1'b0;            
            end
        else
            begin
                case(status)
                    WAIT_DOWN:
                                begin
                                    if(flag_down_r)
                                        status <= DOWN; 
                                    else
                                        status <= WAIT_DOWN;
                                end
                    DOWN:
                                begin
                                    cnt <= 20'd0;
                                    status <= DOWN_Fiter;   
                                end
                    DOWN_Fiter:
                                begin
                                    if(flag_down_r || flag_up_r)
                                        status <= DOWN;
                                    else
                                        begin
                                            if(cnt == T_10ms-1)
                                                begin
                                                    //flag拉高,产生脉冲
                                                    flag_down <= 1'b1;
                                                    cnt <= 20'd0;
                                                    status <= WAIT_UP;
                                                end
                                            else
                                                cnt <= cnt   1'b1;                                      
                                        end
                                end
                    WAIT_UP:
                                begin
                                    //flag拉低,只产生一个clk的脉冲
                                    flag_down <= 1'b0;                              
                                    if(flag_up_r)
                                        status <= UP;   
                                    else
                                        status <= WAIT_UP;  
                                end                                                                
                    UP:
                                begin
                                    cnt <= 20'd0;
                                    status <= UP_Fiter; 
                                end
                    UP_Fiter:
                                begin
                                    if(flag_down_r || flag_up_r)
                                        status <= UP;
                                    else
                                        begin
                                            if(cnt == T_10ms-1)
                                                begin
                                                    //flag拉高,产生脉冲
                                                    flag_up <= 1'b1;
                                                    cnt <= 20'd0;
                                                    status <= OK;
                                                end
                                            else
                                                cnt <= cnt   1'b1;                                      
                                        end
                                end
                    OK:
                                begin
                                    //flag拉低,产生脉冲
                                    flag_up <= 1'b0;                            
                                    status <= WAIT_DOWN;
                                end                                
                    default:
                                begin
                                    status <= WAIT_DOWN;
                                    flag_down <= 1'b0;
                                    flag_up <= 1'b0;                                
                                    cnt <= 20'd0;
                                end
                endcase
            end
    end
 
endmodule

二、数码管显示模块seven_tube_driver.v

代码语言:javascript复制
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    10:23:31 12/01/2020
// Design Name:
// Module Name:    seven_tube_driver
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module seven_tube_driver(
    input                       clk,
    input                       rst_n,
    input       [23:0]      data,
     
    output  reg [7:0]   seg_out,
    output  reg     [2:0]   sel_out
    );
     
    parameter           T_1K            = 50_000;
    parameter           Sel_Total   = 6;
     
    reg                     flag_1k;
     
    reg         [15:0]  cnt_1k;
    reg         [3:0]       show_data;
    reg         [3:0]       sel_38;
     
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            begin
                cnt_1k <= 16'b0;
                flag_1k <= 1'b0;
            end
        else if(cnt_1k == T_1K-1)
            begin
                cnt_1k <= 16'b0;
                flag_1k <= 1'b1;
            end
        else
            begin
                cnt_1k <= cnt_1k   1'b1;
                flag_1k <= 1'b0;
            end
    end
     
    //1KHz 的频率 ,同时切换显示是数据和数码管
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            sel_out <= 3'b0;
        else if(flag_1k)
            if(sel_out == Sel_Total-1)
                sel_out <= 3'b0;
            else
                sel_out <= sel_out   1'b1;
        else
            sel_out <= sel_out;
         
    end
     
    always@(*)begin
        case(sel_out)
            3'b000  : show_data = data/100000;
            3'b001  : show_data = data/10000;
            3'b010  : show_data = data/1000;
            3'b011  : show_data = data/100;
            3'b100  : show_data = data/10;
            3'b101  : show_data = data;
            default:show_data = 0;
        endcase
    end
     
    reg     flag_dp;        //显示小数点标志
 
    always@(*)begin
        case(sel_out)
            3'b001  :   flag_dp = 1;
            3'b011  :   flag_dp = 1;
            default :   flag_dp = 0;
        endcase
    end
 
    always@(*)begin
        case(show_data)
            0:seg_out = 8'b11000000;
            1:seg_out = 8'b11111001;
            2:seg_out = 8'b10100100;
            3:seg_out = 8'b10110000;
            4:seg_out = 8'b10011001;
            5:seg_out = 8'b10010010;
            6:seg_out = 8'b10000010;
            7:seg_out = 8'b11111000;
            8:seg_out = 8'b10000000;
            9:seg_out = 8'b10010000;
            default:seg_out = 8'b11111111;
        endcase
        if(flag_dp)
            seg_out = seg_out & 8'b01111111;  //显示小数点,只需要将最高位写0即可
        else
            seg_out = seg_out;
    end
 
endmodule

三、顶层模块key_tube_display.v

代码语言:javascript复制
module key_tube_display(
        input           clk,
        input               rst_n,
        input           key,
 
        output  [7:0]   seg,
        output  [2:0]   sel    
);
 
    wire                    flag_up;
    wire                    flag_down;
     
    reg     [23:0]  data;
 
    FSM_key_fiter   FSM_key_fiter_inst(
        .clk            (clk),
        .rst_n      (rst_n),
        .key            (key),
         
        .flag_up        (flag_up),
        .flag_down  (flag_down)
    );
 
    seven_tube_driver seven_tube_driver_inst(
        .clk            (clk),
        .rst_n      (rst_n),
        .data           (data),
     
        .seg_out        (seg),
        .sel_out        (sel)
    );
 
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            data <= 24'd0;
        else
            begin
                if(flag_down)
                    data <= data   1'b1;
                else
                    data <= data;
            end
    end
     
endmodule

四、硬件下板 Intel Cycle IV FPGA平台验证

我用的是叁芯智能的开发板(intel Cycle IV:EP4CE6E22C8)

1、管脚配置请查看我之前的文章

2、硬件效果

0 人点赞