• FPGA project : DS18B20


    本想着一天发一个实验的,这个ds18b20,耗时两天。代码写了两次,呜呜~

    由于第二次写代码没画时序图,所以代码和时序图一些参数有些不一致,但问题不大。

    这里有几件事情值得一提:

    1:关于状态机的编写,我觉得还是三段式比较好。

    2:关于生成其他时钟信号,用来做触发边沿。我不喜欢用这种方法(提一个概念“全局时钟网络”)。所以用产生一个1us base基础计时器,产生一个1us的标志信号。之后的计数器与该计数器级联,记得把这个标志信号加上。

    我犯下的错误:

    1:在画时序图是,没有画标志信号,直接默认时钟为周期为1us,造成了混乱。所以以后要注意。

    2:&& 逻辑写成了 || 逻辑

    3:三态门输出 Z 写成了 1

    4:数据位宽定义错误,因为少思考了一个数据对应的位宽。

    4:读取温度时,少记一位。注意data_bit跳转条件,和发指令时不一样的。

     

     

    1. module ds18b20(
    2. input wire sys_clk ,
    3. input wire sys_rst_n ,
    4. inout wire dq ,
    5. output reg [19:0] data ,
    6. output reg sign
    7. );
    8. // localparam 指令,先发低位。
    9. localparam WR_CMD_WORD = 16'h44CC ,
    10. RD_CMD_WORD = 16'hBECC ;
    11. localparam INIT = 6'b000_001 ,
    12. WR_CMD = 6'b000_010 ,
    13. WAIT = 6'b000_100 ,
    14. INIT_AGIN = 6'b001_000 ,
    15. RD_CMD = 6'b010_000 ,
    16. RD_TEMP = 6'b100_000 ;
    17. // wire signal define
    18. wire end_cnt_base ;
    19. wire INITtoWR_CMD ;
    20. wire WR_CMDtoWAIT ;
    21. wire WAITtoINIT_AGIN ;
    22. wire INIT_AGINtoRD_CMD ;
    23. wire RD_CMDtoRD_TEMP ;
    24. wire RD_TEMPtoINIT ;
    25. // reg signal define
    26. reg [5:0] cnt_base ;
    27. reg dq_en ;
    28. reg dq_out ;
    29. reg [5:0] state_c /*synthesis preserve*/;
    30. reg [5:0] state_n /*synthesis preserve*/;
    31. reg [19:0] cnt ;
    32. reg [4:0] data_bit ;
    33. reg flag_respond ;
    34. reg data_done ;
    35. reg [15:0] data_temp ; // 读取高速缓存器的byte0和byte1,一共16位。
    36. /****************************************************************************************/
    37. // reg [5:0] cnt_base ;
    38. // wire end_cnt_base ;
    39. always @(posedge sys_clk or negedge sys_rst_n)
    40. if(~sys_rst_n)
    41. cnt_base <= 6'd0 ;
    42. else if(end_cnt_base)
    43. cnt_base <= 6'd0 ;
    44. else
    45. cnt_base <= cnt_base + 1'b1 ;
    46. assign end_cnt_base = cnt_base == 49;
    47. // reg [5:0] state_c ;
    48. always @(posedge sys_clk or negedge sys_rst_n)
    49. if(~sys_rst_n)
    50. state_c <= INIT;
    51. else
    52. state_c <= state_n ;
    53. // reg [5:0] state_n ;
    54. always @(*)
    55. case (state_c)
    56. INIT :if(INITtoWR_CMD)
    57. state_n <= WR_CMD ;
    58. else
    59. state_n <= INIT ;
    60. WR_CMD :if(WR_CMDtoWAIT)
    61. state_n <= WAIT ;
    62. else
    63. state_n <= WR_CMD ;
    64. WAIT :if(WAITtoINIT_AGIN)
    65. state_n <= INIT_AGIN ;
    66. else
    67. state_n <= WAIT ;
    68. INIT_AGIN :if(INIT_AGINtoRD_CMD)
    69. state_n <= RD_CMD ;
    70. else
    71. state_n <= INIT_AGIN ;
    72. RD_CMD :if(RD_CMDtoRD_TEMP)
    73. state_n <= RD_TEMP ;
    74. else
    75. state_n <= RD_CMD ;
    76. RD_TEMP :if(RD_TEMPtoINIT)
    77. state_n <= INIT ;
    78. else
    79. state_n <= RD_TEMP ;
    80. default : state_n <= INIT ;
    81. endcase
    82. // 状态转移条件
    83. assign INITtoWR_CMD = (state_c == INIT ) && (end_cnt_base && flag_respond == 1'b1 && cnt == 999);
    84. assign WR_CMDtoWAIT = (state_c == WR_CMD ) && (end_cnt_base ==1'b1 && cnt == 60 && data_bit == 15) ;
    85. assign WAITtoINIT_AGIN = (state_c == WAIT ) && (end_cnt_base && cnt == 749_999) ;
    86. assign INIT_AGINtoRD_CMD = (state_c == INIT_AGIN ) && (end_cnt_base && flag_respond == 1'b1 && cnt == 999);
    87. assign RD_CMDtoRD_TEMP = (state_c == RD_CMD ) && (end_cnt_base ==1'b1 && cnt == 60 && data_bit == 15) ;
    88. assign RD_TEMPtoINIT = (state_c == RD_TEMP ) && (end_cnt_base ==1'b1 && cnt == 60 && data_done == 1'b1);
    89. // reg [19:0] cnt ;
    90. always @(posedge sys_clk or negedge sys_rst_n)
    91. if(~sys_rst_n)
    92. cnt <= 20'd0 ;
    93. else case (state_c)
    94. INIT : if(cnt == 999 && end_cnt_base == 1'b1)
    95. cnt <= 20'd0 ;
    96. else if(end_cnt_base == 1'b1)
    97. cnt <= cnt + 1'b1 ;
    98. WR_CMD : if(cnt == 60 && end_cnt_base == 1'b1)
    99. cnt <= 20'd0 ;
    100. else if(end_cnt_base == 1'b1)
    101. cnt <= cnt + 1'b1 ;
    102. WAIT : if(cnt == 749_999 && end_cnt_base == 1'b1)
    103. cnt <= 20'd0 ;
    104. else if(end_cnt_base == 1'b1)
    105. cnt <= cnt + 1'b1 ;
    106. INIT_AGIN : if(cnt == 999 && end_cnt_base == 1'b1)
    107. cnt <= 20'd0 ;
    108. else if(end_cnt_base == 1'b1)
    109. cnt <= cnt + 1'b1 ;
    110. RD_CMD : if(cnt == 60 && end_cnt_base == 1'b1)
    111. cnt <= 20'd0 ;
    112. else if(end_cnt_base == 1'b1)
    113. cnt <= cnt + 1'b1 ;
    114. RD_TEMP : if(cnt == 60 && end_cnt_base == 1'b1)
    115. cnt <= 20'd0 ;
    116. else if(end_cnt_base == 1'b1)
    117. cnt <= cnt + 1'b1 ;
    118. default : cnt <= 20'd0 ;
    119. endcase
    120. // reg [3:0] data_bit ;
    121. always @(posedge sys_clk or negedge sys_rst_n)
    122. if(~sys_rst_n)
    123. data_bit <= 5'd0 ;
    124. else case (state_c)
    125. INIT : data_bit <= 5'd0 ;
    126. WR_CMD : if(end_cnt_base == 1'b1 && cnt == 60 && data_bit == 15)
    127. data_bit <= 5'd0 ;
    128. else if(end_cnt_base == 1'b1 && cnt == 60)
    129. data_bit <= data_bit + 1'b1 ;
    130. else
    131. data_bit <= data_bit ;
    132. WAIT : data_bit <= 5'd0 ;
    133. INIT_AGIN : data_bit <= 5'd0 ;
    134. RD_CMD : if(end_cnt_base == 1'b1 && cnt == 60 && data_bit == 15)
    135. data_bit <= 5'd0 ;
    136. else if(end_cnt_base == 1'b1 && cnt == 60)
    137. data_bit <= data_bit + 1'b1 ;
    138. else
    139. data_bit <= data_bit ;
    140. RD_TEMP : if(end_cnt_base == 1'b1 && cnt == 10 && data_bit == 16) // 第十微秒的时候采样。
    141. data_bit <= 5'd0 ;
    142. else if(end_cnt_base == 1'b1 && cnt == 10)
    143. data_bit <= data_bit + 1'b1 ;
    144. else
    145. data_bit <= data_bit ;
    146. default : data_bit <= 5'd0 ;
    147. endcase
    148. // reg flag_respond ;
    149. always @(posedge sys_clk or negedge sys_rst_n)
    150. if(~sys_rst_n)
    151. flag_respond <= 1'b0 ;
    152. else if(state_c != INIT && state_c != INIT_AGIN)
    153. flag_respond <= 1'b0 ;
    154. else if((state_c == INIT || state_c == INIT_AGIN) && cnt == 590 && dq == 1'b0)
    155. flag_respond <= 1'b1 ;
    156. else
    157. flag_respond <= flag_respond ;
    158. // reg data_done ;
    159. always @(posedge sys_clk or negedge sys_rst_n)
    160. if(~sys_rst_n)
    161. data_done <= 1'b0 ;
    162. else if(state_c != RD_TEMP)
    163. data_done <= 1'b0 ;
    164. else if(state_c == RD_TEMP && end_cnt_base == 1'b1 && data_bit == 16)
    165. data_done <= 1'b1 ;
    166. else
    167. data_done <= data_done ;
    168. // reg [15:0] data_temp ;
    169. always @(posedge sys_clk or negedge sys_rst_n)
    170. if(~sys_rst_n)
    171. data_temp <= 16'd0 ;
    172. else if(state_c == RD_TEMP && end_cnt_base == 1'b1 && cnt == 13)
    173. data_temp <= {dq,data_temp[15:1]} ;
    174. else
    175. data_temp <= data_temp ;
    176. // reg dq_en ;
    177. // reg dq_out ;
    178. always @(posedge sys_clk or negedge sys_rst_n) begin
    179. if(~sys_rst_n) begin
    180. dq_en <= 1'b0 ;
    181. dq_out <= 1'b0 ;
    182. end else begin
    183. case (state_c)
    184. INIT : begin
    185. if(cnt >= 0 && cnt <= 499) begin
    186. dq_en <= 1'b1 ;
    187. dq_out <= 1'b0 ;
    188. end else begin
    189. dq_en <= 1'b0 ;
    190. dq_out <= 1'b0 ;
    191. end
    192. end
    193. WR_CMD : begin
    194. if(cnt == 60) begin
    195. dq_en <= 1'b0 ;
    196. dq_out <= 1'b0 ;
    197. end else begin
    198. if(WR_CMD_WORD[data_bit] == 1'b1) begin
    199. if(cnt >= 0 && cnt <= 14) begin
    200. dq_en <= 1'b1 ;
    201. dq_out <= 1'b0 ;
    202. end else begin
    203. dq_en <= 1'b0 ;
    204. dq_out <= 1'b0 ;
    205. end
    206. end else begin
    207. dq_en <= 1'b1 ;
    208. dq_out <= 1'b0 ;
    209. end
    210. end
    211. end
    212. WAIT : begin
    213. dq_en <= 1'b1 ;
    214. dq_out <= 1'b1 ;
    215. end
    216. INIT_AGIN: begin
    217. if(cnt >= 0 && cnt <= 499) begin
    218. dq_en <= 1'b1 ;
    219. dq_out <= 1'b0 ;
    220. end else begin
    221. dq_en <= 1'b0 ;
    222. dq_out <= 1'b0 ;
    223. end
    224. end
    225. RD_CMD : begin
    226. if(cnt == 60) begin
    227. dq_en <= 1'b0 ;
    228. dq_out <= 1'b0 ;
    229. end else begin
    230. if(RD_CMD_WORD[data_bit] == 1'b1) begin
    231. if(cnt >= 0 && cnt <= 14) begin
    232. dq_en <= 1'b1 ;
    233. dq_out <= 1'b0 ;
    234. end else begin
    235. dq_en <= 1'b0 ;
    236. dq_out <= 1'b0 ;
    237. end
    238. end else begin
    239. dq_en <= 1'b1 ;
    240. dq_out <= 1'b0 ;
    241. end
    242. end
    243. end
    244. RD_TEMP : begin
    245. if(cnt == 0 || cnt == 1) begin
    246. dq_en <= 1'b1 ;
    247. dq_out <= 1'b0 ;
    248. end else begin
    249. dq_en <= 1'b0 ;
    250. dq_out <= 1'b0 ;
    251. end
    252. end
    253. default: begin
    254. dq_en <= 1'b0 ;
    255. dq_out <= 1'b0 ;
    256. end
    257. endcase
    258. end
    259. end
    260. /***********************************************************************/
    261. // wire dq
    262. assign dq = (dq_en == 1'b1) ? dq_out : 1'bz ;
    263. // reg [19:0] data
    264. always @(posedge sys_clk or negedge sys_rst_n)
    265. if(~sys_rst_n)
    266. data <= 20'd0 ;
    267. else if(state_c == RD_TEMP && data_done == 1'b1)
    268. if(data_temp[15] == 1'b0)
    269. data <= data_temp[10:0] * 10'd625;
    270. else
    271. data <= (~data_temp[10:0] + 1'b1 ) * 10'd625;
    272. else
    273. data <= data ;
    274. // reg sign
    275. always @(posedge sys_clk or negedge sys_rst_n)
    276. if(~sys_rst_n)
    277. sign <= 1'b0 ;
    278. else if(state_c == RD_TEMP && data_done == 1'b1)
    279. sign <= data_temp[15];
    280. else
    281. sign <= sign ;
    282. endmodule
    1. module top(
    2. input wire sys_clk ,
    3. input wire sys_rst_n ,
    4. inout wire dq ,
    5. output wire ds ,
    6. output wire oe ,
    7. output wire shcp ,
    8. output wire stcp
    9. );
    10. wire [19:0] data_w /*synthesis keep */;
    11. wire sign_w ;
    12. wire [05:00] point_w ;
    13. wire seg_en_w ;
    14. assign seg_en_w= 1'b1 ;
    15. assign point_w = 6'b010_000 ;
    16. ds18b20 ds18b20_insert(
    17. .sys_clk ( sys_clk ) ,
    18. .sys_rst_n ( sys_rst_n ) ,
    19. .dq ( dq ) ,
    20. .data ( data_w ) ,
    21. .sign ( sign_w )
    22. );
    23. seg_595_dynamic seg_595_dynamic_insert(
    24. .sys_clk ( sys_clk ) ,
    25. .sys_rst_n ( sys_rst_n ) ,
    26. .data ( data_w ) ,
    27. .point ( point_w ) ,
    28. .sign ( sign_w ) ,
    29. .seg_en ( seg_en_w ) ,
    30. .ds ( ds ) ,
    31. .oe ( oe ) ,
    32. .shcp ( shcp ) ,
    33. .stcp ( stcp )
    34. );
    35. endmodule

  • 相关阅读:
    笔试强训第22天--(第一个只出现一次的字符 小易的升级之路)
    2022-2028全球视频监控软件行业调研及趋势分析报告
    顾樵 量子力学I 导读(1)
    05高级变量
    JavaEE初阶:文件操作 和 IO
    数据库优化(8月27号)
    等级保护定级之备案!
    【Java开发】实用小技巧
    远程桌面登录Windows云服务器报错0x112f
    通讯录实现之进阶版将通讯录数据保存在文件中(完整代码)
  • 原文地址:https://blog.csdn.net/Meng_long2022/article/details/133152033