时间代码编译但不能工作VHDL ModelSim

时间:2013-10-23 04:00:14

标签: time vhdl clock modelsim

因此,本实验的目的是模拟ModelSim中的模块代码,以显示计时器使用测试工作台(我无法改变)。当我模拟时,只改变时钟波形,并且我的所有十六进制显示始终为0b1000000。有人可以帮我找到为什么计时器不运行?

CODE:

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

entity PRELAB7 is
port (clk,load_n,reset_n : in std_logic;
    sw : in std_logic_vector (15 downto 0);
--for the set hr min sec
     hex2   : out std_logic_vector(6 downto 0);
     hex4 : out std_logic_vector(6 downto 0);
     hex6   : out std_logic_vector(6 downto 0);
     hex3 : out std_logic_vector(6 downto 0);
     hex5 : out std_logic_vector(6 downto 0);
     hex7   : out std_logic_vector(6 downto 0)
     );
    end PRELAB7;

    architecture Behavioral of PRELAB7 is
    SIGNAL sec,min,hour         :std_logic_vector(6 DOWNTO 0);
    SIGNAL int_count                :std_logic_vector(27 DOWNTO 0);
    CONSTANT MAX_VAL                :std_logic_vector(27 DOWNTO 0):= x"2FAF080";
    SIGNAL timer_flag               :std_logic;
    SIGNAL temp_sec,temp_min,temp_hour :std_logic_vector(6 DOWNTO 0) := "0000000";

    CONSTANT ZERO   : STD_LOGIC_VECTOR(6 downto 0) :="1000000"; --0
    CONSTANT ONE    : STD_LOGIC_VECTOR(6 downto 0) :="1111001"; --1
    CONSTANT TWO    : STD_LOGIC_VECTOR(6 downto 0) :="0100100"; --2
    CONSTANT THREE  : STD_LOGIC_VECTOR(6 downto 0) :="0110000"; --3
    CONSTANT FOUR   : STD_LOGIC_VECTOR(6 downto 0) :="0011001"; --4
    CONSTANT FIVE   : STD_LOGIC_VECTOR(6 downto 0) :="0010010"; --5
    CONSTANT SIX    : STD_LOGIC_VECTOR(6 downto 0) :="0000010"; --6
    CONSTANT SEVEN  : STD_LOGIC_VECTOR(6 downto 0) :="1111000"; --7
CONSTANT EIGHT  : STD_LOGIC_VECTOR(6 downto 0) :="0000000"; --8
CONSTANT NINE   : STD_LOGIC_VECTOR(6 downto 0) :="0010000"; --9

