1
0
mirror of https://github.com/cclassic/ws2812b-vhdl synced 2024-11-21 08:55:04 +01:00

Cleanup, restructuring and doc

This commit is contained in:
Markus Koch 2016-10-16 15:02:28 +02:00
parent afef8ef269
commit 491c833a48
8 changed files with 61 additions and 22 deletions

View File

@ -1,12 +1,43 @@
# WS2812B CONTROLLER FOR FPGAS # WS2812B CONTROLLER FOR FPGAS
A controller for the WorldSemi WS2812B RGB LEDs written in plain VHDL. A controller for the WorldSemi WS2812B RGB LEDs written in plain VHDL.
## Directory structure
* ws2812b: Contains the actual library.
* demo: Contains demo designs to visualize the functionality of the design.
* bench: Contains various test benches used during the development of the library.
* gtkwave: Contains GtkWave layouts for some test benches.
For directories containing VHDL source files, the directory name denotes the VHDL library.
## Entity description ## Entity description
### ws2812b_phy ### ws2812b_phy
Low level driver for the WorldSemi WS2812B RGB LEDs. Handles bit timing and command separation. Low level driver for the WorldSemi WS2812B RGB LEDs. Handles bit timing and command separation.
*Documentation coming soon*
For an example, see Rainbow.
### ws2812b_controller ### ws2812b_controller
WS2812B Controller to render picture data from SRAM. WS2812B Controller to render picture data from SRAM.
*Documentation coming soon*
For an example, see demo_sram.
## Demos
### Rainbow
Displays a simple moving rainbow pattern over a strip of fixed length.
Make sure the '''F_CLK''' is set to the actual frequency present on the hardware for '''clk'''.
To set the length, change the '''LENGTH''' constant. To change the speed of the animation, change the '''F_SYSTICK''' constant. To change the length of one iteration of the rainbow, set the '''INCREMENT''' constant. To change the maximum brightness, change the '''PIXDATA_MAX''' constant while making sure that it is a multiple of '''INCREMENT'''.
### demo_sram
Steps through some predefined colors by writing the to the controller's RAM and simply issuing a *render* strobe.
Make sure the '''F_CLK''' is set to the actual frequency present on the hardware for '''clk'''.
## License ## License
This work is released under the Mozilla Public License (MPL) Version 2. It may be interpreted in the same way the Open Hardware Description License (OHDL) by Julius Baxter does. Read more about it here: http://juliusbaxter.net/ohdl/ohdl.txt This work is released under the Mozilla Public License (MPL) Version 2. It may be interpreted in the same way the Open Hardware Description License (OHDL) by Julius Baxter does. Read more about it here: http://juliusbaxter.net/ohdl/ohdl.txt
Authors: Markus Koch <markus@notsyncing.net>

View File

@ -15,8 +15,8 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;
use ieee.math_real.all; use ieee.math_real.all;
library design; library ws2812b;
use design.all; use ws2812b.all;
entity bench_ws2812b_controller is entity bench_ws2812b_controller is
end entity bench_ws2812b_controller; end entity bench_ws2812b_controller;
@ -39,7 +39,7 @@ architecture RTL of bench_ws2812b_controller is
signal vsync : std_logic; signal vsync : std_logic;
begin begin
ws2812b_controller_inst : entity design.ws2812b_controller ws2812b_controller_inst : entity ws2812b.ws2812b_controller
generic map( generic map(
length => length, length => length,
f_clk => 100000000) f_clk => 100000000)

View File

@ -13,8 +13,8 @@ library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;
library design; library ws2812b;
use design.all; use ws2812b.all;
entity bench_ws2812b_phy is entity bench_ws2812b_phy is
end entity bench_ws2812b_phy; end entity bench_ws2812b_phy;
@ -39,7 +39,7 @@ begin
wait for period / 2; wait for period / 2;
end process clock_driver; end process clock_driver;
ws2812b_phy_inst : entity design.ws2812b_phy ws2812b_phy_inst : entity ws2812b.ws2812b_phy
generic map( generic map(
f_clk => 100000000 f_clk => 100000000
) )

View File

