0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FPGA学习系列:36.实时时钟的设计

FPGA学习交流 2018-09-10 17:12 次阅读

设计背景:

DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM实时时钟电路,它可以对年、月、日、周、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器


设计原理:

DS1302芯片的封装如下:

image.png


它有8个引脚,在我们的设计中我们只要驱动3个引脚就可以了,另外的引脚都是我们的硬件相连接的,和FPGA连接的有时钟先sclk,串行数据数据接口IO,以及CE.。

工作原理就是在数据的传送过程中先把CE拉高,在每个数据的上升沿写入数据,在下降沿输入数据,一次只能读写一位数据。最初我们通过一个8位的控制指令来选择读写,如果控制指令是单字节模式,连续的8个脉冲上升沿写入,下降沿读出数据,一次只能读取一个字节,如果是突发模式通过连续的脉冲一次性的写完7个字节的时间寄存器也可以一次性的读完8--328位的ram数据。

控制指令有8位,第七位必须为高,如果是0写入被禁止,第六位0是对时钟寄存器的读写操作,为1对是控制对RAM区的读写操作。

bit1 -- 5 是对相关寄存器的操作,bit0是读写操作。

image.png


各个寄存器的的设置,和每位的表示如下图,图中高速我们读写时控制字是多少以及写入寄存器的地址,和写入的8位的时间表示我们可以通过下表来设置一个初始的时间。

image.png


涓流寄存器主要决定了DS1302的充电特性,涓流充电选择位4--7位,1010涓流充电其他禁止充电,二级管选择位3--2位,电阻选择1--0位具体的选择如下表:

image.png


突发模式下,表示我们可以连续写,连读,连续写时必须写满7个时钟寄存器。时序图如下,是SPI通信。


下表表示数据传送过程中数据的延迟,时钟的周期等时间。


image.png


image.png


本次设计是通过配置DS1302芯片来实现实时时钟的监测,我们通过通过控制2个按键来选择我们要在数码管上显示的时间,按下按键1我们来显示周几,按下按键2来显示年月日,不按显示时分秒,这样显示复合我们的数字表的显示。

我的思路是先打开写保护,一个一个寄存器的写进去,然后关闭写保护,然后再读出数据。


设计架构图:

image.png


设计代码:

顶层模块

0moduleds_1302(clk,rst_n,sclk,ce,data,sel ,seg7,key);

1

2 inputclk,rst_n;

3 wire[23:0]shi_fen_miao;

4 wire[23:0]nian_yue_ri;

5 wire[23:0]day;

6 outputsclk,ce;

7 inoutdata;

8 output[7:0]seg7;

9 output[5:0]sel;

10 input[1:0]key;

11

12 seg seg_dut(

13 .clk(clk),

14 .rst_n(rst_n),

15 .sel(sel),

16 .seg7(seg7),

17 .data_in(shi_fen_miao)

18 );

19

20 time_ce time_ce(

21 .clk(clk),

22 .rst_n(rst_n),

23 .data(data),

24 .sclk(sclk),

25 .show_data(shi_fen_miao),

26 .ce(ce),

27 .key(key)

28 );

29

30 endmodule

设计模块

0moduletime_ce(clk,rst_n,data,sclk,show_data,ce,key);

1

2 inputclk,rst_n;

3 inoutdata;

4 outputregsclk;

5 outputregce;

6 input[1:0]key;

7

8 regbuff;

9 regflag;

10 reg[7:0]times;

11 outputreg[23:0]show_data;

12 reg[23:0]shi_fen_miao;

13 reg[23:0]nian_yue_ri;

14 reg[7:0]day;

15

16

17 assigndata =flag ?buff :1'bz;//定义一个三态,来控制IO口的输入输出

18

19 parameterw_1302 =16'h8e00; //取消写保护

20 parameterw_miao =16'h8030; // 30

21 parameterw_fen =16'h8211;//11

22 parameterw_shi =16'h8408; //24小时制的 8

23 parameterw_ri =16'h8621; //21

24 parameterw_yue =16'h8803; //3

25 parameterw_nian =16'h8c17; //2017

26 parameterw_day =16'h8a03; //星期3

27 parameterr_1302 =16'h8e80;//写保护

28 parameterw_dian =16'h90a7;//二个二极管8

29

30 //读寄存器的设置

31 parameterr_miao =8'h81;

32 parameterr_fen =8'h83;

33 parameterr_shi =8'h85;

34 parameterr_ri =8'h87;

35 parameterr_yue =8'h89;

36 parameterr_nian =8'h8d;

37 parameterr_day =8'h8b;

