在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 5332|回复: 2

[解决] 请高人指点 Verilog 数字时钟的键盘调时

[复制链接]
发表于 2011-5-12 20:19:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
在实现键盘调时是 按一下change键会一下加了很多数 不知道具体是什么原因 以为是需要键盘防抖 可是加上了 键盘到不好使了 怎么按 都调不了了 帮忙指点一下啊 急死了 这个用的时钟clk是100MHZ的





  1. module caclock(clk, key_in, key_out, cpld_e, counter);
  2. input clk;
  3. input [5:0] key_in;
  4. output [3:0] key_out;
  5. output [1:0] cpld_e;
  6. output [15:0] counter;

  7. //状态器状态值
  8. reg[15:0] counter;
  9. reg[3:0] key_out;
  10. reg[2:0] state =3'b000;
  11. reg[9:0] key_value;
  12. reg ND = 0;
  13. reg clk_20ms_r=0;

  14. reg[6:0] cnt_f=7'b0;
  15. reg[31:0] cnt_s=32'd0;
  16. reg[7:0] sec=8'h0;
  17. reg[7:0] min=8'h0;
  18. reg[7:0] hour=8'h0;
  19. reg[7:0] day=8'h1;
  20. reg[7:0] mon=8'h5;
  21. reg[7:0] year=8'h11;
  22. reg[3:0] week=4'h7;//开机显示日历为11年05月01日,星期七

  23. reg[0:0] clk_f=1'b1;
  24. reg[0:0] clk_s=1'b1;
  25. reg[0:0] clk_m=1'b1;
  26. reg[0:0] clk_h=1'b1;
  27. reg[0:0] clk_d=1'b1;
  28. reg[0:0] clk_mon=1'b1;
  29. reg[0:0] clk_y=1'b1;

  30. reg[7:0] inta=8'd0;
  31. reg flag=0;
  32. reg[1:0] e=2'd0;
  33. reg[1:0] t=2'd0;
  34. reg turn,change,enter;
  35. reg chg_y,chg_mon,chg_d,chg_w,chg_h,chg_m;
  36. wire yclk,monclk,dclk,wclk,hclk,mclk;

  37. assign cpld_e=2'b01;

  38. always@(posedge clk)
  39. begin
  40. if(cnt_f==7'b1000000)
  41. begin
  42. clk_f<=~clk_f;
  43. cnt_f<=0;
  44. end
  45. else
  46. cnt_f<=cnt_f+1;
  47. end
  48. always@(posedge clk) //得到周期为1s的脉冲信号
  49. begin
  50. if(cnt_s==32'd50000000)
  51. begin
  52. clk_s<=~clk_s;
  53. cnt_s<=0;
  54. end
  55. else
  56. cnt_s<=cnt_s+1;
  57. end

  58. //以下是通过按键实现调时功能
  59. always @(posedge clk) //检查是哪个按键按下
  60. begin
  61. case (state)
  62. 0: begin
  63. key_out[3:0]=4'b0000;
  64. ND=0;
  65. if(key_in !=6'b111111)
  66. begin
  67. state=1;
  68. key_out[3:0]=4'b1110;
  69. end
  70. else
  71. state=0;
  72. end
  73. 1: begin
  74. if(key_in !=6'b111111)
  75. begin
  76. state=5;
  77. end
  78. else
  79. begin
  80. state=2;
  81. key_out[3:0]=4'b1101;
  82. end
  83. end
  84. 2: begin
  85. if(key_in !=6'b111111)
  86. begin
  87. state=5;
  88. end
  89. else
  90. begin
  91. state=3;
  92. key_out[3:0]=4'b1011;
  93. end
  94. end
  95. 3: begin
  96. if(key_in !=6'b111111)
  97. begin
  98. state=5;
  99. end
  100. else
  101. begin
  102. state=4;
  103. key_out[3:0]=4'b0111;
  104. end
  105. end
  106. 4: begin
  107. if(key_in !=6'b111111)
  108. begin
  109. state=5;
  110. end
  111. else
  112. state=0;
  113. end
  114. 5: begin
  115. if(clk_20ms_r == 2000000)
  116. begin
  117. key_value[9:0]={key_in,key_out};
  118. ND=1;
  119. state=0;
  120. clk_20ms_r <= 20'b0;
  121. end
  122. else
  123. clk_20ms_r <= clk_20ms_r+1'b1;

  124. end
  125. endcase
  126. end
  127. always @(clk_f or key_in or key_out)
  128. begin
  129. if(ND==1)
  130. begin
  131. case(key_value)
  132. 10'b1111101011:turn<=0; //按键“turn”(即按键0)被按下时
  133. 10'b1101111110:change<=0; //按键“change”(即按键+)被按下时
  134. 10'b0111111110:enter<=0; //按键“切换”(即按键enter)被按下时
  135. default:{turn,change,enter}<=3'b111;//将三个按键置1,即按键没被按下
  136. endcase
  137. end
  138. else
  139. {turn,change,enter}<=3'b111;//将三个按键置1,即按键没被按下
  140. end
  141. always@(negedge enter) //enter信号控制系统在三种功能间的转换,即正常显示、调整日历、调整时钟
  142. begin
  143. if(e==2)
  144. e<=0;
  145. else
  146. e<=e+1;
  147. end
  148. always@(negedge turn) //turn信号控制显示调整当前调整参数右侧的参数
  149. begin
  150. if(t==3)
  151. t<=0;
  152. else
  153. t<=t+1;
  154. end
  155. always@(negedge change)
  156. begin
  157. case(e)
  158. 2:begin //e=2是调整日历
  159. if(t==0)
  160. begin
  161. chg_y<=!change;
  162. end
  163. else if(t==1)
  164. begin
  165. chg_mon<=!change;
  166. end
  167. else if(t==2)
  168. begin
  169. chg_d<=!change;
  170. end
  171. else
  172. begin
  173. chg_w<=!change;
  174. end
  175. {chg_h,chg_m}<=2'b00;
  176. end
  177. 1:begin //e=1是调整时钟
  178. if(t==0)
  179. begin
  180. chg_h<=!change;
  181. end
  182. else if(t==1)
  183. begin
  184. chg_m<=!change;
  185. end
  186. else if(t==2)
  187. begin
  188. chg_h<=!change;
  189. end
  190. else
  191. begin
  192. chg_m<=!change;
  193. end
  194. {chg_y,chg_mon,chg_d,chg_w}<=4'b0000;
  195. end
  196. default:{chg_y,chg_mon,chg_d,chg_w,chg_h,chg_m}<=0;
  197. endcase
  198. end

  199. //以下是计时功能
  200. always@(posedge clk_s) //秒计数的变化,得到周期为1秒的脉冲信号clk_m
  201. begin
  202. if(!(sec^8'h59)|(!turn)&(!e))
  203. begin
  204. sec<=0;
  205. if(!((!turn)&(!e)))
  206. clk_m<=1;
  207. end //按住“turn”按键一段时间,可使秒信号清零,该功能用于手动精确调时
  208. else
  209. begin
  210. if(sec[3:0]==4'b1001)
  211. begin
  212. sec[3:0]<=4'b0000;
  213. sec[7:4]<=sec[7:4]+1;
  214. end
  215. else
  216. begin
  217. sec[3:0]<=sec[3:0]+1;
  218. clk_m<=0;
  219. end
  220. end
  221. end
  222. always@(posedge mclk) //分计数的变化,得到周期为1分钟的脉冲信号clk_h
  223. begin
  224. if(min==8'h59)
  225. begin
  226. min<=0;
  227. clk_h<=1;
  228. end
  229. else
  230. begin
  231. if(min[3:0]==4'b1001)
  232. begin
  233. min[3:0]<=4'b0000;
  234. min[7:4]<=min[7:4]+1;
  235. end
  236. else
  237. begin
  238. min[3:0]<=min[3:0]+1;
  239. clk_h<=0;
  240. end
  241. end
  242. end
  243. always@(posedge hclk) //时计数的变化,得到周期为一天的脉冲信号clk_d
  244. begin
  245. if(hour==8'h23)
  246. begin
  247. hour<=0;
  248. clk_d<=1;
  249. end
  250. else
  251. begin
  252. if(hour[3:0]==4'b1001)
  253. begin
  254. hour[3:0]<=4'b0000;
  255. hour[7:4]<=hour[7:4]+1;
  256. end
  257. else
  258. begin
  259. hour[3:0]<=hour[3:0]+1;
  260. clk_d<=0;
  261. end
  262. end
  263. end
  264. always@(posedge dclk) //天计数的变化,得到周期为月的脉冲信号clk_mon
  265. begin
  266. if(((mon<=4'b1000)&&(mon%2==1))||((mon>=4'b1000)&&(mon%2==0))) //当月份是1,3,5,7,8,10,12时制定clk_mon
  267. begin
  268. if(day==8'h31)
  269. begin
  270. day<=8'h01;
  271. clk_mon<=1;
  272. end
  273. else
  274. begin
  275. if(day[3:0]==4'b1001)
  276. begin
  277. day[3:0]<=4'b0000;
  278. day[7:4]<=day[7:4]+1;
  279. end
  280. else
  281. begin
  282. day[3:0]<=day[3:0]+1;
  283. clk_mon<=0;
  284. end
  285. end
  286. end
  287. else if(mon==2) //当月份是2月时,制定脉冲信号clk_mon
  288. begin
  289. if(year%4==0) //年份是闰年时
  290. begin
  291. if(day==8'h29)
  292. begin
  293. day<=8'h01;
  294. clk_mon<=1;
  295. end
  296. else
  297. begin
  298. if(day[3:0]==4'b1001)
  299. begin
  300. day[3:0]<=4'b0000;
  301. day[7:4]<=day[7:4]+1;
  302. end
  303. else
  304. begin
  305. day[3:0]<=day[3:0]+1;
  306. clk_mon<=0;
  307. end
  308. end
  309. end
  310. else //年份是平年时
  311. begin
  312. if(day==8'h28)
  313. begin
  314. day<=8'h01;
  315. clk_mon<=1;
  316. end
  317. else
  318. begin
  319. if(day[3:0]==4'b1001)
  320. begin
  321. day[3:0]<=4'b0000;
  322. day[7:4]<=day[7:4]+1;
  323. end
  324. else
  325. begin
  326. day[3:0]<=day[3:0]+1;
  327. clk_mon<=0;
  328. end
  329. end
  330. end
  331. end
  332. else //当月份是4,6,9,11时,制定脉冲信号clk_mon
  333. begin
  334. if(day==8'h30)
  335. begin
  336. day<=8'h01;
  337. clk_mon<=1;
  338. end
  339. else
  340. begin
  341. if(day[3:0]==4'b1001)
  342. begin
  343. day[3:0]<=4'b0000;
  344. day[7:4]<=day[7:4]+1;
  345. end
  346. else
  347. begin
  348. day[3:0]<=day[3:0]+1;
  349. clk_mon<=0;
  350. end
  351. end
  352. end
  353. end
  354. always@(posedge monclk) //月计数的变化,得到周期为年的脉冲信号clk_y
  355. begin
  356. if(mon==8'h12)
  357. begin
  358. mon<=8'h01;
  359. clk_y<=1;
  360. end
  361. else
  362. begin
  363. if(mon[3:0]==4'b1001)
  364. begin
  365. mon[3:0]<=4'b0000;
  366. mon[7:4]<=mon[7:4]+1;
  367. end
  368. else
  369. begin
  370. mon[3:0]<=mon[3:0]+1;
  371. clk_y<=0;
  372. end
  373. end
  374. end
  375. always@(posedge yclk) //年计数的变化,只显示2000—2099年之间
  376. begin
  377. if(year==8'h99)
  378. year<=0;
  379. else
  380. begin
  381. if(year[3:0]==4'b1001)
  382. begin
  383. year[3:0]<=4'b0000;
  384. year[7:4]<=year[7:4]+1;
  385. end
  386. else
  387. year[3:0]<=year[3:0]+1;
  388. end
  389. end
  390. always@(posedge wclk) //周计数的变化
  391. begin
  392. if(week==4'h7)
  393. week<=4'h01;
  394. else
  395. week<=week+1;
  396. end
  397. assign yclk=clk_y||chg_y;
  398. assign monclk=clk_mon||chg_mon;
  399. assign dclk=clk_d||chg_d;
  400. assign wclk=clk_d||chg_w;
  401. assign hclk=clk_h||chg_h;
  402. assign mclk=clk_m||chg_m;

  403. always@(posedge clk_m)
  404. flag<=~flag;
  405. always@(posedge clk_f) //控制动态显示各位
  406. begin
  407. if(flag==0)
  408. begin
  409. if(inta==hour[7:4]+50)
  410. inta=sec[3:0];
  411. else if(inta==sec[3:0])
  412. inta=sec[7:4]+10;
  413. else if(inta==sec[7:4]+10)
  414. inta=8'd16;
  415. else if(inta==8'd16)
  416. inta=min[3:0]+20;
  417. else if(inta==min[3:0]+20)
  418. inta=min[7:4]+30;
  419. else if(inta==min[7:4]+30)
  420. inta=8'd36;
  421. else if(inta==8'd36)
  422. inta=hour[3:0]+40;
  423. else
  424. inta=hour[7:4]+50;

  425. case(inta)
  426. 0:counter<=16'h7F3F;
  427. 1:counter<=16'h7F06;
  428. 2:counter<=16'h7F5B;
  429. 3:counter<=16'h7F4F;
  430. 4:counter<=16'h7F66;
  431. 5:counter<=16'h7F6D;
  432. 6:counter<=16'h7F7D;
  433. 7:counter<=16'h7F07;
  434. 8:counter<=16'h7F7F;
  435. 9:counter<=16'h7F6F;
  436. 10:counter<=16'hBF3F;
  437. 11:counter<=16'hBF06;
  438. 12:counter<=16'hBF5B;
  439. 13:counter<=16'hBF4F;
  440. 14:counter<=16'hBF66;
  441. 15:counter<=16'hBF6D;
  442. 16:counter<=16'hDF40;
  443. 20:counter<=16'hEF3F;
  444. 21:counter<=16'hEF06;
  445. 22:counter<=16'hEF5B;
  446. 23:counter<=16'hEF4F;
  447. 24:counter<=16'hEF66;
  448. 25:counter<=16'hEF6D;
  449. 26:counter<=16'hEF7D;
  450. 27:counter<=16'hEF07;
  451. 28:counter<=16'hEF7F;
  452. 29:counter<=16'hEF6F;
  453. 30:counter<=16'hF73F;
  454. 31:counter<=16'hF706;
  455. 32:counter<=16'hF75B;
  456. 33:counter<=16'hF74F;
  457. 34:counter<=16'hF766;
  458. 35:counter<=16'hF76D;
  459. 36:counter<=16'hFB40;
  460. 40:counter<=16'hFD3F;
  461. 41:counter<=16'hFD06;
  462. 42:counter<=16'hFD5B;
  463. 43:counter<=16'hFD4F;
  464. 44:counter<=16'hFD66;
  465. 45:counter<=16'hFD6D;
  466. 46:counter<=16'hFD7D;
  467. 47:counter<=16'hFD07;
  468. 48:counter<=16'hFD7F;
  469. 49:counter<=16'hFD6F;
  470. 50:counter<=16'hFE3F;
  471. 51:counter<=16'hFE06;
  472. 52:counter<=16'hFE5B;
  473. default:counter<=16'hFE7F;
  474. endcase
  475. end
  476. else
  477. begin
  478. if(inta==year[7:4]+60)
  479. inta=week;
  480. else if(inta==week)
  481. inta=8'd8;
  482. else if(inta==8'd8)
  483. inta=day[3:0]+10;
  484. else if(inta==day[3:0]+10)
  485. inta=day[7:4]+20;
  486. else if(inta==day[7:4]+20)
  487. inta=mon[3:0]+30;
  488. else if(inta==mon[3:0]+30)
  489. inta=mon[7:4]+40;
  490. else if(inta==mon[7:4]+40)
  491. inta=year[3:0]+50;
  492. else
  493. inta=year[7:4]+60;

  494. case(inta)
  495. 0:counter<=16'h7F3F;
  496. 1:counter<=16'h7F06;
  497. 2:counter<=16'h7F5B;
  498. 3:counter<=16'h7F4F;
  499. 4:counter<=16'h7F66;
  500. 5:counter<=16'h7F6D;
  501. 6:counter<=16'h7F7D;
  502. 7:counter<=16'h7F07;
  503. 8:counter<=16'hBF40;
  504. 10:counter<=16'hDF3F;
  505. 11:counter<=16'hDF06;
  506. 12:counter<=16'hDF5B;
  507. 13:counter<=16'hDF4F;
  508. 14:counter<=16'hDF66;
  509. 15:counter<=16'hDF6D;
  510. 16:counter<=16'hDF7D;
  511. 17:counter<=16'hDF07;
  512. 18:counter<=16'hDF7F;
  513. 19:counter<=16'hDF6F;
  514. 20:counter<=16'hEF3F;
  515. 21:counter<=16'hEF06;
  516. 22:counter<=16'hEF5B;
  517. 23:counter<=16'hEF4F;
  518. 24:counter<=16'hEF66;
  519. 25:counter<=16'hEF6D;
  520. 26:counter<=16'hEF7D;
  521. 27:counter<=16'hEF07;
  522. 28:counter<=16'hEF7F;
  523. 29:counter<=16'hEF6F;
  524. 30:counter<=16'hF7BF;
  525. 31:counter<=16'hF786;
  526. 32:counter<=16'hF7DB;
  527. 33:counter<=16'hF7CF;
  528. 34:counter<=16'hF7E6;
  529. 35:counter<=16'hF7ED;
  530. 36:counter<=16'hF7FD;
  531. 37:counter<=16'hF787;
  532. 38:counter<=16'hF7FF;
  533. 39:counter<=16'hF7EF;
  534. 40:counter<=16'hFB3F;
  535. 41:counter<=16'hFB06;
  536. 42:counter<=16'hFB5B;
  537. 43:counter<=16'hFB4F;
  538. 50:counter<=16'hFDBF;
  539. 51:counter<=16'hFD86;
  540. 52:counter<=16'hFDDB;
  541. 53:counter<=16'hFDCF;
  542. 54:counter<=16'hFDE6;
  543. 55:counter<=16'hFDED;
  544. 56:counter<=16'hFDFD;
  545. 57:counter<=16'hFD87;
  546. 58:counter<=16'hFDFF;
  547. 59:counter<=16'hFDEF;
  548. 60:counter<=16'hFE3F;
  549. 61:counter<=16'hFE06;
  550. 62:counter<=16'hFE5B;
  551. 63:counter<=16'hFE4F;
  552. 64:counter<=16'hFE66;
  553. 65:counter<=16'hFE6D;
  554. 66:counter<=16'hFE7D;
  555. 67:counter<=16'hFE07;
  556. 68:counter<=16'hFE7F;
  557. 69:counter<=16'hFE6F;
  558. default:counter<=16'h7F7F;
  559. endcase
  560. end
  561. end
  562. endmodule


复制代码
发表于 2011-5-13 11:27:32 | 显示全部楼层
先说一下我是菜鸟!没有看你的程序从你描述的情况来看,觉得是检测过快!你可以尝试检测按键放开以后再执行下面的任务!(这样做按一次建,不管按多长都只能加一)如果想实现能自动连续加可以在设置一个定时器,只有在按键没有松开的情况下定时满了自动加一。
发表于 2011-5-14 18:38:16 | 显示全部楼层
不知道你是使用边沿,还是使用电平;最好使用边沿触发,同时防抖功能必须要的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /3 下一条

×

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-19 14:00 , Processed in 0.026600 second(s), 11 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表