FPGA系统性学习笔记连载_Day13【简易计时器实验】之【Xilinx Spartan-6实现】篇

2021-04-07 11:48:49 浏览数 (1)

FPGA系统性学习笔记连载_Day13【简易计时器实验】之【Xilinx Spartan-6实现】篇

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

连载《叁芯智能fpga设计与研发-第13天》 【简易计时器实验】之【Xilinx Spartan-6实现】

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

本实验记录一个简易计时器,要求时间分为 时、分、秒,增加2个按键,1个为启动计时、1个为停止计时。

数码管的驱动原理,网上有太多的例程,这里我先不赘述,请自行上网查询,后续到了数码管专题篇再给大家出对应的文章

一、一位数码管显示原理

二、四位数码管显示原理

三、我用的是6位数码管,原理和4位是一样的

我的实验要用6个数码管,位选用了一个38译码器,因为FPGA的引脚不够用了

四、整体设计框架

我分为digital_clock.v、seven_tube_driver.v、clock.v

seven_tube_driver.v是6个数码管的驱动文件

clock.v是计时器计数模块

digital_clock.v是顶层的设计模块,包含按键的检测和计数器的实例化

五、digital_clock.v代码实现

代码语言:javascript复制
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    15:42:30 12/01/2020
// Design Name:
// Module Name:    digital_clock
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module digital_clock(
    input               clk,
    input               rst_n,
    input               on,
    input               off,
     
    output      [7:0]   seg_out,
    output      [2:0]   sel_out
);
 
    reg     flag_start_cnt;    //启动计数标志
     
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            flag_start_cnt = 1'b0; 
        else if (on == 1'b0)
                flag_start_cnt = 1'b1;
        else if (off == 1'b0)
                flag_start_cnt = 1'b0; 
        else
            flag_start_cnt = flag_start_cnt;
    end
     
     
    clk clk_inst(
            .clk        (clk),
            .rst_n      (rst_n),
            .start      (flag_start_cnt),
            .seg_out    (seg_out),
            .sel_out    (sel_out)              
        );
 
endmodule

六、clock.v代码实现

代码语言:javascript复制
module   clk(
        input               clk,
        input               rst_n,
        input               start,
         
        output      [7:0]   seg_out,
        output      [2:0]   sel_out
     
    );
 
        wire        [23:0]  data;
 
        //parameter T_1s        = 50_000_000;   //1s
        parameter   T_1s        = 50_000_00;    //100ms,看的数码管走的比较快
             
        reg         [25:0]  cnt_clk;
     
        reg         [5:0]   cnt_1s;
        reg         [5:0]   cnt_1min;
        reg         [5:0]   cnt_1h;
        reg         [5:0]   cnt_1d;    
         
        reg                 flag_1s;
        reg                 flag_1min;
        reg                 flag_1h;
        reg                 flag_1d;
 
 
         
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            begin
                cnt_clk <= 0;
                flag_1s <= 0;
            end
        else if(cnt_clk == T_1s-1)
            begin
                cnt_clk <= 0;
                flag_1s <= 1;
            end
        else
            begin
                flag_1s <= 0;
                //判断是否启动计数
                if(start)
                    cnt_clk <= cnt_clk    1'b1;
                else
                    cnt_clk <= cnt_clk;
            end
    end
 
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            begin
                cnt_1s <= 0;
                flag_1min <= 0;
            end
        else if(flag_1s)
            begin
                if(cnt_1s == 59)
                    begin
                        cnt_1s <= 0;
                        flag_1min <= 1;
                    end
                else
                    begin
                        cnt_1s <= cnt_1s   1'b1;
                        flag_1min <= 0;
                    end
            end
        else
            begin
                cnt_1s  <= cnt_1s;
                flag_1min <= 0;
            end
    end
 
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            begin
                cnt_1min <= 0;
                flag_1h <= 0;
            end
        else if(flag_1min)
            if(cnt_1min == 59)
                begin
                    cnt_1min <= 0;
                    flag_1h <= 1;
                end
            else   
                begin
                    cnt_1min <= cnt_1min   1'b1;
                    flag_1h <= 0;
                end
        else
            begin
                cnt_1min <= cnt_1min;
                flag_1h <= 0;
            end
    end
 
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            begin
                cnt_1h <= 0;
                flag_1d <= 0;
            end
        else if(flag_1h)
            if(flag_1h == 23)
                begin
                    cnt_1h <= 0;
                    flag_1d <= 1;
                end
            else   
                begin
                    cnt_1h <= cnt_1h   1'b1;
                    flag_1d <= 0;
                end
        else
            begin
                cnt_1h <= cnt_1h;
                flag_1d <= 0;
            end
    end
 
    seven_tube_driver seven_tube_driver_inst(
        .clk        (clk),
        .rst_n      (rst_n),
        .data       (data),
                   
        .seg_out    (seg_out),
        .sel_out    (sel_out)  
        );
 
    assign data = cnt_1h*10000   cnt_1min * 100   cnt_1s;
 
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

八、硬件原理图

九、硬件效果

【QQ交流群】

群号:173560979,进群暗语:FPGA技术江湖粉丝。

多年的FPGA企业开发经验,各种通俗易懂的学习资料以及学习方法,浓厚的交流学习氛围,QQ群目前已有1000多名志同道合的小伙伴,无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有。

【微信交流群】

现微信交流群已建立09群,人数已达数千人,欢迎关注“FPGA技术江湖”微信公众号,可获取进群方式。

后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。

江湖偌大,继续闯荡,愿大侠一切安好,有缘再见!

0 人点赞