Таисия
Таисия

Reputation: 43

VHDL - comparing signals (integers) in IF-statement

I am trying to write code to change the frequency of my clock. But the output is always zeroes...

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;

When i put instead of HALFCYCLES-1 some integer value, all is working just fine, but i need this signal to be changeable. I believe, that the problem is in comparing, but can't detect it.

I tried to make HALFCYCLES a variable, instead of signal, but compiler was against it :)

Full code (main goan - to put in the LED two different animations. Frequency and type of animation you should choose via switchers (input 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;

testbench

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;

Upvotes: 1

Views: 5374

Answers (1)

Matthew
Matthew

Reputation: 14007

I think you are changing S far too quickly in your testbench. I changed line in your testbench to wait for a much longer time and it seems to work OK.

As recommended by Andy, I would change line 26 of your design to

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

Here's the (modified) testbench in full. I have also added a process to stop the simulation; otherwise, it runs forever:

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

Upvotes: 1

Related Questions