From: Vladimir Burian Date: Sun, 20 Mar 2011 19:05:15 +0000 (+0100) Subject: Added MCC_Master. X-Git-Url: http://rtime.felk.cvut.cz/gitweb/fpga/pwm.git/commitdiff_plain/f56fcef27b0f079f45010d5da7502207c953a356 Added MCC_Master. This is entity which should control execution of Motion-Control-Chain, e.g. IRC->Angle encoder, vector generator, current regulator, etc. --- diff --git a/mcc_master.vhd b/mcc_master.vhd new file mode 100644 index 0000000..64bf9ef --- /dev/null +++ b/mcc_master.vhd @@ -0,0 +1,147 @@ +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; + diff --git a/tb/Makefile b/tb/Makefile index 17fb380..fe0fb03 100644 --- a/tb/Makefile +++ b/tb/Makefile @@ -1,9 +1,10 @@ -VHDL_MAIN = tb_priority_encoder +VHDL_MAIN = tb_mcc_master VHDL_ENTITIES = counter.o \ pwm.o \ wave_table.o \ vector_gen.o \ - priority_encoder.o + priority_encoder.o \ + mcc_master.o STOP_TIME = 50us diff --git a/tb/tb_mcc_master.sav b/tb/tb_mcc_master.sav new file mode 100644 index 0000000..fceecae --- /dev/null +++ b/tb/tb_mcc_master.sav @@ -0,0 +1,17 @@ +[timestart] 0 +[size] 1280 746 +[pos] -1 -1 +*-33.430180 2370000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +@28 +clk_i +rst_i +stb_i +ack_o +dbg_mem0[15:0] +@22 +dbg_mem1[15:0] +dbg_mem2[15:0] +dbg_mem3[15:0] +dbg_mem4[15:0] +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/tb/tb_mcc_master.vhd b/tb/tb_mcc_master.vhd new file mode 100644 index 0000000..7b99fb1 --- /dev/null +++ b/tb/tb_mcc_master.vhd @@ -0,0 +1,221 @@ +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; +