Demo Code for WS2812b LEDs created

This commit is contained in:
Mario Hüttel 2016-10-24 00:07:41 +02:00
commit 5bdf863277
8 changed files with 460 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.bak
quartus

10
.library_mapping.xml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<com.sigasi.hdt.shared.librarymapping.model:LibraryMappings xmlns:com.sigasi.hdt.shared.librarymapping.model="com.sigasi.hdt.vhdl.scoping.librarymapping" Version="2">
<Mappings Location="bench" Library="bench"/>
<Mappings Location="src" Library="design"/>
<Mappings Location="Common Libraries/IEEE" Library="ieee"/>
<Mappings Location="Common Libraries" Library="not mapped"/>
<Mappings Location="quartus" Library="not mapped"/>
<Mappings Location="Common Libraries/STD" Library="std"/>
<Mappings Location="" Library="work"/>
</com.sigasi.hdt.shared.librarymapping.model:LibraryMappings>

45
.project Normal file
View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ws2812b</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.sigasi.hdt.vhdl.ui.vhdlNature</nature>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
</natures>
<linkedResources>
<link>
<name>Common Libraries</name>
<type>2</type>
<locationURI>virtual:/virtual</locationURI>
</link>
<link>
<name>Common Libraries/DRAG_REUSABLE_LIBRARIES_HERE.txt</name>
<type>1</type>
<locationURI>sigasiresource:/vhdl/readme2.txt</locationURI>
</link>
<link>
<name>Common Libraries/IEEE</name>
<type>2</type>
<locationURI>sigasiresource:/vhdl/93/IEEE</locationURI>
</link>
<link>
<name>Common Libraries/STD</name>
<type>2</type>
<locationURI>sigasiresource:/vhdl/93/STD</locationURI>
</link>
<link>
<name>Common Libraries/IEEE/Synopsys</name>
<type>2</type>
<locationURI>sigasiresource:/vhdl/93/IEEE%20Synopsys</locationURI>
</link>
</linkedResources>
</projectDescription>

View File

@ -0,0 +1,5 @@
eclipse.preferences.version=1
encoding//Common\ Libraries/IEEE=utf-8
encoding//Common\ Libraries/IEEE/Synopsys=utf-8
encoding//Common\ Libraries/STD=utf-8
encoding/Common\ Libraries=utf-8

View File

@ -0,0 +1,42 @@
library ieee;
library design;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use design.all;
entity ws2812test_bench is
end entity ws2812test_bench;
architecture RTL of ws2812test_bench is
signal clk : std_logic;
signal rst : std_logic;
signal ws_out : std_logic;
begin
clock_driver : process
constant period : time := 20 ns;
begin
clk <= '0';
wait for period / 2;
clk <= '1';
wait for period / 2;
end process clock_driver;
resetprovider : process is
begin
rst <= '0';
wait for 3 ns;
rst <= '1';
wait;
end process resetprovider;
ws2812test_inst : entity design.ws2812test
port map(
clk => clk,
reset => rst,
ws_out => ws_out,
gamma_req => '1'
);
end architecture RTL;

35
src/gamma8bit.vhd Normal file
View File

