134 lines
3.1 KiB
VHDL
134 lines
3.1 KiB
VHDL
-- See the file "LICENSE" for the full license governing this code. --
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
use work.lt16x32_global.all;
|
|
use work.wishbone.all;
|
|
use work.config.all;
|
|
|
|
entity wb_timer is
|
|
generic(
|
|
memaddr : generic_addr_type; --:= CFG_BADR_TIMER;
|
|
addrmask : generic_mask_type --:= CFG_MADR_TIMER;
|
|
);
|
|
port(
|
|
clk : in std_logic;
|
|
rst : in std_logic;
|
|
wslvi : in wb_slv_in_type;
|
|
wslvo : out wb_slv_out_type;
|
|
|
|
interrupt : out std_logic
|
|
);
|
|
end wb_timer;
|
|
|
|
architecture Behavioral of wb_timer is
|
|
constant COUNT_MAX : integer := 32 - 1;
|
|
|
|
signal ack : std_logic;
|
|
|
|
signal counter : integer range 0 to COUNT_MAX;
|
|
|
|
signal enable : std_logic;
|
|
signal repeat : std_logic;
|
|
signal reset : std_logic;
|
|
|
|
signal counter_vector : std_logic_vector(31 downto 0);
|
|
signal status_register : std_logic_vector(31 downto 0);
|
|
|
|
signal data_in : std_logic_vector(2 downto 0);
|
|
signal data_in_changed : std_logic;
|
|
|
|
begin
|
|
|
|
process(clk)
|
|
begin
|
|
if clk'event and clk='1' then
|
|
if rst = '1' then
|
|
counter <= 0;
|
|
else
|
|
if reset = '1' then -- reset register
|
|
counter <= 0;
|
|
else
|
|
if enable = '1' then
|
|
if counter = COUNT_MAX then
|
|
counter <= 0;
|
|
else
|
|
counter <= counter + 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process(clk)
|
|
begin
|
|
if clk'event and clk='1' then
|
|
if rst = '1' then
|
|
enable <= '0';
|
|
repeat <= '0';
|
|
reset <= '0';
|
|
else
|
|
reset <= '0';
|
|
|
|
if data_in_changed = '1' then
|
|
enable <= data_in(0);
|
|
repeat <= data_in(1);
|
|
reset <= data_in(2);
|
|
end if;
|
|
|
|
-- Reset enable bit
|
|
if counter = COUNT_MAX and repeat = '0' then
|
|
enable <= '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process(clk)
|
|
begin
|
|
if clk'event and clk='1' then
|
|
if rst = '1' then
|
|
ack <= '0';
|
|
data_in <= (others => '0');
|
|
data_in_changed <= '0';
|
|
else
|
|
data_in <= (others => '0');
|
|
data_in_changed <= '0';
|
|
|
|
if wslvi.stb = '1' and wslvi.cyc = '1' then
|
|
if wslvi.we='1' and wslvi.adr(2) = '1' then
|
|
data_in <= dec_wb_dat(wslvi.sel,wslvi.dat)(2 downto 0);
|
|
data_in_changed <= '1';
|
|
end if;
|
|
|
|
if ack = '0' then
|
|
ack <= '1';
|
|
else
|
|
ack <= '0';
|
|
end if;
|
|
else
|
|
ack <= '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
counter_vector <= std_logic_vector(to_unsigned(counter, counter_vector'length));
|
|
|
|
status_register(0) <= enable; -- enable
|
|
status_register(1) <= repeat; -- repeat
|
|
status_register(31 downto 2) <= (others => '0'); -- reset bit always reads as 0
|
|
|
|
wslvo.dat <= counter_vector when wslvi.adr(2) = '0'
|
|
else status_register when wslvi.adr(2) = '1'
|
|
else (others => '0');
|
|
|
|
interrupt <= '1' when counter = COUNT_MAX else '0';
|
|
|
|
wslvo.ack <= ack;
|
|
wslvo.wbcfg <= wb_membar(memaddr, addrmask);
|
|
|
|
end Behavioral;
|