]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blobdiff - hw/qcounter.vhd
RoCoN: USB CDC ACM use maximal packet length - 64 bytes.
[fpga/lx-cpu1/lx-rocon.git] / hw / qcounter.vhd
index 1e9489e408a509a5f4f1a4c77a4b417133770ced..4ef4ded68c02a8dc33472084567cf1bb1f2bbf51 100644 (file)
@@ -3,102 +3,172 @@ use ieee.std_logic_1164.all;
 use ieee.std_logic_arith.all;
 use ieee.std_logic_unsigned.all;
 use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
 
 -- Quadcounter (for IRC)
 
 entity qcounter is
   port
        (
-    clk      : in std_logic;
-    reset    : in std_logic;
-    a0, b0   : in std_logic;
-
-    qcount   : out std_logic_vector (31 downto 0);
-    a_rise, a_fall, b_rise, b_fall, ab_event: out std_logic;
-    ab_error : out std_logic
+               -- Inputs
+    clk_i                : in std_logic;
+    reset_i              : in std_logic;
+    a0_i, b0_i           : in std_logic;
+               index0_i             : in std_logic;
+               -- State
+               reset_index_event_i  : in std_logic;
+               reset_index_event2_i : in std_logic;
+               reset_ab_error_i     : in std_logic;
+               -- Outputs
+    qcount_o             : out std_logic_vector (7 downto 0);
+               qcount_index_o       : out std_logic_vector (7 downto 0);
+               index_o              : out std_logic;
+               index_event_o        : out std_logic;
+               index_event2_o       : out std_logic;
+    a_rise_o, a_fall_o   : out std_logic;
+               b_rise_o, b_fall_o   : out std_logic;
+               ab_event_o           : out std_logic;
+    ab_error_o           : out std_logic
   );
 end qcounter;
 
 architecture behavioral of qcounter is
-  component dff
-       port
+
+       signal last_reset_s       : std_logic;
+  signal a_s, b_s           : std_logic;
+       signal a_prev_s, b_prev_s : std_logic;
+       signal ab_error_s         : std_logic;
+       signal ab_error_int_s     : std_logic;
+       signal index_event_int_s  : std_logic;
+       signal index_event2_int_s : std_logic;
+       signal index_s            : std_logic;
+       signal index_prev_s       : std_logic;
+  signal count_prev_s       : std_logic_vector (5 downto 0);
+  signal count_s            : std_logic_vector (5 downto 0);
+       signal count_out_s        : std_logic_vector (7 downto 0);
+  signal count_index_s      : std_logic_vector (7 downto 0);
+
+begin
+dff_a: dff3
+       port map
        (
-               clk   : in std_logic;
-               reset : in std_logic;
-               d     : in std_logic;
-               q     : out std_logic
+               clk_i   => clk_i,
+               d_i     => a0_i,
+               q_o     => a_s
        );
-  end component;
 
-subtype std_logic4 is std_logic_vector (3 downto 0);
-  signal a, b, a_prev, b_prev: std_logic;
-  signal count_prev: std_logic_vector (29 downto 0);
-  signal count: std_logic_vector (29 downto 0);
-begin
-       dff_a: dff
+ dff_b: dff3
        port map
        (
-               clk => clk,
-               reset => reset,
-               d => a0,
-               q => a
+               clk_i   => clk_i,
+               d_i     => b0_i,
+               q_o     => b_s
        );
 
-  dff_b: dff
+dff_index: dff3
        port map
        (
-               clk => clk,
-               reset => reset,
-               d => b0,
-               q => b
+               clk_i   => clk_i,
+               d_i     => index0_i,
+               q_o     => index_s
        );
 
