0

我真的是 vhdl 的新手,我想做某种 KIT led mechanizm。我的代码应该像这样工作-我使用 18 种不同的状态来点亮从 led0 到 led7 的 LED,然后从 led7 回到 led0 等等。实际上,我的状态和 select 函数做了我想要的,它就像一个梦想,但我想加速这个 mod,并为此代码添加 2 个其他 pwm 信号。我写了 pwm 信号,但不能在 with case 状态下使用这些信号。

这取决于当前状态。例如。当我在s5时,我想做这样的事情-

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

是我必须在其他 2 个进程中编写 pwm 信号的问题,还是我应该如何处理它才能工作?谢谢您的帮助。

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;
4

1 回答 1

1

不需要将使用PWM 的代码重写为单独的进程,但它可能有助于结构和可读性,从而使您更容易让代码工作。一些观察和建议:

  • 在单独的过程中创建 PWM 输出,因为不同 PWM 信号的生成与状态更新或 LED 驱动没有直接关系,因此如果您在单独的过程中分离不相关的功能,您可能更容易保持良好的概览。

  • 在 knight_rider 进程中,可以从 case 中删除对“0”的复位信号检查,因为在该进程中通过 if 的第一部分将 reset 用作异步复位,因此当第二部分生效时,它始终为“0” .

  • 代替 state_type 中的 18 个状态,您可以考虑使用受控的 std_logic_vector 作为上下计数器,因为看起来您以这种方式使用状态。

  • 使 LED 成为std_logic_vector(0 to 7)单独的输出而不是单独的输出,并使用上面建议的 std_logic_vector 状态来索引 LED,因此可以避免在代码中显式驱动每个 LED。

  • 而不是Counter = "10011000100101101000000"use CONV_STD_LOGIC_VECTOR(5000000, Counter'length),因为这使得读取值更容易。

  • 为了可读性,而不是Counter <= "0000000000000000000000000"使用Counter <= (others => '0')或 CONV_STD_LOGIC_VECTOR(0, Counter'length)。

  • 如果您使用一致的缩进,您可以显着提高代码的可读性,例如,不让三个end case; end if; end if;都在同一级别。也只使用空格进行缩进,以避免使用制表符时可能出现的任何奇怪的格式。

  • 中的语法错误with ... select,因为 clkout60 和 clkout20 不应该是 'clkout60' 和 'clkout20',只是普通的 clkout60 和 clkout20。

  • clk_out_20 和 clk_out_60 inwith ... select不存在,但这可能正在进行中。

于 2013-08-13T05:51:01.273 回答