本文為明德?lián)P原創(chuàng)及錄用文章,轉(zhuǎn)載請(qǐng)注明出處!
1.1 總體設(shè)計(jì)
1.1.1 概述
發(fā)光二極管簡(jiǎn)稱為L(zhǎng)ED,是一種常用的發(fā)光器件,通過電子與空穴復(fù)合釋放能量發(fā)光,可以高效的將電能轉(zhuǎn)化為光能,在現(xiàn)代社會(huì)具有廣泛的用途,如照明、平板顯示、醫(yī)療器件等。可通過高低電平的變化來控制LED燈的明滅狀態(tài),當(dāng)輸出信號(hào)為低電平時(shí),LED燈亮,反之,當(dāng)輸出信號(hào)為高電平時(shí),LED燈滅。
1.1.2 設(shè)計(jì)目標(biāo)
內(nèi)容:開發(fā)板上有紅黃綠 LED 燈各四個(gè),分別放在東西南北方向。參考交通燈的情況,即每個(gè)方向都是綠燈亮 10 秒,然后黃燈亮 5 秒,然后紅燈亮 15 秒。綠燈按照東西和南北的順序依次亮。
具體思路:
1. 首先分東西方向和南北方向來設(shè)計(jì)電路。設(shè)計(jì)兩個(gè)不同的狀態(tài)機(jī)來指示不同的狀態(tài)。東西方向的燈狀態(tài)相同,南北方向的燈狀態(tài)相同。
2. 4個(gè)方向的燈依次為紅綠黃的依次循環(huán)時(shí)間為 15+10+5=30 秒,所以可以設(shè)計(jì)一個(gè)計(jì)數(shù)器,計(jì)時(shí) 30 秒鐘,表示一個(gè)循環(huán)。計(jì)數(shù)器可以分兩個(gè)寫,一個(gè)計(jì)時(shí) 1秒,一個(gè)計(jì)時(shí) 30秒。
3. 然后再根據(jù)計(jì)數(shù)器的計(jì)數(shù)值的不同,決定狀態(tài)機(jī)的不同狀態(tài)。
4. 首先設(shè)計(jì)東西方向的狀態(tài)機(jī),復(fù)位的時(shí)候,綠燈亮,計(jì)數(shù)器計(jì)到 10 秒,黃燈亮,計(jì)到15 秒,紅燈亮,計(jì)滿 30 秒,又是綠燈亮......依次循環(huán)。
5. 接著設(shè)計(jì)南北方向的狀態(tài)機(jī),復(fù)位的時(shí)候,紅燈亮,計(jì)數(shù)器計(jì)到15 秒,綠燈亮,計(jì)到20 秒,黃燈亮,計(jì)滿 30 秒,又是紅燈亮......依次循環(huán)。
1.1.3信號(hào)列表

1.1.4 設(shè)計(jì)思路
根據(jù)題目功能要求,東西南北四個(gè)方向LED燈按照“紅燈-綠燈-黃燈”的順序依次循環(huán)時(shí)間為 15+10+5=30 秒,所以可以設(shè)計(jì)一個(gè)計(jì)數(shù)器,計(jì)時(shí) 30 秒鐘表示一個(gè)循環(huán)。該計(jì)數(shù)器可以分兩個(gè)寫,一個(gè)計(jì)時(shí) 1 秒,一個(gè)計(jì)時(shí) 30秒。
因?yàn)樵跀?shù)字電路中的延時(shí)都是通過計(jì)數(shù)器實(shí)現(xiàn)的,計(jì)數(shù)器*時(shí)鐘周期=延時(shí)時(shí)間。本模塊中,由于輸入時(shí)鐘是50MHz,時(shí)鐘周期為20ns,功能要求每1秒變化一次。我們通過counter來表示延時(shí),當(dāng)其值為1s/20ns=5000_0000時(shí),表示1秒時(shí)間到。
兩個(gè)計(jì)數(shù)器的架構(gòu)圖:

