library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; -- top level entity myfirst_niosii entity myfirst_niosii is port ( clk: in std_logic; -- 50 MHz rst: in std_logic; -- rst switch pio_led: out std_logic_vector(31 downto 0); -- LEDs of dev board buttons: in std_logic_vector(7 downto 0); -- push buttons matrix_rows: out std_logic_vector(11 downto 0); -- LED row driver, active high matrix_cols: out std_logic_vector(7 downto 0); -- LED colunm driver, active high lcd_16207_ext_RS : out std_logic; -- RS lcd_16207_ext_RW : out std_logic; -- RW lcd_16207_ext_data : inout std_logic_vector(7 downto 0) := (others => 'X'); -- data lcd_16207_ext_E : out std_logic ); -- the state of the LEDs is stored in a 8 x 12 bit matrix -- the outer index represents the coulumn ID and the std_logic index represents the row ID type matrix_t is array(integer range 0 to 7) of std_logic_vector(11 downto 0); end myfirst_niosii; architecture behav of myfirst_niosii is -- noisII CPU IP wrapper component nios2_uc is port ( clk_clk : in std_logic := 'X'; -- clk reset_reset_n : in std_logic := 'X'; -- reset_n lcd_16207_ext_RS : out std_logic; -- RS lcd_16207_ext_RW : out std_logic; -- RW lcd_16207_ext_data : inout std_logic_vector(7 downto 0) := (others => 'X'); -- data lcd_16207_ext_E : out std_logic; -- E pio_led_ext_conn_export : out std_logic_vector(31 downto 0); -- dev board LEDs pio_button_ext_conn_export : in std_logic_vector(7 downto 0) := (others => 'X'); -- dev board buttons pio_matrix_ext_conn_export : out std_logic_vector(19 downto 0) -- matrix instruction -- matrix instruction contains three parts: -- 20 16 12 8 4 0 -- XXXX CCCC RRRR RRRR RRRR -- -- X: 19 downto 16: unused -- C: 15 downto 12: column number -- R: 11 downto 0: row data -- -- column number: -- 0000: don't set anything -- 0001: set column 0 to row data -- 0010: set column 1 to row data -- 0011: set column 2 to row data -- ... ); end component nios2_uc; -- signals for debouncing -- previous button state signal button_states: std_logic_vector(7 downto 0); -- button polling clock: 50Mhz / 2**20 = 47.7 Hz signal button_timer: integer range 0 to 2**20-1 := 0; -- matrix multiplexing clock: -- 50Mhz / 2**20 = 1526 Hz = 1 / 0.66 ms per column -- 1526 Hz / 8 = 190 Hz matrix refresh rate signal matrix_timer: integer range 0 to 2**15-1 := 0; -- column index signal signal matrix_col_index: integer range 0 to 7 := 0; -- matrix signal signal matrix_s: matrix_t; -- matrix instruction signal signal pio_matrix_s: std_logic_vector(19 downto 0); begin u0: component nios2_uc port map ( clk_clk => clk, pio_led_ext_conn_export => pio_led, reset_reset_n => rst, pio_matrix_ext_conn_export => pio_matrix_s, pio_button_ext_conn_export => button_states ); -- copies the row data according to instructions from CPU matrix_set: process(clk, rst) variable col_id : integer range 0 to 8; begin if rst = '0' then matrix_s <= ( "111110011111", "000100000101", "010000000111", "111110000000", "000000011111", "111110010001", "101010011111", "111010000000" ); elsif rising_edge(clk) then col_id := to_integer(unsigned(pio_matrix_s(15 downto 12))); if col_id > 0 then matrix_s(col_id-1) <= pio_matrix_s(11 downto 0); end if; end if; end process; -- copies rows from matrix_s to the outputs matrix_multiplex: process(clk, rst) begin if rst = '0' then matrix_rows <= "111111111111"; matrix_cols <= "11111111"; matrix_timer <= 0; matrix_col_index <= 0; elsif rising_edge(clk) then -- set outputs to zero at timer overflow -- avoids ghosting of display if matrix_timer = 2**15-1 then matrix_timer <= 0; if matrix_col_index = 7 then matrix_col_index <= 0; else matrix_col_index <= matrix_col_index + 1; end if; matrix_cols <= (others => '0'); matrix_rows <= (others => '0'); -- write actual data only 50MHz / 2**11 = 1 / 0.04 ms after setting outputs to zero elsif matrix_timer = 2**11-1 then matrix_cols(matrix_col_index) <= '1'; matrix_rows <= matrix_s(matrix_col_index); matrix_timer <= matrix_timer + 1; -- else do nothing else matrix_timer <= matrix_timer + 1; end if; end if; end process; -- this process polls the buttons at 47.7 Hz -- edge detection is done in software button_debounce: process(clk, rst) begin if rst = '0' then button_timer <= 0; elsif rising_edge(clk) then if button_timer = 2**20-1 then button_timer <= 0; -- update button states for id in 0 to 7 loop button_states(id) <= buttons(id); end loop; else button_timer <= button_timer + 1; end if; end if; end process; end behav;