Initial commit

This commit is contained in:
Markus Koch 2019-02-20 17:44:15 +01:00
commit c94765003f
17 changed files with 923 additions and 0 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "ws2812b-vhdl"]
path = ws2812b-vhdl
url = git@github.com:cclassic/ws2812b-vhdl.git

9
.library_mapping.xml Normal file
View File

@ -0,0 +1,9 @@
<?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="design" Library="design"/>
<Mappings Location="Common Libraries/IEEE" Library="ieee"/>
<Mappings Location="" Library="not mapped"/>
<Mappings Location="Common Libraries/STD" Library="std"/>
<Mappings Location="ws2812b-vhdl/ws2812b" Library="ws2812b"/>
</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>ws2812-wall</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 @@
<project>=93

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

105
bench/bench_top.vhd Normal file
View File

@ -0,0 +1,105 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library design;
use design.all;
entity bench_top is
end entity bench_top;
architecture RTL of bench_top is
constant SIM_SPEEDUP : natural := 2;
signal clk_hw : std_logic;
signal rst_hw : std_logic;
signal ws2812_out : std_logic_vector(4 - 1 downto 0);
signal uart_tx : std_logic;
begin
top_inst : entity design.top
generic map(
f_clk => 24_000_000 / SIM_SPEEDUP,
ROWS => 4,
COLUMNS => 4
)
port map(
clk_hw => clk_hw,
rst_hw => rst_hw,
ws2812_out => ws2812_out,
uart_rx => uart_tx
);
clock_driver : process
constant period : time := (1 sec / 24_000_000);
begin
clk_hw <= '0';
wait for period / 2;
clk_hw <= '1';
wait for period / 2;
end process clock_driver;
test : process is
constant UART_BITTIME : time := 1 sec / 115200 / SIM_SPEEDUP;
procedure uart_transmit(data : in std_logic_vector(7 downto 0)) is
begin
uart_tx <= '0';
wait for UART_BITTIME;
for i in 0 to 7 loop
uart_tx <= data(i);
wait for UART_BITTIME;
end loop;
uart_tx <= '1';
wait for UART_BITTIME;
end procedure uart_transmit;
begin
rst_hw <= '0';
uart_tx <= '1';
wait until clk_hw = '1';
wait until clk_hw = '1';
rst_hw <= '1';
wait until clk_hw = '1';
wait for UART_BITTIME * 13;
wait until clk_hw = '1';
-- Write LED data (cmd 0x00)
uart_transmit(x"00");
uart_transmit(x"00"); -- Start address 0
uart_transmit(x"00");
uart_transmit(x"00"); -- Write two LEDs
uart_transmit(x"02");
uart_transmit(x"01"); -- First LED
uart_transmit(x"02");
uart_transmit(x"03");
uart_transmit(x"11");
uart_transmit(x"12");
uart_transmit(x"13");
uart_transmit(x"21");
uart_transmit(x"22");
uart_transmit(x"23");
uart_transmit(x"31");
uart_transmit(x"32");
uart_transmit(x"33");
uart_transmit(x"a1"); -- Second LED
uart_transmit(x"a2");
uart_transmit(x"a3");
uart_transmit(x"b1");
uart_transmit(x"b2");
uart_transmit(x"b3");
uart_transmit(x"c1");
uart_transmit(x"c2");
uart_transmit(x"c3");
uart_transmit(x"d1");
uart_transmit(x"d2");
uart_transmit(x"d3");
-- Render (cmd 0x01)
uart_transmit(x"01");
wait;
end process test;
end architecture RTL;

80
bench_top.gtkw Normal file
View File

