--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+library std;
+use std.textio.all;
+
+--------------------------------------------------------------------------------
+
+entity mcc_master is
+ generic (
+ MCC_W : integer := 5;
+ MUX_W : integer := 2;
+ IRF_ADR_W : integer := 5);
+ port (
+ -- Primary slave intefrace
+ ACK_O : out std_logic;
+ CLK_I : in std_logic;
+ RST_I : in std_logic;
+ STB_I : in std_logic;
+ -- Motion Control Chain
+ MCC_STB_O : out std_logic_vector (MCC_W-1 downto 0);
+ MCC_ACK_I : in std_logic_vector (MCC_W-1 downto 0);
+ MCC_MUX_CODE : out std_logic_vector (MUX_W-1 downto 0);
+ MCC_MUX_EN : out std_logic;
+ -- Shared dual-port memory
+ IRF_ACK_I : in std_logic;
+ IRF_ADR_O : out std_logic_vector (IRF_ADR_W-1 downto 0);
+ IRF_DAT_I : in std_logic_vector (15 downto 0);
+ IRF_DAT_O : out std_logic_vector (15 downto 0);
+ IRF_STB_O : out std_logic;
+ IRF_WE_O : out std_logic);
+end entity mcc_master;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of mcc_master is
+
+ type state_t is (ready, read_mask, do_mcc, done);
+
+ signal state : state_t;
+
+ signal mcc_mask : std_logic_vector (MCC_W-1 downto 0);
+ signal mcc_ack_inner : std_logic_vector (MCC_W downto 0);
+ signal mcc_stb_inner : std_logic_vector (MCC_W-1 downto 0);
+ signal mux_code_inner : std_logic_vector (MUX_W-1 downto 0);
+ signal mcc_exec : std_logic;
+
+--------------------------------------------------------------------------------
+
+begin
+
+ IRF_ADR_O <= conv_std_logic_vector(0, IRF_ADR_W);
+ IRF_DAT_O <= (others => '-');
+ IRF_WE_O <= '0';
+
+
+ priority_encoder_1: entity work.priority_encoder
+ generic map (
+ SEL_W => MCC_W,
+ CODE_W => MUX_W)
+ port map (
+ sel => mcc_stb_inner,
+ code => mux_code_inner);
+
+
+ MCC_EXEC_LOGIC : process (RST_I, CLK_I) is
+ begin
+ if RST_I = '1' then
+ mcc_ack_inner <= (others => '0');
+ mcc_stb_inner <= (others => '0');
+
+ elsif rising_edge(CLK_I) then
+ mcc_ack_inner (0) <= mcc_exec;
+
+ for i in 0 to MCC_W-1 loop
+ if mcc_mask (i) = '1' then
+ mcc_ack_inner (i+1) <= MCC_ACK_I (i);
+ mcc_stb_inner (i) <= mcc_ack_inner (i);
+ else
+ mcc_ack_inner (i+1) <= mcc_ack_inner (i);
+ mcc_stb_inner (i) <= '0';
+ end if;
+ end loop;
+ end if;
+ end process;
+
+
+ LATCHES : process (RST_I, CLK_I) is
+ begin
+ if RST_I = '1' then
+ MCC_STB_O <= (others => '0');
+ MCC_MUX_CODE <= (others => '0');
+
+ elsif rising_edge(CLK_I) then
+ MCC_STB_O <= mcc_stb_inner;
+ MCC_MUX_CODE <= mux_code_inner;
+ end if;
+ end process;
+
+
+ FSM : process (CLK_I, RST_I) is
+ begin
+ if RST_I = '1' then
+ state <= ready;
+ ACK_O <= '0';
+ mcc_exec <= '0';
+ MCC_MUX_EN <= '0';
+ IRF_STB_O <= '0';
+
+ elsif rising_edge(CLK_I) then
+ case state is
+ when ready =>
+ if STB_I = '1' then
+ state <= read_mask;
+ IRF_STB_O <= '1';
+ end if;
+
+ when read_mask =>
+ if IRF_ACK_I = '1' then
+ state <= do_mcc;
+ mcc_mask <= IRF_DAT_I (mcc_mask'RANGE);
+ MCC_MUX_EN <= '1';
+ mcc_exec <= '1';
+ end if;
+
+ when do_mcc =>
+ if mcc_ack_inner (MCC_W) = '1' then
+ state <= done;
+ ACK_O <= '1';
+ IRF_STB_O <= '0';
+ MCC_MUX_EN <= '0';
+ mcc_exec <= '0';
+ end if;
+
+ when done =>
+ if STB_I = '0' then
+ state <= ready;
+ ACK_O <= '0';
+ end if;
+ end case;
+ end if;
+ end process;
+
+end architecture behavioral;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity tb_mcc_master is
+end tb_mcc_master;
+
+--------------------------------------------------------------------------------
+
+architecture testbench of tb_mcc_master is
+
+ constant period : time := 1 us;
+ constant offset : time := 0 us;
+
+ constant LUT_DAT_W : integer := 10;
+ constant LUT_ADR_W : integer := 9;
+ constant LUT_INIT_FILE : string := "../sin.lut";
+ constant IRF_ADR_W : integer := 5;
+
+ constant WAVE_SIZE : integer := 2**LUT_ADR_W;
+
+
+ signal ACK_O : std_logic;
+ signal CLK_I : std_logic;
+ signal RST_I : std_logic;
+ signal STB_I : std_logic;
+
+ signal IRF_ACK_I : std_logic;
+ signal IRF_ADR_O : std_logic_vector (IRF_ADR_W-1 downto 0);
+ signal IRF_CYC_O : std_logic;
+ signal IRF_DAT_I : std_logic_vector (15 downto 0);
+ signal IRF_DAT_O : std_logic_vector (15 downto 0);
+ signal IRF_STB_O : std_logic;
+ signal IRF_WE_O : std_logic;
+
+ signal LUT_ADR_O : std_logic_vector (LUT_ADR_W-1 downto 0);
+ signal LUT_DAT_I : std_logic_vector (LUT_DAT_W-1 downto 0);
+ signal LUT_STB_O : std_logic;
+
+ signal MCC_ACK : std_logic_vector (3 downto 0);
+ signal MCC_STB : std_logic_vector (3 downto 0);
+ signal MCC_MUX_CODE : std_logic_vector (1 downto 0);
+ signal MCC_MUX_EN : std_logic;
+
+
+ signal MASTER_IRF_ADR_O : std_logic_vector (IRF_ADR_W-1 downto 0);
+ signal MASTER_IRF_DAT_O : std_logic_vector (15 downto 0);
+ signal MASTER_IRF_STB_O : std_logic;
+ signal MASTER_IRF_WE_O : std_logic;
+
+ signal VECTOR_IRF_ADR_O : std_logic_vector (IRF_ADR_W-1 downto 0);
+ signal VECTOR_IRF_DAT_O : std_logic_vector (15 downto 0);
+ signal VECTOR_IRF_STB_O : std_logic;
+ signal VECTOR_IRF_WE_O : std_logic;
+
+
+ subtype word_t is std_logic_vector (15 downto 0);
+
+ signal dbg_mem0 : word_t := "0000000000000010"; -- read only by UUT
+ signal dbg_mem1 : word_t := (others => '0'); -- read only by vector_gen
+ signal dbg_mem2 : word_t := (others => '0');
+ signal dbg_mem3 : word_t := (others => '0');
+ signal dbg_mem4 : word_t := (others => '0');
+ signal dbg_ack : std_logic := '0';
+
+--------------------------------------------------------------------------------
+
+begin
+
+ IRF_ADR_O <= MASTER_IRF_ADR_O when MCC_MUX_EN = '0' else
+ VECTOR_IRF_ADR_O when MCC_MUX_CODE = 1 else
+ (others => '-');
+
+ IRF_DAT_O <= MASTER_IRF_DAT_O when MCC_MUX_EN = '0' else
+ VECTOR_IRF_DAT_O when MCC_MUX_CODE = 1 else
+ (others => '-');
+
+ IRF_STB_O <= MASTER_IRF_STB_O when MCC_MUX_EN = '0' else
+ VECTOR_IRF_STB_O when MCC_MUX_CODE = 1 else
+ '0';
+
+ IRF_WE_O <= MASTER_IRF_WE_O when MCC_MUX_EN = '0' else
+ VECTOR_IRF_WE_O when MCC_MUX_CODE = 1 else
+ '0';
+
+
+ uut : entity work.mcc_master
+ generic map (
+ MCC_W => 4,
+ MUX_W => 2,
+ IRF_ADR_W => IRF_ADR_W)
+ port map (
+ ACK_O => ACK_O,
+ CLK_I => CLK_I,
+ RST_I => RST_I,
+ STB_I => STB_I,
+ MCC_STB_O => MCC_STB,
+ MCC_ACK_I => MCC_ACK,
+ MCC_MUX_CODE => MCC_MUX_CODE,
+ MCC_MUX_EN => MCC_MUX_EN,
+ IRF_ACK_I => IRF_ACK_I,
+ IRF_ADR_O => MASTER_IRF_ADR_O,
+ IRF_DAT_I => IRF_DAT_I,
+ IRF_DAT_O => MASTER_IRF_DAT_O,
+ IRF_STB_O => MASTER_IRF_STB_O,
+ IRF_WE_O => MASTER_IRF_WE_O);
+
+ vector_gen_1 : entity work.vector_gen
+ generic map (
+ A_BASE => 1,
+ P_BASE => 2)
+ port map (
+ ACK_O => MCC_ACK (1),
+ CLK_I => CLK_I,
+ RST_I => RST_I,
+ STB_I => MCC_STB (1),
+ IRF_ACK_I => IRF_ACK_I,
+ IRF_ADR_O => VECTOR_IRF_ADR_O,
+ IRF_CYC_O => open,
+ IRF_DAT_I => IRF_DAT_I,
+ IRF_DAT_O => VECTOR_IRF_DAT_O,
+ IRF_STB_O => VECTOR_IRF_STB_O,
+ IRF_WE_O => VECTOR_IRF_WE_O,
+ LUT_ADR_O => LUT_ADR_O,
+ LUT_DAT_I => LUT_DAT_I,
+ LUT_STB_O => LUT_STB_O);
+
+ wave_table_1 : entity work.wave_table
+ generic map (
+ DAT_W => LUT_DAT_W,
+ ADR_W => LUT_ADR_W,
+ INIT_FILE => LUT_INIT_FILE)
+ port map (
+ ACK_O => open,
+ ADR_I => LUT_ADR_O,
+ CLK_I => CLK_I,
+ DAT_I => (others => '0'),
+ DAT_O => LUT_DAT_I,
+ STB_I => LUT_STB_O,
+ WE_I => '0');
+
+
+ SYSCON_CLK : process is
+ begin
+ CLK_I <= '0';
+ wait for offset;
+ loop
+ CLK_I <= '1';
+ wait for period/2;
+ CLK_I <= '0';
+ wait for period/2;
+ end loop;
+ end process;
+
+ SYSCON_RST : process is
+ begin
+ RST_I <= '0';
+ wait for offset;
+ wait for 0.75*period;
+ RST_I <= '1';
+ wait for 2*period;
+ RST_I <= '0';
+ wait;
+ end process;
+
+
+ DBG_MEM : process (IRF_STB_O, CLK_I) is
+ begin
+ IRF_ACK_I <= IRF_STB_O and (IRF_WE_O or dbg_ack);
+
+ if rising_edge(CLK_I) then
+ dbg_ack <= IRF_STB_O;
+ end if;
+
+ if rising_edge(CLK_I) and IRF_STB_O = '1' then
+ if IRF_WE_O = '0' then
+ case conv_integer(IRF_ADR_O) is
+ when 0 => IRF_DAT_I <= dbg_mem0;
+ when 1 => IRF_DAT_I <= dbg_mem1;
+ when 2 => IRF_DAT_I <= dbg_mem2;
+ when 3 => IRF_DAT_I <= dbg_mem3;
+ when 4 => IRF_DAT_I <= dbg_mem4;
+ when others => IRF_DAT_I <= (others => '0');
+ end case;
+ else
+ case conv_integer(IRF_ADR_O) is
+ when 1 => dbg_mem1 <= IRF_DAT_O;
+ when 2 => dbg_mem2 <= IRF_DAT_O;
+ when 3 => dbg_mem3 <= IRF_DAT_O;
+ when 4 => dbg_mem4 <= IRF_DAT_O;
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end process;
+
+--------------------------------------------------------------------------------
+
+ UUT_FEED : process is
+ begin
+ STB_I <= '0';
+
+ wait for offset;
+ wait for 4*period;
+
+ for i in 0 to 1 loop
+ --dbg_mem0 <= (others => '0');
+ --dbg_mem0(LUT_ADR_O'RANGE) <= conv_std_logic_vector(i, LUT_ADR_W);
+
+ STB_I <= '1';
+ wait until rising_edge(CLK_I) and ACK_O = '1';
+ STB_I <= '0';
+ wait for 4*period;
+ end loop;
+
+ wait;
+ end process;
+
+end testbench;
+