diff --git a/lib/CPUs/MIPS/src/tb_mips_top.vhd b/lib/CPUs/MIPS/src/tb_mips_top.vhd index e2e2ed0..138d365 100644 --- a/lib/CPUs/MIPS/src/tb_mips_top.vhd +++ b/lib/CPUs/MIPS/src/tb_mips_top.vhd @@ -100,7 +100,8 @@ ARCHITECTURE behavior OF tb_mips_top IS signal gpo1 : unsigned(31 downto 0); signal gpi0 : unsigned(31 downto 0) := (others => '0'); signal gpi1 : unsigned(31 downto 0) := (others => '0'); - + + signal int_timer : std_logic; signal int_uart_rx : std_logic; signal rx : std_logic := '1'; signal tx : std_logic; @@ -214,6 +215,7 @@ uut: entity work.mips_top INT => INT ); INT(1) <= int_uart_rx; + INT(5) <= int_timer; inst_rom : entity work.rom_wb PORT MAP @@ -244,6 +246,7 @@ inst_gpio : entity work.gpio_wb ADDR_I => ADDR_O, DAT_I => DAT_O, DAT_O => DAT_O_gpio, + INT_TIM_O => int_timer, sys_gpo0 => gpo0, sys_gpo1 => gpo1, @@ -382,7 +385,7 @@ SRAM_WRITE: FLASH_READ: process(rst, flash_cs_n, flash_oe_n, flash_a) type file_t is file of integer; - file load_flash : file_t open read_mode is "hello.flash.bin"; + file load_flash : file_t open read_mode is "test_timer.flash.bin"; variable instr : integer; variable index : natural; variable temp : signed(31 downto 0); diff --git a/lib/misc/gpio_wb.vhd b/lib/misc/gpio_wb.vhd index 851399c..0d2e151 100644 --- a/lib/misc/gpio_wb.vhd +++ b/lib/misc/gpio_wb.vhd @@ -17,6 +17,7 @@ ENTITY gpio_wb IS ADDR_I : in unsigned(31 downto 0); DAT_I : in unsigned(31 downto 0); DAT_O : out unsigned(31 downto 0); + INT_TIM_O : out STD_LOGIC; sys_gpo0 : out unsigned(31 downto 0); sys_gpo1 : out unsigned(31 downto 0); @@ -44,9 +45,21 @@ ARCHITECTURE behavior OF gpio_wb IS signal cnt_sec_en : std_logic; signal cnt_sec_we : std_logic; + signal cnt_timer : unsigned(31 downto 0); + signal cnt_timer_cmp : unsigned(31 downto 0); + signal cnt_timer_en : std_logic; + signal cnt_timer_inten : std_logic; + signal cnt_timer_irq : std_logic; + signal cnt_timer_ovl : std_logic; + signal timer_irq_ack : std_logic; + signal timer_we : std_logic; + signal timer_cmp_we : std_logic; + signal reg_data_wr : unsigned(31 downto 0); + begin - SRDY_O <= CYC_I; + SRDY_O <= CYC_I; + INT_TIM_O <= cnt_timer_irq; ------------------------------------------------------------------ led_out: @@ -75,10 +88,16 @@ registers_write: if rising_edge(CLK_I) then cnt_usec_we <= '0'; cnt_sec_we <= '0'; + timer_we <= '0'; + timer_cmp_we <= '0'; + timer_irq_ack <= '0'; if RST_I = '1' then gpo0_reg <= (others => '0'); gpo1_reg <= (others => '0'); + cnt_timer_en <= '0'; + cnt_timer_inten <= '0'; elsif (STB_I and CYC_I and WE_I) = '1' then + reg_data_wr <= DAT_I; case ADDR_I(5 downto 2) is when "0000" => @@ -110,17 +129,24 @@ registers_write: end if; when "0010" => - if SEL_I(3) = '1' then - cnt_usec_we <= '1'; - cnt_usec_preset <= DAT_I; - end if; + cnt_usec_we <= '1'; when "0011" => - if SEL_I(3) = '1' then - cnt_sec_we <= '1'; - cnt_sec_preset <= DAT_I; - end if; + cnt_sec_we <= '1'; + when "0100" => -- timer control + cnt_timer_en <= DAT_I(0); + cnt_timer_inten <= DAT_I(1); + + when "0101" => -- timer status + timer_irq_ack <= DAT_I(0); -- IRQ acknowledge + + when "0110" => -- timer count + timer_we <= '1'; + + when "0111" => -- timer compare + timer_cmp_we <= '1'; + when others => null; end case; end if; @@ -149,13 +175,27 @@ registers_read: when "0011" => DAT_O <= cnt_sec; + when "0100" => -- timer control + DAT_O(0) <= cnt_timer_en; + DAT_O(1) <= cnt_timer_inten; + + when "0101" => -- timer status + DAT_O(0) <= cnt_timer_irq; + DAT_O(1) <= cnt_timer_ovl; + + when "0110" => -- timer count + DAT_O <= cnt_timer; + + when "0111" => -- timer compare + DAT_O <= cnt_timer_cmp; + when others => null; end case; end if; end if; end process; -tick_usec_timer: +cnt_usec_tick: process(CLK_I) begin if rising_edge(CLK_I) then @@ -169,13 +209,14 @@ tick_usec_timer: end if; end process; -cnt_usec_timer: +-- H/W Clock +cnt_usec_clock: process(CLK_I) begin if rising_edge(CLK_I) then cnt_sec_en <= '0'; if cnt_usec_we = '1' then - cnt_usec <= cnt_usec_preset; + cnt_usec <= reg_data_wr; elsif cnt_usec_en = '1' then if cnt_usec >= to_unsigned(1E6 - 1, 32) then cnt_usec <= (others => '0'); @@ -187,17 +228,56 @@ cnt_usec_timer: end if; end process; -cnt_sec_timer: +cnt_sec_clock: process(CLK_I) begin if rising_edge(CLK_I) then if cnt_sec_we = '1' then - cnt_sec <= cnt_sec_preset; + cnt_sec <= reg_data_wr; elsif cnt_sec_en = '1' then cnt_sec <= cnt_sec + 1; end if; end if; end process; +-- Interrupt timer +proc_int_timer: + process(CLK_I) + begin + if rising_edge(CLK_I) then + if RST_I = '1' then + cnt_timer_ovl <= '0'; + cnt_timer_irq <= '0'; + elsif timer_irq_ack = '1' then + cnt_timer_ovl <= '0'; + cnt_timer_irq <= '0'; + elsif timer_we = '1' then + cnt_timer <= reg_data_wr; + elsif cnt_timer_en = '1' then + if cnt_timer >= cnt_timer_cmp then + cnt_timer <= (others => '0'); + if cnt_timer_inten = '1' then + if cnt_timer_irq = '1' then + cnt_timer_ovl <= '1'; + end if; + cnt_timer_irq <= '1'; + end if; + else + cnt_timer <= cnt_timer + 1; + end if; + end if; + end if; + end process; + +proc_int_timer_reload: + process(CLK_I) + begin + if rising_edge(CLK_I) then + if timer_cmp_we = '1' then + cnt_timer_cmp <= reg_data_wr; + end if; + end if; + end process; + ------------------------------------------------------------------ end behavior; diff --git a/projects/mips_sys/src/mips_sys.vhd b/projects/mips_sys/src/mips_sys.vhd index 4e9c360..3e5cd7d 100644 --- a/projects/mips_sys/src/mips_sys.vhd +++ b/projects/mips_sys/src/mips_sys.vhd @@ -243,6 +243,7 @@ ARCHITECTURE behavior OF mips_sys IS ADDR_I : in unsigned(31 downto 0); DAT_I : in unsigned(31 downto 0); DAT_O : out unsigned(31 downto 0); + INT_TIM_O : out STD_LOGIC; sys_gpo0 : out unsigned(31 downto 0); sys_gpo1 : out unsigned(31 downto 0); @@ -307,6 +308,7 @@ ARCHITECTURE behavior OF mips_sys IS signal clk270 : std_logic; signal clk270var : std_logic; signal rst_in : std_logic; + signal int_timer : std_logic; signal int_uart_rx : std_logic; signal locked : std_logic; signal usb_addr : unsigned(31 downto 0); @@ -480,7 +482,7 @@ int_sample: process(clk) begin if rising_edge(clk) then - int <= "00" & INT_O_ac97 & sys_usb_int & int_uart_rx & sys_btn(4); + INT <= int_timer & '0' & INT_O_ac97 & sys_usb_int & int_uart_rx & sys_btn(4); end if; end process; @@ -635,6 +637,7 @@ inst_gpio_wb : gpio_wb ADDR_I => ADDR_O, DAT_I => MDAT_O, DAT_O => SDAT_O_gpio, + INT_TIM_O => int_timer, sys_gpo0 => gpo0, sys_gpo1 => gpo1, diff --git a/projects/mips_sys/src/mips_sys_sim.vhd b/projects/mips_sys/src/mips_sys_sim.vhd index 160e06c..f08540f 100644 --- a/projects/mips_sys/src/mips_sys_sim.vhd +++ b/projects/mips_sys/src/mips_sys_sim.vhd @@ -287,6 +287,7 @@ ARCHITECTURE behavior OF mips_sys IS ADDR_I : in unsigned(31 downto 0); DAT_I : in unsigned(31 downto 0); DAT_O : out unsigned(31 downto 0); + INT_TIM_O : out STD_LOGIC; sys_gpo0 : out unsigned(31 downto 0); sys_gpo1 : out unsigned(31 downto 0); @@ -351,6 +352,7 @@ ARCHITECTURE behavior OF mips_sys IS signal clk270 : std_logic; signal clk270var : std_logic; signal rst_in : std_logic; + signal int_timer : std_logic; signal int_uart_rx : std_logic; signal locked : std_logic; signal ac97_rstn : std_logic; @@ -570,7 +572,7 @@ int_sample: process(clk) begin if rising_edge(clk) then - int <= "00" & INT_O_ac97 & sys_usb_int & int_uart_rx & sys_btn(4); + INT <= int_timer & '0' & INT_O_ac97 & sys_usb_int & int_uart_rx & sys_btn(4); end if; end process; @@ -733,6 +735,7 @@ inst_gpio_wb : gpio_wb ADDR_I => ADDR_O, DAT_I => MDAT_O, DAT_O => SDAT_O_gpio, + INT_TIM_O => int_timer, sys_gpo0 => gpo0, sys_gpo1 => gpo1,