2013-08-13 2 views
0

Я действительно новичок в vhdl, и я хочу сделать какой-то KIT led mechanizm. Мой код должен работать следующим образом: я использую 18 различных состояний для подсвечивания светодиодов от led0 до led7, и он возвращается от led7 до led0 и т. Д. На самом деле мои состояния и с функцией выбора выполняли то, что я хочу, и он работал как Dream, но я хотел, чтобы Turbo этот мод, и добавить еще 2 pwm сигнал для этого кода. Я написал сигналы pwm, но не могу использовать их в состоянии case.PWM-сигнал в vhdl-KIT led mechanizm

Это зависит от текущего состояния. Например. когда я в s5, я хочу сделать некоторые, как this-

led5-100% led4-60% led3-20%

Есть проблема, что я должен написать Pwm сигналы в другом 2 процесса, или что мне с ним делать? Спасибо за помощь.

Here is my code: 

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.STD_LOGIC_UNSIGNED.ALL; 
use IEEE.STD_LOGIC_ARITH.ALL; 

entity knight_rider is 
port(
LED0, LED1, LED2, LED3, LED4, LED5, LED6, LED7: out std_logic; 
clk, reset: in std_logic); 

end knight_rider; 

architecture Behavioral of knight_rider is 
type state_type is (start0,s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15,s16); 
signal current_s: state_type; 
signal Counter: std_logic_vector(24 downto 0); 
signal temp1_20: std_logic; 
signal temp1_60: std_logic; 
signal temp2_20: std_logic; 
signal temp2_60: std_logic; 
signal temp3_20: std_logic; 
signal temp3_60: std_logic; 
signal counter1_20: integer range 0 to 2048 := 0; -- counter1 for 20% bright 
signal counter1_60: integer range 0 to 2048 := 0; -- counter1 for 60% bright 
signal counter2_20: integer range 0 to 2048 := 0; -- counter2 for 20% bright 
signal counter2_60: integer range 0 to 2048 := 0; -- counter2 for 60% bright 
signal clkout60,clkout20: std_logic; 
begin 

knight_rider: process (clk, reset) 

begin 

    if (reset='1') then 
    current_s <=start0; 

    elsif rising_edge(clk) then 
    counter1_60<=counter1_60 + 1;     --pwm for 60% briht 

     if (counter1_60 = 2048) then 
       temp1_60 <= '1'; 

       counter1_60 <= 0; 

    end if; 

       if temp1_60 = '1' then 
        temp3_60 <='1'; 
        temp2_60 <= '1'; 
        temp1_60 <='0'; 
       end if; 

       if temp3_60 = '1' then 

        counter2_60 <=counter2_60 + 1; 
        if (counter2_60 =1230) then 
          temp2_60 <= '0'; 
          temp3_60 <='0'; 
          counter2_60 <= 0; 
          clkout60<=temp2_60; 
        end if; 
       end if; 
    counter1_20<=counter1_20 + 1; --pwm for 20% bright 

     if (counter1_20 = 2048) then 
       temp1_20 <= '1'; 

       counter1_20 <= 0; 

      end if; 

       if temp1_20 = '1' then 
        temp3_20 <='1'; 
        temp2_20 <= '1'; 
        temp1_20 <='0'; 
       end if; 

       if temp3_20 = '1' then 

        counter2_20 <=counter2_20 + 1; 
        if (counter2_20 <=410) then 
          temp2_20 <= '0'; 
          temp3_20 <='0'; 
          counter2_20 <= 0; 
          clkout20<=temp2_20; 
        end if; 
       end if; 

     Counter<= Counter + 1;        -- statements: From here, its actually do what I want... 
     if Counter="10011000100101101000000" then  -- but with clkout20, and clkout60 something's wrong 
      Counter<="0000000000000000000000000"; 
      case current_s is 

       when start0 => 
        current_s <=s0; 

       when s0 => 
        if (reset ='0') then 
         current_s <=s1; 

        else 
         current_s <= start0; 
        end if; 

       when s1 => 
        if (reset = '0') then 
         current_s <=s2; 
        else 
         current_s <= s0; 
        end if; 

       when s2 => 
        if (reset = '0') then 
         current_s <=s3; 

        else 
         current_s <= s1; 
        end if; 

       when s3 => 
        if (reset = '0') then 
         current_s <=s4; 

        else 
         current_s <= s2; 
        end if; 

       when s4 => 
        if (reset = '0') then 
         current_s <=s5; 

        else 
         current_s <= s3; 
        end if; 

       when s5 => 
        if (reset = '0') then 
         current_s <=s6; 

        else 
         current_s <= s4; 
        end if; 

       when s6 => 
        if (reset = '0') then 
         current_s <=s7; 

        else 
         current_s <= s5; 
        end if; 

       when s7 => 
        if (reset = '0') then 
         current_s <=s8; 

        else 
         current_s <= s6; 
        end if; 

       when s8 => 
        if (reset = '0') then 
         current_s <=s9; 
        else 
         current_s <= s7; 
        end if; 

       when s9 => 
        if (reset = '0') then 
         current_s <=s10; 
        else 
         current_s <= s8; 
        end if; 

       when s10 => 
        if (reset = '0') then 
         current_s <=s11; 
        else 
         current_s <= s9; 
        end if; 

       when s11 => 
        if (reset = '0') then 
         current_s <=s12; 
        else 
         current_s <= s10; 
        end if; 

       when s12 => 
        if (reset = '0') then 
         current_s <=s13; 
        else 
         current_s <= s11; 
        end if; 


       when s13 => 
        if (reset = '0') then 
         current_s <=s14; 
        else 
         current_s <= s12; 
        end if; 

       when s14 => 
        if (reset = '0') then 
         current_s <=s15; 
        else 
         current_s <= s13; 
        end if; 

       when s15 => 
        if (reset = '0') then 
         current_s <=s16; 
        else 
         current_s <= s14; 
        end if; 

       when s16=> current_s <= s0; 

       when others => null; 
      end case; 
      end if; 
      end if; 