38

39 reg[14:0]count;

40 reg[15:0]reg_data;

41 regw_flag;

42 regr_flag;

43 reg[1:0]state_r;

44

45 //定义一个序列及,来控制读写的时序

46 always@(posedgeclk)

47 if(!rst_n)

48 begin

49 count <=0;

50 state_r <=0;

51 end

52 else

53 case(state_r)

54 0 : if(r_flag ||w_flag)

55 state_r <=1;

56 else

57 state_r <=0;

58 1 : if(count <(400+34*250))

59 count <=count +1;

60 else

61 begin

62 state_r <=0;

63 count <=0;

64 end

65 default:state_r <=0;

66 endcase

67

68 //开始ce为低,然后拉高,过上最少4US后拉高SCLK

69 //在写的时候我们控制总线,写入命令,读的时候释放总线

70 //在上升沿写入数据,我们就要在上升沿前准备数据,

71 //在下降沿读出数据,我们就要在下降沿后接收数据

72 reg[7:0]time_temp;

73 always@(posedgeclk)

74 if(!rst_n)

75 begin

76 sclk <=0;

77 ce <=0;

78 flag <=0;

79 times <=0;

80 buff <=0;

81 time_temp <=0;

82 end

83 else

84 case(count)

85 20 : begince <=1;flag <=1;end

86 400+1*250 : beginsclk <=0;buff <=reg_data[8];end

87 400+2*250 : beginsclk <=1;end

88 400+3*250 : beginsclk <=0;buff <=reg_data[9];end

89 400+4*250 : beginsclk <=1;end

90 400+5*250 : beginsclk <=0;buff <=reg_data[10];end

91 400+6*250 : beginsclk <=1;end

92 400+7*250 : beginsclk <=0;buff <=reg_data[11];end

93 400+8*250 : beginsclk <=1;end

94 400+9*250 : beginsclk <=0;buff <=reg_data[12];end

95 400+10*250 : beginsclk <=1;end

96 400+11*250 : beginsclk <=0;buff <=reg_data[13];end

97 400+12*250 : beginsclk <=1;end

98 400+13*250 : beginsclk <=0;buff <=reg_data[14];end

99 400+14*250 : beginsclk <=1;end

100 400+15*250 : beginsclk <=0;buff <=reg_data[15];end

101

102 400+16*250 : if(w_flag)

103 sclk <=1;

104 elseif(r_flag)

105 beginsclk <=1;end

106

107 400+17*250 : if(w_flag)

108 beginsclk <=0;buff <=reg_data[0];end

109 elseif(r_flag)

110 beginsclk <=0;flag <=0;end

111

112 400+18*250 : if(w_flag)

113 sclk <=1;

114 elseif(r_flag)

115 beginsclk <=1;times[0]<=data;end

116

117 400+19*250 : if(w_flag)

118 beginsclk <=0;buff <=reg_data[1];end

119 elseif(r_flag)

120 sclk <=0;

121

122 400+20*250 : if(w_flag)

123 sclk <=1;

124 elseif(r_flag)

125 beginsclk <=1;times[1]<=data;end

126

127

128 400+21*250 : if(w_flag)

129 beginsclk <=0;buff <=reg_data[2];end

130 elseif(r_flag)

131 sclk <=0;

132

133 400+22*250 : if(w_flag)

134 sclk <=1;

135 elseif(r_flag)

136 beginsclk <=1;times[2]<=data;end

137

138 400+23*250 : if(w_flag)

139 beginsclk <=0;buff <=reg_data[3];end

140 elseif(r_flag)

141 sclk <=0;

142

143 400+24*250 : if(w_flag)

144 sclk <=1;

145 elseif(r_flag)

146 beginsclk <=1;times[3]<=data;end

147

148 400+25*250 : if(w_flag)

149 beginsclk <=0;buff <=reg_data[4];end

150 elseif(r_flag)

151 sclk <=0;

152

153 400+26*250 : if(w_flag)

154 sclk <=1;

155 elseif(r_flag)

156 beginsclk <=1;times[4]<=data;end

157

158 400+27*250 : if(w_flag)

159 beginsclk <=0;buff <=reg_data[5];end

160 elseif(r_flag)

161 sclk <=0;

162

163 400+28*250 : if(w_flag)

164 sclk <=1;

165 elseif(r_flag)

166 beginsclk <=1;times[5]<=data;end

167

168 400+29*250 : if(w_flag)

169 beginsclk <=0;buff <=reg_data[6];end

170 elseif(r_flag)

171 sclk <=0;

172

173 400+30*250 : if(w_flag)

