当前位置:   article > 正文

基于FPGA ---ds1302实时时钟显示_ds1302芯片显示

ds1302芯片显示

ds1302使用手册

  1. 实验目的

使用型号为DS1302的实时时钟芯片完成日期、时间的实时显示。(通过UART发送至上位机显示)。

  1. 实验原理

1.ds1302硬件介绍

(1) 内含一个钮电池,断电情况下运行 10 年以上不丢失数据。

(2) 可计秒、 分、 时、 星期、 日、 月、 年,并有闰年补偿功能,有效年份 为 2100 年以前。

(3) 可选二进制码或 BCD 码表示时间、日历,具有闹钟定时功能。

(4) 可选 12 小时或 24 小时制,12 小时时钟模式带有 PM 和 AM 指示,有夏令时功能。

(5) 简单的3线接口。

1.1硬件结构图

1 DS1302的工作原理

2.1控制字节

DS1302 的控制字符表示。控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出

2.2输入输出

在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

2.3寄存器

DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字。

第一个寄存器读写地址分别为0x81和0x80,其最高位CH用来判断系统上一次掉电后时钟是否仍然在正常工作,为1则系统掉电后备用电源没电或其他原因导致的时钟部分未正常工作,为0则掉电后DS1302正常使用备用电源。第六位至第四位表示的是秒数的十位数,最后四位则表示秒数的个位数,表示范围0~59。

第二个寄存器读写地址分别为0x83和0x82,最高位保留,后面七位同第一个寄存器一致,但表示结果是分数。

第三个寄存器读写地址分别为0x85和0x84,最高位为1表示使用12小时制,当选择12小时制时,第五位为0表示AM,为1表示PM,最高位为0时使用24小时制,第五位和第四位一块表示小时的十位数,最后四位则表示小时的个位数。

第四个寄存器读写地址分别为0x87和0x86,第五位和第四位表示日数的十位数,后四位表示日数的个位数。

第五个寄存器读写地址分别为0x89和0x88,第四位表示月份的十位数,后四位表示月份的个位数。

第六个寄存器读写地址分别为0x8B和0x8A,后三位表示星期几。

第七个寄存器读写地址分别为0x8D和0x8C,前四位表示年份的十位数,后四位表示年份的个位数,这里的0~99表示范围2000~2099。

这七个寄存器的数据需要同时读出,才能确保所读数据的准确性。举个不同时读取的例子,读秒数是59,分钟数是0,当下一次读分钟时,分钟变成了1,读出的时间可能是01:59,而实际时间却是00:59,显然是不正确的。为此,DS1302提供了一个burst模式一次性读出这七个寄存器的所有数据。burst模式读写地址分别为0xBF和0xBE,DS1302收到这两个指令后,将时间信息一并存入缓存器,从而保证了时间信息的准确性。

2 DS1302的功能分析及时序分析

DS1302实时时钟芯片,一旦初始化后,它就会随着现实的时钟一直计数。

3.1写操作时序图

下图是 DS1302 芯片写操作的时序图。第一个字节是“访问寄存器的地址”,第二字节是“写数据”。在写操作的时候,都是“上升沿有效”,然而还有一个条件,就是 CE(/RST)信号必须拉高。(数据都是从 LSB 开始发送,亦即是最低位开始至最高位结束)。

需要注意的是在突发模式下,ce保持高,发送额外的扫描周期,直到突发结束。

3.2读操作时序图

下图是DS1302芯片读操作的时序图。基本上和写操作的时序图大同小异,区别的地方就是在第二个字节时“读数据”的动作。第二字节读数据开始时, SCLK 信号都是“下降沿有效”。嗯,别忘了 CE(/RST)信号同样是必须拉高。(第一节数据是从 LSB 开始输出,第二节数据是从 LSB 开始读入)。

3.3DS1302时序参数

DS1302 最高速率为 2Mhz 并且无下限, 50Mhz 的量化结果为 25。时钟信号拉高 TCH 或拉低 TCL至少需要保持 250ns,量化结果为 12.5。至于时钟信号上升时间 TR 或者下降时间 TF 最大时间为500ns,极端说是最小时间是 0ns。

系统架构设计                          

1.系统框图 

                

2.模块端口信号列表