時(shí)鐘計(jì)數(shù)器counter:該計(jì)數(shù)器用于計(jì)算1s的時(shí)鐘個(gè)數(shù),加一條件為1,表示一直計(jì)數(shù);數(shù)到5000_0000下,則表示數(shù)到1秒的時(shí)間了。
秒計(jì)數(shù)器:該計(jì)數(shù)器用于計(jì)算1個(gè)周期內(nèi)三色LED按順序各點(diǎn)亮1次的時(shí)間,1周期的時(shí)間為30秒,加一條件為時(shí)鐘計(jì)數(shù)器的結(jié)束條件,表示時(shí)鐘計(jì)數(shù)器每數(shù)完1s,秒計(jì)數(shù)器計(jì)數(shù)加一;數(shù)到30下,則表示數(shù)到30秒的時(shí)間了。
下面是兩個(gè)計(jì)數(shù)器的代碼:
1. parameter COUNT_TIME = 26'd5000_0000; 2. parameter CYCLE_TIME = 5'd30 ; 3. parameter COUNT_WID = 26 ; 4. parameter SEC_WID = 5 ; 5. 6. reg [COUNT_WID-1:0] counter ; 7. wire add_counter ; 8. wire end_counter ; 9. reg [SEC_WID-1:0] second ; 10. wire add_second ; 11. wire end_second ; 12. 13. always @(posedge clk or negedge rst_n) begin 14. if (rst_n==0) begin 15. counter <= 0; 16. end 17. else if(add_counter) begin 18. if(end_counter) 19. counter <= 0; 20. else 21. counter <= counter+1 ; 22. end 23. end 24. assign add_counter = 1; 25. assign end_counter = add_counter && counter == COUNT_TIME-1 ; 26. 27. 28. always @(posedge clk or negedge rst_n) begin 29. if (rst_n==0) begin 30. second <= 0; 31. end 32. else if(add_second) begin 33. if(end_second) 34. second <= 0; 35. else 36. second <= second+1 ; 37. end 38. end 39. assign add_second = end_counter; 40. assign end_second = add_second && second == CYCLE_TIME-1 ;
按照題目要求:分東西方向和南北方向來設(shè)計(jì)電路,因此設(shè)計(jì)兩個(gè)不同的狀態(tài)機(jī)來指示不同的狀態(tài)——同一時(shí)間內(nèi),東西方向的燈狀態(tài)相同,南北方向的燈狀態(tài)相同。
兩個(gè)狀態(tài)機(jī)的架構(gòu):


