因此,本实验的目的是模拟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;
答案 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
部分可能在意外时间为真,并且
根据内部时序,这可能导致(部分)异步复位
如果用硬件实现,这些问题很难被捕获,因为它们不会
在模拟中展示。