174 sclk <=1;

175 elseif(r_flag)

176 beginsclk <=1;times[6]<=data;end

177

178 400+31*250 : if(w_flag)

179 beginsclk <=0;buff <=reg_data[7];end

180 elseif(r_flag)

181 sclk <=0;

182

183 400+32*250 :beginsclk <=1;times[7]<=data;end

184 400+33*250:beginsclk <=0;if(w_flag)flag <=0;elseif(r_flag)flag <=1;end

185 400+34*250 :ce <=0;

186 400+35*250 : ce <=1;

187

188 endcase

189

190 //一下模块是控制模块,每当写完一个寄存器后,计数会到400+35*25

191 //然后跳转下一个状态执行下一个寄存器命令

192 //在读模式下,计数到400+35*25是表示读出了一个时间我们接收

193 //放到寄存器中

194

195 reg[5:0]state;

196 always@(posedgeclk)

197 if(!rst_n)

198 begin

199 reg_data <=0;

200 w_flag <=0;

201 r_flag <=0;

202 state <=0;

203 end

204 else

205 case(state)

206 0 : begin

207 w_flag <=1;

208 reg_data <=w_1302;

209 state <=1;

210 end

211

212 1 : begin

213 if(count ==400+34*250)

214 begin

215 reg_data <=w_miao;

216 state <=2;

217 end

218 else

219 state <=1;

220 end

221

222 2 : begin

223 if(count ==400+34*250)

224 begin

225 reg_data <=w_fen;

226 state <=3;

227 end

228 else

229 state <=2;

230 end

231 3 : begin

232 if(count ==400+34*250)

233 begin

234 reg_data <=w_shi;

235 state <=4;

236 end

237 else

238 state <=3;

239 end

240

241 4 : begin

242 if(count ==400+34*250)

243 begin

244 reg_data <=w_ri;

245 state <=5;

246 end

247 else

248 state <=4;

249 end

250

251 5 : begin

252 if(count ==400+34*250)

253 begin

254 reg_data <=w_yue;

255 state <=6;

256 end

257 else

258 state <=5;

259 end

260

261 6 : begin

262 if(count ==400+34*250)

263 begin

264 reg_data <=w_nian;

265 state <=7;

266 end

267 else

268 state <=6;

269 end

270

271 7 : begin

272 if(count ==400+34*250)

273 begin

274 reg_data <=w_day;

275 state <=8;

276 end

277 else

278 state <=7;

279 end

280

281 8 : begin

282 if(count ==400+34*250)

283 begin

284 reg_data <=r_1302;

285 state <=9;

286 end

287 else

288 state <=8;

289 end

290

291

292 ///////////////////////

293

294 9 : begin

295 if(count ==(400+250*34-1))

296 begin

297 w_flag <=0;

298 r_flag =1;

299 state <=10;

300 end

301 else

302 state <=9;

303 end

304 /////////////////时分秒

305 10 : begin

306 state <=11;

307 end

308

309 11 : begin

310 if(count ==400+34*250)

311 begin

312 state <=12;

313 shi_fen_miao[7:0]<=times;

314 end

315 else

316 begin

317 state <=11;

318 reg_data[15:8]<=r_miao;

319 end

320 end

321

322 12 : begin

323 if(count ==400+34*250)

324 begin

325 state <=13;

326 shi_fen_miao[15:8]<=times;

327 end

328 else

329 begin

330 state <=12;

331 reg_data[15:8]<=r_fen;

332 end

333 end

334

335 13 : begin

336 if(count ==400+34*250)

337 begin

338 shi_fen_miao[23:16]<=times;

339 state <=14;

340 end

341 else

342 begin

343 reg_data[15:8]<=r_shi;

344 state <=13;

345 end

346 end

347

348 //////////////// 年月日

349 14 : begin

350 if(count ==400+34*250)

351 begin

352 state <=15;

353 nian_yue_ri[7:0]<=times;

354 end

355 else

356 begin

357 state <=14;

358 reg_data[15:8]<=r_ri;

359 end

360 end

361

362 15 : begin

363 if(count ==400+34*250)

364 begin

365 state <=16;

366 nian_yue_ri[15:8]<=times;

367 end

368 else

369 begin

370 state <=15;

371 reg_data[15:8]<=r_yue;

372 end

373 end

374

375 16 : begin

376 if(count ==400+34*250)

377 begin

378 nian_yue_ri[23:16]<=times;

379 state <=17;

380 end

381 else

382 begin

383 reg_data[15:8]<=r_nian;

384 state <=16;

385 end

386 end

387

388 ////////