3.状态图

代码设计

1.ds1302接口设计

  1. /**************************************功能介绍***********************************
  2. Date : 2023年10月16日19:16:20
  3. Author : Xlin.
  4. Version : 1.0
  5. Description: ds1302接口设计
  6. *********************************************************************************/
  7. //---------<模块及端口声名>------------------------------------------------------
  8. module ds1302_if(
  9. input clk ,
  10. input rst_n ,
  11. output reg [7:0] tx_data ,//输出数据
  12. output tx_vld ,//输出数据有效
  13. output done ,//读完一次时间
  14. //ds1302接口
  15. output sclk,
  16. inout io ,
  17. output ce
  18. );
  19. //---------<参数定义>---------------------------------------------------------
  20. parameter TIME_1S = 50_000_000,
  21. CYCLE = 50 ;
  22. //---------<内部信号定义>-----------------------------------------------------
  23. //DS1302 寄存器地址定义
  24. parameter SEC_RD = 8'h81,
  25. MIN_RD = 8'h83,
  26. HOUR_RD = 8'h85,
  27. DATA_RD = 8'h87,
  28. MON_RD = 8'h89,
  29. DAY_RD = 8'h8b,
  30. YEAR_RD = 8'h8d,
  31. WP_RD = 8'h8f;
  32. parameter SEC_WR = 8'h80,
  33. MIN_WR = 8'h82,
  34. HOUR_WR = 8'h84,
  35. DATA_WR = 8'h86,
  36. MON_WR = 8'h88,
  37. DAY_WR = 8'h8a,
  38. YEAR_WR = 8'h8c;
  39. //初始时间定义 23年10月15日 星期日 15:30:00
  40. parameter YEAR = 8'h23,//年
  41. MON = 8'h10,//月
  42. DATA = 8'h15,//日
  43. DAY = 8'h07,//星期
  44. HOUR = 8'h15,//小时
  45. MIN = 8'h30,//分
  46. SEC = 8'h00;//秒
  47. parameter BIT_MAX = 8 ;
  48. //状态机参数定义
  49. localparam IDLE = 'b0001,
  50. WRITE = 'b0010,
  51. READ = 'b0100,
  52. DONE = 'b1000;
  53. reg [3:0] state_c ;//现态
  54. reg [3:0] state_n ;//次态
  55. //状态机转移条件定义
  56. wire idle2write ;
  57. wire write2read ;
  58. wire write2done ;
  59. wire read2done ;
  60. wire done2idle ;
  61. //写信号
  62. reg write_flag ;
  63. //初始化完成
  64. reg start_flag ;
  65. //8bit计数器
  66. reg [2:0] cnt_bit ;
  67. wire add_cnt_bit ;
  68. wire end_cnt_bit ;
  69. //写字节计数器
  70. reg [2:0] cnt_byte ;
  71. wire add_cnt_byte ;
  72. wire end_cnt_byte ;
  73. //指令计数器
  74. reg [2:0] cnt_done ;
  75. reg [2:0] max ;
  76. wire add_cnt_done ;
  77. wire end_cnt_done ;
  78. //1s计数器
  79. reg [26:0] cnt_sec ;
  80. wire add_cnt_sec ;
  81. wire end_cnt_sec ;
  82. //周期计数器
  83. reg [5:0] cnt_cyc ;
  84. wire add_cnt_cyc ;
  85. wire end_cnt_cyc ;
  86. //三太门控制
  87. wire data_in ;
  88. reg data_out ;
  89. wire data_en ;
  90. //第一段:时序逻辑描述状态转移
  91. always @(posedge clk or negedge rst_n)begin
  92. if(!rst_n)begin
  93. state_c <= state_n;
  94. end
  95. else begin
  96. state_c <= state_n;
  97. end
  98. end
  99. //第二段:组合逻辑描述状态转移规律和状态转移条件
  100. always @(*) begin
  101. case(state_c)
  102. IDLE : if(idle2write)
  103. state_n = WRITE;
  104. else
  105. state_n = state_c;
  106. WRITE : if(write2read)
  107. state_n = READ ;
  108. else if(write2done)
  109. state_n = DONE;
  110. else
  111. state_n = state_c;
  112. READ : if(read2done )
  113. state_n = DONE ;
  114. else
  115. state_n = state_c;
  116. DONE : if(done2idle )
  117. state_n = IDLE ;
  118. else
  119. state_n = state_c;
  120. default : state_n = IDLE ;
  121. endcase
  122. end
  123. assign idle2write = state_c == IDLE && write_flag;//初始化信号,完成拉低
  124. assign write2read = state_c == WRITE && end_cnt_bit && start_flag;//写地址写完
  125. assign write2done = state_c == WRITE && end_cnt_byte&&~start_flag;//写的包括地址 和初始时间
  126. assign read2done = state_c == READ && end_cnt_bit;//读地址写完
  127. assign done2idle = state_c == DONE && 1'b1;
  128. //****************************************************************
  129. //-- 写信号 和 初始化完成信号
  130. //****************************************************************
  131. always @(posedge clk or negedge rst_n)begin
  132. if(!rst_n)begin
  133. write_flag<= 'd1;
  134. end
  135. else if(state_c==READ && end_cnt_done)begin
  136. write_flag<='d0;
  137. end
  138. else if(end_cnt_sec)//1s结束有开始读取时间
  139. write_flag<='d1;
  140. end
  141. always @(posedge clk or negedge rst_n)begin
  142. if(!rst_n)begin
  143. start_flag<= 'd0;
  144. end
  145. else if(done2idle)begin //初始化完成拉低
  146. start_flag<='d1;
  147. end
  148. end
  149. //****************************************************************
  150. //-- 计数器
  151. //****************************************************************
  152. //1s计数器
  153. always @(posedge clk or negedge rst_n)begin
  154. if(!rst_n)begin
  155. cnt_sec <= 'd0;
  156. end
  157. else if(add_cnt_sec)begin
  158. if(end_cnt_sec)begin
  159. cnt_sec <= 'd0;
  160. end
  161. else begin
  162. cnt_sec <= cnt_sec + 1'b1;
  163. end
  164. end
  165. end
  166. assign add_cnt_sec = 1;
  167. assign end_cnt_sec = add_cnt_sec && cnt_sec == TIME_1S-1;
  168. //bit计数器
  169. always @(posedge clk or negedge rst_n)begin
  170. if(!rst_n)begin
  171. cnt_bit <= 'd0;
  172. end
  173. else if(add_cnt_bit)begin
  174. if(end_cnt_bit)begin
  175. cnt_bit <= 'd0;
  176. end
  177. else begin
  178. cnt_bit <= cnt_bit + 1'b1;
  179. end
  180. end
  181. end
  182. assign add_cnt_bit = end_cnt_cyc;
  183. assign end_cnt_bit = add_cnt_bit && cnt_bit == BIT_MAX -1;
  184. //写字节计数器 写的地址加数据
  185. //字节计数 共计16bit
  186. always @(posedge clk or negedge rst_n)begin
  187. if(!rst_n)begin
  188. cnt_byte <= 'd0;
  189. end
  190. else if(add_cnt_byte)begin
  191. if(end_cnt_byte)begin
  192. cnt_byte <= 'd0;
  193. end
  194. else begin
  195. cnt_byte <= cnt_byte + 1'b1;
  196. end
  197. end
  198. end
  199. assign add_cnt_byte = end_cnt_bit;
  200. assign end_cnt_byte = add_cnt_byte && cnt_byte == 1;
  201. //指令个数计数
  202. //地址计数
  203. always @(posedge clk or negedge rst_n)begin
  204. if(!rst_n)begin
  205. cnt_done <= 'd0;
  206. end
  207. else if(add_cnt_done)begin
  208. if(end_cnt_done)begin
  209. cnt_done <= 'd0;
  210. end
  211. else begin
  212. cnt_done <= cnt_done + 1'b1;
  213. end
  214. end
  215. end
  216. assign add_cnt_done = read2done || write2done;
  217. assign end_cnt_done = add_cnt_done && cnt_done == max;
  218. assign done = read2done;
  219. always @(posedge clk or negedge rst_n)begin
  220. if(!rst_n)begin
  221. max <= 'd0;
  222. end
  223. else if(start_flag)begin
  224. max <= 'd6;
  225. end
  226. else begin
  227. max <= 'd7;
  228. end
  229. end
  230. //****************************************************************
  231. //-- ds1302 片选 时钟 数据设计
  232. //****************************************************************
  233. //片选信号 读数据 写数据拉高
  234. assign ce=(state_c==READ || state_c==WRITE);
  235. //时钟sclk
  236. always @(posedge clk or negedge rst_n)begin
  237. if(!rst_n)begin
  238. cnt_cyc <= 'd0;
  239. end
  240. else if(add_cnt_cyc)begin
  241. if(end_cnt_cyc)begin
  242. cnt_cyc <= 'd0;
  243. end
  244. else begin
  245. cnt_cyc <= cnt_cyc + 1'b1;
  246. end
  247. end
  248. end
  249. assign add_cnt_cyc = (state_c == WRITE) || (state_c == READ);
  250. assign end_cnt_cyc = add_cnt_cyc && cnt_cyc == CYCLE-1;
  251. assign sclk = cnt_cyc < (CYCLE>>1) ? 0 : 1;
  252. //三态门控制数据 io口
  253. assign data_in = io;
  254. assign io = data_en ? data_out : 1'bz;
  255. assign data_en = state_c == WRITE;
  256. //第三段:描述输出,时序逻辑或组合逻辑皆可
  257. //****************************************************************
  258. //-- 数据输出
  259. //****************************************************************
  260. always @(posedge clk or negedge rst_n)begin
  261. if(!rst_n)begin
  262. data_out <= 'd0;
  263. end
  264. else if(state_c == WRITE && cnt_cyc == 0 && ~start_flag)begin //写数据+地址 只有在初始化的时候才需要写入数据
  265. case (cnt_done)
  266. 0: begin
  267. case (cnt_byte)
  268. 0: data_out <= WP_RD[cnt_bit];//地址
  269. 1: data_out <= 1'b0;//数据
  270. default: data_out <= 'd0;
  271. endcase
  272. end
  273. 1: begin
  274. case (cnt_byte)
  275. 0: data_out <= YEAR_WR[cnt_bit];
  276. 1: data_out <= YEAR[cnt_bit];//初始年份
  277. default: data_out <= 'd0;
  278. endcase
  279. end
  280. 2: begin
  281. case (cnt_byte)
  282. 0: data_out <= MON_WR[cnt_bit];
  283. 1: data_out <= MON[cnt_bit];//初始月份
  284. default: data_out <= 'd0;
  285. endcase
  286. end
  287. 3: begin
  288. case (cnt_byte)
  289. 0: data_out <= DATA_WR[cnt_bit];
  290. 1: data_out <= DATA[cnt_bit];//初始日
  291. default: data_out <= 'd0;
  292. endcase
  293. end
  294. 4: begin
  295. case (cnt_byte)
  296. 0: data_out <= DAY_WR[cnt_bit];
  297. 1: data_out <= DAY[cnt_bit];//初始星期
  298. default: data_out <= 'd0;
  299. endcase
  300. end
  301. 5: begin
  302. case (cnt_byte)
  303. 0: data_out <= HOUR_WR[cnt_bit];
  304. 1: data_out <= HOUR[cnt_bit];
  305. default: data_out <= 'd0;
  306. endcase
  307. end
  308. 6: begin
  309. case (cnt_byte)
  310. 0: data_out <= MIN_WR[cnt_bit];
  311. 1: data_out <= MIN[cnt_bit];
  312. default: data_out <= 'd0;
  313. endcase
  314. end
  315. 7: begin
  316. case (cnt_byte)
  317. 0: data_out <= SEC_WR[cnt_bit];
  318. 1: data_out <= SEC[cnt_bit];
  319. default: data_out <= 'd0;
  320. endcase
  321. end
  322. default: data_out <= 'd0;
  323. endcase
  324. end
  325. else if(state_c == WRITE && cnt_cyc == 0 && start_flag)begin //写数据地址
  326. case (cnt_done)
  327. 0: data_out <= YEAR_RD[cnt_bit];
  328. 1: data_out <= MON_RD [cnt_bit];
  329. 2: data_out <= DATA_RD[cnt_bit];
  330. 3: data_out <= DAY_RD [cnt_bit];
  331. 4: data_out <= HOUR_RD[cnt_bit];
  332. 5: data_out <= MIN_RD [cnt_bit];
  333. 6: data_out <= SEC_RD [cnt_bit];
  334. default: data_out <= 'd0;
  335. endcase
  336. end
  337. end
  338. //****************************************************************
  339. //-- 数据采集
  340. //****************************************************************
  341. always @(posedge clk or negedge rst_n)begin
  342. if(!rst_n)begin
  343. tx_data <= 'd0;
  344. end
  345. else if(state_c == READ && cnt_cyc == (CYCLE>>1))begin
  346. tx_data[cnt_bit] = data_in;
  347. end
  348. end
  349. //采集完成
  350. assign tx_vld = read2done;
  351. endmodule

 2.控制模块设计

  1. /**************************************功能介绍***********************************flag
  2. Date : 2023年10月15日14:11:59
  3. Author : xlin
  4. Version :
  5. Description: ds1302控制模块
  6. *********************************************************************************/
  7. //---------<模块及端口声名>------------------------------------------------------
  8. module ds1302_ctrl(
  9. input clk ,
  10. input rst_n ,
  11. input ds_vld ,
  12. input [7:0] ds_data ,
  13. input done ,
  14. output reg uart_vld ,
  15. output reg [7:0] uart_data
  16. );
  17. //---------<内部信号定义>-----------------------------------------------------
  18. reg [3:0] cnt ;
  19. wire add_cnt ;
  20. wire end_cnt ;
  21. reg [4:0] max ;
  22. reg [4:0] cnt_num ;
  23. wire add_cnt_num ;
  24. wire end_cnt_num ;
  25. reg start_flag ;
  26. reg [7:0] data_reg ;
  27. reg uart_vld_r ;
  28. //****************************************************************
  29. //-- 数据寄存
  30. //****************************************************************
  31. always @(posedge clk or negedge rst_n)begin
  32. if(!rst_n)begin
  33. data_reg<= 'd0;
  34. end
  35. else if(ds_vld)begin
  36. data_reg<=ds_data;
  37. end
  38. end
  39. //****************************************************************
  40. //-- 开始信号
  41. //****************************************************************
  42. always @(posedge clk or negedge rst_n)begin
  43. if(!rst_n)begin
  44. start_flag <= 'd0;
  45. end
  46. else if(done)begin
  47. start_flag <= 'd1;
  48. end
  49. else if(end_cnt_num)begin
  50. start_flag <= 'd0;
  51. end
  52. end
  53. //数据计数器
  54. always @(posedge clk or negedge rst_n)begin
  55. if(!rst_n)begin
  56. cnt_num <= 'd0;
  57. end
  58. else if(add_cnt_num)begin
  59. if(end_cnt_num)begin
  60. cnt_num <= 'd0;
  61. end
  62. else begin
  63. cnt_num <= cnt_num + 1'b1;
  64. end
  65. end
  66. end
  67. assign add_cnt_num = start_flag;
  68. assign end_cnt_num = add_cnt_num && cnt_num == max-1;
  69. //年月日 星期 时分秒计数
  70. always @(posedge clk or negedge rst_n)begin
  71. if(!rst_n)begin
  72. cnt <= 'd0;
  73. end
  74. else if(add_cnt)begin
  75. if(end_cnt)begin
  76. cnt <= 'd0;
  77. end
  78. else begin
  79. cnt <= cnt + 1'b1;
  80. end
  81. end
  82. end
  83. assign add_cnt = end_cnt_num;
  84. assign end_cnt = add_cnt && cnt == 7 -1;
  85. always @(*)begin
  86. case (cnt)
  87. 0: max = 6;
  88. 1: max = 4;
  89. 2: max = 4;
  90. 3: max = 6;
  91. 4: max = 3;
  92. 5: max = 3;
  93. 6: max = 6;
  94. default: max = 1;
  95. endcase
  96. end
  97. //数据有效信号
  98. always @(posedge clk or negedge rst_n)begin
  99. if(!rst_n)begin
  100. uart_vld <= 'd0;
  101. end
  102. else begin
  103. uart_vld <= start_flag;
  104. end
  105. end
  106. //数据输出
  107. always @(posedge clk or negedge rst_n)begin
  108. if(!rst_n)begin
  109. uart_data <= 'd0;
  110. end
  111. else begin
  112. case (cnt)
  113. 0: begin
  114. case (cnt_num)
  115. 0: uart_data <= 8'h32;//2
  116. 1: uart_data <= 8'h30;//0
  117. 2: uart_data <= {4'h3,data_reg[7:4]};//2
  118. 3: uart_data <= {4'h3,data_reg[3:0]};//3
  119. 4: uart_data <= 8'hc4;//年
  120. 5: uart_data <= 8'hea;
  121. default: uart_data <= 'd0;
  122. endcase
  123. end
  124. 1: begin
  125. case (cnt_num)
  126. 0: uart_data <= {4'h3,data_reg[7:4]};
  127. 1: uart_data <= {4'h3,data_reg[3:0]};
  128. 2: uart_data <= 8'hd4;//月
  129. 3: uart_data <= 8'hc2;
  130. default: uart_data <= 'd0;
  131. endcase
  132. end
  133. 2: begin
  134. case (cnt_num)
  135. 0: uart_data <= {4'h3,data_reg[7:4]};
  136. 1: uart_data <= {4'h3,data_reg[3:0]};
  137. 2: uart_data <= 8'hc8;//日
  138. 3: uart_data <= 8'hd5;
  139. default: uart_data <= 'd0;
  140. endcase
  141. end
  142. 3: begin
  143. case (cnt_num)
  144. 0: uart_data <= 8'h20;//空格
  145. 1: uart_data <= 8'hd0;//星
  146. 2: uart_data <= 8'hc7;
  147. 3: uart_data <= 8'hc6;//期
  148. 4: uart_data <= 8'hda;
  149. 5: uart_data <= {4'h3,data_reg[3:0]};
  150. default: uart_data <= 'd0;
  151. endcase
  152. end
  153. 4: begin
  154. case (cnt_num)
  155. 0: uart_data <= 8'h20;//空格
  156. 1: uart_data <= {4'h3,2'h0,data_reg[5:4]};//时
  157. 2: uart_data <= {4'h3,data_reg[3:0]};
  158. default: uart_data <= 'd0;
  159. endcase
  160. end
  161. 5: begin
  162. case (cnt_num)
  163. 0: uart_data <= 8'h3a;//:
  164. 1: uart_data <= {4'h3,data_reg[7:4]};//分
  165. 2: uart_data <= {4'h3,data_reg[3:0]};
  166. default: uart_data <= 'd0;
  167. endcase
  168. end
  169. 6: begin
  170. case (cnt_num)
  171. 0: uart_data <= 8'h3a;//:
  172. 1: uart_data <= {4'h3,data_reg[7:4]};//秒
  173. 2: uart_data <= {4'h3,data_reg[3:0]};
  174. 3: uart_data <= 8'h0d;
  175. 4: uart_data <= 8'h0d;
  176. default: uart_data <= 'd0;
  177. endcase
  178. end
  179. default: uart_data <= 'd0;
  180. endcase
  181. end
  182. end
  183. endmodule

3.顶层模块设计

  1. /**************************************功能介绍***********************************
  2. Date : 2023年10月15日14:26:41
  3. Author : Xlin.
  4. Version:
  5. Description: ds1302顶层模块
  6. *********************************************************************************/
  7. module ds1302_top(
  8. input clk , //系统时钟
  9. input rst_n , //复位按键
  10. output tx ,
  11. output ds1302_sclk, //ds1302时钟线
  12. output ds1302_ce , //ds1302片选线
  13. inout ds1302_data //ds1302数据线
  14. );
  15. //-----------------参数定义----------------
  16. wire ds_vld ;
  17. wire [7:0] ds_data ;
  18. wire done ;
  19. wire uart_vld ;
  20. wire [7:0] uart_data ;
  21. //fifo 参数定义
  22. wire fifo_rdreq;
  23. wire fifo_wrreq;
  24. wire fifo_empty;
  25. wire fifo_full;
  26. wire [7:0] fifo_data;
  27. wire tx_ready ;
  28. //ds1302控制模块
  29. ds1302_ctrl top_ctrl(
  30. /*input */.clk (clk ),
  31. /*input */.rst_n (rst_n ),
  32. /*input */.ds_vld (ds_vld ),
  33. /*input [7:0] */.ds_data (ds_data ),
  34. /*input */.done (done ),
  35. /*output reg */.uart_vld (uart_vld ),
  36. /*output reg [7:0] */.uart_data(uart_data)
  37. );
  38. // );
  39. ds1302_if top_interface(
  40. /*input */ .clk (clk ) ,
  41. /*input */ .rst_n (rst_n ) ,
  42. /*output */.done (done ) ,//操作完成
  43. /*output */.tx_vld (ds_vld ) ,//数据有效信号
  44. /*output reg [7:0] */.tx_data (ds_data ) ,//数据
  45. /*output */.ce (ds1302_ce ) ,
  46. /*output */.sclk(ds1302_sclk) ,
  47. /*inout */ .io (ds1302_data)
  48. );
  49. //fifo 调用
  50. fifo fifo_inst (
  51. .aclr (~rst_n ),
  52. .clock (clk ),
  53. .data (uart_data ),
  54. .rdreq (fifo_rdreq ),
  55. .wrreq (fifo_wrreq ),
  56. .empty (fifo_empty ),
  57. .full (fifo_full ),
  58. .q (fifo_data ),
  59. .usedw ()
  60. );
  61. assign fifo_wrreq=~fifo_full && uart_vld;
  62. assign fifo_rdreq=~fifo_empty && tx_ready;
  63. //列化接口
  64. uart_tx #(.BAUD (115200 ) ,//"NONE"无校验位,"ODD"奇校验位,"EVEN"偶校验位
  65. .CLK (50000000) ,
  66. .check("NONE" )
  67. )u_uart_tx(
  68. .clk (clk ),
  69. .rst_n (rst_n ),
  70. .tx_din ( fifo_data ),
  71. .tx_din_vld ( fifo_rdreq ),
  72. .ready ( tx_ready ),
  73. .tx_dout ( tx )
  74. );
  75. endmodule

4.串口模块设计

  1. /**************************************功能介绍***********************************
  2. Date : 2023年8月16日13:30:25
  3. Author : Xlin.
  4. Version :
  5. Description: UART--TX端口
  6. *********************************************************************************/
  7. //列化接口
  8. // uart_tx #(.BAUD (115200 ) ,//"NONE"无校验位,"ODD"奇校验位,"EVEN"偶校验位
  9. // .CLK (50000000) ,
  10. // .check("NONE" )
  11. // )u_uart_tx(
  12. // .clk (clk ),
  13. // .rst_n (rst_n ),
  14. // .tx_din ( ),
  15. // .tx_din_vld ( ),
  16. // .ready ( ),
  17. // .tx_dout ( )
  18. // );
  19. //---------<模块及端口声名>------------------------------------------------------
  20. module uart_tx#(parameter BAUD = 115200,
  21. CLK=50000000 ,
  22. check="EVEN")//"NONE"无校验位,"ODD"奇校验位,"EVEN"偶校验位
  23. (
  24. input clk ,
  25. input rst_n ,
  26. input [7:0] tx_din ,
  27. input tx_din_vld,
  28. output ready ,
  29. output reg tx_dout
  30. );
  31. //---------<参数定义>---------------------------------------------------------
  32. reg [7:0] tx_data;
  33. wire jo_check;
  34. //---------<内部信号定义>-----------------------------------------------------
  35. //波特率计数器
  36. reg [9:0] cnt_bit ;
  37. wire add_cnt_bit ;
  38. wire end_cnt_bit ;
  39. //bit计数器
  40. reg [3:0] max ;
  41. reg [3:0] cnt_1bit ;
  42. wire add_cnt_1bit ;
  43. wire end_cnt_1bit ;
  44. //状态机参数定义
  45. localparam IDLE = 'b00001,//空闲
  46. START = 'b00010,//起始位
  47. DATA = 'b00100,//数据位
  48. CHECK = 'b01000,
  49. STOP = 'b10000;//结束位
  50. reg [4:0] state_c ;//现态
  51. reg [4:0] state_n ;//次态
  52. //状态跳转条件
  53. wire idle2start;
  54. wire start2data;
  55. wire data2check;
  56. wire data2stop;
  57. wire check2stop;
  58. wire stop2idle;
  59. //第一段:时序逻辑描述状态转移
  60. always @(posedge clk or negedge rst_n)begin
  61. if(!rst_n)begin
  62. state_c <= IDLE;
  63. end
  64. else begin
  65. state_c <= state_n;
  66. end
  67. end
  68. //第二段:组合逻辑描述状态转移规律和状态转移条件
  69. always @(*) begin
  70. case(state_c)
  71. IDLE : if(idle2start)
  72. state_n=START;
  73. else
  74. state_n=IDLE;
  75. START : if(start2data)
  76. state_n=DATA;
  77. else
  78. state_n=START;
  79. DATA : if(data2stop)//无校验
  80. state_n=STOP;
  81. else if(data2check)//有校验
  82. state_n=CHECK;
  83. else
  84. state_n=DATA;
  85. CHECK :if(check2stop)
  86. state_n=STOP;
  87. else
  88. state_n=CHECK;
  89. STOP : if(stop2idle)
  90. state_n=IDLE;
  91. else
  92. state_n=STOP;
  93. default :state_n=IDLE ;
  94. endcase
  95. end
  96. assign idle2start = state_c ==IDLE && tx_din_vld;
  97. assign start2data = state_c ==START && end_cnt_1bit;
  98. assign data2check = state_c ==DATA && end_cnt_1bit;
  99. assign data2stop = state_c ==DATA && end_cnt_1bit && check=="NONE";
  100. assign stop2idle = state_c ==STOP && end_cnt_1bit;
  101. assign check2stop = state_c ==CHECK && end_cnt_1bit;
  102. //****************************************************************
  103. //--波特率 计数器
  104. //****************************************************************
  105. always @(posedge clk or negedge rst_n)begin
  106. if(!rst_n)begin
  107. cnt_bit <= 'd0;
  108. end
  109. else if(add_cnt_bit)begin
  110. if(end_cnt_bit)begin
  111. cnt_bit <= 'd0;
  112. end
  113. else begin
  114. cnt_bit <= cnt_bit + 1'b1;
  115. end
  116. end
  117. end
  118. assign add_cnt_bit = state_c!=IDLE;
  119. assign end_cnt_bit = add_cnt_bit && cnt_bit == (CLK/BAUD) - 1;//计算波特率115200对应434
  120. //****************************************************************
  121. //--bit 计数器
  122. //****************************************************************
  123. always @(posedge clk or negedge rst_n)begin
  124. if(!rst_n)begin
  125. cnt_1bit <= 'd0;
  126. end
  127. else if(add_cnt_1bit)begin
  128. if(end_cnt_1bit)begin
  129. cnt_1bit <= 'd0;
  130. end
  131. else begin
  132. cnt_1bit <= cnt_1bit + 1'b1;
  133. end
  134. end
  135. end
  136. assign add_cnt_1bit = end_cnt_bit;
  137. assign end_cnt_1bit = add_cnt_1bit && cnt_1bit == max - 1;
  138. always @(*)begin
  139. case(state_c)
  140. IDLE :max=1;
  141. START:max=1;
  142. DATA :max=8;
  143. CHECK:max=1;
  144. STOP :max=1;
  145. endcase
  146. end
  147. //数据寄存一拍
  148. always @(posedge clk or negedge rst_n) begin
  149. if(!rst_n)
  150. tx_data<=0;
  151. else
  152. tx_data<=tx_din;
  153. end
  154. //****************************************************************
  155. //--判断奇偶检验
  156. //~^tx_data奇校验
  157. //^tx_data偶检验
  158. //****************************************************************
  159. assign jo_check=(check=="ODD")?~^tx_data:^tx_data;
  160. //第三段:描述输出,时序逻辑或组合逻辑皆可
  161. always @(*) begin
  162. case(state_c)
  163. IDLE :tx_dout=1;
  164. START:tx_dout=0;
  165. DATA :if(tx_data[cnt_1bit])
  166. tx_dout=1;
  167. else
  168. tx_dout=0;
  169. CHECK:tx_dout=jo_check;
  170. STOP :tx_dout=1;
  171. default:;
  172. endcase
  173. end
  174. assign ready=state_c==IDLE;
  175. endmodule

 5.结果展示:

时钟视频

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号