ws2812b-spi/top.vhd

185 lines
5.0 KiB
VHDL

-------------------------------------------------------------------------------
-- Title : Top Level of SPI => WS2812b
-- Project :
-------------------------------------------------------------------------------
-- File : top.vhd
-- Author : Mario Hüttel <mario.huettel@gmx.net>
-- Company :
-- Created : 2018-04-15
-- Last update: 2018-04-15
-- Platform :
-- Standard : VHDL'93/02
-------------------------------------------------------------------------------
-- Description:
-------------------------------------------------------------------------------
-- Copyright (c) 2018 GPLv2
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity top is
port (
clk : in std_logic;
rst_hw : in std_logic;
sck : in std_logic;
mosi : in std_logic;
cs : in std_logic;
ready : out std_logic; -- goes high when at least 10 LEDs can
-- be accepted
ws_out : out std_logic);
end entity top;
architecture RTL of top is
constant FIFO_DEPTH : positive := 20;
signal rst : std_logic;
signal fifo_empty : std_logic;
signal fifo_full : std_logic;
signal fifo_wr : std_logic;
signal fifo_rd : std_logic;
signal fifo_i : std_logic_vector(23 downto 0);
signal fifo_o : std_logic_vector(23 downto 0);
signal spi_dat_o : std_logic_vector(23 downto 0);
signal spi_dat_o_strb : std_logic;
signal fifo_fill_cnt : integer range 0 to FIFO_DEPTH;
signal ws_strb : std_logic;
signal red : unsigned(7 downto 0);
signal green : unsigned(7 downto 0);
signal blue : unsigned(7 downto 0);
signal ws_busy : std_logic;
signal fifo_inc : std_logic;
signal fifo_dec : std_logic;
signal fifo_data_req : std_logic;
signal fifo_data_avail : std_logic;
begin -- architecture RTL
reset_sync : process (clk, rst_hw) is
begin -- process reset_sync
if rst_hw = '1' then -- asynchronous reset (active high)
rst <= '1';
elsif rising_edge(clk) then -- rising clock edge
rst <= rst_hw;
end if;
end process reset_sync;
STD_FIFO_1 : entity work.STD_FIFO
generic map (
DATA_WIDTH => 24,
FIFO_DEPTH => FIFO_DEPTH) -- 20 LEDs FIFO depth
port map (
CLK => clk,
RST => rst,
WriteEn => fifo_wr,
DataIn => fifo_i,
ReadEn => fifo_rd,
DataOut => fifo_o,
Empty => fifo_empty,
Full => fifo_full);
spi_slave_1 : entity work.spi_slave
generic map (
DAT_WIDTH => 24)
port map (
clk => clk,
rst => rst,
cs => cs,
sck => sck,
miso => open,
mosi => mosi,
dat_o => spi_dat_o,
dat_i => (others => '0'),
dat_o_strb => spi_dat_o_strb,
dat_i_ack => open);
ws2812bphy_1 : 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,
green => green,
blue => blue);
fill_cnt_proc : process (clk, rst) is
variable inc_dec : std_logic_vector(1 downto 0);
begin -- process fill_cnt_proc
if rst = '1' then -- asynchronous reset (active high)
fifo_fill_cnt <= 0;
elsif rising_edge(clk) then -- rising clock edge
inc_dec := fifo_inc & fifo_dec;
if inc_dec = "10" then
fifo_fill_cnt <= fifo_fill_cnt + 1;
elsif inc_dec = "01" then
fifo_fill_cnt <= fifo_fill_cnt -1;
end if;
end if;
end process fill_cnt_proc;
ready <= '1' when fifo_fill_cnt <= 10 else '0';
spi2fifo_proc : process (clk, rst) is
begin -- process spi2fifo_proc
if rst = '1' then -- asynchronous reset (active high)
fifo_inc <= '0';
fifo_wr <= '0';
fifo_i <= (others => '0');
elsif rising_edge(clk) then -- rising clock edge
fifo_wr <= '0';
fifo_inc <= '0';
if spi_dat_o_strb = '1' and fifo_full /= '1' then
fifo_wr <= '1';
fifo_i <= spi_dat_o;
fifo_inc <= '1';
end if;
end if;
end process spi2fifo_proc;
fifo2ws_proc : process (clk, rst) is
begin -- process fifo2ws_proc
if rst = '1' then -- asynchronous reset (active high)
fifo_rd <= '0';
fifo_dec <= '0';
ws_strb <= '0';
red <= x"00";
blue <= x"00";
green <= x"00";
fifo_data_req <= '0';
fifo_data_avail <= '0';
elsif rising_edge(clk) then -- rising clock edge
fifo_rd <= '0';
ws_strb <= '0';
fifo_dec <= '0';
-- TODO: Write following lines as statemachine
if fifo_empty = '0' and fifo_data_req = '0' and fifo_data_avail = '0' then
fifo_data_req <= '1';
fifo_rd <= '1';
fifo_dec <= '1';
end if;
if fifo_data_req = '1' then
fifo_data_avail <= '1';
fifo_data_req <= '0';
end if;
if ws_busy = '0' and ws_strb = '0' and fifo_data_avail = '1' then
red <= unsigned(fifo_o(23 downto 16));
green <= unsigned(fifo_o(15 downto 8));
blue <= unsigned(fifo_o(7 downto 0));
ws_strb <= '1';
fifo_data_avail <= '0';
end if;
end if;
end process fifo2ws_proc;
end architecture RTL;