389 17 : begin

390 if(count ==400+34*250)

391 begin

392 day <=times;

393 state <=10;

394 end

395 else

396 begin

397 reg_data[15:8]<=r_day;

398 state <=17;

399 end

400 end

401

402 default:state <=0;

403 endcase

404

405 //按键判断需要输出的时间是什么

406 always@(posedgeclk)

407 if(!rst_n)

408 begin

409 show_data <=0;

410 end

411 elseif(!key[0])

412 show_data <=day;

413 elseif(!key[1])

414 show_data <=nian_yue_ri;

415 else

416 show_data <=shi_fen_miao;

417

418 endmodule

数码管模块

0moduleseg(clk,rst_n,sel,seg7,data_in);

1

2 inputclk;

3 inputrst_n;

4 input[23:0]data_in;

5 outputreg[5:0]sel;

6 outputreg[7:0]seg7;

7

8 parameters0 =3'b000;

9 parameters1 =3'b001;

10 parameters2 =3'b010;

11 parameters3 =3'b011;

12 parameters4 =3'b100;

13 parameters5 =3'b101;

14

15 `defineT1ms 50_000

16 //`define T1ms 5

17 reg[15:0]count;

18 regflag;

19

20 //分频模块 1K的时钟

21 always@(posedgeclk ornegedgerst_n)

22 if(!rst_n)

23 begin

24 count <=16'd0;

25 flag <=1;

26 end

27 else