-       qcount(0) <= a xor b;
-       qcount(1) <= b;
-       qcount(31 downto 2) <= count;
-
-  comb_event: process (a_prev, b_prev, a, b)
-  begin
-    a_rise <= '0';
-    a_fall <= '0';
-    b_rise <= '0';
-    b_fall <= '0';
-    ab_event <= '0';
-    ab_error <= '0';
-    if ((a xor a_prev) and (b xor b_prev)) = '1' then
-      -- forbidden double transition
-      ab_error <= '1';
-    else
-      a_rise <= (a xor a_prev) and a;
-      a_fall <= (a xor a_prev) and not a;
-      b_rise <= (b xor b_prev) and b;
-      b_fall <= (b xor b_prev) and not b;
-      ab_event <= (a xor a_prev) or (b xor b_prev);
-    end if;
+       count_out_s(0)          <= a_s xor b_s;
+       count_out_s(1)          <= b_s;
+       count_out_s(7 downto 2) <= count_s;
+       --
+       qcount_o                <= count_out_s;
+       qcount_index_o          <= count_index_s;
+       --
+       ab_error_o              <= ab_error_int_s;
+       index_o                 <= index_s;
+       index_event_o           <= index_event_int_s;
+       index_event2_o          <= index_event2_int_s;
+
+comb_event:
+       process (reset_i, last_reset_s, a_prev_s, b_prev_s, a_s, b_s)
+       begin
+    a_rise_o   <= '0';
+    a_fall_o   <= '0';
+    b_rise_o   <= '0';
+    b_fall_o   <= '0';
+    ab_event_o <= '0';
+    ab_error_s <= '0';
+
+               if reset_i = '0' and last_reset_s = '0' then
+                       if ((a_s xor a_prev_s) and (b_s xor b_prev_s)) = '1' then
+                               -- forbidden double transition
+                               ab_error_s <= '1';
+                               ab_event_o <= '0';
+                       else
+                               a_rise_o   <= (a_s xor a_prev_s) and a_s;
+                               a_fall_o   <= (a_s xor a_prev_s) and (not a_s);
+                               b_rise_o   <= (b_s xor b_prev_s) and b_s;
+                               b_fall_o   <= (b_s xor b_prev_s) and (not b_s);
+                               ab_event_o <= (a_s xor a_prev_s) or (b_s xor b_prev_s);
+                       end if;
+               end if;
   end process;
 
-  comb_count: process (a_prev, b_prev, a, b, count, count_prev)
-  begin
-    if (a_prev = '0') and (b_prev = '1') and (a = '0') and (b = '0') then
-      count <= count_prev + 1;
-    elsif (a_prev = '0') and (b_prev = '0') and (a = '0') and (b = '1') then
-      count <= count_prev - 1;
+comb_count:
+       process (reset_i, last_reset_s, a_prev_s, b_prev_s, a_s, b_s,
+                                               index_s, count_prev_s)
+       begin
+
+               if reset_i = '1' or last_reset_s = '1' then
+                       count_s                      <= count_prev_s;
+               elsif (a_prev_s = '0') and (b_prev_s = '1') and (a_s = '0') and
+                                               (b_s = '0') then
+      count_s                      <= count_prev_s + 1;
+    elsif (a_prev_s = '0') and (b_prev_s = '0') and (a_s = '0') and
+                                               (b_s = '1') then
+      count_s                      <= count_prev_s - 1;
     else
-      count <= count_prev;
+      count_s                      <= count_prev_s;
     end if;
+
   end process;
 
-  seq: process (clk)
-  begin
-    if clk = '1' and clk'event then
-                       if reset = '0' then
-                               count_prev <= (others => '0');
-                       else
-                               count_prev <= count;
+seq:
+       process
+               variable index_event_v      : std_logic;
+       begin
+               -- Reset for qcounter is synchronous and lasts at least one more cycle
+               -- to prevent hazardous states after releasing it
+               wait until clk_i'event and clk_i = '1';
+
+               index_event_v         := '0';
+
+               if reset_i = '1' then
+                       count_prev_s        <= (others => '0');
+                       count_index_s       <= (others => '0');
+                       index_event_int_s   <= '0';
+                       index_event2_int_s  <= '0';
+                       ab_error_int_s      <= '0';
+                       index_prev_s        <= '1';
+               else
+
+                       if index_s = '1' and index_prev_s = '0' then
+                               count_index_s     <= count_out_s;
+                               index_event_v     := '1';
                        end if;
-                       a_prev <= a;
-                       b_prev <= b;
+                       --
+                       index_event_int_s <= (index_event_int_s and not reset_index_event_i) or
+                                            index_event_v;
+                       --
+                       index_event2_int_s <= (index_event2_int_s and not reset_index_event2_i) or
+                                             reset_index_event_i;
+                       --
+                       ab_error_int_s    <= (ab_error_int_s and not reset_ab_error_i) or ab_error_s;
+                       --
+                       count_prev_s        <= count_s;
+                       index_prev_s        <= index_s;
+
                end if;
+
+               a_prev_s              <= a_s;
+               b_prev_s              <= b_s;
+               last_reset_s          <= reset_i;
   end process;
 
 end behavioral;