OpenCores
URL https://opencores.org/ocsvn/p9813_rgb_led_string_driver/p9813_rgb_led_string_driver/trunk

Subversion Repositories p9813_rgb_led_string_driver

[/] [p9813_rgb_led_string_driver/] [trunk/] [rtl/] [VHDL/] [rgb_pixel_pack.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jclaytons
--------------------------------------------------------------------------
2
-- Package of components
3
--
4
--
5
 
6
library ieee;
7
use ieee.std_logic_1164.all;
8
use ieee.numeric_std.all;
9
 
10
package rgb_pixel_pack is
11
 
12
-- Component declarations not provided any more.
13
-- With VHDL '93 and newer, component declarations are allowed,
14
-- but not required.
15
--
16
-- Please to try direct instantiation instead, for example:
17
--
18
--   instance_name : entity work.entity_name(beh)
19
--
20
 
21
end rgb_pixel_pack;
22
 
23
package body rgb_pixel_pack is
24
end rgb_pixel_pack;
25
 
26
-------------------------------------------------------------------------------
27
-- WS2812 "GRB" LED chain driver module
28
-------------------------------------------------------------------------------
29
--
30
-- Author: John Clayton
31
-- Update: Oct. 19, 2013 Started Coding, wrote description.
32
--
33
-- Description
34
-------------------------------------------------------------------------------
35
-- This module outputs a serial stream of NRZ data pulses which
36
-- are intended for driving a chain of WS2812 LED PWM driver ICs.
37
-- Actually, the WS2811 is the driver as a separate IC, and the WS2812 is
38
-- a complete RGB LED pixel with the driver built right in.  As costs drop
39
-- the popularity of this device is rising.
40
--
41
-- The datasheet seems to indicate some very specific timing requirements.
42
--
43
-- A '1' bit is apparently 0.35us high, followed by 0.8us low.
44
-- A '0' bit is apparently 0.7us high, followed by 0.6us low.
45
--
46
-- The datasheet also states that Th+Tl = 1.25us +/- 600 ns.
47
--
48
-- Well, based on that, this module chooses to use 1.25 microseconds
49
-- per bit time, which corresponds to 800kbps.  Internally, the system clock
50
-- rate is divided by 800000, and the result is the number of clock cycles
51
-- per bit available for creating the serial bitstream.
52
--
53
-- Then, constants are determined based on CLKS_PER_BIT according to the
54
-- following formulae:
55
--
56
--   CLKS_T0h = 0.28*CLKS_PER_BIT
57
--   CLKS_T1h = 0.54*CLKS_PER_BIT
58
--
59
-- This means that the timing will be closer or farther from ideal,
60
-- depending on the SYS_CLK_RATE.  For example:
61
--
62
--   Fsys_clk = 50 MHz
63
--   CLKS_PER_BIT = 62.5 which is rounded down to 62.
64
--   CLKS_T0h = 17.36 which is rounded down to 17.
65
--   CLKS_T1h = 33.48 which is rounded down to 33.
66
--   This leaves 45 clocks for the T0l time.
67
--   This leaves 29 clocks for the T1l time.
68
--
69
--   For this example, the bit time is 1.24us.
70
--   The T0h is 0.34us and T0l is 0.9us.
71
--   The T1h is 0.66us and T1l is 0.58us.
72
--
73
-- The lower the SYS_CLK_RATE, the tougher it is to meet the stated timing
74
-- requirements of the WS2812 device.  Using this scheme, the lowest clock
75
-- rate supported is 20 MHz.
76
--
77
-- The LEDs are driven with 24-bit color, that is 8 bits for red
78
-- intensity, 8 bits for green intensity and 8 bits for blue intensity.
79
--
80
-- I stopped short of calling it an "RGB LED driver" since WS2811/WS2812
81
-- receives the data in the order "GRB."  The ordering of the color
82
-- bits should not really matter anyway, so let's just be very accepting,
83
-- shall we not?
84
--
85
-- After the entire sequence of serial bits is driven out for updating the
86
-- GRB colors of the LEDs, then a reset interval of RESET_CLKS is given,
87
-- where RESET_CLKS is set by constants.
88
--
89
-- Interestingly, it seems that sending extra color information will not
90
-- affect the LED string in a negative way.  So, for example, if there
91
-- are only eight devices in the string, and the module is configured to
92
-- send out data for 10 devices, then the first eight devices will run
93
-- just fine.
94
--
95
-- Yes, that is correct, the LEDs closest to the source of sdat_o get lit
96
-- first, then they become "passthrough" so that the next one gets lit, and
97
-- so forth.
98
--
99
-- This module latches color information from an external source.
100
-- It provides the c_adr_o signal to specify which information
101
-- should be selected.  In this way, the module can be used with a variable
102
-- numbers of WS2811/WS2812 devices in the chain.
103
--
104
-- Just to keep things on an even keel, the c_adr_o address
105
-- advances according to the following pattern:
106
--
107
-- 0,1,2,4,5,6,8,9,A,C,D,E...
108
--
109
-- What is happening is that one address per LED is getting skipped
110
-- or "wasted" in order to start with each LEDs green value on an
111
-- even multiple N*4, where N is the LED number, beginning with zero
112
-- for the "zeroth" LED.  Then the red values are at N*4+1, while
113
-- the blue values are at N*4+2.  The N*4+3 values are simply skipped.
114
-- Isn't that super organized?
115
--
116
-- This unit runs continuously, the only way to stop it is to lower
117
-- the sys_clk_en input.
118
--
119
 
120
 
121
library IEEE;
122
use IEEE.STD_LOGIC_1164.ALL;
123
use IEEE.NUMERIC_STD.ALL;
124
use IEEE.MATH_REAL.ALL;
125
 
126
library work;
127
use work.dds_pack.all;
128
use work.function_pack.all;
129
 
130
  entity ws2812_LED_chain_driver is
131
    generic (
132
      SYS_CLK_RATE : real := 50000000.0; -- underlying clock rate
133
      ADR_BITS     : natural := 8; -- Must equal or exceed BIT_WIDTH(N_LEDS)+2.
134
      N_LEDS       : natural := 8  -- Number of LEDs in chain
135
    );
136
    port (
137
 
138
      -- System Clock, Reset and Clock Enable
139
      sys_rst_n  : in  std_logic;
140
      sys_clk    : in  std_logic;
141
      sys_clk_en : in  std_logic;
142
 
143
      -- Selection of color information
144
      c_adr_o    : out unsigned(ADR_BITS-1 downto 0);
145
      c_dat_i    : in  unsigned(7 downto 0);
146
 
147
      -- Output
148
      sdat_o     : out std_logic
149
    );
150
    end ws2812_LED_chain_driver;
151
 
152
architecture beh of ws2812_LED_chain_driver is
153
 
154
-- Constants
155
constant LED_BIT_RATE   : real := 800000.0;
156
constant CLKS_PER_BIT   : natural := integer(floor(SYS_CLK_RATE/LED_BIT_RATE));
157
constant CLKS_T0_H      : natural := integer(floor(0.28*SYS_CLK_RATE/LED_BIT_RATE));
158
constant CLKS_T1_H      : natural := integer(floor(0.54*SYS_CLK_RATE/LED_BIT_RATE));
159
constant SUB_COUNT_BITS : natural := bit_width(CLKS_PER_BIT);
160
constant STRING_BYTES   : natural := 3*N_LEDS;
161
constant RESET_TIME     : real := 0.000050; -- "time" data type could have been used...
162
constant RESET_BCOUNT   : natural := integer(floor(RESET_TIME*LED_BIT_RATE));
163
constant RESET_BITS     : natural := timer_width(RESET_BCOUNT);
164
 
165
-- Signals
166
signal reset_count : unsigned(RESET_BITS-1 downto 0);
167
signal sub_count   : unsigned(SUB_COUNT_BITS-1 downto 0);
168
signal bit_count   : unsigned(2 downto 0);
169
signal byte_count  : unsigned(bit_width(STRING_BYTES)-1 downto 0);
170
signal c_adr       : unsigned(ADR_BITS-1 downto 0);
171
signal c_dat       : unsigned(7 downto 0);
172
 
173
-----------------------------------------------------------------------------
174
begin
175
 
176
  c_adr_proc: Process(sys_rst_n,sys_clk)
177
  begin
178
    if (sys_rst_n = '0') then
179
      reset_count <= to_unsigned(RESET_BCOUNT,reset_count'length);
180
      sub_count  <= (others=>'0');
181
      byte_count <= (others=>'0');
182
      c_adr      <= (others=>'0');
183
      c_dat      <= (others=>'0');
184
      bit_count  <= (others=>'0');
185
    elsif (sys_clk'event and sys_clk='1') then
186
      if (sys_clk_en='1') then
187
        -- Sub count just keeps going all the time, during reset
188
        -- and during data transition.
189
        sub_count <= sub_count+1;
190
        if (sub_count=CLKS_PER_BIT-1) then
191
          sub_count <= (others=>'0');
192
        end if;
193
 
194
        -- Reset count decrements until reaching one, then
195
        -- it is set to zero while data is shifted out.
196
        -- It decrements once for each bit time.
197
        if (reset_count>0) then
198
          if (sub_count=CLKS_PER_BIT-1) then
199
            reset_count <= reset_count-1;
200
          end if;
201
        end if;
202
 
203
        -- When reset count reaches zero, color data shifting occurs
204
        if (reset_count>0) then
205
          c_adr <= (others=>'0');
206
          if (reset_count=1 and sub_count=CLKS_PER_BIT-1) then
207
            c_adr <= c_adr+1; -- Data from first address is loaded during reset time...
208
          end if;
209
          c_dat <= c_dat_i;
210
        else
211
          if (sub_count=CLKS_PER_BIT-1) then
212
            c_dat <= c_dat(c_dat'length-2 downto 0) & '0'; -- shift
213
            bit_count <= bit_count+1;
214
            if (bit_count=7) then
215
              c_dat <= c_dat_i;
216
              if (c_adr(1 downto 0)="10") then
217
                c_adr <= c_adr+2;
218
                if (byte_count=STRING_BYTES-1) then
219
                  byte_count <= (others=>'0');
220
                  reset_count <= to_unsigned(RESET_BCOUNT,reset_count'length);
221
                else
222
                  byte_count <= byte_count+1;
223
                end if;
224
              else
225
                c_adr <= c_adr+1;
226
              end if;
227
            end if;
228
          end if;
229
        end if;
230
      end if;
231
    end if; -- sys_clk
232
  end process;
233
  sdat_o <= '0' when (reset_count>0) else
234
            '1' when (c_dat(7)='1') and (sub_count<CLKS_T1_H) else
235
            '1' when (sub_count<CLKS_T0_H) else
236
            '0';
237
  c_adr_o <= c_adr;
238
 
239
end beh;
240
 
241
 
242
-------------------------------------------------------------------------------
243
-- LPD8806 "GRB" LED chain driver module
244
-------------------------------------------------------------------------------
245
--
246
-- Author: John Clayton
247
-- Update: Apr.  8, 2013 Started Coding, wrote description.
248
--         Apr. 10, 2013 Simulated and tested in hardware.
249
--
250
-- Description
251
-------------------------------------------------------------------------------
252
-- This module outputs a serial stream of clock and data pulses which
253
-- are intended for driving a chain of LPD8806 LED PWM driver ICs.
254
--
255
-- This type of LED driver is commonly sold pre-built into strips
256
-- of LEDs, with each LPD8806 circuit driving two multi-color LEDs.
257
--
258
-- The LEDs are driven with 21-bit color, that is 7 bits for red
259
-- intensity, 7 bits for green intensity and 7 bits for blue intensity.
260
--
261
-- I stopped short of calling it an "RGB LED driver" since lpd8806
262
-- receives the data in the order "GRB."  The ordering of the color
263
-- bits should not really matter anyway, so just be happy, OK?
264
--
265
-- The first bit, the MSB, is set for updating the LED colors, and cleared
266
-- for resetting the drivers.  Therefore, after each sequence of color
267
-- information bits, about 24 bits of zero are sent out to reset
268
-- everything in order to be ready for the next update.
269
--
270
-- This module generates its own serial bit clock by using a DDS based
271
-- on the underlying system clock rate.  It has been suggested that
272
-- 2 MHz is a good number, although I'll bet many other speeds will
273
-- also work, both higher and lower.
274
--
275
-- Another DDS generates the update rate pulse, which kicks off
276
-- the updating process.  Beware, if one sets the update rate too
277
-- high, it may become impossible to transmit all the required color
278
-- bits, and so the LEDs at the end of the chain may get left out
279
-- of the process!
280
--
281
-- Yes, that is correct, the LEDs closest to the source of SCLK
282
-- and SDAT get lit first, then they become "passthrough" so that
283
-- the next one gets set, and so forth.
284
--
285
-- This module latches color information from an external source.
286
-- It provides the c_adr_o signal to specify which information
287
-- should be selected.  In this way, the module can be used with
288
-- different numbers of drivers and LED pairs in the strip.
289
--
290
-- Just to keep things on an even keel, the c_adr_o address
291
-- advances according to the following pattern:
292
--
293
-- 0,1,2,4,5,6,8,9,A,C,D,E...
294
--
295
-- What is happening is that one address per LED is getting skipped
296
-- or "wasted" in order to start with each LEDs green value on an
297
-- even multiple N*4, where N is the LED number, beginning with zero
298
-- for the "zeroth" LED.  Then the red values are at N*4+1, while
299
-- the blue values are at N*4+2.  The N*4+3 values are simply skipped.
300
-- Isn't that super organized?
301
--
302
--
303
 
304
 
305
library IEEE;
306
use IEEE.STD_LOGIC_1164.ALL;
307
use IEEE.NUMERIC_STD.ALL;
308
use IEEE.MATH_REAL.ALL;
309
 
310
library work;
311
use work.dds_pack.all;
312
 
313
  entity lpd8806_LED_chain_driver is
314
    generic (
315
      SCLK_FREQ    : real := 2000000.0;    -- Desired lpd8806 serial clock frequency
316
      UPDATE_FREQ  : real := 20.0;    -- Desired LED chain update frequency
317
      SYS_CLK_RATE : real := 50000000.0;    -- underlying clock rate
318
      N_LEDS       : integer := 8  -- Number of LEDs in chain
319
    );
320
    port (
321
 
322
      -- System Clock, Reset and Clock Enable
323
      sys_rst_n  : in  std_logic;
324
      sys_clk    : in  std_logic;
325
      sys_clk_en : in  std_logic;
326
 
327
      -- Selection of color information
328
      c_adr_o    : out unsigned(7 downto 0);
329
      c_dat_i    : in  unsigned(6 downto 0);
330
 
331
      -- Output
332
      sclk_o     : out std_logic;
333
      sdat_o     : out std_logic
334
    );
335
    end lpd8806_LED_chain_driver;
336
 
337
architecture beh of lpd8806_LED_chain_driver is
338
 
339
-- Constants
340
constant N_ZERO_BYTES : natural := 3;
341
 
342
-- Signals
343
signal sclk            : std_logic;
344
signal sclk_pulse      : std_logic;
345
signal update_pulse    : std_logic;
346
signal bit_count       : unsigned(3 downto 0);
347
signal byte_count      : unsigned(7 downto 0); -- Widen for chains of 64+ LEDs.
348
signal c_adr           : unsigned(7 downto 0); -- Widen for chains of 64+ LEDs.
349
signal c_dat           : unsigned(7 downto 0);
350
 
351
-----------------------------------------------------------------------------
352
begin
353
 
354
  c_adr_proc: Process(sys_rst_n,sys_clk)
355
  begin
356
    if (sys_rst_n = '0') then
357
      byte_count <= (others=>'0');
358
      c_adr      <= (others=>'0');
359
      c_dat      <= (others=>'0');
360
      bit_count  <= (others=>'0');
361
    elsif (sys_clk'event and sys_clk='1') then
362
      if (sys_clk_en='1') then
363
        if (byte_count=0) then
364
          c_adr <= (others=>'0');
365
        end if;
366
        if (byte_count>0 and sclk_pulse='1') then
367
          bit_count <= bit_count-1;
368
          if (bit_count<8) then
369
            c_dat <= c_dat(6 downto 0) & '0'; -- Default is to shift color data
370
            if (bit_count=0) then
371
              byte_count <= byte_count-1;
372
              bit_count  <= to_unsigned(7,bit_count'length);
373
              -- Set color data MSB appropriately
374
              if (byte_count<=4) then
375
                c_dat <= (others=>'0');
376
              else
377
                c_dat <= '1' & c_dat_i;
378
              end if;
379
              -- Cause c_adr to skip every address.ending in "11"
380
              if (c_adr(1 downto 0)="10") then
381
                c_adr <= c_adr+2;
382
              else
383
                c_adr <= c_adr+1;
384
              end if;
385
            end if;
386
          end if;
387
        end if;
388
        -- Update pulse gets highest priority
389
        if (update_pulse='1') then
390
          byte_count <= to_unsigned(N_LEDS*3+1+N_ZERO_BYTES,byte_count'length);
391
          if (sclk_pulse='1') then
392
            bit_count  <= to_unsigned(7,bit_count'length);
393
          else
394
            bit_count  <= to_unsigned(8,bit_count'length); -- means "pending"
395
          end if;
396
          c_dat      <= '1' & c_dat_i;
397
          c_adr      <= c_adr+1;
398
        end if;
399
      end if;
400
    end if; -- sys_clk
401
  end process;
402
  sdat_o <= c_dat(7) when (byte_count>0 and bit_count<8) else '0';
403
  c_adr_o <= c_adr;
404
 
405
  -------------------------
406
  -- Update pulse generation
407
  update_gen: entity work.dds_constant_squarewave(beh)
408
    generic map(
409
      OUTPUT_FREQ  => UPDATE_FREQ,  -- Desired output frequency
410
      SYS_CLK_RATE => SYS_CLK_RATE, -- underlying clock rate
411
      ACC_BITS     => 24 -- Bit width of DDS phase accumulator
412
    )
413
    port map(
414
 
415
      sys_rst_n    => sys_rst_n,
416
      sys_clk      => sys_clk,
417
      sys_clk_en   => sys_clk_en,
418
 
419
      -- Output
420
      pulse_o      => update_pulse,
421
      squarewave_o => open
422
    );
423
 
424
  -------------------------
425
  -- Serial clock generation
426
  sclk_gen: entity work.dds_constant_squarewave(beh)
427
    generic map(
428
      OUTPUT_FREQ  => SCLK_FREQ,   -- Desired output frequency
429
      SYS_CLK_RATE => SYS_CLK_RATE, -- underlying clock rate
430
      ACC_BITS     => 16 -- Bit width of DDS phase accumulator
431
    )
432
    port map(
433
 
434
      sys_rst_n    => sys_rst_n,
435
      sys_clk      => sys_clk,
436
      sys_clk_en   => sys_clk_en,
437
 
438
      -- Output
439
      pulse_o      => sclk_pulse,
440
      squarewave_o => sclk
441
    );
442
  sclk_o <= not sclk when (byte_count>0 and bit_count<8) else '0';
443
 
444
end beh;
445
 
446
 
447
-------------------------------------------------------------------------------
448
-- SPI byte writer module
449
-------------------------------------------------------------------------------
450
--
451
-- Author: John Clayton
452
-- Update: Apr.  8, 2013 Started Coding, wrote description.
453
--
454
-- Description
455
-------------------------------------------------------------------------------
456
-- I conceived of this module while debugging a serial driver for a
457
-- string of LPD8806 LED drivers.  It essentially latches the input
458
-- data, and sends it out serially at the desired rate.  When the byte
459
-- is fully transmitted, it stops and waits for the next byte.
460
--
461
-- The output clock is gated by ssel_o.  If you need a continuous
462
-- clock, please ungate it yourself.
463
--
464
-- Unlike with asynchronous data which shift out the lsb first, this
465
-- unit shifts out the msb first.
466
--
467
 
468
 
469
library IEEE;
470
use IEEE.STD_LOGIC_1164.ALL;
471
use IEEE.NUMERIC_STD.ALL;
472
use IEEE.MATH_REAL.ALL;
473
 
474
library work;
475
use work.dds_pack.all;
476
 
477
  entity spi_byte_writer is
478
    generic (
479
      SCLK_FREQ    : real := 2000000.0;    -- Desired lpd8806 serial clock frequency
480
      SYS_CLK_RATE : real := 50000000.0    -- underlying clock rate
481
    );
482
    port (
483
 
484
      -- System Clock, Reset and Clock Enable
485
      sys_rst_n  : in  std_logic;
486
      sys_clk    : in  std_logic;
487
      sys_clk_en : in  std_logic;
488
 
489
      -- Data to send.
490
      sel_i      : in  std_logic;
491
      we_i       : in  std_logic;
492
      dat_i      : in  unsigned(7 downto 0);
493
 
494
      -- Output
495
      ssel_o     : out std_logic;
496
      sclk_o     : out std_logic;
497
      sdat_o     : out std_logic
498
    );
499
    end spi_byte_writer;
500
 
501
architecture beh of spi_byte_writer is
502
 
503
-- Signals
504
signal sclk            : std_logic;
505
signal sclk_pulse      : std_logic;
506
signal ssel            : std_logic;
507
signal sdat            : unsigned(7 downto 0);
508
signal bit_count       : unsigned(3 downto 0);
509
 
510
-----------------------------------------------------------------------------
511
begin
512
 
513
  spi_write_proc: Process(sys_rst_n,sys_clk)
514
  begin
515
    if (sys_rst_n = '0') then
516
      sdat      <= (others=>'0');
517
      bit_count <= (others=>'0');
518
    elsif (sys_clk'event and sys_clk='1') then
519
      if (sys_clk_en='1') then
520
        if (sclk_pulse='1') then
521
          if (bit_count>0) then
522
            bit_count <= bit_count-1;
523
          end if;
524
          if ssel='1' then
525
            sdat <= sdat(6 downto 0) & '0';
526
          end if;
527
        elsif (sel_i='1' and we_i='1') then
528
          if (sclk_pulse='1') then
529
            bit_count  <= to_unsigned(8,bit_count'length);
530
          else
531
            bit_count  <= to_unsigned(9,bit_count'length); -- means "pending"
532
          end if;
533
          sdat <= dat_i;
534
        end if;
535
      end if;
536
    end if; -- sys_clk
537
  end process;
538
  sdat_o <= sdat(7) when ssel='1' else '0';
539
 
540
  -------------------------
541
  -- Serial clock generation
542
  sclk_gen: entity work.dds_constant_squarewave(beh)
543
    generic map(
544
      OUTPUT_FREQ  => SCLK_FREQ,   -- Desired output frequency
545
      SYS_CLK_RATE => SYS_CLK_RATE, -- underlying clock rate
546
      ACC_BITS     => 16 -- Bit width of DDS phase accumulator
547
    )
548
    port map(
549
 
550
      sys_rst_n    => sys_rst_n,
551
      sys_clk      => sys_clk,
552
      sys_clk_en   => sys_clk_en,
553
 
554
      -- Output
555
      pulse_o      => sclk_pulse,
556
      squarewave_o => sclk
557
    );
558
  sclk_o <= not sclk when ssel='1' else '0';
559
  ssel   <= '1'  when (bit_count<9 and bit_count>0) else '0';
560
  ssel_o <= ssel;
561
 
562
end beh;
563
 
564
 
565
-------------------------------------------------------------------------------
566
-- DMS P9813 "BGR" chainable LED driver module
567
-------------------------------------------------------------------------------
568
--
569
-- Author: John Clayton
570
-- Update: Apr. 23, 2018 Started Coding, wrote description.
571
--
572
-- Description
573
-------------------------------------------------------------------------------
574
-- This module outputs a serial stream of clock and data pulses which
575
-- are intended for driving a chain of P9813 LED PWM driver ICs.
576
--
577
-- This type of LED driver is commonly sold pre-built into the "Grove"
578
-- chainable RGB LED module, among others.
579
--
580
-- The LEDs are driven with 24-bit color, that is 8 bits for red
581
-- intensity, 8 bits for green intensity and 8 bits for blue intensity.
582
--
583
-- I stopped short of calling it an "RGB LED driver" since P9813
584
-- receives the data in the order "BGR."  The ordering of the color
585
-- bits should not really matter anyway, so just be happy, OK?
586
--
587
-- For each P9813 driver in the chain, 32-bits are transferred.  The
588
-- first byte is a "flag" byte, consisting of the following bits:
589
--
590
--   1  1 B7' B6' G7' G6' R7' R6'
591
--
592
--   Where B7' = ~B7 (B7 prime is the inverse of B7)
593
--     and so forth.
594
--
595
-- The flag byte is followed by eight bits for each of the colors,
596
-- blue, green and red, delivered most sigificant bit first.
597
--
598
-- The falling edge of the clock is in the middle of the data bit.
599
-- The clock frequency can be in the range [0..15] MHz.
600
--
601
-- This module generates its own serial bit clock by using a DDS based
602
-- on the underlying system clock rate.
603
--
604
-- Another DDS generates the update rate pulse, which kicks off
605
-- the updating process.  Beware, if one sets the update rate too
606
-- high, it may become impossible to transmit all the required color
607
-- bits, and so the LEDs at the end of the chain may get left out
608
-- of the process!
609
--
610
-- Yes, that is correct, the LEDs closest to the source of SCLK
611
-- and SDAT get lit first, then they become "passthrough" so that
612
-- the next one gets set, and so forth.
613
--
614
-- This module latches color information from an external source.
615
-- It provides the c_adr_o signal to specify which information
616
-- should be selected.  In this way, the module can be used with
617
-- different numbers of drivers and LED pairs in the strip.
618
--
619
--
620
 
621
 
622
library IEEE;
623
use IEEE.STD_LOGIC_1164.ALL;
624
use IEEE.NUMERIC_STD.ALL;
625
use IEEE.MATH_REAL.ALL;
626
 
627
library work;
628
use work.dds_pack.all;
629
use work.function_pack.all;
630
 
631
  entity p9813_LED_chain_driver is
632
    generic (
633
      SCLK_FREQ    : real := 2000000.0;    -- Desired lpd8806 serial clock frequency
634
      UPDATE_FREQ  : real := 20.0;    -- Desired LED chain update frequency
635
      SYS_CLK_RATE : real := 50000000.0;    -- underlying clock rate
636
      N_LEDS       : integer := 8  -- Number of LEDs in chain
637
    );
638
    port (
639
 
640
      -- System Clock, Reset and Clock Enable
641
      sys_rst_n  : in  std_logic;
642
      sys_clk    : in  std_logic;
643
      sys_clk_en : in  std_logic;
644
 
645
      -- Selection of color information
646
      c_adr_o    : out unsigned(7 downto 0);
647
      red_i      : in  unsigned(7 downto 0);
648
      grn_i      : in  unsigned(7 downto 0);
649
      blu_i      : in  unsigned(7 downto 0);
650
 
651
      -- Output
652
      sclk_o     : out std_logic;
653
      sdat_o     : out std_logic
654
    );
655
    end p9813_LED_chain_driver;
656
 
657
architecture beh of p9813_LED_chain_driver is
658
 
659
-- Constants
660
 
661
-- Signals
662
signal sclk            : std_logic;
663
signal sclk_pulse      : std_logic;
664
signal update_pulse    : std_logic;
665
signal bit_count       : unsigned(5 downto 0);
666
signal driver_count    : unsigned(bit_width(N_LEDS)-1 downto 0);
667
signal c_dat           : unsigned(31 downto 0);
668
signal flag_byte       : unsigned(7 downto 0);
669
 
670
-----------------------------------------------------------------------------
671
begin
672
 
673
  shift_register_proc: Process(sys_rst_n,sys_clk)
674
  begin
675
    if (sys_rst_n = '0') then
676
      driver_count <= (others=>'0');
677
      bit_count    <= (others=>'0');
678
      c_dat        <= (others=>'0');
679
    elsif (sys_clk'event and sys_clk='1') then
680
      if (sys_clk_en='1') then
681
        if (sclk_pulse='1') then
682
          if (bit_count>0) then
683
            bit_count <= bit_count-1;
684
          end if;
685
          if (bit_count<33) then
686
            c_dat <= c_dat(c_dat'length-2 downto 0) & '0'; -- Default is to shift color data
687
            if (bit_count=1 and driver_count>0) then -- reload
688
              driver_count <= driver_count-1;
689
              bit_count  <= to_unsigned(32,bit_count'length);
690
              c_dat <= flag_byte & blu_i & grn_i & red_i;
691
            end if;
692
          end if;
693
        end if;
694
        -- Update pulse gets highest priority
695
        if (update_pulse='1') then
696
          driver_count <= to_unsigned(N_LEDS-1,driver_count'length);
697
          if (sclk_pulse='1') then
698
            bit_count  <= to_unsigned(32,bit_count'length);
699
          else
700
            bit_count  <= to_unsigned(33,bit_count'length); -- means "pending"
701
          end if;
702
          c_dat <= flag_byte & blu_i & grn_i & red_i;
703
        end if;
704
      end if;
705
    end if; -- sys_clk
706
  end process;
707
  sdat_o <= c_dat(31) when (bit_count<33) and (bit_count>0) else '0';
708
  c_adr_o <= resize(driver_count,c_adr_o'length);
709
 
710
  -- Flag byte is composed of several inverted bits from the input, combined
711
  -- with two '1' bits.
712
  flag_byte <= "11" & not blu_i(7) & not blu_i(6) & not grn_i(7) & not grn_i(6) & not red_i(7) & not red_i(6);
713
 
714
  -------------------------
715
  -- Update pulse generation
716
  update_gen: entity work.dds_constant_squarewave(beh)
717
    generic map(
718
      OUTPUT_FREQ  => UPDATE_FREQ,  -- Desired output frequency
719
      SYS_CLK_RATE => SYS_CLK_RATE, -- underlying clock rate
720
      ACC_BITS     => 24 -- Bit width of DDS phase accumulator
721
    )
722
    port map(
723
 
724
      sys_rst_n    => sys_rst_n,
725
      sys_clk      => sys_clk,
726
      sys_clk_en   => sys_clk_en,
727
 
728
      -- Output
729
      pulse_o      => update_pulse,
730
      squarewave_o => open
731
    );
732
 
733
  -------------------------
734
  -- Serial clock generation
735
  sclk_gen: entity work.dds_constant_squarewave(beh)
736
    generic map(
737
      OUTPUT_FREQ  => SCLK_FREQ,   -- Desired output frequency
738
      SYS_CLK_RATE => SYS_CLK_RATE, -- underlying clock rate
739
      ACC_BITS     => 16 -- Bit width of DDS phase accumulator
740
    )
741
    port map(
742
 
743
      sys_rst_n    => sys_rst_n,
744
      sys_clk      => sys_clk,
745
      sys_clk_en   => sys_clk_en,
746
 
747
      -- Output
748
      pulse_o      => sclk_pulse,
749
      squarewave_o => sclk
750
    );
751
--  sclk_o <= sclk when (bit_count<33) and (bit_count>0) else '0';
752
  sclk_o <= sclk;
753
 
754
end beh;
755
 
756
 
757
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.