2013-03-21 2 views
0

Я написал несколько компонентов для перемещения шагового двигателя назад и вперед. Я имитировал его в modelsim, и он работает так, как ожидалось, но он совсем не работает на аппаратном уровне.VHDL имитирует штраф, но не действует на аппаратном уровне

В основном у меня есть компонент управления двигателем, который принимает команду за количество шагов, удерживает время и скорость, а затем выполняет движение. Затем у меня есть control_arbiter, который является лишь промежуточным мостом, который соединяет компоненты, желающие получить доступ к моторам и компонентам привода двигателя. Наконец, у меня есть компонент «шаблон поиска», который в основном выдает команды для перемещения двигателя вперед и назад.

Моя проблема в том, что я не могу изменить направление, когда оно работает на аппаратном обеспечении, независимо от того, работает ли оно в симуляции.

Любая помощь с этим было бы весьма признателен

водитель

двигателя:

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.std_logic_unsigned.all; 


entity motor_ctrl is 

port( clk: in std_logic; 

     -- Hardware ports 
     SCLK, CW, EN: out std_logic; -- stepper driver control pins 

     -- Soft ports 
     Speed, steps: in integer; 
     dir: in std_logic;   -- 1 = CW; 0 = CCW; 
     hold_time: in integer;  -- if > 0, steppers will be held on for this many clock periods after moving 
     ready: out std_logic;  -- indicates if ready for a movement 
     activate: in std_logic;  -- setting activate starts instructed motion. 
     pos_out: out integer   -- starts at 2000, 180deg = 200 steps, 10 full rotations trackable 
     ); 

end motor_ctrl; 


architecture behavioural of motor_ctrl is 

type action is (IDLE, HOLD, MOVE); 
signal motor_action: action := IDLE; 

signal clk_new: std_logic; 
signal position: integer := 2000; 

signal step_count: integer := 0; 
signal drive: boolean := false; 

begin 

-- Clock divider 
clk_manipulator: entity work.clk_divide port map(clk, speed, clk_new); 

-- Drive motors 
with drive select 
    SCLK <= clk_new when true, 
        '0' when false; 

pos_out <= position; 

process(clk_new) 
    -- Counter variables 
    variable hold_count: integer := 0;  
begin 

    if rising_edge(clk_new) then 
     case motor_action is 

      when IDLE => 
       -- reset counter vars, disable the driver and assert 'ready' signal 
       hold_count := 0; 
       step_count <= 0; 
       drive <= false; 
       EN <= '0'; 
       ready <= '1'; 

       -- When activated, start moving and de-assert ready signal 
       if(activate = '1') then 
        motor_action <= MOVE; 
       end if; 

      when HOLD => 
       -- Stop the step clock signal 
       ready <= '0'; 
       drive <= false; 
       -- Hold for given number of clock periods before returning to idle state 
       if(hold_count = hold_time) then 
        motor_action <= IDLE; 
       end if; 
       -- increment counter 
       hold_count := hold_count + 1; 

      when MOVE =>      
       -- Enable driver, apply clock output and set direction 
       ready <= '0'; 
       EN <= '1'; 
       drive <= true; 
       CW <= dir;  

       -- track the position of the motor 
       --if(dir = '1') then  
       -- position <= steps + step_count; 
       --else 
       -- position <= steps - step_count; 
       --end if; 

       -- Increment count until complete, then hold/idle 
       if(step_count < steps-1) then 
        step_count <= step_count + 1; 
       else 
        motor_action <= HOLD; 
       end if; 

     end case; 
    end if; 

end process; 


end behavioural; 

Control_arbiter:

entity Control_arbiter is 

port (clk: in std_logic; 
     EN, RST, CTRL, HALF, SCLK, CW: out std_logic_vector(2 downto 0) 
     -- needs signals for levelling and lock 
     ); 

end Control_arbiter; 


architecture fsm of Control_arbiter is 

type option is (INIT, SEARCH); 
signal arbitration: option := INIT; 

-- Motor controller arbiter signals 
-- ELEVATION 
signal El_spd, El_stps, El_hold, El_pos: integer; 
signal El_dir, El_rdy, El_run: std_logic; 


-- Search signals 
signal search_spd, search_stps, search_hold: integer; 
signal search_dir, search_Az_run, search_El_run: std_logic := '0'; 
-- status 
signal lock: std_logic := '0'; 

begin 

-- Motor controller components 
El_motor: entity work.motor_ctrl port map(clk, SCLK(0), CW(0), EN(0), 
                 El_spd, El_stps, El_dir, El_hold, El_rdy, El_run);              


-- Search component 
search_cpmnt: entity work.search_pattern port map( clk, '1', search_dir, search_stps, search_spd, search_hold, 
                    El_rdy, search_El_run); 


process(clk, arbitration) 

