]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - hw/qcounter.vhd
FPGA: Improvements & Fixes
[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
7 -- Quadcounter (for IRC)
8
9 entity qcounter is
10   port
11         (
12     clk      : in std_logic;
13     reset    : in std_logic;
14     a0, b0   : in std_logic;
15
16     qcount   : out std_logic_vector (31 downto 0);
17     a_rise, a_fall, b_rise, b_fall, ab_event: out std_logic;
18     ab_error : out std_logic
19   );
20 end qcounter;
21
22 architecture behavioral of qcounter is
23   component dff
24         port
25         (
26                 clk   : in std_logic;
27                 reset : in std_logic;
28                 d     : in std_logic;
29                 q     : out std_logic
30         );
31   end component;
32
33 subtype std_logic4 is std_logic_vector (3 downto 0);
34         signal last_reset: std_logic;
35   signal a, b, a_prev, b_prev: std_logic;
36   signal count_prev: std_logic_vector (29 downto 0);
37   signal count: std_logic_vector (29 downto 0);
38 begin
39         dff_a: dff
40         port map
41         (
42                 clk => clk,
43                 reset => reset,
44                 d => a0,
45                 q => a
46         );
47
48   dff_b: dff
49         port map
50         (
51                 clk => clk,
52                 reset => reset,
53                 d => b0,
54                 q => b
55         );
56
57         qcount(0) <= a xor b;
58         qcount(1) <= b;
59         qcount(31 downto 2) <= count;
60
61   comb_event: process (reset, last_reset, a_prev, b_prev, a, b)
62   begin
63     a_rise <= '0';
64     a_fall <= '0';
65     b_rise <= '0';
66     b_fall <= '0';
67     ab_event <= '0';
68     ab_error <= '0';
69
70                 if reset = '0' and last_reset = '0' then
71                         if ((a xor a_prev) and (b xor b_prev)) = '1' then
72                                 -- forbidden double transition
73                                 ab_error <= '1';
74                         else
75                                 a_rise <= (a xor a_prev) and a;
76                                 a_fall <= (a xor a_prev) and not a;
77                                 b_rise <= (b xor b_prev) and b;
78                                 b_fall <= (b xor b_prev) and not b;
79                                 ab_event <= (a xor a_prev) or (b xor b_prev);
80                         end if;
81                 end if;
82   end process;
83
84   comb_count: process (reset, last_reset, a_prev, b_prev, a, b, count_prev)
85   begin
86                 if reset = '1' or last_reset = '1' then
87                         count <= count_prev;
88                 elsif (a_prev = '0') and (b_prev = '1') and (a = '0') and (b = '0') then
89       count <= count_prev + 1;
90     elsif (a_prev = '0') and (b_prev = '0') and (a = '0') and (b = '1') then
91       count <= count_prev - 1;
92     else
93       count <= count_prev;
94     end if;
95   end process;
96
97   seq: process (clk)
98   begin
99                 -- Reset for qcounter is synchronous and lasts at least one more cycle
100                 -- to prevent hazardous states after releasing it
101                 if clk = '1' and clk'event then
102                         if reset = '0' then
103                                 count_prev <= count;
104                         else
105                                 count_prev <= (others => '0');
106                         end if;
107                         a_prev <= a;
108                         b_prev <= b;
109                         last_reset <= reset;
110                 end if;
111   end process;
112
113 end behavioral;