////////////////////////////////////////////////////////////////////////////////
// Engineer : chick_kid
// Create Date : 2009.05.12
// Design Name :
// Module Name : led8
// Project Name : led8
// Target Device: Cyclone EP2C5T144C8
// Tool versions: Quartus II 9.1
// Description : 24秒数码管倒计时显示
////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
module led8(
clk,rst_n,
led,led_seg
);
input clk; //25Mhz输入时钟信号
input rst_n; //复位信号输入,低有效
output[7:0] led; //输出数码管段选码
output[3:0] led_seg; //输出数码管位选码
//数码管显示 0~9 对应段选输出
parameter seg_num0 = 8'h03,
seg_num1 = 8'h9f,
seg_num2 = 8'h25,
seg_num3 = 8'h0d,
seg_num4 = 8'h99,
seg_num5 = 8'h49,
seg_num6 = 8'h41,
seg_num7 = 8'h1f,
seg_num8 = 8'h01,
seg_num9 = 8'h09;
//数码管位选 0~3 对应输出
parameter seg_en0 = 4'b1110,
seg_en1 = 4'b1101,
seg_en2 = 4'b1011,
seg_en3 = 4'b0111;
reg[24:0] cnt_1s; //1s计数器,0-24999999
reg[3:0] count1; //数码管显示数据高位,4位
reg[3:0] count2; //数码管显示数据低位,4位
reg[7:0] led_reg; //输出数码管段选码寄存器
reg[3:0] led_seg_reg; //输出数码管位选码寄存器
//1s定时计数
always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt_1s <= 25'd0;
else if(cnt_1s == 25'd24_999_999)
cnt_1s <= 25'd0;
else
cnt_1s <= cnt_1s+1'b1;
wire clk_div = (cnt_1s == 25'd24_999_999); //1s定时到标志位,高有效一个时钟周期
//显示数据每秒递减
always @(posedge clk_div or negedge rst_n)
if(!rst_n)
begin
count1 <= 4'd2;
count2 <= 4'd4;
end
else if( (count1 == 4'd0) && (count2 == 4'd0) )
begin
count1 <= 4'd2;
count2 <= 4'd4;
end
else if(count2 == 4'd0)
begin
count1 <= count1 - 1'b1;
count2 <= 4'd9;
end
else
count2 <= count2 - 1'b1;
reg[24:0] cnt_1ms; //显示刷新计数器
always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt_1ms <= 25'd0;
else if(cnt_1ms == 25'd24_999)
cnt_1ms <= 25'd0;
else
cnt_1ms <= cnt_1ms+1'b1;
wire clk_dis = (cnt_1ms == 20'd24_999); //1ms定时到标志位,高有效一个时钟周期
//状态寄存器
reg[2:0] state;
//数码管显示
always @(posedge clk_dis or negedge rst_n)
begin
if(!rst_n)
begin
led_reg <= 8'hff;
led_seg_reg <= 4'b1111;
state <= 2'b00;
end
else
if(state == 2'b00)
begin
state <= 2'b01;
led_seg_reg <= 4'b1101;
case (count2)
4'd0 : led_reg <= seg_num0;
4'd1 : led_reg <= seg_num1;
4'd2 : led_reg <= seg_num2;
4'd3 : led_reg <= seg_num3;
4'd4 : led_reg <= seg_num4;
4'd5 : led_reg <= seg_num5;
4'd6 : led_reg <= seg_num6;
4'd7 : led_reg <= seg_num7;
4'd8 : led_reg <= seg_num8;
4'd9 : led_reg <= seg_num9;
default : led_reg <= seg_num0;
endcase
end
else if(state == 2'b01)
begin
state <= 2'b00;
led_seg_reg <= 4'b1110;
case (count1)
4'd0 : led_reg <= seg_num0;
4'd1 : led_reg <= seg_num1;
4'd2 : led_reg <= seg_num2;
4'd3 : led_reg <= seg_num3;
4'd4 : led_reg <= seg_num4;
4'd5 : led_reg <= seg_num5;
4'd6 : led_reg <= seg_num6;
4'd7 : led_reg <= seg_num7;
4'd8 : led_reg <= seg_num8;
4'd9 : led_reg <= seg_num9;
default : led_reg <= seg_num0;
endcase
end
end
assign led = led_reg;
assign led_seg = led_seg_reg;
endmodule
像我们这样的菜鸟会发现,我的代码里面没有分频模块,我用的是使能的思想,wire clk_div = (cnt_1s == 25'd24_999_999); //1s定时到标志位,高有效一个时钟周期,就是当计数器计到24999999是,给clk_div一个高电平,这样clk_div每隔40ns*(24999999+1)= 1s就有一个高电平(计数器从0到24999999),这样也可以驱动每1秒让数码管计数加1或减1。
个人觉得使能思想比分频要好。然后还有一个问题,就是时间的问题。如果用:wire clk_div = (cnt_1s == 25'd24_999_999);这样就是每隔1s一个高电平。
仿真代码:
`timescale 1 ns/ 1 ps
module led8_vlg_tst();
reg clk;
reg rst_n;
// wires
wire [7:0] led;
wire [3:0] led_seg;
// assign statements (if any)
led8 i1 (
// port map - connection between master ports and signals/registers
.clk(clk),
.led(led),
.led_seg(led_seg),
.rst_n(rst_n)
);
initial
begin
clk = 0;
forever #20 clk = ~clk; //每20ns翻转一次,T=40ns
end
initial
begin
rst_n = 0;
#40_00;
rst_n = 1;
end
endmodule
然后看仿真结果
但是如果用分频就有个2倍的时间关系
reg clk_div;
always @(posedge clk or negedge rst_n)
if(!rst_n)
clk_div <= 0;
else if(cnt_1s == 25'd24_999_999)
clk_div <= ~clk_div;
else
clk_div <= 0;
这样的clk_div的周期就是2s,没2s有一个上升沿。这样我就不仿真了。
呵呵,仿真的时候能体会到1s的时间是多么的长,可以现实生活中的1s是那么的短暂。
总结也是学习的过程。
文章评论(0条评论)
登录后参与讨论