begin
    timer:PROCESS(clk,reset_n)
    BEGIN
        if(reset_n = '0') then  
            int_count <=(others => '0');
        elsif(rising_edge(clk)) then    
            if(int_count = MAX_VAL) then
                int_count <= (others => '0');
                timer_flag <= '1';
            else
                int_count <= int_count + 1;
                timer_flag <= '0';
            end if;
        end if;
    END PROCESS;

    seconds:PROCESS(reset_n,sec,clk,load_n)
    BEGIN
        if (reset_n = '1' OR sec > 59 OR load_n = '1') then
            sec <= "0000000";
        else
            if(rising_edge(clk)) then
    --          if timer_flag = '1' then
                sec <= sec + 1;
    --          end if;
            else
                sec <= sec;
            end if;
        end if;
    END PROCESS;

    minutes:PROCESS(reset_n,min,sec,clk,load_n,sw)
    BEGIN
        if (reset_n = '1' OR min > 59) then
            min <= "0000000";
        Elsif load_n = '1' then
            min(6 DOWNTO 4) <= sw(6 downto 4);
            min(3 DOWNTO 0) <= sw(3 downto 0);
        else
            if(sec = 59) then
                if rising_edge(clk) then
    --              if timer_flag = '1' then
                    min <= min + 1;
    --              end if;
                end if;
            else
                min <= min;
            end if;
        end if;
    END PROCESS;

    hours:PROCESS(reset_n,hour,min,sec,clk,load_n,sw)
    BEGIN
        if (reset_n = '1' OR hour > 23) then
            hour <= "0000000";
        elsif (load_n = '1') then
            hour(6 DOWNTO 4) <= sw(13 downto 11);
            hour(3 DOWNTO 0) <= sw(10 downto 7);
        else
            if ((min = 59) AND (sec = 59)) then
                if (rising_edge(clk)) then
    --              if timer_flag = '1' then
                    hour <= hour + 1;
    --              end if;
                end if;
            else
                hour <= hour;
            end if;
        end if;
    END PROCESS;



    tenhour_display:PROCESS(hour)
    BEGIN
        IF(hour < 10) THEN
            hex7 <= ZERO;
        ELSIF(hour < 20)THEN
            hex7 <= ONE;
        else
            hex7 <= TWO;
        END IF;
    END PROCESS;

    onehour_display:PROCESS(hour,temp_hour)
    BEGIN
        IF(hour < 10) THEN
            temp_hour <= hour;
        ELSIF (hour < 20) THEN
            temp_hour <= hour - 10;
        ELSE
            temp_hour <= hour -20;
        END IF;

        IF temp_hour = 0 THEN
            hex6 <= ZERO;
        ELSIF temp_hour = 1 THEN
            hex6 <= ONE;
        ELSIF temp_hour = 2 THEN
            hex6 <= TWO;
        ELSE
            hex6 <= THREE;
        END IF;
    END PROCESS;

    tenmin_display:PROCESS(min)
    BEGIN
        IF(min < 10) THEN
            hex5 <= ZERO;
        ELSIF (min < 20) THEN
            hex5 <= ONE;
        ELSIF (min < 30) THEN
            hex5 <= TWO;
        ELSIF (min < 40) THEN
            hex5 <= THREE;
        ELSIF (min < 50) THEN
            hex5 <= FOUR;
        ELSE
            hex5 <= FIVE;
        END IF;
    END PROCESS;

    onemin_display:PROCESS(min,temp_min)
    BEGIN
        IF(min < 10) THEN
            temp_min <= min;
        ELSIF (min < 20) THEN
            temp_min <= min - 10;
        ELSIF (min < 30) THEN
            temp_min <= min -20;
        ELSIF (min < 40) THEN
            temp_min <= min -30;
        ELSIF (min < 50) THEN
            temp_min <= min -40;
        ELSE
            temp_min <= min - 50;
        END IF;

        IF temp_min = 0 THEN
            hex4 <= ZERO;
        ELSIF temp_min = 1 THEN
            hex4 <= ONE;
        ELSIF temp_min = 2 THEN
            hex4 <= TWO;
        ELSIF temp_min = 3 THEN
            hex4 <= THREE;
        ELSIF temp_min = 4 THEN
            hex4 <= FOUR;
        ELSIF   temp_min = 5 THEN
            hex4 <= FIVE;
        ELSIF temp_min = 6 THEN
            hex4 <= SIX;
        ELSIF temp_min = 7 THEN
            hex4 <= SEVEN;
        ELSIF temp_min = 8 THEN
            hex4 <= EIGHT;
        ELSE 
            hex4 <= NINE;
        END IF;
    END PROCESS;

    tensec_display:PROCESS(sec)
    BEGIN
        IF(sec < 10) THEN
            hex3 <= ZERO;
        ELSIF (sec < 20) THEN
            hex3 <= ONE;
        ELSIF (sec < 30) THEN
            hex3 <= TWO;
        ELSIF (sec < 40) THEN
            hex3 <= THREE;
        ELSIF (sec < 50) THEN
            hex3 <= FOUR;
        ELSE
            hex3 <= FIVE;
        END IF;
    END PROCESS;

    sec_display:PROCESS(sec,temp_sec)
    BEGIN
        IF(sec < 10) THEN
            temp_sec <= sec;
        ELSIF (sec < 20) THEN
            temp_sec <= sec - 10;
        ELSIF (sec < 30) THEN
            temp_sec <= sec -20;
        ELSIF (sec < 40) THEN
            temp_sec <= sec -30;
        ELSIF (sec < 50) THEN
            temp_sec <= sec -40;
        ELSE
            temp_sec <= sec - 50;
        END IF;    

        IF temp_sec = 0 THEN
            hex2 <= ZERO;
        ELSIF temp_sec = 1 THEN
            hex2 <= ONE;
        ELSIF temp_sec = 2 THEN
            hex2 <= TWO;
        ELSIF temp_sec = 3 THEN
            hex2 <= THREE;
        ELSIF temp_sec = 4 THEN
            hex2 <= FOUR;
        ELSIF   temp_sec = 5 THEN
            hex2 <= FIVE;
        ELSIF temp_sec = 6 THEN
            hex2 <= SIX;
        ELSIF temp_sec = 7 THEN
            hex2 <= SEVEN;
        ELSIF temp_sec = 8 THEN
            hex2 <= EIGHT;
        ELSE 
            hex2 <= NINE;
        END IF;
    END PROCESS;