begin 

    if rising_edge(clk) then 

     case arbitration is 

      when INIT => 
       -- Initialise driver signals 
       EN(2 downto 1) <= "11"; 
       CW(2 downto 1) <= "11"; 
       SCLK(2 downto 1) <= "11"; 
       RST <= "111"; 
       CTRL <= "111"; 
       HALF <= "111"; 
       -- Move to first stage 
       arbitration <= SEARCH; 

      when SEARCH => 
       -- Map search signals to motor controllers 
       El_dir <= search_dir; 
       El_stps <= search_stps; 
       El_spd <= search_spd; 
       El_hold <= search_hold; 
       El_run <= search_El_run; 
       -- Pass control to search 
       -- Once pointed, begin search maneuvers 
       -- map search signals to motor controllers 
       -- set a flag to begin search 
       -- if new pointing instruction received, break and move to that position (keep track of change) 
       -- On sensing 'lock', halt search 
       -- return to holding that position 


     end case; 

    end if; 

end process; 


end fsm; 

Поиск Узор:

entity search_pattern is 

generic (step_inc: unsigned(7 downto 0) := "00010000" 
      ); 
port (clk: in std_logic; 
     enable: in std_logic; 
     dir: out std_logic; 
     steps, speed, hold_time: out integer; 
     El_rdy: in std_logic; 
     El_run: out std_logic 
     ); 

end search_pattern; 


architecture behavioural of search_pattern is 

type action is (WAIT_FOR_COMPLETE, LATCH_WAIT, MOVE_EL_CW, MOVE_EL_CCW); 
signal search_state: action := WAIT_FOR_COMPLETE; 
signal last_state: action := MOVE_EL_CCW; 

begin 

hold_time <= 1; 
speed <= 1; 
steps <= 2; 

process(clk) 

begin 

    if rising_edge(clk) then 

     -- enable if statement 

      case search_state is 

       when LATCH_WAIT => 
        -- Make sure a GPMC has registered the command before waiting for it to complete 
        if(El_rdy = '0') then  -- xx_rdy will go low if a stepper starts moving 
         search_state <= WAIT_FOR_COMPLETE;  -- Go to waiting state and get ready to issue next cmd 
        end if; 

       when WAIT_FOR_COMPLETE => 

        -- Wait for the movement to complete before making next 
        if(El_rdy = '1') then  
         -- Choose next command based on the last 
         if last_state = MOVE_EL_CCW then 
          search_state <= MOVE_EL_CW; 
         elsif last_state = MOVE_EL_CW then 
          search_state <= MOVE_EL_CCW; 
         end if; 
        end if;    

       when MOVE_EL_CW => 
        dir <= '1'; 
        El_run <= '1'; 
        last_state <= MOVE_EL_CW; 
        search_state <= LATCH_WAIT; 

       when MOVE_EL_CCW => 
        dir <= '0'; 
        El_run <= '1'; 
        last_state <= MOVE_EL_CCW; 
        search_state <= LATCH_WAIT; 

       when others => 
        null; 
      end case; 

     -- else step reset on not enable 

    end if; 

end process; 

end behavioural;   

Sim: http://i.imgur.com/JAuevvP.png

+0

У вас больше шансов получить ответы от специалистов VHDL по адресу http://electronics.stackexchange.com/. – Lundin

+0

Я только что быстро взглянул на код и заметил, что у вашего контрольного арбитра есть так называемый процесс, который также чувствителен к сигналу «арбитраж». Синхронизированные процессы должны быть чувствительны только к тактовому сигналу и, возможно, к асинхронному сбросу. Вы можете попробовать исследование, что дальше ... – sonicwave

+0

Когда моделирование и реальная жизнь расходятся: http://stackoverflow.com/a/15204291/106092 –

ответ

1

сканирования быстро через ваш код, есть некоторые вещи, которые вы должны изменить для синтеза:

1) часы делителя: сделать процесс motor_driver чувствителен к CLK вместо clk_new. для деления часов генерируйте сигнал разрешения одного тактового цикла каждые n часов. Бегин процесса может выглядеть следующим образом:

process(clk) 
     ... 
    begin 

    if rising_edge(clk) then 
     if enable='1' then 
      case motor_action is 
      ... 

2) инициализация вида

signal position: integer := 2000; 

работает только для моделирования, но не работает для синтеза. для инициализации в синтезе используют сигнал сброса в процессе.

3) добавьте во все свои государственные машины условие «когда другие», где состояние установлено на определенное значение (например, search_state < = INIT).

+0

Я думаю, что я понимаю, что вы говорите, в основном, но я m с реальной трудностью понимая, как я буду генерировать эти часы. Будет ли это просто подсчет границ часов в отдельном процессе и запуск разрешения, когда он достигнет желаемого значения? – Kureigu

+0

Да, если счетчик достигнет целевого значения, перезапустите счетчик, чтобы активировать сигнал включения. убедитесь, что вы активируете активировать только один цикл clk! – baldyHDL

+0

Я сейчас пробовал это, но у меня все еще такая же проблема. Независимо от того, что я делаю, выход «dir» все равно не изменится, несмотря на то, что время от времени он меняет тонкость моделирования. Если кому-то интересно, [здесь zip компонентов] (https://www.dropbox.com/s/bsy2vgwuv6wt8uh/TB_search_pattern.zip) – Kureigu

Смежные вопросы