]> rtime.felk.cvut.cz Git - fpga/pwm.git/commitdiff
Added MCC_Master.
authorVladimir Burian <buriavl2@fel.cvut.cz>
Sun, 20 Mar 2011 19:05:15 +0000 (20:05 +0100)
committerVladimir Burian <buriavl2@fel.cvut.cz>
Sun, 20 Mar 2011 19:05:15 +0000 (20:05 +0100)
This is entity which should control execution of Motion-Control-Chain,
e.g. IRC->Angle encoder, vector generator, current regulator, etc.

mcc_master.vhd [new file with mode: 0644]
tb/Makefile
tb/tb_mcc_master.sav [new file with mode: 0644]
tb/tb_mcc_master.vhd [new file with mode: 0644]

diff --git a/mcc_master.vhd b/mcc_master.vhd
new file mode 100644 (file)
index 0000000..64bf9ef
--- /dev/null
@@ -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;
+
index 17fb380c8876a8637416d601e495ee18c637c0d3..fe0fb03548889010eb04274ba12cbfff29b268c2 100644 (file)
@@ -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 (file)
index 0000000..fceecae
--- /dev/null
@@ -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 (file)
index 0000000..7b99fb1
--- /dev/null
@@ -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;
+