You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LED_control.sv 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. // ==================================================================
  2. // >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
  3. // ------------------------------------------------------------------
  4. // Copyright (c) 2017 by Lattice Semiconductor Corporation
  5. // ALL RIGHTS RESERVED
  6. // ------------------------------------------------------------------
  7. //
  8. // Permission:
  9. //
  10. // Lattice SG Pte. Ltd. grants permission to use this code
  11. // pursuant to the terms of the Lattice Reference Design License Agreement.
  12. //
  13. //
  14. // Disclaimer:
  15. //
  16. // This VHDL or Verilog source code is intended as a design reference
  17. // which illustrates how these types of functions can be implemented.
  18. // It is the user's responsibility to verify their design for
  19. // consistency and functionality through the use of formal
  20. // verification methods. Lattice provides no warranty
  21. // regarding the use or functionality of this code.
  22. //
  23. // --------------------------------------------------------------------
  24. //
  25. // Lattice SG Pte. Ltd.
  26. // 101 Thomson Road, United Square #07-02
  27. // Singapore 307591
  28. //
  29. //
  30. // TEL: 1-800-Lattice (USA and Canada)
  31. // +65-6631-2000 (Singapore)
  32. // +1-503-268-8001 (other locations)
  33. //
  34. // web: http://www.latticesemi.com/
  35. // email: techsupport@latticesemi.com
  36. //
  37. // --------------------------------------------------------------------
  38. //
  39. // Project: iCE5UP 5K RGB LED Tutorial
  40. // File: LED_control.v
  41. // Title: LED PWM control
  42. // Description: Creates RGB PWM per control inputs
  43. //
  44. //
  45. // --------------------------------------------------------------------
  46. //
  47. //------------------------------------------------------------
  48. // Notes:
  49. //
  50. //
  51. //------------------------------------------------------------
  52. // Development History:
  53. //
  54. // __DATE__ _BY_ _REV_ _DESCRIPTION___________________________
  55. // 04/05/17 RK 1.0 Initial tutorial design for Lattice Radiant
  56. //
  57. //------------------------------------------------------------
  58. // Dependencies:
  59. //
  60. //
  61. //
  62. //------------------------------------------------------------
  63. module LED_control1 (
  64. // inputs
  65. input wire clk12M, // 12M clock
  66. input wire rst, // Asynchronous reset
  67. input wire [1:0] color_sel, // for selecting color using switches
  68. input wire rw, // read or write select switch
  69. //outputs
  70. output reg red_pwm, // Red
  71. output reg blu_pwm, // Blue
  72. output reg grn_pwm // Green
  73. );
  74. //------------------------------
  75. // INTERNAL SIGNAL DECLARATIONS:
  76. //------------------------------
  77. // parameters (constants)
  78. parameter on_hi = 2'b10;
  79. parameter on_lo = 2'b01;
  80. parameter off = 2'b00;
  81. parameter LED_OFF = 2'b00;
  82. parameter RAMP_UP = 2'b01;
  83. parameter LED_ON = 2'b10;
  84. parameter RAMP_DOWN = 2'b11;
  85. parameter on_max_cnt = 28'h16E35ED; // 1 sec steady
  86. parameter Brightness=4'b0111; //50% Brightness
  87. parameter BreatheRamp=4'b0111; //4x
  88. parameter BlinkRate=4'b0101; //1sec
  89. // wires (assigns)
  90. wire [3:0]RGB_color;
  91. wire [4:0] red_intensity;
  92. wire [4:0] grn_intensity;
  93. wire [4:0] blu_intensity;
  94. wire clk24M;
  95. wire LOCK;
  96. // regs (always)
  97. reg [1:0] clk_div_cnt; //
  98. reg [3:0] RGB_color_s; // sample values from SPI i/f
  99. reg [3:0] Brightness_s;
  100. reg [3:0] BreatheRamp_s;
  101. reg [3:0] BlinkRate_s;
  102. reg [1:0] red_set; // hi/lo/off
  103. reg [1:0] grn_set;
  104. reg [1:0] blu_set;
  105. reg [31:0] red_peak; // LED 'on' peak intensity (high precision)
  106. reg [31:0] grn_peak;
  107. reg [31:0] blu_peak;
  108. reg [27:0] off_max_cnt; // LED off duration
  109. reg [3:0] step_shift; // scaling calculation aid
  110. reg [27:0] ramp_max_cnt; // LED ramp up/down duration
  111. reg [31:0] red_intensity_step; // LED intensity step when ramping
  112. reg [31:0] grn_intensity_step;
  113. reg [31:0] blu_intensity_step;
  114. reg [1:0] blink_state; // state variable
  115. reg [27:0] ramp_count; // counter for LED on/off duration
  116. reg [27:0] steady_count; // counter for LED ramp up/down duration
  117. reg [31:0] red_accum; // intensity accumulator during ramp
  118. reg [31:0] grn_accum;
  119. reg [31:0] blu_accum;
  120. reg [17:0] curr_red; // current LED intensity ( /256 = PWM duty cycle)
  121. reg [17:0] curr_grn;
  122. reg [17:0] curr_blu;
  123. reg [17:0] pwm_count; // PWM counter
  124. reg [7:0] count = 8'b0;
  125. //------------------------------
  126. // PLL Instantiation
  127. //------------------------------
  128. //Block to reset the PLL initially
  129. pll_24M __(.ref_clk_i(clk12M ), .rst_n_i(~rst), .lock_o(LOCK), .outcore_o( ), .outglobal_o(clk24M));
  130. //Selecting color using "color_sel"
  131. assign RGB_color = {2'b0,color_sel};
  132. // Capture stable parameters in local clock domain
  133. always @ (posedge clk24M or posedge rst)
  134. if (rst) begin
  135. RGB_color_s <= 4'b0000;
  136. Brightness_s <= 4'b0111;
  137. BreatheRamp_s <= 4'b0000;
  138. BlinkRate_s <= 4'b0101;
  139. //end else if(!RGB_Blink_En) begin //TODO ReadWrite Difference
  140. //RGB_color_s <= RGB_color ;
  141. //Brightness_s <= Brightness ;
  142. //BreatheRamp_s <= 4'b0000 ;
  143. //BlinkRate_s <= 4'b0000 ;
  144. end else begin
  145. RGB_color_s <= RGB_color ;
  146. Brightness_s <= Brightness ;
  147. BreatheRamp_s <= 4'b0000 ;
  148. BlinkRate_s <= 4'b0000 ;
  149. end
  150. // interpret 'brightness' setting
  151. assign red_intensity = Brightness_s + 1'b1;
  152. assign grn_intensity = Brightness_s + 1'b1;
  153. assign blu_intensity = Brightness_s + 1'b1;
  154. // interpret 'color' setting
  155. always @ (RGB_color_s)
  156. case (RGB_color_s)
  157. 4'b0000: begin red_set <= on_hi; grn_set <= off; blu_set <= off; end //Red
  158. 4'b0001: begin red_set <= on_hi; grn_set <= on_lo; blu_set <= off; end //Orange
  159. 4'b0010: begin red_set <= off; grn_set <= on_hi; blu_set <= off; end //Green
  160. 4'b0011: begin red_set <= off; grn_set <= on_hi; blu_set <= on_hi; end //Cyan
  161. 4'b0100: begin red_set <= off; grn_set <= on_hi; blu_set <= on_lo; end //SpringGreen
  162. 4'b0101: begin red_set <= on_hi; grn_set <= on_hi; blu_set <= off; end //Yellow
  163. 4'b0110: begin red_set <= on_lo; grn_set <= on_hi; blu_set <= off; end //Chartreuse
  164. 4'b0111: begin red_set <= off; grn_set <= on_lo; blu_set <= on_hi; end //Azure
  165. 4'b1000: begin red_set <= off; grn_set <= off; blu_set <= on_hi; end //Blue
  166. 4'b1001: begin red_set <= on_lo; grn_set <= off; blu_set <= on_hi; end //Violet
  167. 4'b1010: begin red_set <= on_hi; grn_set <= off; blu_set <= on_hi; end //Magenta
  168. 4'b1011: begin red_set <= on_hi; grn_set <= off; blu_set <= on_lo; end //Rose
  169. 4'b1111: begin red_set <= on_hi; grn_set <= on_hi; blu_set <= on_hi; end //White
  170. default: begin red_set <= off; grn_set <= off; blu_set <= off; end //2'b00
  171. endcase
  172. // set peak values per 'brightness' and 'color'
  173. // when color setting is 'on_lo', then peak intensity is divided by 2
  174. always @ (posedge clk24M or posedge rst)
  175. if (rst) begin
  176. red_peak <= 32'b0;
  177. end else begin
  178. case (red_set)
  179. on_hi: red_peak <= {red_intensity, 27'h000}; // 100%
  180. on_lo: red_peak <= {1'b0,red_intensity, 26'h000}; // 50%
  181. default: red_peak <= 32'h00000;
  182. endcase
  183. end
  184. always @ (posedge clk24M or posedge rst)
  185. if (rst) begin
  186. grn_peak <= 32'b0;
  187. end else begin
  188. case (grn_set)
  189. on_hi: grn_peak <= {grn_intensity, 27'h000}; // 100%
  190. on_lo: grn_peak <= {1'b0,grn_intensity, 26'h000}; // 50%
  191. default: grn_peak <= 32'h00000;
  192. endcase
  193. end
  194. always @ (posedge clk24M or posedge rst)
  195. if (rst) begin
  196. blu_peak <= 32'b0;
  197. end else begin
  198. case (blu_set)
  199. on_hi: blu_peak <= {blu_intensity, 27'h000}; // 100%
  200. on_lo: blu_peak <= {1'b0,blu_intensity, 26'h000}; // 50%
  201. default: blu_peak <= 32'h00000;
  202. endcase
  203. end
  204. // interpret 'Blink rate' setting
  205. // 'off_max_cnt' is time spent in 'LED_OFF' states
  206. // 'step_shift' is used to scale the intensity step size.
  207. // Stated period is blink rate with no ramp. Ramping adds to the period.
  208. always @ (posedge clk24M or posedge rst)
  209. if (rst) begin
  210. off_max_cnt <= 28'h0 - 1;
  211. //step_shift <= 4'b0;
  212. end else begin
  213. case (BlinkRate_s)
  214. 4'b0001: begin off_max_cnt <= 28'h016E35F; end // 1/16sec
  215. 4'b0010: begin off_max_cnt <= 28'h02DC6BE; end // 1/8 sec
  216. 4'b0011: begin off_max_cnt <= 28'h05B8D7B; end // 1/4 sec
  217. 4'b0100: begin off_max_cnt <= 28'h0B71AF6; end // 1/2 sec
  218. 4'b0101: begin off_max_cnt <= 28'h16E35ED; end // 1 sec
  219. 4'b0110: begin off_max_cnt <= 28'h2DC6BDA; end // 2 sec
  220. 4'b0111: begin off_max_cnt <= 28'h5B8D7B3; end // 4 sec
  221. default: begin off_max_cnt <= 28'h0; end //
  222. endcase
  223. end
  224. // interpret 'Breathe Ramp' setting
  225. // 'ramp_max_cnt' is time spent in 'RAMP_UP', RAMP_DOWN' states
  226. // '***_intensity_step' is calculated to add to color accumulators each ramp step
  227. always @ (posedge clk24M or posedge rst)
  228. if (rst) begin
  229. ramp_max_cnt <= 28'b0;
  230. red_intensity_step <= 28'b0;
  231. grn_intensity_step <= 28'b0;
  232. blu_intensity_step <= 28'b0;
  233. end else begin
  234. case (BreatheRamp_s)
  235. 4'b0001: begin
  236. ramp_max_cnt <= 28'h016E35F; // 1/16sec
  237. red_intensity_step <= red_peak >> (21) ;
  238. grn_intensity_step <= grn_peak >> (21) ;
  239. blu_intensity_step <= blu_peak >> (21) ;
  240. end
  241. 4'b0010: begin
  242. ramp_max_cnt <= 28'h02DC6BE; // 1/8 sec
  243. red_intensity_step <= red_peak >> (22) ;
  244. grn_intensity_step <= grn_peak >> (22) ;
  245. blu_intensity_step <= blu_peak >> (22) ;
  246. end
  247. 4'b0011: begin
  248. ramp_max_cnt <= 28'h05B8D7B; // 1/4 sec
  249. red_intensity_step <= red_peak >> (23) ;
  250. grn_intensity_step <= grn_peak >> (23) ;
  251. blu_intensity_step <= blu_peak >> (23) ;
  252. end
  253. 4'b0100: begin
  254. ramp_max_cnt <=28'h0B71AF6;
  255. red_intensity_step <= red_peak >> (24) ;//1/2
  256. grn_intensity_step <= grn_peak >> (24) ;
  257. blu_intensity_step <= blu_peak >> (24) ;
  258. end
  259. 4'b0101: begin
  260. ramp_max_cnt <= 28'h16E35ED; // 1 sec
  261. red_intensity_step <= red_peak >> (25) ;
  262. grn_intensity_step <= grn_peak >> (25) ;
  263. blu_intensity_step <= blu_peak >> (25) ;
  264. end
  265. 4'b0110: begin
  266. ramp_max_cnt <= 28'h2DC6BDA;
  267. red_intensity_step <= red_peak >> (26) ; //2 sec
  268. grn_intensity_step <= grn_peak >> (26) ;
  269. blu_intensity_step <= blu_peak >> (26) ;
  270. end
  271. 4'b0111: begin
  272. ramp_max_cnt <= 28'h5B8D7B3; // 4 sec
  273. red_intensity_step <= red_peak >> (27) ;
  274. grn_intensity_step <= grn_peak >> (27) ;
  275. blu_intensity_step <= blu_peak >> (27) ;
  276. end
  277. default: begin
  278. ramp_max_cnt <= 28'd0;
  279. red_intensity_step <= 28'b0;
  280. grn_intensity_step <= 28'b0;
  281. blu_intensity_step <= 28'b0;
  282. end
  283. endcase
  284. end
  285. // state machine to create LED ON/OFF/RAMP periods
  286. // state machine is held (no cycles) if LED is steady state on/off
  287. // state machine is reset to LED_ON state whenever parameters are updated.
  288. always @ (posedge clk24M or posedge rst)
  289. if (rst) begin
  290. blink_state <= LED_OFF;
  291. ramp_count <= 28'b0;
  292. steady_count <= 28'b0;
  293. end else begin
  294. if(BlinkRate_s == 4'b0000) begin
  295. blink_state <= LED_ON;
  296. ramp_count <= 0;
  297. steady_count <= 0;
  298. end else if (BlinkRate_s == 4'b1000) begin
  299. blink_state <= LED_OFF;
  300. ramp_count <= 0;
  301. steady_count <= 0;
  302. end else begin
  303. case (blink_state)
  304. LED_OFF: begin
  305. if(steady_count >= off_max_cnt) begin
  306. ramp_count <= 0;
  307. steady_count <= 0;
  308. blink_state <= RAMP_UP;
  309. end else begin
  310. steady_count <= steady_count + 1;
  311. end
  312. end
  313. RAMP_UP: begin
  314. if(ramp_count >= ramp_max_cnt) begin
  315. ramp_count <= 0;
  316. steady_count <= 0;
  317. blink_state <= LED_ON;
  318. end else begin
  319. ramp_count <= ramp_count + 1;
  320. end
  321. end
  322. LED_ON: begin
  323. if(steady_count >= on_max_cnt) begin
  324. ramp_count <= 0;
  325. steady_count <= 0;
  326. blink_state <= RAMP_DOWN;
  327. end else begin
  328. steady_count <= steady_count + 1;
  329. end
  330. end
  331. RAMP_DOWN: begin
  332. if(ramp_count >= ramp_max_cnt) begin
  333. ramp_count <= 0;
  334. steady_count <= 0;
  335. blink_state <= LED_OFF;
  336. end else begin
  337. ramp_count <= ramp_count + 1;
  338. end
  339. end
  340. default: begin
  341. blink_state <= LED_OFF;
  342. ramp_count <= 28'b0;
  343. steady_count <= 28'b0;
  344. end
  345. endcase
  346. end
  347. end
  348. // RampUP/DN accumulators
  349. always @ (posedge clk24M or posedge rst)
  350. if (rst) begin
  351. red_accum <= 32'b0;
  352. grn_accum <= 32'b0;
  353. blu_accum <= 32'b0;
  354. end else begin
  355. case (blink_state)
  356. LED_OFF: begin
  357. red_accum <= 0;
  358. grn_accum <= 0;
  359. blu_accum <= 0;
  360. end
  361. LED_ON: begin
  362. // red_accum <= red_accum;
  363. // grn_accum <= grn_accum;
  364. // blu_accum <= blu_accum;
  365. red_accum <= red_peak;
  366. grn_accum <= grn_peak;
  367. blu_accum <= blu_peak;
  368. end
  369. RAMP_UP: begin
  370. red_accum <= red_accum + red_intensity_step;
  371. grn_accum <= grn_accum + grn_intensity_step;
  372. blu_accum <= blu_accum + blu_intensity_step;
  373. end
  374. RAMP_DOWN: begin
  375. red_accum <= red_accum - red_intensity_step;
  376. grn_accum <= grn_accum - grn_intensity_step;
  377. blu_accum <= blu_accum - blu_intensity_step;
  378. end
  379. default: begin
  380. red_accum <= 0;
  381. grn_accum <= 0;
  382. blu_accum <= 0;
  383. end
  384. endcase
  385. end
  386. // set PWM duty cycle. 8-bit resolution 0x100 is 100% on
  387. always @ (posedge clk24M or posedge rst)
  388. if (rst) begin
  389. curr_red <= 18'b0;
  390. curr_grn <= 18'b0;
  391. curr_blu <= 18'b0;
  392. end else begin
  393. case (blink_state)
  394. LED_ON: begin
  395. curr_red <= red_peak[31:14]; // there should be no discrepancy between _peak and _accum in this state
  396. curr_grn <= grn_peak[31:14];
  397. curr_blu <= blu_peak[31:14];
  398. end
  399. RAMP_UP: begin
  400. curr_red <= red_accum[31:14];
  401. curr_grn <= grn_accum[31:14];
  402. curr_blu <= blu_accum[31:14];
  403. end
  404. RAMP_DOWN: begin
  405. curr_red <= red_accum[31:14];
  406. curr_grn <= grn_accum[31:14];
  407. curr_blu <= blu_accum[31:14];
  408. end
  409. LED_OFF: begin
  410. curr_red <= 0;
  411. curr_grn <= 0;
  412. curr_blu <= 0;
  413. end
  414. default: begin
  415. curr_red <= 0;
  416. curr_grn <= 0;
  417. curr_blu <= 0;
  418. end
  419. endcase
  420. end
  421. // generate PWM outputs
  422. always @ (posedge clk24M or posedge rst)
  423. if (rst) begin
  424. pwm_count <= 18'b0;
  425. red_pwm <= 0;
  426. grn_pwm <= 0;
  427. blu_pwm <= 0;
  428. end else begin
  429. if(pwm_count < 131071)
  430. pwm_count <= pwm_count + 1;
  431. else
  432. pwm_count <= 0;
  433. if(pwm_count < curr_red)
  434. red_pwm <= 1;
  435. else
  436. red_pwm <= 0;
  437. if(pwm_count < curr_grn)
  438. grn_pwm <= 1;
  439. else
  440. grn_pwm <= 0;
  441. if(pwm_count < curr_blu)
  442. blu_pwm <= 1;
  443. else
  444. blu_pwm <= 0;
  445. end
  446. endmodule // LED_control