- added 2. Interrupt timer
Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@455 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
+102
-65
@@ -29,6 +29,8 @@ END gpio_wb;
|
|||||||
|
|
||||||
ARCHITECTURE behavior OF gpio_wb IS
|
ARCHITECTURE behavior OF gpio_wb IS
|
||||||
|
|
||||||
|
constant num_timers : natural := 2;
|
||||||
|
|
||||||
signal gpo0_reg : unsigned(31 downto 0);
|
signal gpo0_reg : unsigned(31 downto 0);
|
||||||
signal gpo1_reg : unsigned(31 downto 0);
|
signal gpo1_reg : unsigned(31 downto 0);
|
||||||
signal gpi0_reg : unsigned(31 downto 0);
|
signal gpi0_reg : unsigned(31 downto 0);
|
||||||
@@ -45,21 +47,33 @@ ARCHITECTURE behavior OF gpio_wb IS
|
|||||||
signal cnt_sec_en : std_logic;
|
signal cnt_sec_en : std_logic;
|
||||||
signal cnt_sec_we : std_logic;
|
signal cnt_sec_we : std_logic;
|
||||||
|
|
||||||
signal cnt_timer : unsigned(31 downto 0);
|
type timer_array_t is array (0 to num_timers-1) of unsigned(31 downto 0);
|
||||||
signal cnt_timer_cmp : unsigned(31 downto 0);
|
signal timer_cnt : timer_array_t;
|
||||||
signal cnt_timer_en : std_logic;
|
signal timer_cmp : timer_array_t;
|
||||||
signal cnt_timer_inten : std_logic;
|
signal timer_en : unsigned(0 to num_timers-1);
|
||||||
signal cnt_timer_irq : std_logic;
|
signal timer_inten : unsigned(0 to num_timers-1);
|
||||||
signal cnt_timer_ovl : std_logic;
|
signal timer_irq : unsigned(0 to num_timers-1);
|
||||||
signal timer_irq_ack : std_logic;
|
signal timer_ovl : unsigned(0 to num_timers-1);
|
||||||
signal timer_we : std_logic;
|
signal timer_irq_ack : unsigned(0 to num_timers-1);
|
||||||
signal timer_cmp_we : std_logic;
|
signal timer_cnt_we : unsigned(0 to num_timers-1);
|
||||||
|
signal timer_cmp_we : unsigned(0 to num_timers-1);
|
||||||
|
|
||||||
signal reg_data_wr : unsigned(31 downto 0);
|
signal reg_data_wr : unsigned(31 downto 0);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
SRDY_O <= CYC_I;
|
SRDY_O <= CYC_I;
|
||||||
INT_TIM_O <= cnt_timer_irq;
|
|
||||||
|
tim_irq:
|
||||||
|
process(timer_irq)
|
||||||
|
variable irq : std_logic;
|
||||||
|
begin
|
||||||
|
irq := '0';
|
||||||
|
for i in 0 to num_timers-1 loop
|
||||||
|
irq := irq or timer_irq(i);
|
||||||
|
end loop;
|
||||||
|
INT_TIM_O <= irq;
|
||||||
|
end process;
|
||||||
|
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
led_out:
|
led_out:
|
||||||
@@ -88,19 +102,19 @@ registers_write:
|
|||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
cnt_usec_we <= '0';
|
cnt_usec_we <= '0';
|
||||||
cnt_sec_we <= '0';
|
cnt_sec_we <= '0';
|
||||||
timer_we <= '0';
|
timer_cnt_we <= (others => '0');
|
||||||
timer_cmp_we <= '0';
|
timer_cmp_we <= (others => '0');
|
||||||
timer_irq_ack <= '0';
|
timer_irq_ack <= (others => '0');
|
||||||
if RST_I = '1' then
|
if RST_I = '1' then
|
||||||
gpo0_reg <= (others => '0');
|
gpo0_reg <= (others => '0');
|
||||||
gpo1_reg <= (others => '0');
|
gpo1_reg <= (others => '0');
|
||||||
cnt_timer_en <= '0';
|
timer_en <= (others => '0');
|
||||||
cnt_timer_inten <= '0';
|
timer_inten <= (others => '0');
|
||||||
elsif (STB_I and CYC_I and WE_I) = '1' then
|
elsif (STB_I and CYC_I and WE_I) = '1' then
|
||||||
reg_data_wr <= DAT_I;
|
reg_data_wr <= DAT_I;
|
||||||
case ADDR_I(5 downto 2) is
|
case ADDR_I(6 downto 2) is
|
||||||
|
|
||||||
when "0000" =>
|
when "00000" =>
|
||||||
if SEL_I(0) = '1' then
|
if SEL_I(0) = '1' then
|
||||||
gpo0_reg(7 downto 0) <= DAT_I(7 downto 0);
|
gpo0_reg(7 downto 0) <= DAT_I(7 downto 0);
|
||||||
end if;
|
end if;
|
||||||
@@ -114,7 +128,7 @@ registers_write:
|
|||||||
gpo0_reg(31 downto 24) <= DAT_I(31 downto 24);
|
gpo0_reg(31 downto 24) <= DAT_I(31 downto 24);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
when "0001" =>
|
when "00001" =>
|
||||||
if SEL_I(0) = '1' then
|
if SEL_I(0) = '1' then
|
||||||
gpo1_reg(7 downto 0) <= DAT_I(7 downto 0);
|
gpo1_reg(7 downto 0) <= DAT_I(7 downto 0);
|
||||||
end if;
|
end if;
|
||||||
@@ -128,24 +142,33 @@ registers_write:
|
|||||||
gpo1_reg(31 downto 24) <= DAT_I(31 downto 24);
|
gpo1_reg(31 downto 24) <= DAT_I(31 downto 24);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
when "0010" =>
|
when "00010" =>
|
||||||
cnt_usec_we <= '1';
|
cnt_usec_we <= '1';
|
||||||
|
|
||||||
when "0011" =>
|
when "00011" =>
|
||||||
cnt_sec_we <= '1';
|
cnt_sec_we <= '1';
|
||||||
|
|
||||||
when "0100" => -- timer control
|
when "00110" => -- timer control
|
||||||
cnt_timer_en <= DAT_I(0);
|
for i in 0 to num_timers-1 loop
|
||||||
cnt_timer_inten <= DAT_I(1);
|
timer_en(i) <= DAT_I(2*i+0);
|
||||||
|
timer_inten(i) <= DAT_I(2*i+1);
|
||||||
|
end loop;
|
||||||
|
when "00111" => -- timer status
|
||||||
|
for i in 0 to num_timers-1 loop
|
||||||
|
timer_irq_ack(i) <= DAT_I(2*i); -- IRQ acknowledge
|
||||||
|
end loop;
|
||||||
|
|
||||||
when "0101" => -- timer status
|
when "01000" => -- timer count 0
|
||||||
timer_irq_ack <= DAT_I(0); -- IRQ acknowledge
|
timer_cnt_we(0) <= '1';
|
||||||
|
|
||||||
when "0110" => -- timer count
|
when "01001" => -- timer count 1
|
||||||
timer_we <= '1';
|
timer_cnt_we(1) <= '1';
|
||||||
|
|
||||||
when "0111" => -- timer compare
|
when "01100" => -- timer compare 0
|
||||||
timer_cmp_we <= '1';
|
timer_cmp_we(0) <= '1';
|
||||||
|
|
||||||
|
when "01101" => -- timer compare 1
|
||||||
|
timer_cmp_we(1) <= '1';
|
||||||
|
|
||||||
when others => null;
|
when others => null;
|
||||||
end case;
|
end case;
|
||||||
@@ -161,33 +184,43 @@ registers_read:
|
|||||||
if (STB_I and CYC_I) = '1' then
|
if (STB_I and CYC_I) = '1' then
|
||||||
ACK_O <= not WE_I;
|
ACK_O <= not WE_I;
|
||||||
DAT_O <= (others => '0');
|
DAT_O <= (others => '0');
|
||||||
case ADDR_I(5 downto 2) is
|
case ADDR_I(6 downto 2) is
|
||||||
|
|
||||||
when "0000" =>
|
when "00000" =>
|
||||||
DAT_O <= gpi0_reg;
|
DAT_O <= gpi0_reg;
|
||||||
|
|
||||||
when "0001" =>
|
when "00001" =>
|
||||||
DAT_O <= gpi1_reg;
|
DAT_O <= gpi1_reg;
|
||||||
|
|
||||||
when "0010" =>
|
when "00010" =>
|
||||||
DAT_O <= cnt_usec;
|
DAT_O <= cnt_usec;
|
||||||
|
|
||||||
when "0011" =>
|
when "00011" =>
|
||||||
DAT_O <= cnt_sec;
|
DAT_O <= cnt_sec;
|
||||||
|
|
||||||
when "0100" => -- timer control
|
when "00110" => -- timer control
|
||||||
DAT_O(0) <= cnt_timer_en;
|
for i in 0 to num_timers-1 loop
|
||||||
DAT_O(1) <= cnt_timer_inten;
|
DAT_O(2*i+0) <= timer_en(i);
|
||||||
|
DAT_O(2*i+1) <= timer_inten(i);
|
||||||
|
end loop;
|
||||||
|
|
||||||
when "0101" => -- timer status
|
when "00111" => -- timer status
|
||||||
DAT_O(0) <= cnt_timer_irq;
|
for i in 0 to num_timers-1 loop
|
||||||
DAT_O(1) <= cnt_timer_ovl;
|
DAT_O(2*i+0) <= timer_irq(i);
|
||||||
|
DAT_O(2*i+1) <= timer_ovl(i);
|
||||||
|
end loop;
|
||||||
|
|
||||||
when "0110" => -- timer count
|
when "01000" => -- timer count 0
|
||||||
DAT_O <= cnt_timer;
|
DAT_O <= timer_cnt(0);
|
||||||
|
|
||||||
when "0111" => -- timer compare
|
when "01001" => -- timer count 1
|
||||||
DAT_O <= cnt_timer_cmp;
|
DAT_O <= timer_cnt(1);
|
||||||
|
|
||||||
|
when "01100" => -- timer compare 0
|
||||||
|
DAT_O <= timer_cmp(0);
|
||||||
|
|
||||||
|
when "01101" => -- timer compare 1
|
||||||
|
DAT_O <= timer_cmp(1);
|
||||||
|
|
||||||
when others => null;
|
when others => null;
|
||||||
end case;
|
end case;
|
||||||
@@ -245,27 +278,29 @@ proc_int_timer:
|
|||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if RST_I = '1' then
|
for i in 0 to num_timers-1 loop
|
||||||
cnt_timer_ovl <= '0';
|
if RST_I = '1' then
|
||||||
cnt_timer_irq <= '0';
|
timer_ovl(i) <= '0';
|
||||||
elsif timer_irq_ack = '1' then
|
timer_irq(i) <= '0';
|
||||||
cnt_timer_ovl <= '0';
|
elsif timer_irq_ack(i) = '1' then
|
||||||
cnt_timer_irq <= '0';
|
timer_ovl(i) <= '0';
|
||||||
elsif timer_we = '1' then
|
timer_irq(i) <= '0';
|
||||||
cnt_timer <= reg_data_wr;
|
elsif timer_cnt_we(i) = '1' then
|
||||||
elsif cnt_timer_en = '1' then
|
timer_cnt(i) <= reg_data_wr;
|
||||||
if cnt_timer >= cnt_timer_cmp then
|
elsif timer_en(i) = '1' then
|
||||||
cnt_timer <= (others => '0');
|
if timer_cnt(i) >= timer_cmp(i) then
|
||||||
if cnt_timer_inten = '1' then
|
timer_cnt(i) <= (others => '0');
|
||||||
if cnt_timer_irq = '1' then
|
if timer_inten(i) = '1' then
|
||||||
cnt_timer_ovl <= '1';
|
if timer_irq(i) = '1' then
|
||||||
|
timer_ovl(i) <= '1';
|
||||||
|
end if;
|
||||||
|
timer_irq(i) <= '1';
|
||||||
end if;
|
end if;
|
||||||
cnt_timer_irq <= '1';
|
else
|
||||||
|
timer_cnt(i) <= timer_cnt(i) + 1;
|
||||||
end if;
|
end if;
|
||||||
else
|
|
||||||
cnt_timer <= cnt_timer + 1;
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end loop;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
@@ -273,9 +308,11 @@ proc_int_timer_reload:
|
|||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if timer_cmp_we = '1' then
|
for i in 0 to num_timers-1 loop
|
||||||
cnt_timer_cmp <= reg_data_wr;
|
if timer_cmp_we(i) = '1' then
|
||||||
end if;
|
timer_cmp(i) <= reg_data_wr;
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user