【问题标题】:VHDL - comparing signals (integers) in IF-statementVHDL - 在 IF 语句中比较信号(整数)
【发布时间】:2016-02-12 13:30:52
【问题描述】:

我正在尝试编写代码来更改我的时钟频率。但是输出总是零……

signal cycle_counter : integer := 0;
signal HALFCYCLES : integer;
signal MY_CLK1, temporal : std_logic :='0';

frequency_divider: process (Clk,cycle_counter, HALFCYCLES) 
begin
   if rising_edge(Clk) then
          cycle_counter <= cycle_counter + 1;
          if cycle_counter = (HALFCYCLES-1) then 
              temporal <= NOT(temporal);
              cycle_counter <= 0;
          end if;
   end if;
      MY_CLK1 <= temporal;  
    end process frequency_divider;

当我输入某个整数值而不是 HALFCYCLES-1 时,一切正常,但我需要这个信号是可变的。 我相信,问题在于比较,但无法检测到。

我试图将 HALFCYCLES 设为变量,而不是信号,但编译器反对它:)

完整代码(主要目标 - 将两种不同的动画放入 LED 中。您应该通过切换器选择动画的频率和类型(输入 logic_vector S)

    library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity LED2 is
  generic (FIFT : std_logic_vector (15 downto 0) := "1111111111111111";
        ZERO : std_logic_vector (15 downto 0) := "0000000000000000");
    Port ( S : in  STD_LOGIC_VECTOR (7 downto 0);
           Clk : in  STD_LOGIC;
           R : in  STD_LOGIC;
           LED : out  STD_LOGIC_VECTOR (7 downto 0));
end LED2;

architecture Behavioral of LED2 is
signal statement: std_logic_vector (7 downto 0);
signal cycle_counter : integer := 0;
signal CNT1, CNT2, CURCNT, CNT_NO : integer:= 0;
signal HALFCYCLES : integer;
signal MY_CLK1, MY_CLK2, temporal : std_logic :='0';

begin

frequency_divider: process (Clk,cycle_counter, HALFCYCLES) begin
  if rising_edge(Clk) then
      cycle_counter <= cycle_counter + 1;
    if cycle_counter = (HALFCYCLES-1) then --(HALFCYCLES-1)
      temporal <= NOT(temporal);
      cycle_counter <= 0;
    end if;
  end if;
  MY_CLK1 <= temporal;
  MY_CLK2 <= temporal;  
end process frequency_divider;




counter1: PROCESS (MY_CLK1, R)
BEGIN
IF (MY_CLK1 = '1' AND MY_CLK1'EVENT) THEN
    IF (R='1')  THEN 
    CNT1 <=0;
    ELSIF (CNT1 = 15) THEN
      CNT1 <= 0;
    ELSE
      CNT1 <= CNT1 + 1;
   END IF;
END IF;
END PROCESS counter1;

counter2: PROCESS (MY_CLK2, R)
BEGIN
IF (MY_CLK2 = '1' AND MY_CLK2'EVENT) THEN
    IF (R='1')  THEN 
    CNT2 <=0;
    ELSE
    if (CNT2 = 15) then
      CNT2 <= 0;
      else
      CNT2 <= CNT2 + 1;
    end if;
  END IF;
END IF;
END PROCESS counter2;

freq_changer: PROCESS (CNT1, CNT2, S)
BEGIN
  IF (S(7) = '1')
  THEN HALFCYCLES <= 50000000;  CURCNT <= CNT1; CNT_NO <= 1;--1hz
  ELSIF (S(6) = '1')
  THEN HALFCYCLES <= 5000000;   CURCNT <= CNT2; CNT_NO <= 2;--10hz
  ELSIF (S(5) = '1')
  THEN HALFCYCLES <= 500000;    CURCNT <= CNT1; CNT_NO <= 1;--100hz
  ELSIF (S(4) = '1')
  THEN HALFCYCLES <= 50000;     CURCNT <= CNT2; CNT_NO <= 2;--1khz
  ELSIF (S(3) = '1')
  THEN HALFCYCLES <= 5000;      CURCNT <= CNT1; CNT_NO <= 1;--10khz
  ELSIF (S(2) = '1')
  THEN HALFCYCLES <= 500;           CURCNT <= CNT2; CNT_NO <= 2;--100khz
  ELSIF (S(1) = '1')
  THEN HALFCYCLES <= 50;            CURCNT <= CNT1; CNT_NO <= 1;--1mhz
  ELSIF (S(0) = '1')
  THEN HALFCYCLES <= 10;            CURCNT <= CNT2; CNT_NO <= 2;--5mhz
  ELSE HALFCYCLES <= 5;         CURCNT <= CNT1; CNT_NO <= 1;--10mhz
   END IF;
END PROCESS freq_changer;

main: PROCESS (CNT_NO, CURCNT)
BEGIN
c:  CASE  CNT_NO IS
    WHEN 2 =>
counter2:CASE CURCNT IS
        WHEN 0  => statement <= "00000001";
        WHEN 1  => statement <= "00000010";
        WHEN 2  => statement <= "00000100";
        WHEN 3  => statement <= "00001000";
        WHEN 4  => statement <= "00010000";
        WHEN 5  => statement <= "00100000";
        WHEN 6  => statement <= "01000000";
        WHEN 7  => statement <= "10000000";
        WHEN 8  => statement <= "10000000";
        WHEN 9  => statement <= "01000000";
        WHEN 10     => statement <= "00100000";
        WHEN 11     => statement <= "00010000";
        WHEN 12     => statement <= "00001000";
        WHEN 13     => statement <= "00000100";
        WHEN 14     => statement <= "00000010";
        WHEN 15     => statement <= "00000001";
        WHEN OTHERS => statement <= "00000000";
      END CASE counter2;

    WHEN OTHERS =>
counter1:CASE CURCNT IS
        WHEN 0  => statement <= "10000001";
        WHEN 1  => statement <= "01000010";
        WHEN 2  => statement <= "00100100";
        WHEN 3  => statement <= "00011000";
        WHEN 4  => statement <= "00011000";
        WHEN 5  => statement <= "00100100";
        WHEN 6  => statement <= "01000010";
        WHEN 7  => statement <= "10000001";
        WHEN 8  => statement <= "00011000";
        WHEN 9  => statement <= "00100100";
        WHEN 10     => statement <= "01000010";
        WHEN 11     => statement <= "10000001";
        WHEN 12     => statement <= "10000001";
        WHEN 13     => statement <= "01000010";
        WHEN 14     => statement <= "00100100";
        WHEN 15     => statement <= "00011000";
        WHEN OTHERS => statement <= "00000000";
      END CASE counter1;
  END CASE c;
  LED <= statement;
END PROCESS main;



end Behavioral;

测试台

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.Numeric_Std.all;



ENTITY LED_controller_tb IS
END LED_controller_tb;

ARCHITECTURE behavior OF LED_controller_tb IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT LED2
    PORT(
         S : IN  std_logic_vector(7 downto 0);
         Clk : IN  std_logic;
         R : IN  std_logic;
         LED : OUT  std_logic_vector(7 downto 0)
        );
    END COMPONENT;


   --Inputs
   signal S : std_logic_vector(7 downto 0) := (others => '0');
   signal Clk : std_logic := '0';
   signal R : std_logic := '0';

         --Outputs
   signal LED : std_logic_vector(7 downto 0);

   -- Clock period definitions
   constant Clk_period : time := 10 ns;

BEGIN

        -- Instantiate the Unit Under Test (UUT)
   uut: LED2 PORT MAP (
          S => S,
          Clk => Clk,
          R => R,
          LED => LED
        );

   -- Clock process definitions
   Clk_process :process
   begin
                Clk <= '0';
                wait for Clk_period/2;
                Clk <= '1';
                wait for Clk_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
            wait for Clk_period * 8;    

                S <= std_logic_vector(to_unsigned(to_integer(unsigned(S)) + 1, 8));

      -- insert stimulus here 

   end process;

reset: PROCESS
        BEGIN
                WAIT FOR  1 us;
                R <= '1';
                WAIT FOR 500 ns;
                R <= '0';
        END PROCESS reset;
END;

【问题讨论】:

  • 您似乎从未分配过HALFCYCLES。我建议将其设为常量,例如:constant HALFCYCLES : integer := 16;
  • 我还有另一个流程要分配 HALFYCLES
  • 不完整的例子。比较整数信号是可行的,但如果没有完整的例子,我们只能猜测为什么它不在这里。 stackoverflow.com/help/mcve
  • 没有模拟它:问题之一是您使用比较(“=”)作为计数器。当您更改阈值时,您的计数器实际上可能超过阈值。请改用“大于或等于”。
  • 使用 ModelSim 也可以。至少“时间”不拘泥于任何东西。除了应用我和 Matthew Taylor 上面提到的更改之外,我什么也没做。

标签: if-statement integer compare comparison vhdl


【解决方案1】:

我认为您在测试台中更改 S 太快了。我在您的测试台中更改了线路以等待更长的时间,它似乎工作正常。

按照 Andy 的建议,我会将您设计的第 26 行更改为

if cycle_counter >= (HALFCYCLES-1) then --(HALFCYCLES-1)

这是完整的(修改后的)测试平台。我还添加了一个停止模拟的过程;否则,它将永远运行:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.Numeric_Std.all;



ENTITY LED_controller_tb IS
END LED_controller_tb;

ARCHITECTURE behavior OF LED_controller_tb IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT LED2
    PORT(
         S : IN  std_logic_vector(7 downto 0);
         Clk : IN  std_logic;
         R : IN  std_logic;
         LED : OUT  std_logic_vector(7 downto 0)
        );
    END COMPONENT;


   --Inputs
   signal S : std_logic_vector(7 downto 0) := (others => '0');
   signal Clk : std_logic := '0';
   signal R : std_logic := '0';

         --Outputs
   signal LED : std_logic_vector(7 downto 0);

   -- Clock period definitions
   constant Clk_period : time := 10 ns;

BEGIN

        -- Instantiate the Unit Under Test (UUT)
   uut: LED2 PORT MAP (
          S => S,
          Clk => Clk,
          R => R,
          LED => LED
        );

   -- Clock process definitions
   Clk_process :process
   begin
                Clk <= '0';
                wait for Clk_period/2;
                Clk <= '1';
                wait for Clk_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
            wait for Clk_period * 800;   -- WAIT MUCH LONGER BEFORE CHANGING S ! 

                S <= std_logic_vector(to_unsigned(to_integer(unsigned(S)) + 1, 8));

      -- insert stimulus here 

   end process;

reset: PROCESS
        BEGIN
                WAIT FOR  1 us;
                R <= '1';
                WAIT FOR 500 ns;
                R <= '0';
        END PROCESS reset;

        STOP_SIM: process      -- OTHERWISE THE SIM RUNS FOREVER
        begin
          wait for Clk_period * 4000;
          assert FALSE severity FAILURE;
        end process;
END;

http://www.edaplayground.com/x/7XS

【讨论】:

  • 您应该在reset 进程的末尾添加一个wait;。要停止模拟,只需停止 clk_process 中的时钟即可。
猜你喜欢
  • 2016-05-09
  • 1970-01-01
  • 1970-01-01
  • 2018-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多