@ -0,0 +1,80 @@
[*]
[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI
[*] Sun Jan 21 17:51:06 2018
[*]
[dumpfile] "/tmp/SigasiCompileCache7616390032050217445/ws2812-wall/mentor/bench_top.ghw"
[dumpfile_mtime] "Sun Jan 21 17:50:57 2018"
[dumpfile_size] 5545813
[savefile] "/home/markus/workspaceSigasi/ws2812-wall/bench_top.gtkw"
[timestart] 1288000000000
[size] 1920 1043
[pos] -1 -1
*-34.891136 1372229144711 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] top.
[treeopen] top.bench_top.
[treeopen] top.bench_top.top_inst.
[treeopen] top.bench_top.top_inst.uart_rx_inst.
[sst_width] 267
[signals_width] 261
[sst_expanded] 1
[sst_vpaned_height] 298
@420
top.bench_top.top_inst.renderer_state
@28
top.bench_top.top_inst.render_stb
top.bench_top.top_inst.rst
top.bench_top.top_inst.clk
top.bench_top.top_inst.rst_hw
top.bench_top.top_inst.clk_hw
@c00022
#{top.bench_top.ws2812_out[6:0]} top.bench_top.ws2812_out[3] top.bench_top.ws2812_out[2] top.bench_top.ws2812_out[1] top.bench_top.ws2812_out[0]
@28
top.bench_top.ws2812_out[3]
top.bench_top.ws2812_out[2]
top.bench_top.ws2812_out[1]
top.bench_top.ws2812_out[0]
@1401200
-group_end
@22
#{top.bench_top.top_inst.renderer_data[167:0]} top.bench_top.top_inst.renderer_data[95] top.bench_top.top_inst.renderer_data[94] top.bench_top.top_inst.renderer_data[93] top.bench_top.top_inst.renderer_data[92] top.bench_top.top_inst.renderer_data[91] top.bench_top.top_inst.renderer_data[90] top.bench_top.top_inst.renderer_data[89] top.bench_top.top_inst.renderer_data[88] top.bench_top.top_inst.renderer_data[87] top.bench_top.top_inst.renderer_data[86] top.bench_top.top_inst.renderer_data[85] top.bench_top.top_inst.renderer_data[84] top.bench_top.top_inst.renderer_data[83] top.bench_top.top_inst.renderer_data[82] top.bench_top.top_inst.renderer_data[81] top.bench_top.top_inst.renderer_data[80] top.bench_top.top_inst.renderer_data[79] top.bench_top.top_inst.renderer_data[78] top.bench_top.top_inst.renderer_data[77] top.bench_top.top_inst.renderer_data[76] top.bench_top.top_inst.renderer_data[75] top.bench_top.top_inst.renderer_data[74] top.bench_top.top_inst.renderer_data[73] top.bench_top.top_inst.renderer_data[72] top.bench_top.top_inst.renderer_data[71] top.bench_top.top_inst.renderer_data[70] top.bench_top.top_inst.renderer_data[69] top.bench_top.top_inst.renderer_data[68] top.bench_top.top_inst.renderer_data[67] top.bench_top.top_inst.renderer_data[66] top.bench_top.top_inst.renderer_data[65] top.bench_top.top_inst.renderer_data[64] top.bench_top.top_inst.renderer_data[63] top.bench_top.top_inst.renderer_data[62] top.bench_top.top_inst.renderer_data[61] top.bench_top.top_inst.renderer_data[60] top.bench_top.top_inst.renderer_data[59] top.bench_top.top_inst.renderer_data[58] top.bench_top.top_inst.renderer_data[57] top.bench_top.top_inst.renderer_data[56] top.bench_top.top_inst.renderer_data[55] top.bench_top.top_inst.renderer_data[54] top.bench_top.top_inst.renderer_data[53] top.bench_top.top_inst.renderer_data[52] top.bench_top.top_inst.renderer_data[51] top.bench_top.top_inst.renderer_data[50] top.bench_top.top_inst.renderer_data[49] top.bench_top.top_inst.renderer_data[48] top.bench_top.top_inst.renderer_data[47] top.bench_top.top_inst.renderer_data[46] top.bench_top.top_inst.renderer_data[45] top.bench_top.top_inst.renderer_data[44] top.bench_top.top_inst.renderer_data[43] top.bench_top.top_inst.renderer_data[42] top.bench_top.top_inst.renderer_data[41] top.bench_top.top_inst.renderer_data[40] top.bench_top.top_inst.renderer_data[39] top.bench_top.top_inst.renderer_data[38] top.bench_top.top_inst.renderer_data[37] top.bench_top.top_inst.renderer_data[36] top.bench_top.top_inst.renderer_data[35] top.bench_top.top_inst.renderer_data[34] top.bench_top.top_inst.renderer_data[33] top.bench_top.top_inst.renderer_data[32] top.bench_top.top_inst.renderer_data[31] top.bench_top.top_inst.renderer_data[30] top.bench_top.top_inst.renderer_data[29] top.bench_top.top_inst.renderer_data[28] top.bench_top.top_inst.renderer_data[27] top.bench_top.top_inst.renderer_data[26] top.bench_top.top_inst.renderer_data[25] top.bench_top.top_inst.renderer_data[24] top.bench_top.top_inst.renderer_data[23] top.bench_top.top_inst.renderer_data[22] top.bench_top.top_inst.renderer_data[21] top.bench_top.top_inst.renderer_data[20] top.bench_top.top_inst.renderer_data[19] top.bench_top.top_inst.renderer_data[18] top.bench_top.top_inst.renderer_data[17] top.bench_top.top_inst.renderer_data[16] top.bench_top.top_inst.renderer_data[15] top.bench_top.top_inst.renderer_data[14] top.bench_top.top_inst.renderer_data[13] top.bench_top.top_inst.renderer_data[12] top.bench_top.top_inst.renderer_data[11] top.bench_top.top_inst.renderer_data[10] top.bench_top.top_inst.renderer_data[9] top.bench_top.top_inst.renderer_data[8] top.bench_top.top_inst.renderer_data[7] top.bench_top.top_inst.renderer_data[6] top.bench_top.top_inst.renderer_data[5] top.bench_top.top_inst.renderer_data[4] top.bench_top.top_inst.renderer_data[3] top.bench_top.top_inst.renderer_data[2] top.bench_top.top_inst.renderer_data[1] top.bench_top.top_inst.renderer_data[0]
@800022
#{top.bench_top.top_inst.pixdata_next[6:0]} top.bench_top.top_inst.pixdata_next[3] top.bench_top.top_inst.pixdata_next[2] top.bench_top.top_inst.pixdata_next[1] top.bench_top.top_inst.pixdata_next[0]
@28
top.bench_top.top_inst.pixdata_next[3]
top.bench_top.top_inst.pixdata_next[2]
top.bench_top.top_inst.pixdata_next[1]
top.bench_top.top_inst.pixdata_next[0]
@1001200
-group_end
@800022
#{top.bench_top.top_inst.pixdata_valid[6:0]} top.bench_top.top_inst.pixdata_valid[3] top.bench_top.top_inst.pixdata_valid[2] top.bench_top.top_inst.pixdata_valid[1] top.bench_top.top_inst.pixdata_valid[0]
@28
top.bench_top.top_inst.pixdata_valid[3]
top.bench_top.top_inst.pixdata_valid[2]
top.bench_top.top_inst.pixdata_valid[1]
top.bench_top.top_inst.pixdata_valid[0]
@1001200
-group_end
@420
top.bench_top.top_inst.controller_state
@28
top.bench_top.top_inst.uart_rx
@420
top.bench_top.top_inst.uart_rx_inst.state
top.bench_top.top_inst.uart_rx_inst.bitcounter
@22
#{top.bench_top.top_inst.uart_rx_inst.clkdivider[15:0]} top.bench_top.top_inst.uart_rx_inst.clkdivider[15] top.bench_top.top_inst.uart_rx_inst.clkdivider[14] top.bench_top.top_inst.uart_rx_inst.clkdivider[13] top.bench_top.top_inst.uart_rx_inst.clkdivider[12] top.bench_top.top_inst.uart_rx_inst.clkdivider[11] top.bench_top.top_inst.uart_rx_inst.clkdivider[10] top.bench_top.top_inst.uart_rx_inst.clkdivider[9] top.bench_top.top_inst.uart_rx_inst.clkdivider[8] top.bench_top.top_inst.uart_rx_inst.clkdivider[7] top.bench_top.top_inst.uart_rx_inst.clkdivider[6] top.bench_top.top_inst.uart_rx_inst.clkdivider[5] top.bench_top.top_inst.uart_rx_inst.clkdivider[4] top.bench_top.top_inst.uart_rx_inst.clkdivider[3] top.bench_top.top_inst.uart_rx_inst.clkdivider[2] top.bench_top.top_inst.uart_rx_inst.clkdivider[1] top.bench_top.top_inst.uart_rx_inst.clkdivider[0]
@28
top.bench_top.top_inst.uart_rx_stb
@22
#{top.bench_top.top_inst.uart_rx_data[7:0]} top.bench_top.top_inst.uart_rx_data[7] top.bench_top.top_inst.uart_rx_data[6] top.bench_top.top_inst.uart_rx_data[5] top.bench_top.top_inst.uart_rx_data[4] top.bench_top.top_inst.uart_rx_data[3] top.bench_top.top_inst.uart_rx_data[2] top.bench_top.top_inst.uart_rx_data[1] top.bench_top.top_inst.uart_rx_data[0]
@29
top.bench_top.top_inst.controller_ram_we
@420
top.bench_top.top_inst.byte_cnt
@22
#{top.bench_top.top_inst.sr[167:0]} top.bench_top.top_inst.sr[95] top.bench_top.top_inst.sr[94] top.bench_top.top_inst.sr[93] top.bench_top.top_inst.sr[92] top.bench_top.top_inst.sr[91] top.bench_top.top_inst.sr[90] top.bench_top.top_inst.sr[89] top.bench_top.top_inst.sr[88] top.bench_top.top_inst.sr[87] top.bench_top.top_inst.sr[86] top.bench_top.top_inst.sr[85] top.bench_top.top_inst.sr[84] top.bench_top.top_inst.sr[83] top.bench_top.top_inst.sr[82] top.bench_top.top_inst.sr[81] top.bench_top.top_inst.sr[80] top.bench_top.top_inst.sr[79] top.bench_top.top_inst.sr[78] top.bench_top.top_inst.sr[77] top.bench_top.top_inst.sr[76] top.bench_top.top_inst.sr[75] top.bench_top.top_inst.sr[74] top.bench_top.top_inst.sr[73] top.bench_top.top_inst.sr[72] top.bench_top.top_inst.sr[71] top.bench_top.top_inst.sr[70] top.bench_top.top_inst.sr[69] top.bench_top.top_inst.sr[68] top.bench_top.top_inst.sr[67] top.bench_top.top_inst.sr[66] top.bench_top.top_inst.sr[65] top.bench_top.top_inst.sr[64] top.bench_top.top_inst.sr[63] top.bench_top.top_inst.sr[62] top.bench_top.top_inst.sr[61] top.bench_top.top_inst.sr[60] top.bench_top.top_inst.sr[59] top.bench_top.top_inst.sr[58] top.bench_top.top_inst.sr[57] top.bench_top.top_inst.sr[56] top.bench_top.top_inst.sr[55] top.bench_top.top_inst.sr[54] top.bench_top.top_inst.sr[53] top.bench_top.top_inst.sr[52] top.bench_top.top_inst.sr[51] top.bench_top.top_inst.sr[50] top.bench_top.top_inst.sr[49] top.bench_top.top_inst.sr[48] top.bench_top.top_inst.sr[47] top.bench_top.top_inst.sr[46] top.bench_top.top_inst.sr[45] top.bench_top.top_inst.sr[44] top.bench_top.top_inst.sr[43] top.bench_top.top_inst.sr[42] top.bench_top.top_inst.sr[41] top.bench_top.top_inst.sr[40] top.bench_top.top_inst.sr[39] top.bench_top.top_inst.sr[38] top.bench_top.top_inst.sr[37] top.bench_top.top_inst.sr[36] top.bench_top.top_inst.sr[35] top.bench_top.top_inst.sr[34] top.bench_top.top_inst.sr[33] top.bench_top.top_inst.sr[32] top.bench_top.top_inst.sr[31] top.bench_top.top_inst.sr[30] top.bench_top.top_inst.sr[29] top.bench_top.top_inst.sr[28] top.bench_top.top_inst.sr[27] top.bench_top.top_inst.sr[26] top.bench_top.top_inst.sr[25] top.bench_top.top_inst.sr[24] top.bench_top.top_inst.sr[23] top.bench_top.top_inst.sr[22] top.bench_top.top_inst.sr[21] top.bench_top.top_inst.sr[20] top.bench_top.top_inst.sr[19] top.bench_top.top_inst.sr[18] top.bench_top.top_inst.sr[17] top.bench_top.top_inst.sr[16] top.bench_top.top_inst.sr[15] top.bench_top.top_inst.sr[14] top.bench_top.top_inst.sr[13] top.bench_top.top_inst.sr[12] top.bench_top.top_inst.sr[11] top.bench_top.top_inst.sr[10] top.bench_top.top_inst.sr[9] top.bench_top.top_inst.sr[8] top.bench_top.top_inst.sr[7] top.bench_top.top_inst.sr[6] top.bench_top.top_inst.sr[5] top.bench_top.top_inst.sr[4] top.bench_top.top_inst.sr[3] top.bench_top.top_inst.sr[2] top.bench_top.top_inst.sr[1] top.bench_top.top_inst.sr[0]
@28
top.bench_top.top_inst.controller_ram_addr[0]
[pattern_trace] 1
[pattern_trace] 0

