xilinx FPGA实现数字钟——数码管显示

这两天学习xilinx的板子,做了一个数码管显示的数字时钟,本设计实现了数字时钟的数码管显示,没有实现调时间功能,现将实现过程记录下来。供有类似需要的童鞋做个参考。

 设计主要分为三个模块:时钟分频模块,时钟位数据产生模块,数码管扫描显示模块。

一、时钟显示模块 clk_div

  由于FPGA工作频率很高,我的板子上时钟是50MHz,数码管显示的最佳扫描频率是1KHz,第一个模块是做的一个50K的分频电路,是一个整数分频,这里并不复杂,具体整数分频实现思路可以参考我的博文:http://blog.csdn.net/baijingdong/article/details/20066327

代码:

module clk_div(clk,rst,clk_out);input clk;input rst;output clk_out;parameter N2=50000;reg clk3=1'b0;reg [16:0]count3=17'd0;assign clk_out=clk3;	always @(posedge clk or negedge rst)beginif (!rst)begincount3<=17'd0;clk3<=1'b0;endelseif(count3

二、时钟位数据产生模块 clk_dis1_count

 该模块前面也有一个时钟分频模块,因为分频后的时钟为1KHz,这个时钟直接做计数时钟频率还是太高,这里前面要先加一个1K分频的整数分频模块。clk1-in(1khz),clk3-out(1Hz).

 我的板子上只有四个数码管,因此只实现了秒和分的时间显示,与单片机和其他嵌入式开发不同,FPGA是一个纯硬件的电路,因此,设计相对很不灵活,我们知道数码管显示是扫描显示的,每次只能显示分、秒四个数字中的一个数字,若是按照C语言的思路可以定义一个sec作为一个秒变量,sec%10,sec/10分别可以作为秒的个位和十位的数据,但是在FPGA中却不推荐这么做,因为纯硬件电路做除法等运算直接综合会耗费大量资源,有的运算比如开根号等甚至是无法综合的。

因此,用定义一个计数器分别取其十位和个位的方法设计并不好,我最初的思路也是这样,从我的模块名中就可以看出。但是这种方法起码在fpga设计中不推荐。

这里分别定义了四个寄存器变量,分别代表分和秒的十位和个位数据,利用四层判断语句完成判决。思路并不复杂,但还是很容易让人糊涂的。

模块代码如下:

module clk_dis1_count(clk1,rst,op1,op2,op3,op4);
input clk1,rst;       //声明时钟和复位信号,此处时钟为分频后得到的1KHz信号;
output reg [3:0]op1=4'd0;
output reg [3:0]op2=4'd0;
output reg [3:0]op3=4'd0;
output reg [3:0]op4=4'd0; /*op1,op2...为数码管显示时钟,这里分别定义,op1,op3范围为【0-9】,op2,op4范围为【0-5】*/
//**************************************************************//											
//reg [9:0] count_clk1=10'd0;//parameter N2=500;				//1KHz->2Hz,500分频电路;
parameter  N2=1000;     //更改成为1hz,每一秒输出一次,做电子表使用。	十位数可以达到1024,不会溢出。	reg clk3=1'b0;     //输出clk3 ,2Hzreg [9:0]count_clk1=10'd0;//计数器,足够用了。always @(posedge clk1 or negedge rst)beginif (!rst)begincount_clk1<=10'd0;clk3<=1'b0;endelseif(count_clk100.后两位为00分位置加一。elsebeginif(op3<9)op3<=op3+1'b1;//由于分和秒都是60进制,因此方法同上。elsebeginif(op4<5)op4<=op4+1'b1;else op4<='d0;op3<='d0;endop2<='d0;endop1<='d0;end		end
endendmodule

三、数码管扫描显示模块 顶层模块

我的板子上的数码管是共阴极的,建立一个查询表,设计过程中用case(Num)语句改变输出。

数码管片选电平为高时数码管点亮,这里设计一个状态机,设计一个IDLE状态和四个输出状态在对应数码管点亮时输出对应位置的数据,然后切换到下一个输出状态。

这部分的代码如下:

`timescale 1ns / 1ps
//
// Company: bupt ,mr_bai
// Engineer: 
// 
// Create Date:    14:08:33 03/01/2014 
// Design Name: 
// Module Name:    clk_display 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module clk_display(clk,rst,sm_seg,sm_bit);input clk;input rst;output reg[7:0] sm_seg;output reg [3:0]sm_bit;//**********************//定义线网型连接线;//*******************wire clk1;wire [3:0]op1,op2,op3,op4;//*********************	 //定义状态机parameter  IDLE=5'b0000_1,SA =5'b0001_0,SB =5'b0010_0,SC =5'b0100_0,SD =5'b1000_0;reg [4:0]state;//reg [3:0]Num;clk_div M1(.clk(clk),.rst(rst),.clk_out(clk1));
clk_dis1_count M2(
.clk1(clk1),
.rst(rst),
.op1(op1),
.op2(op2),
.op3(op3),
.op4(op4)
);/*always @(posedge clk1)beginsm_bit<={sm_bit[2:0],sm_bit[3]};end*/always @(posedge clk1 or negedge rst)beginif(!rst)state<=IDLE;elsebegincase (state)IDLE:state<=SA ;SA:beginsm_bit<=4'b0001;Num	<=op1;state <=SB;endSB:beginsm_bit<=4'b0010;Num   <=op2;state <=SC;endSC:beginsm_bit<=4'b0100;Num   <=op3;state <=SD;endSD:beginsm_bit<=4'b1000;Num   <=op4;state <=SA;enddefault state<=IDLE;endcase	endendalways @ (Num)//begincase (Num)  4'h0 : sm_seg = 8'h3f;   // "0"4'h1 : sm_seg = 8'h06;   // "1"4'h2 : sm_seg = 8'h5b;   // "2"4'h3 : sm_seg = 8'h4f;   // "3"4'h4 : sm_seg = 8'h66;   // "4"4'h5 : sm_seg = 8'h6d;   // "5"//共阴极数码管表4'h6 : sm_seg = 8'h7d;   // "6"4'h7 : sm_seg = 8'h07;   // "7"4'h8 : sm_seg = 8'h7f;   // "8"4'h9 : sm_seg = 8'h6f;   // "9"4'ha : sm_seg = 8'h77;   // "a"4'hb : sm_seg = 8'h7c;   // "b"4'hc : sm_seg = 8'h39;   // "c"4'hd : sm_seg = 8'h5e;   // "d"4'he : sm_seg = 8'h79;   // "e"4'hf : sm_seg = 8'h71;   // "f"endcase endendmodule


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部