可调时钟

  1 /**********************************************
  2 
  3 工程名:可调时钟
  4 模块名: clock
  5 
  6 -----------------------------------------------
  7 IO说明:
  8     clk:            50MHZ时钟
  9     key_in[3:0]:        四位独立按键
 10     seg_out[7:0]:        七段数码管段选
 11     seg_en[7:0]:        八个数码管位选
 12 -----------------------------------------------
 13 操作说明:
 14 key[0] :set键       调时/选位
 15 key[1] :inc键     增加 
 16 key[2] :sub键     减小
 17 key[3] :ok键      确认
 18 
 19 1. 默认为计时状态,此时点下set键,进入调时状态
 20 2. 此时秒位闪烁,此时点下 inc/sub键,即可调时
 21 3:长按inc/sub键,进行快速调时,每秒加减10次
 22 4:再点下set键,即可更换调时位
 23 5:调完后按下ok键,恢复计时
 24 
 25 ------------------------------------------------
 26 
 27 时间:2012年6月24日
 28 作者:刘文武
 29 
 30 ***********************************************/
 31 module clock(
 32     clk,    
 33     key_in,
 34     seg_out,
 35     seg_en
 36 );
 37 
 38 
 39 input clk; 
 40 input [3:0] key_in;    
 41 output [7:0] seg_out; 
 42 output [7:0] seg_en;
 43 
 44 //时间寄存器
 45 reg [5:0] min,sec;    
 46 reg [4:0] hour;
 47 
 48 //a时    b分   c秒
 49 //1十位      2个位
 50 reg [31:0] a1,a2,b1,b2,c1,c2;
 51 
 52 
 53 reg clk_1khz ;          //用于数码管扫描
 54 reg clk_10hz;           //用于更新时间数据
 55 reg clk_1_2hz;          //用于数码管闪烁
 56 
 57 reg [7:0] seg_out ;     //数码管段选
 58 reg [7:0] seg_en;       //数码管位选
 59 
 60 reg state;              //状态位,计时为0,调时为1
 61 reg [7:0]en_buf;        //en缓冲
 62 reg [2:0] set_pos;      //调时位:{时,分,秒}
 63 reg [3:0] key_buf;      //读键缓冲
 64 
 65 
 66 //寄存器初始化
 67 //----------------------------------------
 68 initial
 69  begin
 70       count <= 24'b1 ;
 71       set_pos <=3'b001;
 72       en_buf <= 8'b1111_1110;
 73       seg_out <= 8'b1111_1111 ;
 74  end
 75 
 76 //分频
 77 //------------------------------------------
 78 reg [24:0] count ;
 79 
 80 always @ (posedge clk )
 81 begin
 82 
 83  if( count == 25000000 ) count <= 1 ;    
 84  else count <= count + 1'b1;
 85 
 86 if(count % 12500000 == 0 )   clk_1_2hz <= ~ clk_1_2hz;      //1_2HZ             
 87 if(count % 2500000 == 0 )    clk_10hz <= ~ clk_10hz;        //10HZ
 88 if(count % 25000 == 0 )      clk_1khz <= ~ clk_1khz;        //1kHZ
 89         
 90 end
 91 
 92 
 93 //数码管扫描
 94 //------------------------------------------
 95 always @ (posedge clk_1khz)
 96 begin
 97  
 98 // 计算时间位    
 99     a1<=hour/10;