28 if(count ==(`T1ms/2-1))

29 begin

30 count <=16'd0;

31 flag <=~flag;

32 end

33 else

34 begin

35 count <=count +1'b1;

36 end

37

38 reg[2:0]state;

39 reg[3:0]num;

40

41 //循坏扫描,选择那一个数码管显示哪一位

42 always@(posedgeflag ornegedgerst_n)

43 if(!rst_n)

44 begin

45 sel <=3'b0;

46 state <=3'b0;

47 num <=4'b0;

48 end

49 else

50 begin

51 case(state)

52 s0:begin

53 state <=s1;

54 sel <=6'b011111;

55 num <=data_in[23:20];

56 end

57 s1:begin

58 state <=s2;

59 sel <=6'b101111;

60 num <=data_in[19:16];

61 end

62 s2:begin

63 state <=s3;

64 sel <=6'b110111;

65 num <=data_in[15:12];

66 end

67 s3:begin

68

69 state <=s4;

70 sel <=6'b111011;

71 num <=data_in[11:8];

72

73 end

74 s4:begin

75 state <=s5;

76 sel <=6'b111101;

77 num <=data_in[7:4];

78 end

79 s5:begin

80 state <=s0;

81 sel <=6'b111110;

82 num <=data_in[3:0];

83 end

84 default:state <=s0;

85 endcase

86 end

87

88 //编码

89 always@(*)

90 begin

91 case(num)

92 0:seg7 =8'b1100_0000;

93 1:seg7 =8'b1111_1001;

94 2:seg7 =8'b1010_0100;

95 3:seg7 =8'b1011_0000;

96 4:seg7 =8'b1001_1001;

97 5:seg7 =8'b1001_0010;

98 6:seg7 =8'b1000_0010;

99 7:seg7 =8'b1111_1000;

100 8:seg7 =8'b1000_0000;

101 9:seg7 =8'b1001_0000;

102 10:seg7 =8'b1000_1000;

103 11:seg7 =8'b1000_0011;

104 12:seg7 =8'b1100_0110;

105 13:seg7 =8'b1010_0001;

106 14:seg7 =8'b1000_0110;

107 15:seg7 =8'b1000_1110;

108 default:;

109 endcase

110 end

111endmodule

测试模块

0`timescale1ns/1ps

1

2moduletb;

3

4 regclk,rst_n;

5

6 wiresclk,ce;

7 wiredata;

8 wire[7:0]seg7;

9 wire[5:0]sel;

10

11 initialbegin

12 clk =1;

13 rst_n =0;

14

15 #200.1rst_n =1;

16

17 end

18

19 always#10clk =~clk;

20

21

22 ds_1302 dut(

23 .clk(clk),

24 .rst_n(rst_n),

25 .sclk(sclk),

26 .ce(ce),

27 .data(data),

28 .sel (sel),

29 .seg7(seg7)

30 );

31

32endmodule

仿真:



我们的测试图中我们可以清楚的看到我们在发送的寄存器命令,时收回总线控制权,读数据时释放了总线控制权。

下图中是突发读的时序图,我的设计是我们一个一个的写寄存器,必须写满7个时钟寄存器,然后突发的读,突发读的时候拉高ce然后不停的读接收数据就行了。



有兴趣的的朋友可以在我设计的基础上,做出突发读写,这样也是对大家的提高。
















声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1610

    文章

    21390

    浏览量

    595440
收藏 人收藏

    评论

    相关推荐

    RX-4571LC、NB、SA实时时钟模块

    RX-4571LC实时时钟模块是EPSON推出的一求款额定频率32.768KHz,接口为SPI(3-wire),月偏差为±60 s的实时时钟模块,12脚贴片,具有小尺寸,高稳定性。该款实时时钟模块
    发表于 01-31 11:46 0次下载

    基于51单片机的实时时钟设计

    电子发烧友网站提供《基于51单片机的实时时钟设计.rar》资料免费下载
    发表于 01-12 10:43 12次下载

    基于51单片机的实时时钟+温度应用设计

    电子发烧友网站提供《基于51单片机的实时时钟+温度应用设计.rar》资料免费下载
    发表于 01-12 10:20 0次下载

    基于51单片机的实时时钟设计

    电子发烧友网站提供《基于51单片机的实时时钟设计.rar》资料免费下载
    发表于 01-02 10:15 41次下载

    基于51单片机的实时时钟+温度应用设计

    基于51单片机的实时时钟+温度应用设计(仿真)
    发表于 01-02 09:55 6次下载

    Arduino篇—实时时钟

    DS1307时钟模块:** DS1307串行实时时钟(RTC)是低功耗,全二进制编码的十进制(BCD)时钟/日历以及56字节的NV SRAM。
    的头像 发表于 11-01 16:49 1375次阅读
    Arduino篇—<b class='flag-5'>实时时钟</b>

    CW32实时时钟(RTC)介绍

    CW32实时时钟(RTC)介绍
    的头像 发表于 10-24 15:36 683次阅读
    CW32<b class='flag-5'>实时时钟</b>(RTC)介绍

    实时时钟芯片DS1302应用资料

    子函数供读者调用。本章最后通过一个具体的实例,讲解了如何使用51系列单片机来操作实时时钟芯片DS1302。
    发表于 09-26 08:27

    DS1302实时时钟资料包分享

    电子发烧友网站提供《DS1302实时时钟资料包分享.zip》资料免费下载
    发表于 09-15 16:01 5次下载
    DS1302<b class='flag-5'>实时时钟</b>资料包分享

    FPGA零基础学习之Vivado-RTC实时时钟系统设计

    及打算进阶提升的职业开发者都可以有系统性学习的机会。 系统性的掌握技术开发以及相关要求,对个人就业以及职业发展都有着潜在的帮助,希望对大家有所帮助。本次带来Vivado系列,RTC实时时钟系统设计。话
    发表于 09-04 20:36

    基于FPGA的RTC实时时钟系统设计

    RTC(real time clock)实时时钟,在电脑、手机等电子产品中都有,应用较多。它的主要作用就是,在产品断电之后,时间还可以继续走数。这样我们在重新使用电子产品时,时间仍然正确。芯片本身可以通过纽扣电池供电,接下来我们一起学习一下RTC的驱动。
    的头像 发表于 08-23 09:29 844次阅读
    基于<b class='flag-5'>FPGA</b>的RTC<b class='flag-5'>实时时钟</b>系统设计

    全新C8系列实时时钟模块现已发布

    近日,Micro Crystal 瑞士微晶公司推出了全新的 C8 系列超小型实时时钟模块,这款模块的设计初衷是致力于满足极小尺寸和轻量级设计的需求。 新发布的 C8 系列首批两款实时时钟
    的头像 发表于 08-04 09:26 613次阅读

    STM32 RTC实时时钟(二)

    上次实验完成了对实时时钟的基本功能——计时的实验,这次在计时的基础上对RTC的可编程闹钟的功能进行测试。
    的头像 发表于 07-22 15:43 1360次阅读
    STM32 RTC<b class='flag-5'>实时时钟</b>(二)

    STM32 RTC实时时钟(一)

    STM32处理器内部集成了实时时钟控制器(RTC),因此在实现实时时钟功能时,无须外扩时钟芯片即可构建实时时钟系统。
    的头像 发表于 07-22 15:41 3571次阅读
    STM32 RTC<b class='flag-5'>实时时钟</b>(一)

    DA1468x SoC 的实时时钟(RTC) 概念

    DA1468x SoC 的实时时钟 (RTC) 概念
    发表于 07-06 19:27 0次下载
    DA1468x SoC 的<b class='flag-5'>实时时钟</b>(RTC) 概念