原创 FPGA课堂实验二:数码管倒计时

2010-5-18 12:21 6142 5 5 分类: FPGA/CPLD

////////////////////////////////////////////////////////////////////////////////
// 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是那么的短暂。


总结也是学习的过程。  

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
5
×
广告
关闭 站长推荐上一条 /3 下一条