nexys3正式开始练手-数码管时钟显示
来源:互联网 发布:淘宝五星好评怎么截图 编辑:程序博客网 时间:2024/05/16 11:42
下决心好好研究一番这个板子了,网上借鉴到一个不错的帖子首先来做一个数码管时钟显示。
数码管时钟我想对于很多学电子的同学来说都不陌生了,闲话不多说,先来说说这个原理。怎么点亮单个数码管我就不说了,无非分清共阴共阳,然后就是置高置低的问题。但是对于4个一起的数码管,要怎么控制他们看起来好像是在同时点亮的而且还能显示不同的内容就比较麻烦了。先上原理图:
显然要控制一个数码管需要两部分的端口--CA...DP和AN0...AN3,我一般叫左边的为段选,右边的为位选。从原理图上来看,位选端接在PNP管的B极,要先让C、E极导通,相应的位选端应该是低电平,比如AN3...AN0四位为1110,就是选择了最后一个数码管。而当数码管选中时(即相应的三极管导通),数码管公共端接的是高电平,显然这些数码管应该是共阳的,于是CA...DP端的编码就可以按共阳数码管的编码方式做了。转换成Verilog代码,可以是一下的常数定义:
parameter AN1 = 4'b1110,AN2 = 4'b1101,AN3 = 4'b1011,AN4 = 4'b0111;//数码管位选定义parameter zero = 8'b0000_0011,one = 8'b1001_1111,two = 8'b0010_0101,three = 8'b0000_1101,four = 8'b1001_1001, five = 8'b0100_1001,six = 8'b0100_0001,seven = 8'b0001_1111,eigth = 8'b0000_0001,nine = 8'b0000_1001;//数码管段选定义好了,现在搞清楚了第一个问题--怎么将0-9几个数显示出来,接下来的问题是怎么让4个数码管看起来是一起显示的,而且还能显示不同的内容。这个问题相信做过单片机数码管实验的同学马上就猜到了,没错,原理就是利用人眼视觉的暂留性(我是这么叫的,再专业点就不是我研究的问题了)--当两个数码管之间的变化小于100ms(貌似是这么长时间)时,我们的眼睛是看不到他们之间的闪烁的。于是,当我们要显示1234这4个数时,我们可以在1ms时显示1,25ms时显示2,50ms时显示3,75ms时显示4,然后循环,看起来就是一起显示1234这4个数了。当然,我们的硬件可以做的更快,这个时间间隔可以根据实际情况选择更短。把它翻译成Verilog语言就有下面的程序段了:
//数码管刷新显示模块always@(posedge div1000hz)begin if(rest) begin seg_count <= 0; an <= 4'b0000; seg <= 8'b0000_0000; end else begin case(seg_count) 0 : begin case(sec1) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN1; end 1 : begin case(sec2) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN2; end 2 : begin case(min1) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN3; end 3 : begin case(min2) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN4; end endcase seg_count <= seg_count + 1; endend
//数码管刷新显示模块always@(posedge div1000hz)begin if(rest) begin seg_count <= 0; an <= 4'b0000; seg <= 8'b0000_0000; end else begin case(seg_count) 0 : begin case(sec1) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN1; end 1 : begin case(sec2) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN2; end 2 : begin case(min1) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN3; end 3 : begin case(min2) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN4; end endcase seg_count <= seg_count + 1; endend好,现在剩最后一个问题了,那就是时钟控制部分。熟悉C的同学会说,那还不简单,分频计数,然后整除求余,将秒、分的十位各位分开不就可以了吗?没错,这是最简单的方式,但是,大家千万不要忽略了我们最后的代码是要变成硬件电路的。先不说Xilinx的IDE内嵌的XST综合器不支持对除号的综合,要实现除法必须要设计除法器(调用IP或自己设计),就算是设计出来了,一个除法器占用的硬件资源可能会比我们剩余部分电路占用的资源还多。从这方面出发考虑,我们要想想是不是有更好的方法实现它。其实只要我们稍微思考一下还是不难的,下面的代码就能很简洁的完成这部分的设计:
//时钟模块
always@(posedge div1hz)
begin
if(rest)
begin
sec1 <= 0;
sec2 <= 0;
min1 <= 0;
min2 <= 0;
end
else
begin
sec1 <= sec1 + 1;
if(sec1 == 9)
begin
sec2 <= sec2 + 1;
sec1 <= 0;
end
if(sec2 == 5 && sec1 == 9)
begin
min1 <= min1 + 1;
sec2 <= 0;
end
if(min1 == 9)
begin
min2 <= min2 + 1;
min1 <= 0;
end
if(min2 == 5 && min1 == 9)
begin
min2 <= 0;
end
end
end
下面是完整的程序:
`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company: // Engineer: // // Create Date: 09:59:26 10/09/2014 // Design Name: // Module Name: sevenseg_demo // Project Name: // Target Devices: // Tool versions: // Description: //// Dependencies: //// Revision: // Revision 0.01 - File Created// Additional Comments: ////////////////////////////////////////////////////////////////////////////////////module segclk( clk,//时钟输入,100M rest,//时钟复位信号,BTNU,高电平时复位 seg,//数码管段选 an,//数码管位选 //led//8个LED ); input clk,rest; output reg [7:0] seg; output reg [3:0] an; //output reg [7:0] led; parameter AN1 = 4'b1110,AN2 = 4'b1101,AN3 = 4'b1011,AN4 = 4'b0111;//数码管位选定义 parameter zero = 8'b0000_0011,one = 8'b1001_1111,two = 8'b0010_0101,three = 8'b0000_1101,four = 8'b1001_1001, five = 8'b0100_1001,six = 8'b0100_0001,seven = 8'b0001_1111,eigth = 8'b0000_0001,nine = 8'b0000_1001;//数码管段选定义 //parameter led_on = 8'b1111_1111,led_off = 8'b0000_0000;//LED亮灭定义 reg [25:0] div1hz_temp;//1秒分频计数 reg [12:0] div1000hz_temp;//数码管刷新时间分频计数 reg div1hz;//1Hz时钟 reg div1000hz;//数码管刷新时钟,频率为(100M/2^13)Hz//reg led_temp;//LED亮灭reg [3:0] sec1;//秒个位 reg [3:0] sec2;//秒十位 reg [3:0] min1;//分个位 reg [3:0] min2;//分十位 reg [1:0] seg_count;//数码管位选定位 //1秒分频模块 always@(posedge clk) begin div1hz_temp <= div1hz_temp + 1; if(div1hz_temp == 50000000) begin div1hz_temp <= 0; div1hz <= ~div1hz; end end //数码管刷新时间分频模块 always@(posedge clk) begin div1000hz_temp <= div1000hz_temp + 1; if(div1000hz_temp == 8191) begin div1000hz <= ~div1000hz; end end //时钟模块 always@(posedge div1hz) begin if(rest) begin sec1 <= 0; sec2 <= 0; min1 <= 0; min2 <= 0; end else begin sec1 <= sec1 + 1; if(sec1 == 9) begin sec2 <= sec2 + 1; sec1 <= 0; end if(sec2 == 5 && sec1 == 9) begin min1 <= min1 + 1; sec2 <= 0; end if(min1 == 9) begin min2 <= min2 + 1; min1 <= 0; end if(min2 == 5 && min1 == 9) begin min2 <= 0; end end end //LED亮灭控制模块 //always@(posedge div1hz) //begin //led_temp = ~led_temp; //if(led_temp) // led <= led_on; //else // led <= led_off; //end //数码管刷新显示模块 always@(posedge div1000hz) begin if(rest) begin seg_count <= 0; an <= 4'b0000; seg <= 8'b0000_0000; end else begin case(seg_count) 0 : begin case(sec1) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN1; end 1 : begin case(sec2) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN2; end 2 : begin case(min1) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN3; end 3 : begin case(min2) 0 : seg <= zero; 1 : seg <= one; 2 : seg <= two; 3 : seg <= three; 4 : seg <= four; 5 : seg <= five; 6 : seg <= six; 7 : seg <= seven; 8 : seg <= eigth; 9 : seg <= nine; endcase an <= AN4; end endcase seg_count <= seg_count + 1; end end endmodule
然后分配一下引脚,经测试程序在板子上运行正常,下一步要去研究下usb uart。
- nexys3正式开始练手-数码管时钟显示
- nexys3练手——vga显示
- 单片机数码管时钟显示
- 数码管显示时钟
- DS1302时钟数码管显示
- 数码管显示时钟
- 利用数码管显示的时钟
- 3、时钟数码管显示--可调时
- 自制NixieDisplay辉光数码管显示时钟
- nexys3
- nexys3练手——USB—UART初探秘
- CPLD 八段数码管时钟显示的VHDL实现
- DS1302实时时钟模块显示到数码管(共阳极)
- 数字时钟(数码管显示)例如:23-59-23
- 利用单片机的数码管模拟时钟的显示时间
- 51单片机 时钟程序设计 数码管可闪烁显示数值
- 时钟一:51单片机用替换的方法在数码管上显示时钟
- [51]数码管作时钟
- 移动联通基站定位演示示例
- Avro简介
- I2C总线协议学习笔记
- JVM日志和参数的理解
- 分布式日志收集系统Apache Flume的设计介绍
- nexys3正式开始练手-数码管时钟显示
- 程序员必须知道的10大基础实用算法及其讲解
- jsp九个隐式对象
- 统治世界的十大算法
- upper_bound,lower_bound,eaual_bound,equal_range二分搜索
- 日志分析方法概述
- MySQL在大型网站的应用架构演变
- listview单选开关设置,listview单击事件无响应
- Stom概念