---------------------------------------------------------------------------------- -- Company: Walla Walla University -- Engineer: L.Aamodt -- -- Create Date: 21:14:50 12/06/2015 -- Design Name: led_8x16_driver -- Module Name: led_8x16_driver - Behavioral -- Project Name: led_8x16_driver -- Target Devices: Spartan 3e -- Tool versions: ISE 14.7 -- Description: Driver to send data to a 8x16 LED array arranged as -- 8 rows of 16 bits (i.e. 16 columns). Data is read -- asynchronously as bytes from a 16 byte RAM, bits in -- the byte are selected sequentially with a multiplexer, -- and together with an address are used to select one -- LED at a time for potential turn on. All 128 bits are -- scanned about 79 times per second. -- -- Dependencies: WWU 8x16 LED matrix with row,column decoding and drivers -- -- Inputs: 50 Mhz master clock -- User system clock - (rate depends on user system) -- Data in - 8bits, one bit per LED in a LED column -- Write enable - assert for one system clock time when a -- new data byte is present on Data in -- Write address - 4 bits selecting one of 16 memory -- bytes. A byte specifies on/off for 8 LEDS in a column -- Outputs: Output to the display - 8-bits: 4 bits specifying a column, -- 3 bits specifying a bit in a column, and one data bit -- Revision: -- Revision 2.0 12/7/16 -- Revision 3.0 05/04/20 -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; library UNISIM; use UNISIM.VComponents.all; entity led_8x16_driver is Port ( mclk : in STD_LOGIC; -- 50 Mhz clock sys_clk : in STD_LOGIC; -- user system clock we : in STD_LOGIC; -- write enable data_in : in STD_LOGIC_VECTOR (7 downto 0); wrt_addr : in STD_LOGIC_VECTOR (3 downto 0); out_to_display : out STD_LOGIC_VECTOR (7 downto 0)); end led_8x16_driver; architecture Behavioral of led_8x16_driver is signal r_reg1: unsigned(11 downto 0); signal r_next1: unsigned(11 downto 0); signal led_addr: unsigned(6 downto 0); signal led_next: unsigned(6 downto 0); signal ram_data: STD_LOGIC_VECTOR(7 downto 0); signal clk_20k: STD_LOGIC; signal led_data: STD_LOGIC; type ram_type is array (0 to 15) of std_logic_vector(7 downto 0); signal RAM: ram_type := ( X"01", X"02", X"04", X"08", -- initial data, V pattern X"10", X"20", X"40", x"80", X"80", X"40", X"20", x"10", X"08", X"04", X"02", x"01" ); begin ------------------------------------------------------------ -- Scan clock generator - 20khz output to run LED update ------------------------------------------------------------ process(mclk,r_reg1) -- create 20000hz signal begin if (mclk'event and mclk='1') then r_reg1 <= r_next1; end if; end process; r_next1 <= (others=>'0') when (r_reg1 = 2499) else r_reg1 + 1; clk_20k <= '1' when r_reg1 = 2499 else '0'; ------------------------------------------------------------ -- RAM -- Dual ported RAM holds an image of what is to be displayed -- synchronous write and asynchronous read ------------------------------------------------------------ process(sys_clk,we) begin if (sys_clk'event and sys_clk = '1') then if (we = '1') then RAM(to_integer(unsigned(wrt_addr))) <= data_in; end if; end if; end process; ram_data <= RAM(to_integer(unsigned(led_addr(6 downto 3)))); ------------------------------------------------------------ -- LED address generator, a 7 bit binary counter ------------------------------------------------------------ process(mclk,clk_20k) begin if (mclk'event and mclk='1') then if (clk_20k = '1') then led_addr <= led_next; end if; end if; end process; led_next <= (others=>'0') when (led_addr = 127) else led_addr + 1; out_to_display(7 downto 1) <= std_logic_vector(led_addr); ------------------------------------------------------------- -- Multiplexer to select one led data bit from a data byte ------------------------------------------------------------- process(led_addr, ram_data) begin case led_addr(2 downto 0) is when "000" => led_data <= ram_data(7); when "001" => led_data <= ram_data(6); when "010" => led_data <= ram_data(5); when "011" => led_data <= ram_data(4); when "100" => led_data <= ram_data(3); when "101" => led_data <= ram_data(2); when "110" => led_data <= ram_data(1); when others => led_data <= ram_data(0); end case; end process; out_to_display(0) <= led_data; end Behavioral;