100     a2<=hour%10;
101     b1<=min/10;
102     b2<=min%10;
103     c1<=sec/10; 
104     c2<=sec%10;
105 //动态扫描
106     seg_en<=en_buf;
107     case (en_buf)
108             //在调时状态下,该调试位为真,且1/2Hz时钟到来时,该数码管灭,实现闪烁效果
109     8'b1111_1110 :   seg_out <= (state && set_pos[0]&& clk_1_2hz) ? 8'b1111_1111:zimu(a1);        
110     8'b1111_1101 :   seg_out <= (state && set_pos[0] && clk_1_2hz) ? 8'b1111_1111: zimu(a2);
111     8'b1111_1011 :   seg_out <= 8'b1011_1111;    //显示"-"
112     8'b1111_0111 :   seg_out <= (state && set_pos[1] && clk_1_2hz) ? 8'b1111_1111:zimu(b1);
113     8'b1110_1111 :   seg_out <= (state && set_pos[1] && clk_1_2hz) ? 8'b1111_1111:zimu(b2);
114     8'b1101_1111 :   seg_out <= 8'b1011_1111;    //显示"-"
115     8'b1011_1111 :   seg_out <= (state && set_pos[2] && clk_1_2hz) ? 8'b1111_1111:zimu(c1);
116     8'b0111_1111 :   seg_out <= (state && set_pos[2] && clk_1_2hz) ? 8'b1111_1111:zimu(c2);
117     default :    en_buf <=  8'b1111_1110;
118     endcase
119     //位选寄存器环形移位
120     if(en_buf == 8'b0111_1111)    en_buf  <=  8'b1111_1110;
121     else    en_buf  <= ~( ( ~en_buf ) << 1 );
122             
123 end 
124 
125 
126 //按键消抖
127 //-----------------------------------------------
128 reg [19:0] key_count;
129 
130 always @ (posedge clk)
131 begin
132  if(key_in != 4'b1111)    //判断是否有键按下
133  begin
134     key_count <= key_count+1'b1;//当检测到有键按下,计数器加1
135     key_buf <= 4'b1111;//此时延时尚未达到,所以输出为高
136 
137     if(key_count>=20'd1000000)
138     begin
139     key_count<=20'd1000001;//当达到延时200us(50MHZ)时,锁存key-count值
140     key_buf <= key_in; //此时延时达到200us,输出为低
141     end
142  end
143  else 
144  begin
145      key_buf <= 4'b1111; //当没有键按下时, 输出为高
146      key_count <= 1'b0; //计数器清0
147  end
148 
149 end
150 
151 //模式选择
152 //---------------------------------------------------
153 reg [3:0] count2;
154 
155 always @ (posedge clk_10hz)
156 begin
157 
158         if(state == 0)
159             begin
160                 //计时状态下,检测到set键按下,转为调时模式
161                 if(key_buf[0]==0) state <= 1'b1;
162              
163              
164                 if(count2==4'd9) 
165                 begin
166                     count2<=4'b0;
167                     //0.1s * 10 = 1s
168                     timerun(sec,min,hour);
169                 end            
170                 else count2<=count2+1'b1;
171             end
172         else timeset(sec,min,hour,set_pos,key_buf);
173     end
174 
175 
176  //取字模函数
177  //---------------------------------------------------
178 
179 function [7:0] zimu;
180     input [3:0]num;
181     begin
182     case(num)
183         4'b0000:         zimu = 8'b1100_0000;    // "0"        
184         4'b0001:         zimu = 8'b1111_1001;    // "1"
185         4'b0010:         zimu = 8'b1010_0100;    // "2"
186         4'b0011:         zimu = 8'b1011_0000;    // "3"
187         4'b0100:         zimu = 8'b1001_1001;    // "4"
188         4'b0101:         zimu = 8'b1001_0010;    // "5"
189         4'b0110:         zimu = 8'b1000_0010;    // "6"
190         4'b0111:         zimu = 8'b1111_1000;    // "7"
191         4'b1000:         zimu = 8'b1000_0000;    // "8"
192         4'b1001:         zimu = 8'b1001_0000;    // "9"
193         default :        zimu = 8'bx;           //不确定
194     endcase    
195     end
196 
197 endfunction
198 
199 //计时任务
200 //------------------------------------------------
201 task timerun;
202 inout [5:0] sec,min;
203 inout [4:0] hour;
204 begin
205 if(sec==6'd59)
206 begin
207     sec<=6'b0;
208     if(min==6'd59)
209     begin
210         min<=6'b0;
211         if(hour == 5'd23)
212             hour<=5'b0;
213         else
214             hour<=hour+1'b1;
215     end
216     else
217     min<=min+1'b1;
218 end
219 else
220 sec<=sec+1'b1;
221 end
222 endtask    
223 
224 
225 //调时任务
226 //------------------------------------------------
227 task timeset;
228 
229 inout [5:0] sec,min;
230 inout [4:0] hour;
231 inout [2:0] set_pos;
232 input [3:0] key_buf;
233 
234 begin
235 
236 if(key_buf[0]==0)//按下set键,调试位左移,时<-分<-秒
237     begin
238         if(set_pos==3'b100) set_pos<=3'b001;
239         else set_pos<=set_pos<<1;
240     end
241     else if (key_buf[1]==0)//按下inc键,调试位+
242     begin
243     
244         case(set_pos)
245         3'b100: begin if(sec==6'd59) sec<=6'd0; else sec<= sec+1'b1;        end    //秒+
246         3'b010: begin if(min==6'd59) min<=6'd0; else min<= min+1'b1;        end    //分+
247         3'b001: begin if(hour==5'd23) hour<=5'd0; else hour<= hour+1'b1;    end    //时+
248         default:;
249         endcase
250     end
251     else if (key_buf[2]==0)//按下sub键,调试位-
252     begin
253         case(set_pos)
254         3'b100: begin if(sec==6'd00) sec<=6'd59; else sec<= sec-1'b1;        end    //秒-
255         3'b010: begin if(min==6'd00) min<=6'd59; else min<= min-1'b1;        end    //分-
256         3'b001: begin if(hour==5'd00) hour<=5'd23; else hour<= hour-1'b1;    end    //时-
257         default:;
258         endcase
259     end
260     else if (key_buf[3]==0)//按下ok键,退出调时模式
261         state<= 1'b0;
262 
263 end
264 endtask
265 
266 
267 //-----------------------------------------------
268 
269 endmodule
原文地址:https://www.cnblogs.com/sky1991/p/2560442.html