東西方向的狀態(tài)機(jī):該狀態(tài)機(jī)用于設(shè)定東西方向LED的顏色跳轉(zhuǎn)狀態(tài)。
1) 上電后,就跳轉(zhuǎn)到綠燈亮狀態(tài),綠燈亮;
2) 10 秒后,黃燈亮,跳轉(zhuǎn)條件為秒計(jì)數(shù)器計(jì)數(shù)10下,即add_second &&second==10-1,則表示數(shù)到10秒了;
3) 5 秒后,紅燈亮,跳轉(zhuǎn)條件為秒計(jì)數(shù)器計(jì)數(shù)15下,即add_second &&second==15-1,則表示數(shù)到15秒了;
4) 15 秒后,又是綠燈亮,跳轉(zhuǎn)條件為秒計(jì)數(shù)器計(jì)滿30下,即add_second &&second==30-1,則表示數(shù)到30秒了......依次循環(huán)。
南北方向的狀態(tài)機(jī):該狀態(tài)機(jī)用于設(shè)定南北方向LED的顏色跳轉(zhuǎn)狀態(tài)。
1) 上電后,就跳轉(zhuǎn)到紅燈亮狀態(tài),紅燈亮;
2) 15 秒后,綠燈亮,跳轉(zhuǎn)條件為秒計(jì)數(shù)器計(jì)數(shù)15下,即add_second &&second==15-1,則表示數(shù)到15秒了;
3) 10 秒后,黃燈亮,跳轉(zhuǎn)條件為秒計(jì)數(shù)器計(jì)數(shù)25下,即add_second &&second==25-1,則表示數(shù)到25秒了;
4) 5 秒后,又是紅燈亮,跳轉(zhuǎn)條件為秒計(jì)數(shù)器計(jì)滿30下,即add_second &&second==30-1,則表示數(shù)到30秒了......依次循環(huán)。
下面是東西、南北方向的兩個(gè)狀態(tài)機(jī)代碼:
41. parameter LED_NUM = 3 ; 42. parameter STA_W = 2 ; 43. 44. parameter STA_G = 2'd1 ; 45. parameter STA_Y = 2'd2 ; 46. parameter STA_R = 2'd3 ; 47. parameter IDLE = 2'd0 ; 48. parameter GREEN = 3'b110 ; 49. parameter YELLOW = 3'b101 ; 50. parameter RED = 3'b011 ; 51. 52. input clk ; 53. input rst_n ; 54. output [LED_NUM-1:0] led_east ; 55. output [LED_NUM-1:0] led_south ; 56. output [LED_NUM-1:0] led_west ; 57. output [LED_NUM-1:0] led_north ; 58. 59. reg [LED_NUM-1:0] led_east ; 60. reg [LED_NUM-1:0] led_south ; 61. reg [LED_NUM-1:0] led_west ; 62. reg [LED_NUM-1:0] led_north ; 63. 64. reg [STA_W-1:0] ew_state_c ; 65. reg [STA_W-1:0] ew_state_n ; 66. wire idle2sta_g_start_ew ; 67. wire sta_g2sta_y_start_ew ; 68. wire sta_y2sta_r_start_ew ; 69. wire sta_r2sta_g_start_ew ; 70. 71. reg [STA_W-1:0] sn_state_c ; 72. reg [STA_W-1:0] sn_state_n ; 73. wire idle2sta_r_start_sn ; 74. wire sta_r2sta_g_start_sn ; 75. wire sta_g2sta_y_start_sn ; 76. wire sta_y2sta_r_start_sn ; 77. 78. always @(posedge clk or negedge rst_n) begin 79. if (rst_n==0) begin 80. ew_state_c <= STA_G ; 81. end 82. else begin 83. ew_state_c <= ew_state_n; 84. end 85. end 86. 87. always @(*) begin 88. case(ew_state_c) 89. STA_G :begin 90. if(sta_g2sta_y_start_ew) 91. ew_state_n = STA_Y ; 92. else 93. ew_state_n = ew_state_c ; 94. end 95. STA_Y :begin 96. if(sta_y2sta_r_start_ew) 97. ew_state_n = STA_R ; 98. else 99. ew_state_n = ew_state_c ; 100. end 101. STA_R :begin 102. if(sta_r2sta_g_start_ew) 103. ew_state_n = STA_G ; 104. else 105. ew_state_n = ew_state_c ; 106. end 107. default : ew_state_n = STA_G ; 108. endcase 109. end 110. 111. assign sta_g2sta_y_start_ew = ew_state_c==STA_G && add_second && second == 10-1; 112. assign sta_y2sta_r_start_ew = ew_state_c==STA_Y && add_second && second == 15-1; 113. assign sta_r2sta_g_start_ew = ew_state_c==STA_R && add_second && second == 30-1; 114. 115. always @(posedge clk or negedge rst_n)begin 116. if(rst_n==1'b0)begin 117. led_east<=GREEN; 118. end 119. else if(ew_state_c==STA_G)begin 120. led_east<=GREEN; 121. end 122. else if(ew_state_c==STA_Y)begin 123. led_east<=YELLOW; 124. end 125. else if(ew_state_c==STA_R)begin 126. led_east<=RED; 127. end 128. else begin 129. led_east<=GREEN; 130. end 131. end 132. 133. always @(posedge clk or negedge rst_n)begin 134. if(rst_n==1'b0)begin 135. led_west<=GREEN; 136. end 137. else if(ew_state_c==STA_G)begin 138. led_west<=GREEN; 139. end 140. else if(ew_state_c==STA_Y)begin 141. led_west<=YELLOW; 142. end 143. else if(ew_state_c==STA_R)begin 144. led_west<=RED; 145. end 146. else begin 147. led_west<=GREEN; 148. end 149. end 150. 151. 152. 153. always @(posedge clk or negedge rst_n) begin 154. if (rst_n==0) begin 155. sn_state_c <= STA_R ; 156. end 157. else begin 158. sn_state_c <= sn_state_n; 159. end 160. end 161. 162. always @(*) begin 163. case(sn_state_c) 164. STA_R :begin 165. if(sta_r2sta_g_start_sn) 166. sn_state_n = STA_G ; 167. else 168. sn_state_n = sn_state_c ; 169. end 170. STA_G :begin 171. if(sta_g2sta_y_start_sn) 172. sn_state_n = STA_Y ; 173. else 174. sn_state_n = sn_state_c ; 175. end 176. STA_Y :begin 177. if(sta_y2sta_r_start_sn) 178. sn_state_n = STA_R ; 179. else 180. sn_state_n = sn_state_c ; 181. end 182. default : sn_state_n = STA_R ; 183. endcase 184. end 185. 186. assign sta_r2sta_g_start_sn = sn_state_c==STA_R && add_second && second == 15-1; 187. assign sta_g2sta_y_start_sn = sn_state_c==STA_G && add_second && second == 25-1; 188. assign sta_y2sta_r_start_sn = sn_state_c==STA_Y && add_second && second == 30-1; 189. 190. always @(posedge clk or negedge rst_n)begin 191. if(rst_n==1'b0)begin 192. led_south<=RED; 193. end 194. else if(sn_state_c==STA_G)begin 195. led_south<=GREEN; 196. end 197. else if(sn_state_c==STA_Y)begin 198. led_south<=YELLOW; 199. end 200. else if(sn_state_c==STA_R)begin 201. led_south<=RED; 202. end 203. else begin 204. led_south<=GREEN; 205. end 206. end 207. 208. always @(posedge clk or negedge rst_n)begin 209. if(rst_n==1'b0)begin 210. led_north<=RED; 211. end 212. else if(sn_state_c==STA_G)begin 213. led_north<=GREEN; 214. end 215. else if(sn_state_c==STA_Y)begin 216. led_north<=YELLOW; 217. end 218. else if(sn_state_c==STA_R)begin 219. led_north<=RED; 220. end 221. else begin 222. led_north<=GREEN; 223. end 224. end
1.1.5參考設(shè)計(jì)代碼
225. /************************************************************************************ 226. The code is designed and produced by MDY Science and Education Co., Ltd, which has the entire ownership. It is only for personal learning, which cannot be used for commercial or profit-making purposes without permission. 227. 228. MDY's Mission: Develop Chip Talents and Realize National Chip Dream. 229. 230. We sincerely hope that our students can learn the real IC / FPGA code through our standard and rigorous code. 231. 232. For more FPGA learning materials, please visit the Forum: http://fpgabbs.com/ and official website: http://old.mdy-edu.com/index.html 233. 234. *************************************************************************************/ 235. 236. 237. module traf_light2( 238. clk , 239. rst_n , 240. led_east , 241. led_south , 242. led_west , 243. led_north 244. ); 245. 246. 247. 248. parameter COUNT_TIME = 26'd5000_0000; 249. parameter CYCLE_TIME = 5'd30 ; 250. parameter COUNT_WID = 26 ; 251. parameter SEC_WID = 5 ; 252. parameter LED_NUM = 3 ; 253. parameter STA_W = 2 ; 254. 255. parameter STA_G = 2'd1 ; 256. parameter STA_Y = 2'd2 ; 257. parameter STA_R = 2'd3 ; 258. parameter GREEN = 3'b110 ; 259. parameter YELLOW = 3'b101 ; 260. parameter RED = 3'b011 ; 261. 262. 263. input clk ; 264. input rst_n ; 265. output [LED_NUM-1:0] led_east ; 266. output [LED_NUM-1:0] led_south ; 267. output [LED_NUM-1:0] led_west ; 268. output [LED_NUM-1:0] led_north ; 269. 270. reg [LED_NUM-1:0] led_east ; 271. reg [LED_NUM-1:0] led_south ; 272. reg [LED_NUM-1:0] led_west ; 273. reg [LED_NUM-1:0] led_north ; 274. 275. reg [COUNT_WID-1:0] counter ; 276. wire add_counter ; 277. wire end_counter ; 278. reg [SEC_WID-1:0] second ; 279. wire add_second ; 280. wire end_second ; 281. 282. reg [STA_W-1:0] ew_state_c ; 283. reg [STA_W-1:0] ew_state_n ; 284. wire idle2sta_g_start_ew ; 285. wire sta_g2sta_y_start_ew ; 286. wire sta_y2sta_r_start_ew ; 287. wire sta_r2sta_g_start_ew ; 288. 289. reg [STA_W-1:0] sn_state_c ; 290. reg [STA_W-1:0] sn_state_n ; 291. wire idle2sta_r_start_sn ; 292. wire sta_r2sta_g_start_sn ; 293. wire sta_g2sta_y_start_sn ; 294. wire sta_y2sta_r_start_sn ; 295. 296. 297. always @(posedge clk or negedge rst_n) begin 298. if (rst_n==0) begin 299. counter <= 0; 300. end 301. else if(add_counter) begin 302. if(end_counter) 303. counter <= 0; 304. else 305. counter <= counter+1 ; 306. end 307. end 308. assign add_counter = 1; 309. assign end_counter = add_counter && counter == COUNT_TIME-1 ; 310. 311. 312. always @(posedge clk or negedge rst_n) begin 313. if (rst_n==0) begin 314. second <= 0; 315. end 316. else if(add_second) begin 317. if(end_second) 318. second <= 0; 319. else 320. second <= second+1 ; 321. end 322. end 323. assign add_second = end_counter; 324. assign end_second = add_second && second == CYCLE_TIME-1 ; 325. 326. 327. always @(posedge clk or negedge rst_n) begin 328. if (rst_n==0) begin 329. ew_state_c <= STA_G ; 330. end 331. else begin 332. ew_state_c <= ew_state_n; 333. end 334. end 335. 336. always @(*) begin 337. case(ew_state_c) 338. STA_G :begin 339. if(sta_g2sta_y_start_ew) 340. ew_state_n = STA_Y ; 341. else 342. ew_state_n = ew_state_c ; 343. end 344. STA_Y :begin 345. if(sta_y2sta_r_start_ew) 346. ew_state_n = STA_R ; 347. else 348. ew_state_n = ew_state_c ; 349. end 350. STA_R :begin 351. if(sta_r2sta_g_start_ew) 352. ew_state_n = STA_G ; 353. else 354. ew_state_n = ew_state_c ; 355. end 356. default : ew_state_n = STA_G ; 357. endcase 358. end 359. 360. assign sta_g2sta_y_start_ew = ew_state_c==STA_G && add_second && second == 10-1; 361. assign sta_y2sta_r_start_ew = ew_state_c==STA_Y && add_second && second == 15-1; 362. assign sta_r2sta_g_start_ew = ew_state_c==STA_R && add_second && second == 30-1; 363. 364. always @(posedge clk or negedge rst_n)begin 365. if(rst_n==1'b0)begin 366. led_east<=GREEN; 367. end 368. else if(ew_state_c==STA_G)begin 369. led_east<=GREEN; 370. end 371. else if(ew_state_c==STA_Y)begin 372. led_east<=YELLOW; 373. end 374. else if(ew_state_c==STA_R)begin 375. led_east<=RED; 376. end 377. else begin 378. led_east<=GREEN; 379. end 380. end 381. 382. always @(posedge clk or negedge rst_n)begin 383. if(rst_n==1'b0)begin 384. led_west<=GREEN; 385. end 386. else if(ew_state_c==STA_G)begin 387. led_west<=GREEN; 388. end 389. else if(ew_state_c==STA_Y)begin 390. led_west<=YELLOW; 391. end 392. else if(ew_state_c==STA_R)begin 393. led_west<=RED; 394. end 395. else begin 396. led_west<=GREEN; 397. end 398. end 399. 400. 401. 402. always @(posedge clk or negedge rst_n) begin 403. if (rst_n==0) begin 404. sn_state_c <= STA_R ; 405. end 406. else begin 407. sn_state_c <= sn_state_n; 408. end 409. end 410. 411. always @(*) begin 412. case(sn_state_c) 413. STA_R :begin 414. if(sta_r2sta_g_start_sn) 415. sn_state_n = STA_G ; 416. else 417. sn_state_n = sn_state_c ; 418. end 419. STA_G :begin 420. if(sta_g2sta_y_start_sn) 421. sn_state_n = STA_Y ; 422. else 423. sn_state_n = sn_state_c ; 424. end 425. STA_Y :begin 426. if(sta_y2sta_r_start_sn) 427. sn_state_n = STA_R ; 428. else 429. sn_state_n = sn_state_c ; 430. end 431. default : sn_state_n = STA_R ; 432. endcase 433. end 434. 435. assign sta_r2sta_g_start_sn = sn_state_c==STA_R && add_second && second == 15-1; 436. assign sta_g2sta_y_start_sn = sn_state_c==STA_G && add_second && second == 25-1; 437. assign sta_y2sta_r_start_sn = sn_state_c==STA_Y && add_second && second == 30-1; 438. 439. always @(posedge clk or negedge rst_n)begin 440. if(rst_n==1'b0)begin 441. led_south<=RED; 442. end 443. else if(sn_state_c==STA_G)begin 444. led_south<=GREEN; 445. end 446. else if(sn_state_c==STA_Y)begin 447. led_south<=YELLOW; 448. end 449. else if(sn_state_c==STA_R)begin 450. led_south<=RED; 451. end 452. else begin 453. led_south<=GREEN; 454. end 455. end 456. 457. always @(posedge clk or negedge rst_n)begin 458. if(rst_n==1'b0)begin 459. led_north<=RED; 460. end 461. else if(sn_state_c==STA_G)begin 462. led_north<=GREEN; 463. end 464. else if(sn_state_c==STA_Y)begin 465. led_north<=YELLOW; 466. end 467. else if(sn_state_c==STA_R)begin 468. led_north<=RED; 469. end 470. else begin 471. led_north<=GREEN; 472. end 473. end 474. 475. endmodule 476.
1.2 效果和總結(jié)
點(diǎn)撥板:
1. 復(fù)位,東西綠燈亮,南北紅燈亮

2. 10秒后,東西黃燈亮,南北還是紅燈亮

3. 15秒后,東西紅燈亮,南北綠燈亮

4. 20秒后。東西還是紅燈亮,南北黃燈亮

5. 30秒后,東西綠燈亮,南北紅燈亮

Mp801:
1. 復(fù)位,東西綠燈亮,南北紅燈亮

2. 10秒后,東西黃燈亮,南北還是紅燈亮

3. 15秒后,東西紅燈亮,南北綠燈亮

4. 20秒后。東西還是紅燈亮,南北黃燈亮

5. 30秒后,東西綠燈亮,南北紅燈亮

實(shí)驗(yàn)箱:
1. 復(fù)位,東西綠燈亮,南北紅燈亮

2. 10秒后,東西黃燈亮,南北還是紅燈亮

3. 15秒后,東西紅燈亮,南北綠燈亮

4. 20秒后。東西還是紅燈亮,南北黃燈亮

5. 30秒后,東西綠燈亮,南北紅燈亮

觀看上面的現(xiàn)象,可以發(fā)現(xiàn),各項(xiàng)功能正常:開發(fā)板上有紅黃綠三色 LED 燈各四個(gè),在東西南北方向各有一組。參考交通燈的情況,即每個(gè)方向都是綠燈亮 10 秒,然后黃燈亮 5 秒,然后紅燈亮 15 秒。綠燈按照東西和南北的順序依次亮。成功完成設(shè)計(jì)目標(biāo)。
溫馨提示:明德?lián)P2023推出了全新課程——邏輯設(shè)計(jì)基本功修煉課,降低學(xué)習(xí)FPGA門檻的同時(shí),增加了學(xué)習(xí)的趣味性,并組織了考試贏積分活動(dòng)
http://m.cqqtmy.cn/ffkc/415.html
(點(diǎn)擊→了解課程詳情?)感興趣請(qǐng)聯(lián)系易老師:13112063618(微信同步)