@ -0,0 +1,35 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity gamma8bit is
port(
color_in : in unsigned(7 downto 0);
color_out : out unsigned(7 downto 0)
);
end entity gamma8bit;
architecture RTL of gamma8bit is
type gammatable_t is array (0 to 255) of integer range 0 to 255;
signal table : gammatable_t;
begin
table <= (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114,
115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142,
144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175,
177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213,
215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255);
color_out <= to_unsigned(table(to_integer(color_in)), color_out'length);
end architecture RTL;

View File

@ -0,0 +1,123 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ws2812bphy is
generic(
constant HIGH1 : integer := 40;
constant LOW1 : integer := 23;
constant HIGH0 : integer := 20;
constant LOW0 : integer := 43
);
port(
clk : in std_logic;
rst : in std_logic;
busy : out std_logic;
ws_out : out std_logic;
strb : in std_logic;
red : in unsigned(7 downto 0);
green : in unsigned(7 downto 0);
blue : in unsigned(7 downto 0)
);
end entity ws2812bphy;
architecture RTL of ws2812bphy is
type ws_output_state_t is (IDLE, TRANSMITTING, INTERLEDDELAY);
signal ws_output_state : ws_output_state_t;
type bitstate_t is (LOW, HIGH);
signal bitstate : bitstate_t;
begin
ws_output : process(clk, rst) is
variable counter : integer range 0 to 255 := 0;
variable color_vector : std_logic_vector(23 downto 0);
variable bitnum : integer range 0 to 23;
begin
if rst = '1' then
ws_output_state <= IDLE;
color_vector := (others => '0');
counter := 0;
bitstate <= LOW;
bitnum := 0;
elsif rising_edge(clk) then
case ws_output_state is
when IDLE =>
bitstate <= LOW;
if strb = '1' then
ws_output_state <= TRANSMITTING;
bitnum := 23;
color_vector := std_logic_vector(green) & std_logic_vector(red) & std_logic_vector(blue);
counter := 0;
bitstate <= HIGH;
end if;
when TRANSMITTING =>
case bitstate is
when HIGH =>
if color_vector(bitnum) = '1' then
if counter < HIGH1 then
counter := counter + 1;
else
bitstate <= LOW;
counter := 0;
end if;
else
if counter < HIGH0 then
counter := counter + 1;
else
bitstate <= LOW;
counter := 0;
end if;
end if;
when LOW =>
if color_vector(bitnum) = '1' then
if counter < LOW1 then
counter := counter + 1;
else
bitstate <= HIGH;
counter := 0;
if bitnum = 0 then
ws_output_state <= INTERLEDDELAY;
counter := 0;
bitstate <= LOW;
else
bitnum := bitnum - 1;
end if;
end if;
else
if counter < LOW0 then
counter := counter + 1;
else
bitstate <= HIGH;
counter := 0;
if bitnum = 0 then
ws_output_state <= INTERLEDDELAY;
counter := 0;
bitstate <= LOW;
else
bitnum := bitnum - 1;
end if;
end if;
end if;
end case;
when INTERLEDDELAY =>
if counter < HIGH1+LOW1+LOW1 then
counter := counter + 1;
else
counter := 0;
ws_output_state <= IDLE;
end if;
end case;
end if;
end process ws_output;
busy <= '0' when ws_output_state = IDLE else '1';
ws_out <= '1' when bitstate = HIGH else '0';
end architecture RTL;

197
src/ws2812test.vhd Normal file
View File

@ -0,0 +1,197 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ws2812test is
port(
clk : in std_logic;
reset : in std_logic;
ws_out : out std_logic;
gamma_req : in std_logic
);
end entity ws2812test;
architecture RTL of ws2812test is
constant LEDCNT_c : integer := 60;
constant HEARTBEATMAX_c : integer := 700000;
signal rst : std_logic;
signal ws_busy : std_logic;
signal ws_strb : std_logic;
signal red_gamma : unsigned(7 downto 0);
signal green_gamma : unsigned(7 downto 0);
signal blue_gamma : unsigned(7 downto 0);
-- Signals for renderer
signal render_active : std_logic;
type transition_t is (RY, YG, GC, CB, BM, MR);
signal transition_active : transition_t;
type color_rec_t is record
red : unsigned(7 downto 0);
green : unsigned(7 downto 0);
blue : unsigned(7 downto 0);
end record color_rec_t;
signal color_active : color_rec_t;
signal lednum : integer range 0 to LEDCNT_c - 1;
-- Signals for rainbow
signal heartbeat : std_logic;
signal transition_start : transition_t;
signal color_start : color_rec_t;
signal red_ws : unsigned(7 downto 0);
signal green_ws : unsigned(7 downto 0);
signal blue_ws : unsigned(7 downto 0);
begin
rst <= not reset;
beatgen : process(clk, rst) is
variable beat_counter : integer range 0 to HEARTBEATMAX_c := 0;
begin
if rst = '1' then
beat_counter := 0;
heartbeat <= '0';
elsif rising_edge(clk) then
heartbeat <= '0';
if beat_counter /= HEARTBEATMAX_c then
beat_counter := beat_counter + 1;
else
beat_counter := 0;
heartbeat <= '1';
end if;
end if;
end process beatgen;
gamma_red : entity work.gamma8bit
port map(
color_in => color_active.red,
color_out => red_gamma
);
gamma_green : entity work.gamma8bit
port map(
color_in => color_active.green,
color_out => green_gamma
);
gamma_blue : entity work.gamma8bit
port map(
color_in => color_active.blue,
color_out => blue_gamma
);
red_ws <= red_gamma when gamma_req = '1' else color_active.red;
green_ws <= green_gamma when gamma_req = '1' else color_active.green;
blue_ws <= blue_gamma when gamma_req = '1' else color_active.blue;
ws2812bphy_inst : entity work.ws2812bphy
generic map(
HIGH1 => 40,
LOW1 => 23,
HIGH0 => 20,
LOW0 => 43
)
port map(
clk => clk,
rst => rst,
busy => ws_busy,
ws_out => ws_out,
strb => ws_strb,
red => red_ws,
green => green_ws,
blue => blue_ws
);
rainbow : process(clk, rst) is
procedure increment_col(signal color : inout unsigned(7 downto 0); is_renderer : boolean; next_state : transition_t) is
begin
color <= color + 20;
if color = 220 then
if is_renderer then
transition_active <= next_state;
else
transition_start <= next_state;
end if;
end if;
end procedure increment_col;
procedure decrement_col(signal color : inout unsigned(7 downto 0); is_renderer : boolean; next_state : transition_t) is
begin
color <= color - 20;
if color = 20 then
if is_renderer then
transition_active <= next_state;
else
transition_start <= next_state;
end if;
end if;
end procedure decrement_col;
begin
if rst = '1' then
render_active <= '1';
color_active.red <= to_unsigned(240, color_start.red'length);
color_active.green <= x"00";
color_active.blue <= x"00";
color_start.red <= to_unsigned(240, color_start.red'length);
color_start.green <= x"00";
color_start.blue <= x"00";
transition_active <= RY;
transition_start <= RY;
lednum <= 0;
elsif rising_edge(clk) then
-- renderer
if render_active = '1' then
ws_strb <= '0';
if ws_busy = '0' and ws_strb = '0' then
ws_strb <= '1';
case transition_active is
when RY =>
increment_col(color_active.green, true, YG);
when YG =>
decrement_col(color_active.red, true, GC);
when GC =>
increment_col(color_active.blue, true, CB);
when CB =>
decrement_col(color_active.green, true, BM);
when BM =>
increment_col(color_active.red, true, MR);
when MR =>
decrement_col(color_active.blue, true, RY);
end case;
end if; -- phy ready
if ws_strb = '1' then
if lednum < (LEDCNT_c - 1) then
lednum <= lednum + 1;
else
lednum <= 0;
render_active <= '0';
end if;
end if;
elsif heartbeat = '1' then
case transition_start is
when RY =>
increment_col(color_start.green, false, YG);
when YG =>
decrement_col(color_start.red, false, GC);
when GC =>
increment_col(color_start.blue, false, CB);
when CB =>
decrement_col(color_start.green, false, BM);
when BM =>
increment_col(color_start.red, false, MR);
when MR =>
decrement_col(color_start.blue, false, RY);
end case;
color_active <= color_start;
transition_active <= transition_start;
render_active <= '1';
end if; -- rainbow
end if; -- rising edge
end process rainbow;
end architecture RTL;