forth-cpu
/
timer.vhd
109 строк · 3.7 Кб
1-------------------------------------------------------------------------------
2--| @file timer.vhd
3--| @brief General Purpose Timer. It is of customizable length,
4--| the minimum being 4-bits, one for the actual timing, the other
5--| three for control. (timer.vhd, original file name)
6--|
7--| @author Richard James Howe.
8--| @copyright Copyright 2017 Richard James Howe.
9--| @license MIT
10--| @email howe.r.j.89@gmail.com
11--|
12--| The control register contains both the value to compare the timer against
13--| as well as three control bits. Given a "timer_length" value of eight the
14--| control bits are:
15--|
16--| Bit Input Description
17--| 7 Clock enable
18--| 6 Timer reset
19--| 5 Interrupt enable
20--| 4 - 0 Timer compare value
21--|
22-------------------------------------------------------------------------------
23
24library ieee,work,std;
25use ieee.std_logic_1164.all;
26use ieee.numeric_std.all;
27use work.util.common_generics;
28
29entity timer is
30generic(
31g: common_generics;
32timer_length: positive := 16);
33port(
34clk: in std_ulogic;
35rst: in std_ulogic;
36
37we: in std_ulogic; -- write enable for control register
38control_i: in std_ulogic_vector(timer_length - 1 downto 0); -- control register
39counter_o: out std_ulogic_vector(timer_length - 4 downto 0);
40irq: out std_ulogic); -- generate interrupt
41end entity;
42
43architecture behav of timer is
44constant highest_bit: positive := timer_length - 1;
45constant control_enable_bit: positive := highest_bit;
46constant timer_reset_bit: positive := highest_bit - 1;
47constant irq_enable_bit: positive := highest_bit - 2;
48constant timer_highest_bit: positive := highest_bit - 3;
49
50signal control_c, control_n: std_ulogic_vector(highest_bit downto 0) := (others => '0');
51
52signal reset_timer: std_ulogic := '0';
53signal enabled: std_ulogic := '0';
54signal irq_en: std_ulogic := '0';
55
56signal timer_reset: std_ulogic := '0';
57
58signal compare: std_ulogic_vector(timer_highest_bit downto 0) := (others => '0');
59signal count: unsigned(timer_highest_bit downto 0) := (others => '0');
60begin
61assert (timer_length >= 4) report "Timer needs to be at least 4 bits wide: 3 bits for control - 1 for counter" severity failure;
62
63enabled <= control_c(control_enable_bit);
64reset_timer <= control_c(timer_reset_bit);
65irq_en <= control_c(irq_enable_bit);
66compare <= control_c(timer_highest_bit downto 0);
67
68counter_o <= std_ulogic_vector(count);
69
70counter: process (clk, rst)
71begin
72if rst = '1' and g.asynchronous_reset then
73count <= (others => '0') after g.delay;
74control_c <= (others => '0') after g.delay;
75elsif rising_edge(clk) then
76if rst = '1' and not g.asynchronous_reset then
77count <= (others => '0') after g.delay;
78control_c <= (others => '0') after g.delay;
79else
80control_c <= control_n;
81if reset_timer = '1' or timer_reset = '1' then
82count <= (others => '0') after g.delay;
83elsif enabled = '1' then
84count <= count + 1 after g.delay;
85else
86count <= count after g.delay;
87end if;
88end if;
89end if;
90end process;
91
92output: process(count, we, control_i, control_c, compare, irq_en, enabled)
93begin
94if we = '1' then
95control_n <= control_i after g.delay;
96else
97control_n <= control_c after g.delay;
98control_n(timer_reset_bit) <= '0' after g.delay; -- reset
99end if;
100
101if count = unsigned(compare) and enabled = '1' then
102irq <= irq_en after g.delay;
103timer_reset <= '1' after g.delay;
104else
105irq <= '0' after g.delay;
106timer_reset <= '0' after g.delay;
107end if;
108end process;
109end architecture;
110
111