123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- 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;
|