END behavioral;     

TEST BENCH:

--*****************************************************************************
--***************************  VHDL Source Code  ******************************
--*********  Copyright 2010, Rochester Institute of Technology  ***************
--*****************************************************************************
--
--  DESIGNER NAME:  Jeanne Christman
--
--       LAB NAME:  VHDL Timers and Counter
--
--      FILE NAME:  TOD_tb.vhd
--
-------------------------------------------------------------------------------
--
--  DESCRIPTION
--
--    This test bench will provide input to test the implemention of the 
--    circuit on the DE2 board that acts as a time-of-day clock. It displays 
--    the hour (from 0 to 23) on the 7-segment displays HEX7-6, the minute 
--    (from 0 to 60) on HEX5-4 and the second (from 0 to 60) on HEX3-2.
--    The contents of the value displayed on the 7-segment displays must be 
--    manually verfied.
--
-------------------------------------------------------------------------------
--
--  REVISION HISTORY
--
--  _______________________________________________________________________
-- |  DATE    | USER | Ver |  Description                                  |
-- |==========+======+=====+================================================
-- |          |      |     |
-- | 10/16/13 | JWC  | 1.0 | Created
-- |          |      |     |
--
--*****************************************************************************
--*****************************************************************************


LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY TOD_tb IS
END TOD_tb;


ARCHITECTURE test OF TOD_tb IS

   -- Component Declaration for the Unit Under Test (UUT)
   -- if you use a package with the component defined then you do not need this
   COMPONENT PRELAB7
      PORT (
         clk       : IN  std_logic;
         reset_n   : IN  std_logic;
         load_n    : IN  std_logic;
         SW        : IN  std_logic_vector(15 DOWNTO 0);
         --
         hex2          : OUT std_logic_vector(6 DOWNTO 0);
         hex3          : OUT std_logic_vector(6 DOWNTO 0);
         hex4          : OUT std_logic_vector(6 DOWNTO 0);
         hex5          : OUT std_logic_vector(6 DOWNTO 0);
         hex6          : OUT std_logic_vector(6 DOWNTO 0);
         hex7          : OUT std_logic_vector(6 DOWNTO 0)
         );
   END COMPONENT;

   -- define signals for component ports
   SIGNAL clock_50      : std_logic                     := '0';
   SIGNAL sys_reset_n   : std_logic                     := '0';
   SIGNAL load_enable_n : std_logic                     := '0';
   SIGNAL bcd_load_time : std_logic_vector(15 DOWNTO 0) := x"0000";
   --
   -- Outputs
   SIGNAL hex2          : std_logic_vector(6 DOWNTO 0);
   SIGNAL hex3          : std_logic_vector(6 DOWNTO 0);
   SIGNAL hex4          : std_logic_vector(6 DOWNTO 0);
   SIGNAL hex5          : std_logic_vector(6 DOWNTO 0);
   SIGNAL hex6          : std_logic_vector(6 DOWNTO 0);
   SIGNAL hex7          : std_logic_vector(6 DOWNTO 0);

   -- signals for test bench control
   SIGNAL sim_done : boolean := false;
   SIGNAL PERIOD_c : time    := 20 ns;  -- 50MHz

