library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity omsp_quadcount is generic ( ADDR : std_logic_vector (15 downto 0) := X"0150"); port ( -- MCU peripheral interface mclk : in std_logic; puc : in std_logic; per_addr : in std_logic_vector (7 downto 0); per_en : in std_logic; per_irq : out std_logic; per_dout : out std_logic_vector (15 downto 0); -- QCounter component interface qclk : in std_logic; qreset : in std_logic; a0, b0 : in std_logic; qcount : out std_logic_vector (31 downto 0)); end omsp_quadcount; -------------------------------------------------------------------------------- architecture behavioral of omsp_quadcount is -- When reading whole 32-bit qcount input, first QCNTL has to be loaded, because -- this event causes QCNTH to latch appropriate value of qcount. This procedure -- ensures that correct value is readed. -- qcount lower word logic address constant QCNTL : std_logic_vector (15 downto 0) := ADDR; -- qcount higher word logic address constant QCNTH : std_logic_vector (15 downto 0) := ADDR + 2; -- Address read decoder signal qcntl_sel : boolean; signal qcnth_sel : boolean; -- Latch of high work of qcounter component signal qcnth_latch : std_logic_vector (15 downto 0); signal qcount_out : std_logic_vector (31 downto 0); -- AB error of qcounter component (lead in peripheral irq) signal ab_error : std_logic; component qcounter is port ( clock : in std_logic; reset : in std_logic; a0, b0 : in std_logic; qcount : out std_logic_vector (31 downto 0); a_rise : out std_logic; a_fall : out std_logic; b_rise : out std_logic; b_fall : out std_logic; ab_event : out std_logic; ab_error : out std_logic); end component qcounter; -------------------------------------------------------------------------------- begin qcounter_1: qcounter port map ( clock => qclk, reset => qreset, a0 => a0, b0 => b0, qcount => qcount_out, a_rise => open, a_fall => open, b_rise => open, b_fall => open, ab_event => open, ab_error => ab_error); qcntl_sel <= (per_addr = QCNTL(8 downto 1)) and (per_en = '1'); qcnth_sel <= (per_addr = QCNTH(8 downto 1)) and (per_en = '1'); per_dout <= qcount_out (15 downto 0) when qcntl_sel else qcnth_latch when qcnth_sel else (others => '0'); qcount <= qcount_out; -- QCNTL latch. process (mclk, puc) begin if (puc = '1') then qcnth_latch <= (others => '0'); elsif (rising_edge(mclk) and qcntl_sel) then qcnth_latch <= qcount_out (31 downto 16); end if; end process; -- Generation of IRQ signal. IRQ is cleared by QCNTL read operation. process (mclk, puc) begin if (puc = '1') then per_irq <= '0'; elsif (rising_edge(mclk)) then if (ab_error = '1') then per_irq <= '1'; elsif (qcntl_sel) then per_irq <= '0'; end if; end if; end process; end behavioral;