Adam Taylors MicroZed Chronicles Part 34 code example 17 KB

advertisement
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;
Download