BEGIN  -- test

   -- component instantiation
   UUT : PRELAB7
      PORT MAP (
         clk           => clock_50,
         reset_n       => sys_reset_n,
         load_n        => load_enable_n,
         SW            => bcd_load_time,
         --
         hex2          => hex2,
         hex3          => hex3,
         hex4          => hex4,
         hex5          => hex5,
         hex6          => hex6,
         hex7          => hex7
         );

   -- This creates an clock_50 that will shut off at the end of the Simulation
   -- this makes a clock_50 that you can shut off when you are done.
   clock_50 <= NOT clock_50 AFTER PERIOD_C/2 WHEN (NOT sim_done) ELSE '0';


   ---------------------------------------------------------------------------
   -- NAME: Stimulus
   --
   -- DESCRIPTION:
   --    This process will apply stimulus to the UUT.
   ---------------------------------------------------------------------------
   stimulus : PROCESS
   BEGIN
      -- de-assert all inputs except the reset which is asserted
      sys_reset_n   <= '0';
      load_enable_n <= '1';
      bcd_load_time <= x"0000";
      WAIT FOR 5 ns;

      -- now lets sync the stimulus to the clock_50
      -- move stimulus 1ns after clock edge
      WAIT UNTIL clock_50 = '1';
      WAIT FOR 1 ns;

      -- de-assert reset and let run for 4 seconds
      sys_reset_n <= '1';
      WAIT FOR 20*PERIOD_C;  -- adjust this time to lengthen/shorten sim

      -- load a new time
      load_enable_n <= '0';
      bcd_load_time <= x"1958";
      WAIT FOR 5*PERIOD_C;
      load_enable_n <= '1';
      WAIT FOR 3 sec;  -- adjust this time to lengthen/shorten sim


      -- shutting down simulation
      sim_done <= true;
      WAIT FOR PERIOD_c*1;

      -----------------------------------------------------------------------
      -- This Last WAIT statement needs to be here to prevent the PROCESS
      -- sequence from re starting.
      -----------------------------------------------------------------------
      WAIT;

   END PROCESS stimulus;



END test;

1 个答案:

答案 0 :(得分:1)

卡住计数器的一个原因是复位信号为reset_n,其中 _n通常表示低电平(0)时复位有效,即 在设计中也是如此,可以在测试台和波形中看到。

但是,PRELAB7模块使用重置,就好像活动为高,如图所示 这个和其他代码部分:

...
seconds:PROCESS(reset_n,sec,clk,load_n)
BEGIN
  if (reset_n = '1' OR sec > 59 OR load_n = '1') then
    sec <= "0000000";
  else
    if(rising_edge(clk)) then
      sec <= sec + 1;
...

所以至少在开始时你应该使用reset_n = '0'来检查是否有效 重置,而不是reset_n = '1'

侧面评论:使用复杂表达式作为条件不能保存 异步复位,如上所述:

if (reset_n = '1' OR sec > 59 OR load_n = '1') then

原因是sec计数器中不同位的更新可能略有偏差 由于内部时序而在硬件中,因此在更新期间sec可能显示为:

  

55:0b110111(结算后的最终价值)

     

63:0b111111(中间值,其中位3在位2:0变为'0'之前变为'1')

     

56:0b111000(结算后的最终价值)

因此表达式的sec > 59部分可能在意外时间为真,并且 根据内部时序,这可能导致(部分)异步复位 如果用硬件实现,这些问题很难被捕获,因为它们不会 在模拟中展示。