end process; 


       with current_s select 
       LED0 <= '1' when s0|s15, 
          'clkout60' when s1, 
          'clkout20' when s2, 
          '0' when others; 

       with current_s select 
       LED1 <= '1' when s1|s14, 
          'temp2_60' when s2|s15, 
          'clkout20' when s3, 
          '0' when others; 

       with current_s select 
       LED2 <= '1' when s2|s13, 
          'clk_out_60' when s3|s14, 
          'clk_out_20' when s4|s15, 
          '0' when others; 

       with current_s select 
       LED3 <= '1' when s3|s12, 
          'clk_out_60' when s4|13, 
          'clk_out_20' when s5|s14, 
          '0' when others; 

       with current_s select 
       LED4 <= '1' when s4|s11, 
          'clk_out_60' when s5|12, 
          'clk_out_20' when s6|s13, 
          '0' when others; 

       with current_s select 
       LED5 <= '1' when s5|s10, 
          'clk_out_60' when s6|s11, 
          'clk_out_20' when s7|s12, 
          '0' when others; 

       with current_s select 
       LED6 <= '1' when s6 | s9, 
          'clk_out_60' when s7|s10, 
          'clk_out_20' when s8|s11, 
          '0' when others; 

       with current_s select 
       LED7 <= '1' when s7 |s8, 
          'clk_out_60' when s9, 
          'clk_out_20' when s10, 
          '0' when others; 

    end Behavioral; 

ответ

1

Не требуется , что вы переписать код с ШИМ для отдельного процесса, но это может помочь в структуре и читаемость, что делает его более легким для вас, чтобы получить код до работы. Некоторые замечания и предложения:

  • Создание ШИМ выходов в отдельном процессе, так как поколение различных сигналов ШИМ не напрямую связаны с государственным обновлением или LED диск, так это, вероятно, проще для вас сохраните хороший обзор, если вы отделите несвязанные функции в отдельных процессах.

  • сброса проверка сигнала для «0» может быть удалена из корпуса в процессе knight_rider , поскольку сброс используется в качестве асинхронного сброса через первую часть в случае, в этом процессе, поэтому, когда вторая часть вступает в силу , всегда '0'.

  • Вместо 18 государств state_type, вы можете рассмотреть возможность использования std_logic_vector контролируемого как счетчик вверх-вниз, так как в этом случае вы используете состояния, что путь.

  • сделать СИД как std_logic_vector(0 to 7) вместо отдельных выходов, и использование государством std_logic_vector предложено выше, индексировать светодиоды, так явно привод каждого светодиода можно избежать в коде.

  • Вместо Counter = "10011000100101101000000" использование CONV_STD_LOGIC_VECTOR(5000000, Counter'length), так как это делает чтение значению гораздо проще.

  • Вместо Counter <= "0000000000000000000000000" использовать Counter <= (others => '0') или CONV_STD_LOGIC_VECTOR (0, длина контрмера), для удобства чтения.

  • Вы можете значительно улучшить читабельность вашего кода, если вы используете согласованный отступ, например. не имея трех end case; end if; end if; все на такой же уровень. Также используйте только пространство для отступа, чтобы избежать какого-либо странного форматирования , которое может возникать при использовании вкладок.

  • Синтаксическая ошибка в with ... select, так как clkout60 и clkout20 не должны быть 'clkout60' и 'clkout20', просто clkout60 и clkout20.

  • Clk_out_20 и clk_out_60 в with ... select не существует, но , вероятно, работает.