]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - hw/qcounter.vhd
Major refactorization in hw
[fpga/lx-cpu1/lx-rocon.git] / hw / qcounter.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.std_logic_arith.all;
4 use ieee.std_logic_unsigned.all;
5 use ieee.numeric_std.all;
6 use work.lx_rocon_pkg.all;
7
8 -- Quadcounter (for IRC)
9
10 entity qcounter is
11   port
12         (
13                 -- Inputs
14     clk_i              : in std_logic;
15     reset_i            : in std_logic;
16     a0_i, b0_i         : in std_logic;
17                 index0_i           : in std_logic;
18                 -- Outputs
19     qcount_o           : out std_logic_vector (31 downto 0);
20                 qcount_index_o     : out std_logic_vector (31 downto 0);
21     a_rise_o, a_fall_o : out std_logic;
22                 b_rise_o, b_fall_o : out std_logic;
23                 ab_event_o         : out std_logic;
24     ab_error_o         : out std_logic
25   );
26 end qcounter;
27
28 architecture behavioral of qcounter is
29
30         signal last_reset_s       : std_logic;
31   signal a_s, b_s           : std_logic;
32         signal a_prev_s, b_prev_s : std_logic;
33         signal index_s            : std_logic;
34   signal count_prev_s       : std_logic_vector (29 downto 0);
35   signal count_s            : std_logic_vector (29 downto 0);
36         signal count_index_prev_s : std_logic_vector (31 downto 0);
37   signal count_index_s      : std_logic_vector (31 downto 0);
38
39 begin
40         dff_a: dff2
41         port map
42         (
43                 clk_i   => clk_i,
44                 reset_i => '0',
45                 d_i     => a0_i,
46                 q_o     => a_s
47         );
48
49   dff_b: dff2
50         port map
51         (
52                 clk_i   => clk_i,
53                 reset_i => '0',
54                 d_i     => b0_i,
55                 q_o     => b_s
56         );
57
58         dff_index: dff2
59         port map
60         (
61                 clk_i   => clk_i,
62                 reset_i => '0',
63                 d_i     => index0_i,
64                 q_o     => index_s
65         );
66
67         qcount_o(0)           <= a_s xor b_s;
68         qcount_o(1)           <= b_s;
69         qcount_o(31 downto 2) <= count_s;
70
71         qcount_index_o        <= count_index_s;
72
73 comb_event:
74         process (reset_i, last_reset_s, a_prev_s, b_prev_s, a_s, b_s)
75         begin
76     a_rise_o   <= '0';
77     a_fall_o   <= '0';
78     b_rise_o   <= '0';
79     b_fall_o   <= '0';
80     ab_event_o <= '0';
81     ab_error_o <= '0';
82
83                 if reset_i = '0' and last_reset_s = '0' then
84                         if ((a_s xor a_prev_s) and (b_s xor b_prev_s)) = '1' then
85                                 -- forbidden double transition
86                                 ab_error_o <= '1';
87                         else
88                                 a_rise_o   <= (a_s xor a_prev_s) and a_s;
89                                 a_fall_o   <= (a_s xor a_prev_s) and (not a_s);
90                                 b_rise_o   <= (b_s xor b_prev_s) and b_s;
91                                 b_fall_o   <= (b_s xor b_prev_s) and (not b_s);
92                                 ab_event_o <= (a_s xor a_prev_s) or (b_s xor b_prev_s);
93                         end if;
94                 end if;
95   end process;
96
97 comb_count:
98         process (reset_i, last_reset_s, a_prev_s, b_prev_s, a_s, b_s,
99                                                 index_s, count_prev_s, count_index_prev_s)
100         begin
101                 if reset_i = '1' or last_reset_s = '1' then
102                         count_s                      <= count_prev_s;
103                         count_index_s                <= count_index_prev_s;
104                 elsif (a_prev_s = '0') and (b_prev_s = '1') and (a_s = '0') and
105                                                 (b_s = '0') then
106       count_s                      <= count_prev_s + 1;
107                         if index_s = '1' then
108                                 count_index_s(0)           <= a_s xor b_s;
109                                 count_index_s(1)           <= b_s;
110                                 count_index_s(31 downto 2) <= count_prev_s + 1;
111                         else
112                                 count_index_s              <= count_index_prev_s;
113                         end if;
114     elsif (a_prev_s = '0') and (b_prev_s = '0') and (a_s = '0') and
115                                                 (b_s = '1') then
116       count_s                      <= count_prev_s - 1;
117
118                         if index_s = '1' then
119                                 count_index_s(0)           <= a_s xor b_s;
120                                 count_index_s(1)           <= b_s;
121                                 count_index_s(31 downto 2) <= count_prev_s - 1;
122                         else
123                                 count_index_s              <= count_index_prev_s;
124                         end if;
125     else
126       count_s                      <= count_prev_s;
127                         if index_s = '1' then
128                                 count_index_s(0)           <= a_s xor b_s;
129                                 count_index_s(1)           <= b_s;
130                                 count_index_s(31 downto 2) <= count_prev_s;
131                         else
132                                 count_index_s              <= count_index_prev_s;
133                         end if;
134     end if;
135
136   end process;
137
138 seq:
139         process (clk_i)
140         begin
141                 -- Reset for qcounter is synchronous and lasts at least one more cycle
142                 -- to prevent hazardous states after releasing it
143                 if clk_i = '1' and clk_i'event then
144                         if reset_i = '0' then
145                                 count_prev_s       <= count_s;
146                                 count_index_prev_s <= count_index_s;
147                         else
148                                 count_prev_s       <= (others => '0');
149                                 count_index_prev_s <= (others => '0');
150                         end if;
151                         a_prev_s             <= a_s;
152                         b_prev_s             <= b_s;
153                         last_reset_s         <= reset_i;
154                 end if;
155   end process;
156
157 end behavioral;