--- /dev/null
+library ieee;
+use ieee.std_logic_1164.ALL;
+use ieee.std_logic_arith.ALL;
+
+--------------------------------------------------------------------------------
+
+entity capture_reg is
+ generic (
+ W : integer := 32);
+ port (
+ -- Peripheral bus interface
+ ACK_O : out std_logic;
+ CLK_I : in std_logic;
+ DAT_O : out std_logic_vector (W-1 downto 0);
+ SEL_I : in std_logic;
+ STB_I : in std_logic;
+ -- QCounter component interface
+ EVENT_I : in std_logic;
+ CAPTURE_I : in std_logic_vector (W-1 downto 0));
+end capture_reg;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of capture_reg is
+
+ signal capture_mem : std_logic_vector (W-1 downto 0);
+
+--------------------------------------------------------------------------------
+
+begin
+
+ ACK_O <= SEL_I and STB_I;
+ DAT_O <= capture_mem;
+
+
+ process (CLK_I)
+ begin
+ if rising_edge(CLK_I) and EVENT_I = '1' then
+ capture_mem <= CAPTURE_I;
+ end if;
+ end process;
+
+end behavioral;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.ALL;
+use ieee.std_logic_arith.ALL;
+
+--------------------------------------------------------------------------------
+
+entity capture_reg16 is
+ port (
+ -- Peripheral bus interface
+ ACK_O : out std_logic;
+ ADR_I : in std_logic_vector (0 downto 0);
+ CLK_I : in std_logic;
+ DAT_O : out std_logic_vector (15 downto 0);
+ SEL_I : in std_logic;
+ STB_I : in std_logic;
+ -- QCounter component interface
+ EVENT_I : in std_logic;
+ CAPTURE_I : in std_logic_vector (31 downto 0));
+end capture_reg16;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of capture_reg16 is
+
+ signal CR_DAT_O : std_logic_vector (31 downto 0);
+
+--------------------------------------------------------------------------------
+
+begin
+
+ with ADR_I select
+ DAT_O <=
+ CR_DAT_O (15 downto 0) when "0",
+ CR_DAT_O (31 downto 16) when "1",
+ (others => 'X') when others;
+
+
+ capture_reg0 : entity work.capture_reg
+ generic map (
+ W => 32)
+ port map (
+ ACK_O => ACK_O,
+ CLK_I => CLK_I,
+ DAT_O => CR_DAT_O,
+ SEL_I => SEL_I,
+ STB_I => STB_I,
+ EVENT_I => EVENT_I,
+ CAPTURE_I => CAPTURE_I);
+
+end behavioral;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+
+--------------------------------------------------------------------------------
+
+entity event_rwc is
+ generic (
+ W : integer := 16); -- Event port width (pin count)
+ port (
+ -- Peripheral bus interface
+ ACK_O : out std_logic;
+ CLK_I : in std_logic;
+ DAT_I : in std_logic_vector (W-1 downto 0);
+ DAT_O : out std_logic_vector (W-1 downto 0);
+ RST_I : in std_logic;
+ SEL_I : in std_logic;
+ STB_I : in std_logic;
+ WE_I : in std_logic;
+ -- Event port pins
+ EVENT_I : in std_logic_vector (W-1 downto 0);
+ EVENT_O : out std_logic_vector (W-1 downto 0));
+end event_rwc;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of event_rwc is
+
+ signal status : std_logic_vector (W-1 downto 0) := (others => '0');
+ signal write_en : std_logic;
+
+begin
+
+ ACK_O <= SEL_I and STB_I;
+ DAT_O <= status;
+
+ EVENT_O <= status;
+
+ write_en <= SEL_I and STB_I and WE_I;
+
+ process (CLK_I, RST_I) is
+ begin
+ if rising_edge(CLK_I) then
+ if RST_I = '1' then
+ status <= (others => '0');
+ else
+ if write_en = '1' then
+ status <= (status and not DAT_I) or EVENT_I;
+ else
+ status <= status or EVENT_I;
+ end if;
+ end if;
+ end if;
+ end process;
+
+end behavioral;
+
vhdl work mcu_periph/gpio.vhd
vhdl work mcu_periph/qcounter_mcu16.vhd
+vhdl work mcu_periph/event_rwc.vhd
+vhdl work mcu_periph/capture_reg.vhd
+vhdl work mcu_periph/capture_reg16.vhd
#==============================================================================#
# Top-level design file #
signal QCNT_SEL : std_logic;
-- Motor feedback IRQ generator
signal MOTOR_IRQ : std_logic;
-
+ -- Event register
+ signal EVENT_DAT_O : std_logic_vector (15 downto 0);
+ signal EVENT_SEL : std_logic;
+ signal event_i : std_logic_vector (15 downto 0);
+ signal event_o : std_logic_vector (15 downto 0);
+ -- Qcounter capture
+ signal CAPTURE_SEL : std_logic;
+ signal CAPTURE_DAT : std_logic_vector (15 downto 0);
+ -- IRC index detection
+ signal INDEX_DETECT_DAT_O : std_logic_vector (15 downto 0);
+ signal INDEX_DETECT_SEL : std_logic;
+
------------------------------------------------------------------------------
-- Dual-port shared memory
------------------------------------------------------------------------------
signal PWM3_OUT : std_logic;
-- IRC value
signal QCNT : std_logic_vector (31 downto 0);
+ -- IRC capturing
+ signal IRC_INDEX_DFF : std_logic; -- IRC_INDEX aligned with global clock
+ signal IRC_INDEX_EVENT : std_logic;
--------------------------------------------------------------------------------
------------------------------------------------------------------------------
per_dout <= GPIO_DAT_O when GPIO_SEL = '1' else
QCNT_DAT_O when QCNT_SEL = '1' else
+ EVENT_DAT_O when EVENT_SEL = '1' else
+ CAPTURE_DAT when CAPTURE_SEL = '1' else
+ INDEX_DETECT_DAT_O when INDEX_DETECT_SEL ='1' else
(others => '0'); -- MUST be 0 when nothing is addressed
GPIO_SEL <= '1' when per_addr(7 downto 2) = 16#0140#/2/4 else '0';
QCNT_SEL <= '1' when per_addr(7 downto 1) = 16#0148#/2/2 else '0';
+ EVENT_SEL <= '1' when per_addr(7 downto 0) = 16#014C#/2 else '0';
+ CAPTURE_SEL <= '1' when per_addr(7 downto 1) = 16#0150#/2/2 else '0';
+ INDEX_DETECT_SEL <= '1' when per_addr(7 downto 1) = 16#0152#/2/2 else '0';
+
+ per_wen16 <= per_wen(0) and per_wen(1);
-- Interrupt signals
------------------------------------------------------------------------------
count => open,
event_ow => MOTOR_IRQ);
+ event_io_0 : entity work.event_rwc
+ port map (
+ -- Peripheral bus interface
+ ACK_O => open,
+ CLK_I => mclk,
+ DAT_I => per_din,
+ DAT_O => EVENT_DAT_O,
+ RST_I => puc,
+ SEL_I => EVENT_SEL,
+ STB_I => per_en,
+ WE_I => per_wen16,
+ -- Event port pins
+ EVENT_I => event_i,
+ EVENT_O => event_o);
+
+ event_i(0) <= (not IRC_INDEX_DFF) and (not event_o(0));
+ IRC_INDEX_EVENT <= event_i(0);
+
+
+ irc_index_dff_0 : entity work.dff
+ port map (
+ clock => mclk,
+ d => IRC_INDEX,
+ q => IRC_INDEX_DFF);
+
+ capture_reg16_0 : entity work.capture_reg16
+ port map (
+ ACK_O => open,
+ ADR_I => per_addr (0 downto 0),
+ CLK_I => mclk,
+ DAT_O => CAPTURE_DAT,
+ SEL_I => CAPTURE_SEL,
+ STB_I => per_en,
+ EVENT_I => IRC_INDEX_EVENT,
+ CAPTURE_I => QCNT);
------------------------------------------------------------------------------
-- Dual-port shared memory