工具 ISE14.7
通过时间分频在4位7段数码管中显示2个数字,给人眼一个错觉是同时显示出两个数字。
实验原理是轮流向各位数码管送出字形码和相应的位选信号,利用数码管闪烁的余晖和人眼视觉的暂留作用,使人感觉像各位管同时在显示
就像单片机数码管的思想一样:这里也要做相同的事情。
单片机步骤如下:
动态显示:
1)位选数码管; 2)段选数码管; 3)延时
dula=1;//段选P0=table[i];dula=0;P0=0xff;wela=1;//位选P0=a;wela=0;delayms(500);//延时
这样的代码实现流水显示,如果延时时间够短肉眼难以分辨;则可以实现几位数据的同时显示;
同理到FPGA中也是这样,不过要考虑用不同的模块实现这个功能
EG 两位数码管显示:
单片机中延时用个delay就可以实现,但是这里的延时要用一个计数器来模拟延时的状态
1.0)段选选择数码管显示的数值
1.1)因为这里我代码中值用了4个位来显示当前的数据(数据位宽为4)所以要在不同的时间选择当前显示的值
2)位选选择数码管的位数
3)延时(保证动态显示肉眼分辨不出)
代码如下:
module seg(clk,ext_rst_n,TimeH,TimeL,dtube_cs_n,dtube_data);input clk;//时钟信号25MHzinput ext_rst_n;//复位信号input [3:0]TimeH;//两位输入高位input [3:0]TimeL;//两位输入低位output reg[1:0] dtube_cs_n;//段选数据位output reg[6:0] dtube_data;//位选数据位reg[3:0] display_num;//当前显示数据reg[15:0] div_cnt;//延时计数器计数位initial div_cnt = 0;//赋初值为0//延时计数器模块always@ (posedge clk or negedge ext_rst_n)beginif(!ext_rst_n) div_cnt <= 8'd0;else if(div_cnt==16'd50000)div_cnt <= 8'd0;else div_cnt <= div_cnt+1'b1;end//显示当前的数据模块always @(posedge clk or negedge ext_rst_n)beginif(!ext_rst_n) display_num <= 4'h0;else if(div_cnt < 25000)display_num <= TimeH;elsedisplay_num <= TimeL;end//段选数据译码模块(共阴数码管)always @(posedge clk or negedge ext_rst_n)beginif(!ext_rst_n) dtube_data <= 8'h00;else begincase(display_num) 4'h0: dtube_data <= 8'h3f;4'h1: dtube_data <= 8'h06;4'h2: dtube_data <= 8'h5b;4'h3: dtube_data <= 8'h4f;4'h4: dtube_data <= 8'h66;4'h5: dtube_data <= 8'h6d;4'h6: dtube_data <= 8'h7d;4'h7: dtube_data <= 8'h07;4'h8: dtube_data <= 8'h7f;4'h9: dtube_data <= 8'h6f;default:dtube_data <= 8'h00;endcaseendend//位选选译模块always @(posedge clk or negedge ext_rst_n)beginif(!ext_rst_n) dtube_cs_n <= 2'b11;else if(div_cnt < 20000)dtube_cs_n <= 2'b01;elsedtube_cs_n <= 2'b10;endendmodule
数码管显示模块定义好了就要想如何实现倒计时的完成
这里的设计思路是
顶层设计模块
分频器模块 --> 计数器模块 -----> 数码管显示模块
输入复位信号 和系统时钟
1)分频器输入25MHz输出1Hz
2)IHz时钟信号传给计数器模块用于计数
3)计数的值在数码管显示
输出数码管的段选和位选
和蜂鸣器(计时完成标志位)
代码如下:
1,.TOP.v
module top(ext_clk_25m,ext_rst_n,beep,dtube_cs_n,dtube_data);//顶层控制模块input ext_clk_25m; //时钟信号25MHzinput ext_rst_n; //复位信号output [1:0] dtube_cs_n;//段选数据位output [6:0] dtube_data;//位选数据位output beep; //计时完成标志位wire clk;//中间变量wire [3:0] TimeL;wire [3:0] TimeH;//分频25MHZ变为1HZdiv d1(.ext_clk_25m(ext_clk_25m),.ext_rst_n(ext_rst_n),.mclk(clk));//倒计时计数模块counter c1(.mclk(clk),.ext_rst_n(ext_rst_n),.TimeH(TimeH),.TimeL(TimeL),.beep(beep));//数码管显示模块seg s1(.clk(ext_clk_25m),.ext_rst_n(ext_rst_n),.TimeH(TimeH),.TimeL(TimeL),.dtube_cs_n(dtube_cs_n),.dtube_data(dtube_data));endmodule
2.div.v
module div(ext_clk_25m,ext_rst_n,mclk);input ext_clk_25m;//输入时钟input ext_rst_n; //复位端口output reg mclk;//输出1Hzreg [23:0] cnt;//存放计数器的值initial cnt = 0;parameter TIME=24'd1250_0000;//时钟25MHz//分频模块//使得输入时钟为25MHz输出时钟为1Hzalways@(posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n)beginmclk <=1'b0;cnt <=25'd0;endelse if(cnt ==TIME-1'b1)beginmclk <=~mclk;cnt <=1'b0;endelsecnt <=cnt + 1'b1;endendmodule
3.counter.v
module counter(mclk,ext_rst_n,TimeH,TimeL,beep);input mclk;//时钟信号input ext_rst_n;//复位信号output reg [3:0]TimeH;//两位数码管显示高位output reg [3:0]TimeL;//两位数码管显示低位output beep;//计数完成位assign beep =({TimeH,TimeL}==8'h00);//当计数为0时,蜂鸣器响initial {TimeH,TimeL} = 8'h50; //计数器赋初值//计数器模块always@(posedge mclk or negedge ext_rst_n)beginif(!ext_rst_n){TimeH,TimeL} <= 8'h50;else if({TimeH,TimeL}==8'h00){TimeH,TimeL} <={TimeH,TimeL};else if(TimeL==4'h0)beginTimeH <=TimeH-1'b1;TimeL <=4'h9;endelsebeginTimeH <=TimeH;TimeL <=TimeL-1'b1;endendendmodule
4.数码管.v
上文已经贴出