pridan quadcount
[fpga/rpi-motor-control.git] / pmsm-control / qcounter.vhdl
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.dff.all;
7
8 entity qcounter is
9   port (
10     clock: in std_logic;
11     reset: in std_logic;
12     a0, b0: in std_logic;
13     qcount: out std_logic_vector (31 downto 0);
14     a_rise, a_fall, b_rise, b_fall, ab_event: out std_logic;
15     ab_error: out std_logic
16   );
17 end qcounter;
18
19 architecture behavioral of qcounter is
20   component dff
21     port (
22       clock: in std_logic;
23       d: in std_logic;
24       q: out std_logic
25     );
26   end component;
27
28 subtype std_logic4 is std_logic_vector (3 downto 0);
29   signal a, b, a_prev, b_prev: std_logic;
30   signal count_prev: std_logic_vector (29 downto 0)
31     := "000000000000000000000000000000";
32   signal count: std_logic_vector (29 downto 0);
33 begin
34   dff_a: dff
35     port map (
36       clock => clock,
37       d => a0,
38       q => a
39     );
40   dff_b: dff
41     port map (
42       clock => clock,
43       d => b0,
44       q => b
45     );
46   
47   qcount(0) <= a xor b;
48   qcount(1) <= b;
49   qcount(31 downto 2) <= count;
50   
51   comb_event: process (a_prev, b_prev, a, b)
52   begin
53     a_rise <= '0';
54     a_fall <= '0';
55     b_rise <= '0';
56     b_fall <= '0';
57     ab_event <= '0';
58     ab_error <= '0';
59     if ((a xor a_prev) and (b xor b_prev)) = '1' then
60       -- forbidden double transition
61       ab_error <= '1';
62     else
63       a_rise <= (a xor a_prev) and a;
64       a_fall <= (a xor a_prev) and not a;
65       b_rise <= (b xor b_prev) and b;
66       b_fall <= (b xor b_prev) and not b;
67       ab_event <= (a xor a_prev) or (b xor b_prev);
68     end if;
69   end process;
70
71   comb_count: process (a_prev, b_prev, a, b, count)
72   begin
73     if (a_prev = '0') and (b_prev = '1') and (a = '0') and (b = '0') then
74       count <= count_prev + 1;
75     elsif (a_prev = '0') and (b_prev = '0') and (a = '0') and (b = '1') then
76       count <= count_prev - 1;
77     else
78       count <= count_prev;
79     end if;
80   end process;
81
82   seq: process
83   begin
84     wait until clock'event and clock = '1';
85     if reset = '1' then
86       count_prev <= "000000000000000000000000000000";
87     else
88       count_prev <= count;
89     end if;
90     a_prev <= a;
91     b_prev <= b;
92   end process;
93
94 end behavioral;