41
design/edgeDetector.vhd Normal file
View File

@ -0,0 +1,41 @@
-- -------------------------------------------------------------------------- --
-- edgeDetector.vhd: Basic edge detector
--
-- Copyright (C) 2017 Markus Koch <markus@notsyncing.net>
--
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at http://mozilla.org/MPL/2.0/.
-- -------------------------------------------------------------------------- --
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity edgeDetector is
port(
clk : in std_logic;
rst : in std_logic;
sig : in std_logic;
risingEdge : out std_logic;
fallingEdge : out std_logic;
anyEdge : out std_logic
);
end entity edgeDetector;
architecture RTL of edgeDetector is
signal temp : std_logic_vector(1 downto 0);
begin
shiftomat : process(rst, clk) is
begin
if rst = '1' then
temp <= "00";
elsif rising_edge(clk) then
temp <= temp(0) & sig;
end if;
end process shiftomat;
risingEdge <= '1' when (temp = "01") else '0';
fallingEdge <= '1' when (temp = "10") else '0';
anyEdge <= '1' when (temp = "01" or temp = "10") else '0';
end architecture RTL;

36
design/ram.vhd Normal file
View File

@ -0,0 +1,36 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ram is
generic(
WIDTH : natural := 8;
DEPTH : natural := 4
);
port(
clk : in std_logic;
addr_a : in std_logic_vector(DEPTH - 1 downto 0);
data_out_a : out std_logic_vector(WIDTH - 1 downto 0);
data_in_a : in std_logic_vector(WIDTH - 1 downto 0);
we_a : in std_logic;
addr_b : in std_logic_vector(DEPTH - 1 downto 0);
data_out_b : out std_logic_vector(WIDTH - 1 downto 0)
);
end entity ram;
architecture rtl of ram is
type memory_t is array (0 to integer(2**DEPTH) - 1) of std_logic_vector(WIDTH - 1 downto 0);
signal memory : memory_t;
begin
ram_p : process(clk) is
begin
if (rising_edge(clk)) then
data_out_a <= memory(to_integer(unsigned(addr_a)));
if (we_a = '1') then
memory(to_integer(unsigned(addr_a))) <= data_in_a;
end if;
data_out_b <= memory(to_integer(unsigned(addr_b)));
end if;
end process ram_p;
end architecture rtl;

