LIBRARY IEEE; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; ENTITY neo_pixel IS PORT( clk : IN std_logic; dout : OUT std_logic; rstb : OUT STD_LOGIC; enb : OUT STD_LOGIC; web : OUT STD_LOGIC_VECTOR(3 DOWNTO 0); addrb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); dinb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); doutb : IN STD_LOGIC_VECTOR(31 DOWNTO 0) ); END ENTITY; ARCHITECTURE rtl OF neo_pixel IS TYPE FSM IS (idle,wait1,led,count,reset,addr_out,wait2,grab,wait_done,done_addr); CONSTANT done : std_logic_vector(25 DOWNTO 0) := "00000000000000000000000001"; --shows when shift reg empty CONSTANT zero : std_logic_vector(24 DOWNTO 0) := "1111111000000000000000000"; --waveform for a zero bit CONSTANT one : std_logic_vector(24 DOWNTO 0) := "1111111111111100000000000"; --waveform for a one bit CONSTANT numb_pixels : integer := 24; --number of bits in a pixel CONSTANT reset_duration : integer := 1000;--number cclocks in the reset period SIGNAL shift_reg : std_logic_vector(24 DOWNTO 0) := (OTHERS=>'0'); -- shift reg containing the output pixel waveform SIGNAL shift_dne : std_logic_vector(25 DOWNTO 0) := (OTHERS=>'0'); -- shift reg for timing the output shift reg for next load SIGNAL current_state : fsm := idle; --fsm to control the pixel beign output SIGNAL prev_state : fsm := idle; --previous state SIGNAL load_shr : std_logic :='0'; --loads the shr with the next pixel SIGNAL pix_cnt : integer RANGE 0 TO 31 := 0; --counts the position in the pixel to op SIGNAL rst_cnt : integer RANGE 0 TO 1023 := 0; --counts number of clocks in the reset period 50 us @ 20 MHz SIGNAL led_numb : integer RANGE 0 TO 1023; --number of LED in the string SIGNAL ram_addr : integer RANGE 0 TO 1023:=0; --address to read from RAM SIGNAL led_cnt : integer RANGE 0 TO 1023;--counts leds it has addressed SIGNAL pixel : std_logic_vector(23 DOWNTO 0); --holds led value to be output BEGIN web <= (OTHERS => '0'); rstb <= '0'; dinb <= (OTHERS =>'0'); pixel_cntrl : PROCESS(clk) BEGIN IF rising_edge(CLK) THEN load_shr <= '0'; enb <= '0'; CASE current_state IS WHEN idle => current_state <= wait1; rst_cnt <= 0; addrb <= std_logic_vector(to_unsigned(ram_addr,32)); enb<='1'; WHEN wait1 => current_state <= led; WHEN led => led_numb <= to_integer(unsigned(doutb)); IF to_integer(unsigned(doutb)) = 0 THEN current_state <= idle; ELSE current_state <= addr_out; ram_addr <= ram_addr +4; END IF; WHEN count => IF pix_cnt = (numb_pixels-1) THEN IF led_cnt = (led_numb-1) THEN current_state <= reset; pix_cnt <= 0; ram_addr <= 0; ELSE ram_addr <= ram_addr+4; current_state <= done_addr; led_cnt <= led_cnt + 1; END IF; ELSE current_state <= wait_done; END IF; WHEN done_addr => IF (shift_dne(shift_dne'high-1) = '1') THEN current_state <= addr_out; END IF; WHEN wait_done => IF (shift_dne(shift_dne'high-1) = '1') THEN load_shr <='1'; pix_cnt <= pix_cnt + 1; current_state <= count; END IF; WHEN addr_out => addrb <= std_logic_vector(to_unsigned(ram_addr,32)); enb<='1'; current_state <= wait2; WHEN wait2 => current_state <= grab; prev_state <= wait2; WHEN grab => pixel <= doutb(doutb'high-8 DOWNTO doutb'low); load_shr <= '1'; current_state <= wait_done; pix_cnt <=0; WHEN reset => pix_cnt <= 0; led_cnt <= 0; IF rst_cnt = (reset_duration-1) THEN current_state <= idle; ram_addr <= 0; ELSE rst_cnt <= rst_cnt + 1; END IF; END CASE; END IF; END PROCESS; shr_op : PROCESS(clk) BEGIN IF rising_edge(clk) THEN IF load_shr ='1' THEN shift_dne <= done; IF pixel((numb_pixels-1)-pix_cnt) = '1' THEN shift_reg <= one; ELSE shift_reg <= zero; END IF; ELSE shift_reg <= shift_reg(shift_reg'high-1 DOWNTO shift_reg'low) & '0'; shift_dne <= shift_dne(shift_dne'high-1 DOWNTO shift_reg'low) & '0'; END IF; END IF; END PROCESS; dout <= shift_reg(shift_reg'high); END ARCHITECTURE; LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; ENTITY tb IS END ENTITY; ARCHITECTURE behavioural OF tb IS COMPONENT neo_pixel IS PORT( clk : IN std_logic; dout : OUT std_logic; rstb : OUT STD_LOGIC; enb : OUT STD_LOGIC; web : OUT STD_LOGIC_VECTOR(3 DOWNTO 0); addrb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); dinb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); doutb : IN STD_LOGIC_VECTOR(31 DOWNTO 0) ); END COMPONENT; COMPONENT uzed_blk_mem_gen_0_0 IS PORT ( clka : IN STD_LOGIC; rsta : IN STD_LOGIC; ena : IN STD_LOGIC; wea : IN STD_LOGIC_VECTOR(3 DOWNTO 0); addra : IN STD_LOGIC_VECTOR(31 DOWNTO 0); dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0); douta : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); clkb : IN STD_LOGIC; rstb : IN STD_LOGIC; enb : IN STD_LOGIC; web : IN STD_LOGIC_VECTOR(3 DOWNTO 0); addrb : IN STD_LOGIC_VECTOR(31 DOWNTO 0); dinb : IN STD_LOGIC_VECTOR(31 DOWNTO 0); doutb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0) ); END COMPONENT uzed_blk_mem_gen_0_0; SUBTYPE vector_size IS std_logic_vector(31 DOWNTO 0); TYPE neo IS ARRAY (0 to 30) OF vector_size; CONSTANT mem_data : neo := ( x"0000001e", x"00DDDAC3", x"006A4D03", x"0027C3F1", x"0046CE04", x"000FB9ED", x"00977D04", x"00C1FDB2", x"007A9E52", x"00B34C36", x"0056640F", x"00F6D97A", x"00F88BBB", x"0012A820", x"00BB1DF2", x"00034EC3", x"0054846C", x"00EF2B7F", x"000D685F", x"005F0F59", x"006BF532", x"00F5A778", x"00C5E351", x"00BA06D8", x"00F9C0F1", x"004BE2D5", x"0055E0F0", x"000A44BA", x"00B9DCB6", x"00B26C94", x"00689745"); CONSTANT clk_period : time := 50 ns; SIGNAL clk : STD_LOGIC:='0'; SIGNAL rst : STD_LOGIC:='0'; SIGNAL ena : STD_LOGIC:='0'; SIGNAL wea : STD_LOGIC_VECTOR(3 DOWNTO 0); SIGNAL addra : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL dina : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL douta : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL enb : STD_LOGIC; SIGNAL web : STD_LOGIC_VECTOR(3 DOWNTO 0); SIGNAL addrb : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL dinb : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL doutb : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL dout : STD_LOGIC; BEGIN clk_gen : PROCESS BEGIN LOOP clk <= NOT(CLK); WAIT FOR(clk_period/2); clk <= NOT(CLK); WAIT FOR(clk_period/2); END LOOP; END PROCESS; ram_uut : uzed_blk_mem_gen_0_0 PORT MAP( clka => clk, rsta => rst, ena => ena, wea => wea, addra => addra, dina => dina, douta => douta, clkb => clk, rstb => rst, enb => enb, web => web, addrb => addrb, dinb => dinb, doutb => doutb); uut : neo_pixel PORT MAP( clk => clk, dout => dout, rstb => OPEN, enb => enb, web => web, addrb => addrb, dinb => dinb, doutb => doutb); ram_load : PROCESS BEGIN FOR i IN 0 TO 30 LOOP WAIT FOR clk_period; WAIT UNTIL rising_edge(clk); wea <= (OTHERS=>'1'); ena <='1'; addra <= std_logic_vector(to_unsigned(i*4,32));--needs to be on boundaires of four dina <= mem_data(i); WAIT UNTIL rising_edge(clk); wea <= (OTHERS=>'0'); ena <='0'; WAIT FOR 10 ns; END LOOP; WAIT; -- REPORT "simulation Complete" SEVERITY failure; END PROCESS; END ARCHITECTURE;