@ -15,6 +15,9 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;
use ieee.math_real.all; use ieee.math_real.all;
library ws2812b;
use ws2812b.all;
entity demo_rainbow is entity demo_rainbow is
port( port(
clk : in std_logic; clk : in std_logic;
@ -62,14 +65,13 @@ architecture RTL of demo_rainbow is
signal color_transition_start : color_transition_t; signal color_transition_start : color_transition_t;
signal pixCount : integer range 0 to LENGTH - 1; signal pixCount : integer range 0 to LENGTH - 1;
signal render_active : std_logic; signal render_active : std_logic;
signal render_stb : std_logic;
signal systick : std_logic; signal systick : std_logic;
begin begin
rst <= not rst_hw; rst <= not rst_hw;
-- WS2812B PHY -- WS2812B PHY
ws2812b_phy_inst : entity work.ws2812b_phy ws2812b_phy_inst : entity ws2812b.ws2812b_phy
generic map( generic map(
f_clk => F_CLK f_clk => F_CLK
) )
@ -85,23 +87,23 @@ begin
); );
-- Gamma correction -- Gamma correction
ws2812b_gamma_red_inst : entity work.ws2812b_gamma ws2812b_gamma_red_inst : entity ws2812b.ws2812b_gamma
port map( port map(
pixelData_in => std_logic_vector(pixData_red), pixelData_in => std_logic_vector(pixData_red),
pixelData_out => pixData_red_corr pixelData_out => pixData_red_corr
); );
ws2812b_gamma_green_inst : entity work.ws2812b_gamma ws2812b_gamma_green_inst : entity ws2812b.ws2812b_gamma
port map( port map(
pixelData_in => std_logic_vector(pixData_green), pixelData_in => std_logic_vector(pixData_green),
pixelData_out => pixData_green_corr pixelData_out => pixData_green_corr
); );
ws2812b_gamma_blue_inst : entity work.ws2812b_gamma ws2812b_gamma_blue_inst : entity ws2812b.ws2812b_gamma
port map( port map(
pixelData_in => std_logic_vector(pixData_blue), pixelData_in => std_logic_vector(pixData_blue),
pixelData_out => pixData_blue_corr pixelData_out => pixData_blue_corr
); );
-- Timebase to advance the animation -- Timebase to advance the animation
systick_p : process(clk, rst) is systick_p : process(clk, rst) is

View File

@ -15,16 +15,19 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;
use ieee.math_real.all; use ieee.math_real.all;
entity top is library ws2812b;
use ws2812b.all;
entity demo_sram is
port( port(
clk : in std_logic; clk : in std_logic;
rst_hw : in std_logic; rst_hw : in std_logic;
btn_n : in std_logic; btn_n : in std_logic;
so : out std_logic so : out std_logic
); );
end entity top; end entity demo_sram;
architecture RTL of top is architecture RTL of demo_sram is
constant length : integer := 120; constant length : integer := 120;
signal rst : std_logic; signal rst : std_logic;
@ -39,12 +42,13 @@ architecture RTL of top is
signal render : std_logic; signal render : std_logic;
signal vsync : std_logic; signal vsync : std_logic;
signal done : std_logic; signal done : std_logic;
signal foo : std_logic_vector(1 downto 0); signal colIdx : std_logic_vector(1 downto 0);
begin begin
rst <= not rst_hw; rst <= not rst_hw;
foo <= addr(1 downto 0); colIdx <= addr(1 downto 0);
ws2812b_controller_inst : entity work.ws2812b_controller
ws2812b_controller_inst : entity ws2812b.ws2812b_controller
generic map( generic map(
length => length, length => length,
f_clk => 50000000 f_clk => 50000000
@ -84,20 +88,22 @@ begin
render <= '0'; render <= '0';
if done = '0' then if done = '0' then
addr <= std_logic_vector(unsigned(addr) + 1); addr <= std_logic_vector(unsigned(addr) + 1);
-- If we wrote the entire strip, render the data!
if to_integer(unsigned(addr)) = length - 1 then if to_integer(unsigned(addr)) = length - 1 then
done <= '1'; done <= '1';
render <= '1'; render <= '1';
end if; end if;
if unsigned(foo) = colRot then if unsigned(colIdx) = colRot then
data_red <= (others => '1'); data_red <= (others => '1');
data_green <= (others => '0'); data_green <= (others => '0');
data_blue <= (others => '0'); data_blue <= (others => '0');
elsif unsigned(foo) = colRot + 1 then elsif unsigned(colIdx) = colRot + 1 then
data_red <= (others => '0'); data_red <= (others => '0');
data_green <= (others => '1'); data_green <= (others => '1');
data_blue <= (others => '0'); data_blue <= (others => '0');
elsif unsigned(foo) = colRot + 2 then elsif unsigned(colIdx) = colRot + 2 then
data_red <= (others => '0'); data_red <= (others => '0');
data_green <= (others => '0'); data_green <= (others => '0');
data_blue <= (others => '1'); data_blue <= (others => '1');