31
design/synchronizer.vhd Normal file
View File

@ -0,0 +1,31 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity synchronizer is
generic(COUNT : integer := 1);
port(
clk : in std_logic;
rst : in std_logic;
dIn : in std_logic_vector(COUNT - 1 downto 0);
dOut : out std_logic_vector(COUNT - 1 downto 0)
);
end entity synchronizer;
architecture RTL of synchronizer is
signal temp : std_logic_vector(COUNT - 1 downto 0);
begin
synch : process(rst, clk) is
begin
for i in 0 to COUNT - 1 loop
if rst = '1' then
temp(i) <= '0';
dOut(i) <= '0';
elsif rising_edge(clk) then
temp(i) <= dIn(i);
dOut(i) <= temp(i);
end if;
end loop;
end process synch;
end architecture RTL;

252
design/top.vhd Normal file
View File

@ -0,0 +1,252 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
library ws2812b;
use ws2812b.all;
use work.top_pkg.all;
entity top is
generic(
f_clk : natural := 24_000_000;
ROWS : natural := 7;
COLUMNS : natural := 64
);
port(
clk_hw : in std_logic; -- HW clock
rst_hw : in std_logic; -- Hardware reset (active low)
uart_rx : in std_logic; -- UART RX pin
ws2812_out : out std_logic_vector(ROWS - 1 downto 0) -- WS2812B data line
);
end entity top;
architecture RTL of top is
constant RAM_WIDTH : natural := 8 * 3 * ROWS;
constant RAM_DEPTH : natural := integer(ceil(log2(real(COLUMNS))));
constant UART_CKDIV : std_logic_vector(15 downto 0) := std_logic_vector(to_unsigned(f_clk / 115200, 16));
signal clk : std_logic;
signal rst : std_logic;
signal pixData_red : color_vector(ROWS - 1 downto 0);
signal pixData_green : color_vector(ROWS - 1 downto 0);
signal pixData_blue : color_vector(ROWS - 1 downto 0);
signal pixData_valid : std_logic_vector(ROWS - 1 downto 0);
signal pixData_next : std_logic_vector(ROWS - 1 downto 0);
signal uart_rx_data : std_logic_vector(7 downto 0);
signal uart_rx_stb : std_logic;
signal uart_rx_error : std_logic;
type controller_state_t is (IDLE, ADDR, LENGTH, DATA);
signal controller_state : controller_state_t;
signal controller_ram_addr : std_logic_vector(RAM_DEPTH - 1 downto 0);
signal controller_ram_din : std_logic_vector(RAM_WIDTH - 1 downto 0);
signal controller_ram_dout : std_logic_vector(RAM_WIDTH - 1 downto 0);
signal controller_ram_we : std_logic;
signal sr : std_logic_vector(controller_ram_din'range);
signal byte_cnt : integer range 0 to ROWS * 3 - 1;
signal leds_left : integer range 0 to 2**RAM_DEPTH - 1;
signal render_stb : std_logic;
type renderer_state_t is (IDLE, RENDER, LOCK);
signal renderer_state : renderer_state_t;
signal renderer_addr : std_logic_vector(RAM_DEPTH - 1 downto 0);
signal renderer_data : std_logic_vector(RAM_WIDTH - 1 downto 0);
begin
clk <= clk_hw;
reset_gen : process(clk, rst_hw) is
variable tmp : std_logic;
begin
if (rst_hw = '0') then
tmp := '1';
rst <= '1';
elsif (rising_edge(clk)) then
rst <= tmp;
tmp := '0';
end if;
end process reset_gen;
ws2812b_phys : for i in 0 to ROWS - 1 generate
ws2812b_phy_inst : entity ws2812b.ws2812b_phy
generic map(
f_clk => f_clk
)
port map(
clk => clk,
rst => rst,
so => ws2812_out(i),
pixData_red => pixData_red(i),
pixData_green => pixData_green(i),
pixData_blue => pixData_blue(i),
pixData_valid => pixData_valid(i),
pixData_next => pixData_next(i)
);
end generate ws2812b_phys;
-- Upon receiving ```renderer_stb```, it sends the data in memory out to the LEDs
renderer : process(clk, rst) is
procedure set_all_valid(state : std_logic) is
begin
for i in 0 to ROWS - 1 loop
pixData_valid(i) <= state;
end loop;
end procedure set_all_valid;
begin
if (rst = '1') then
renderer_state <= IDLE;
renderer_addr <= (others => '0');
set_all_valid('0');
elsif (rising_edge(clk)) then
case renderer_state is
when IDLE =>
set_all_valid('0');
renderer_addr <= (others => '0'); -- Note: We need to have been in this state for at least one cycle
if (render_stb = '1') then
set_all_valid('1');
renderer_state <= RENDER;
end if;
when RENDER =>
if (pixData_next(0) = '1') then -- TODO: This expects all PHYs to run synchronously
renderer_addr <= std_logic_vector(unsigned(renderer_addr) + 1);
if (unsigned(renderer_addr) = (COLUMNS - 1)) then
set_all_valid('0');
renderer_state <= LOCK;
end if;
end if;
when LOCK =>
set_all_valid('0');
if (pixData_next(0) = '1') then
renderer_state <= IDLE;
end if;
end case;
end if;
end process renderer;
pixData_connections : for i in 0 to ROWS - 1 generate
pixData_red(i) <= renderer_data(i * 24 + 7 downto i * 24);
pixData_green(i) <= renderer_data(i * 24 + 15 downto i * 24 + 8);
pixData_blue(i) <= renderer_data(i * 24 + 23 downto i * 24 + 16);
end generate pixData_connections;
ram_inst : entity work.ram
generic map(
WIDTH => RAM_WIDTH,
DEPTH => RAM_DEPTH
)
port map(
clk => clk,
addr_a => controller_ram_addr,
data_out_a => controller_ram_dout,
data_in_a => controller_ram_din,
we_a => controller_ram_we,
addr_b => renderer_addr,
data_out_b => renderer_data
);
controller : process(clk, rst) is
variable sr_v : std_logic_vector(sr'range);
begin
if (rst = '1') then
sr <= (others => '0');
controller_state <= IDLE;
byte_cnt <= 0;
render_stb <= '0';
controller_ram_addr <= (others => '0');
controller_ram_we <= '0';
elsif (rising_edge(clk)) then
render_stb <= '0';
controller_ram_we <= '0';
if (uart_rx_stb = '1') then
sr_v := sr(sr'high - uart_rx_data'length downto sr'low) & uart_rx_data;
sr <= sr_v;
end if;
case controller_state is
when IDLE =>
byte_cnt <= 0;
if (uart_rx_stb = '1') then
if (uart_rx_data = x"00") then
controller_state <= ADDR;
elsif (uart_rx_data = x"01") then
render_stb <= '1';
controller_state <= IDLE;
end if;
end if;
when ADDR =>
if (uart_rx_stb = '1') then
if (byte_cnt = 1) then
controller_ram_addr <= std_logic_vector(to_unsigned(to_integer(unsigned(sr_v(15 downto 0)) * 3), controller_ram_addr'length));
controller_state <= LENGTH;
byte_cnt <= 0;
else
byte_cnt <= byte_cnt + 1;
end if;
end if;
when LENGTH =>
if (uart_rx_stb = '1') then
if (byte_cnt = 1) then
leds_left <= to_integer(unsigned(sr_v(15 downto 0))) - 1;
controller_state <= DATA;
byte_cnt <= 0;
else
byte_cnt <= byte_cnt + 1;
end if;
end if;
when DATA =>
if (controller_ram_we = '1') then
controller_ram_addr <= std_logic_vector(unsigned(controller_ram_addr) + 1);
end if;
if (uart_rx_stb = '1') then
if (byte_cnt = ROWS * 3 - 1) then
byte_cnt <= 0;
controller_ram_we <= '1';
if (leds_left = 0) then
controller_state <= IDLE;
else
leds_left <= leds_left - 1;
end if;
else
byte_cnt <= byte_cnt + 1;
end if;
end if;
end case;
end if;
end process controller;
controller_ram_din <= sr;
uart_rx_inst : entity work.uart_rx
port map(
clk => clk,
rst => rst,
data => uart_rx_data,
byte_ready => uart_rx_stb,
error => uart_rx_error,
ckDiv => UART_CKDIV,
parityEnable => '0',
parityOdd => '0',
twoStopBits => '0',
rx => uart_rx
);
end architecture RTL;

6
design/top_pkg.vhd Normal file
View File

@ -0,0 +1,6 @@
library ieee;
use ieee.std_logic_1164.all;
package top_pkg is
type color_vector is array(natural range <>) of std_logic_vector(7 downto 0);
end package top_pkg;

161
design/uart_rx.vhd Normal file
View File

@ -0,0 +1,161 @@
-- -------------------------------------------------------------------------- --
-- uart_rx.vhd: Basic UART (rx)
--
-- Copyright (C) 2017 Markus Koch <markus@notsyncing.net>
--
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at http://mozilla.org/MPL/2.0/.
-- -------------------------------------------------------------------------- --
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity uart_rx is
port(
clk : in std_logic;
rst : in std_logic;
data : out std_logic_vector(7 downto 0);
byte_ready : out std_logic;
error : out std_logic;
ckDiv : in std_logic_vector(15 downto 0);
parityEnable : in std_logic;
parityOdd : in std_logic;
twoStopBits : in std_logic;
rx : in std_logic
);
end entity uart_rx;
architecture RTL of uart_rx is
constant SYNCH_COUNT : integer := 11; -- Min. 8
constant BITCOUNT : integer := 8;
type state_t is (SYNCH, IDLE, START, RECEIVE, PARITY, STOP);
signal state : state_t;
signal clkDivider : unsigned(15 downto 0);
signal bitCounter : integer range 0 to SYNCH_COUNT;
signal data_i : std_logic_vector(7 downto 0);
signal rx_edge : std_logic;
signal parity_calc : std_logic;
signal rx_i : std_logic;
begin
synchronizer_inst : entity work.synchronizer
generic map(
COUNT => 1
)
port map(
clk => clk,
rst => rst,
dIn(0) => rx,
dOut(0) => rx_i
);
edgeDetector_inst : entity work.edgeDetector
port map(clk => clk,
rst => rst,
sig => rx_i,
risingEdge => open,
fallingEdge => open,
anyEdge => rx_edge);
rxFSM : process(clk, rst, parityOdd, ckDiv) is
begin
if rst = '1' then
state <= SYNCH;
bitCounter <= SYNCH_COUNT;
clkDivider <= unsigned(ckDiv);
error <= '0';
parity_calc <= parityOdd;
data_i <= x"00";
data <= x"00";
byte_ready <= '0';
elsif rising_edge(clk) then
byte_ready <= '0';
error <= '0';
if (clkDivider = 0) then
clkDivider <= unsigned(ckDiv);
else
clkDivider <= clkDivider - 1;
end if;
case state is
when SYNCH => -- Wait for 11 consecutive ones
if (clkDivider = to_unsigned(0, clkDivider'length)) then
if rx_i = '1' then
if bitCounter = 0 then
state <= IDLE;
else
bitCounter <= bitcounter - 1;
end if;
else
bitCounter <= SYNCH_COUNT;
end if;
end if;
when IDLE => -- Detect transition for sync
if rx_i = '0' then
state <= START;
clkDivider <= unsigned('0' & ckDiv(15 downto 1)); -- cMax_half. After that we are in the middle of the start bit
parity_calc <= parityOdd;
end if;
when START =>
if (clkDivider = to_unsigned(0, clkDivider'length)) then
if rx_i = '0' then
state <= RECEIVE;
bitCounter <= 0;
else
report "uart_rx: START BIT ERROR" severity warning;
error <= '1';
state <= SYNCH;
end if;
end if;
when RECEIVE =>
if (clkDivider = to_unsigned(0, clkDivider'length)) then
data_i(bitCounter) <= rx_i;
if rx_i = '1' then
parity_calc <= not parity_calc;
end if;
if bitCounter = BITCOUNT - 1 then
bitCounter <= 0;
if parityEnable = '1' then
state <= PARITY;
else
state <= STOP;
end if;
else
bitCounter <= bitCounter + 1;
end if;
end if;
when PARITY =>
if (clkDivider = to_unsigned(0, clkDivider'length)) then
if parity_calc = rx_i then
state <= STOP;
else
state <= SYNCH;
error <= '1';
report "uart_rx: PARITY ERROR" severity warning;
end if;
end if;
when STOP =>
if (clkDivider = to_unsigned(0, clkDivider'length)) then
if (rx_i = '1') then
bitCounter <= bitCounter + 1;
if bitCounter = 1 or twoStopBits = '0' then
state <= IDLE;
data <= data_i;
byte_ready <= '1';
end if;
else
error <= '1';
state <= SYNCH;
report "uart_rx: STOP BIT ERROR" severity warning;
end if;
end if;
end case;
end if;
end process rxFSM;
end architecture RTL;

110
design/uart_tx.vhd Normal file
View File

@ -0,0 +1,110 @@
-- -------------------------------------------------------------------------- --
-- uart_tx.vhd: Basic UART (tx)
--
-- Copyright (C) 2017 Markus Koch <markus@notsyncing.net>
--
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at http://mozilla.org/MPL/2.0/.
-- -------------------------------------------------------------------------- --
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity uart_tx is
port(
clk : in std_logic;
rst : in std_logic;
data : in std_logic_vector(7 downto 0);
byte_ready : in std_logic;
busy : out std_logic;
ckDiv : in std_logic_vector(15 downto 0);
parityEnable : in std_logic;
parityOdd : in std_logic;
twoStopBits : in std_logic;
tx : out std_logic
);
end entity uart_tx;
architecture RTL of uart_tx is
type state_t is (IDLE, START, TRANSMIT, PARITY, STOP);
signal state : state_t;
signal clkDivider : unsigned(15 downto 0);
signal data_i : std_logic_vector(7 downto 0);
signal bitCounter : integer range 0 to 7;
signal parity_calc : std_logic;
begin
txFSM : process(clk, rst, ckDiv, parityOdd) is
begin
if rst = '1' then
data_i <= x"00";
state <= IDLE;
tx <= '1';
bitCounter <= 0;
busy <= '0';
clkDivider <= unsigned(ckDiv);
parity_calc <= parityOdd;
elsif rising_edge(clk) then
busy <= '1';
if (clkDivider = 0) then
clkDivider <= unsigned(ckDiv);
else
clkDivider <= clkDivider - 1;
end if;
case state is
when IDLE =>
busy <= '0';
tx <= '1';
if byte_ready = '1' then
data_i <= data;
state <= START;
clkDivider <= unsigned(ckDiv);
bitCounter <= 0;
parity_calc <= '0';
busy <= '1';
tx <= '1';
end if;
when START =>
tx <= '0';
state <= TRANSMIT;
when TRANSMIT =>
if (clkDivider = to_unsigned(0, clkDivider'length)) then
tx <= data_i(bitCounter);
if data_i(bitCounter) = '1' then
parity_calc <= not parity_calc;
end if;
if bitCounter = 7 then
bitCounter <= 0;
if parityEnable = '1' then
state <= PARITY;
else
state <= STOP;
end if;
else
bitCounter <= bitCounter + 1;
end if;
end if;
when PARITY =>
if (clkDivider = to_unsigned(0, clkDivider'length)) then
tx <= parity_calc;
state <= STOP;
end if;
when STOP =>
if (clkDivider = to_unsigned(0, clkDivider'length)) then
tx <= '1';
bitCounter <= bitCounter + 1;
if (bitCounter = 1 and twoStopBits = '0') or (bitCounter = 2 and twoStopBits = '1') then
state <= IDLE;
end if;
end if;
end case;
end if;
end process txFSM;
end architecture RTL;

35
diamond/ws2812wall.ldf Normal file
View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<BaliProject version="3.2" title="ws2812wall" device="LCMXO2-7000HC-5TG144C" default_implementation="impl1">
<Options/>
<Implementation title="impl1" dir="impl1" description="impl1" synthesis="lse" default_strategy="Strategy1">
<Options def_top="uart_tx" top="top"/>
<Source name="../design/edgeDetector.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../design/ram.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../design/synchronizer.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../design/top_pkg.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../design/top.vhd" type="VHDL" type_short="VHDL">
<Options top_module="top"/>
</Source>
<Source name="../design/uart_rx.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../design/uart_tx.vhd" type="VHDL" type_short="VHDL">
<Options/>
</Source>
<Source name="../ws2812b-vhdl/ws2812b/ws2812b_phy.vhd" type="VHDL" type_short="VHDL">
<Options lib="ws2812b"/>
</Source>
<Source name="ws2812wall.lpf" type="Logic Preference" type_short="LPF">
<Options/>
</Source>
</Implementation>
<Strategy name="Strategy1" file="ws2812wall1.sty"/>
</BaliProject>

2
diamond/ws2812wall.lpf Normal file
View File

@ -0,0 +1,2 @@
BLOCK RESETPATHS;
BLOCK ASYNCPATHS;

1
ws2812b-vhdl Submodule

@ -0,0 +1 @@
Subproject commit 6e5249641d014cbe0b3723ff22c1637231e351f7