我对总是发送U的vhdl实体的输出有问题。我看了各种论坛,但我找不到解决方案。
该项目是一个5层高的电梯,必须等待5秒才能关门,等待10秒才能到达下一架到达目标的飞机。使用Logisim (2.13.22版)和ghdl (0.29.1版)。
有没有人知道问题出在哪里?提前感谢


这是我写的vhdl代码。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Elevator is
Port (
clk : in std_logic;
rst : in std_logic;
rstPorta : in std_logic;
rstMotore : in std_logic;
zero : in std_logic;
one : in std_logic;
two : in std_logic;
three : in std_logic;
four : in std_logic;
upEngine : out std_logic;
downEngine : out std_logic;
ledReady: out std_logic;
ledUp: out std_logic;
ledDown: out std_logic;
ledDoorOpen: out std_logic;
ledDoorClosed: out std_logic;
ledBusy: out std_logic;
ledUsable: out std_logic;
doorOpenEngine : out std_logic;
doorCloseEngine : out std_logic;
cntPiano : out std_logic_vector(4 downto 0)
);
end Elevator;
architecture Ascensore of Elevator is
type state_type is (s0,s1,s2,s3,s4);
signal current_s,next_s: state_type;
signal cf, df: std_logic_vector(3 downto 0); -- vettore a 4 bit
signal countPorta: std_logic_vector(2 downto 0); -- vettore a 3 bit
signal countMotore: std_logic_vector(3 downto 0); -- vettore a 4 bit
begin
-- Questo processo modifica il segnale countPorta in modo tale da segnalare il tempo rimanente prima della chiusura della porta
process (clk,rstPorta)
begin
if (rstPorta='1') then countPorta <= "000"; -- Condizione di bypass della porta, apre la porta senza tempi d'attesa, per casi di emergenza
elsif (clk'event and clk='1') then
if (countPorta = "100") then countPorta <= "011";
elsif (countPorta = "011") then countPorta <= "010";
elsif (countPorta = "010") then countPorta <= "001";
else countPorta <= "000";
end if;
end if;
end process;
-- Questo processo modifica il segnale countMotore in modo tale da segnalare il tempo necessario all'arrivo al piano successivo
process (clk,rstMotore)
begin
if (rstMotore='1') then countMotore <= "0000"; -- Condizione di bypass del motore, ferma lo spostamento in casi di emergenza
elsif (clk'event and clk='1') then
if (countMotore = "1001") then countMotore <= "1000";
elsif (countMotore = "1000") then countMotore <= "0111";
elsif (countMotore = "0111") then countMotore <= "0110";
elsif (countMotore = "0110") then countMotore <= "0101";
elsif (countMotore = "0101") then countMotore <= "0100";
elsif (countMotore = "0100") then countMotore <= "0011";
elsif (countMotore = "0011") then countMotore <= "0010";
elsif (countMotore = "0010") then countMotore <= "0001";
else countMotore <= "0000";
end if;
end if;
end process;
-- Questo processo serve a controllare le chiamate dell ascensore nei vari piani
process (clk,rst)
begin
-- si inizializza ascensore considerando che esso parta dal piano 0 in una condizione priva di richieste esterne (stato 3)
if (rst='1') then
df <= "0000";
cf <= "0000";
upEngine <= '1';
downEngine <= '1';
ledReady <= '1';
ledUp <= '1';
ledDown <= '1';
ledDoorOpen <= '1';
ledDoorClosed <= '1';
ledBusy <= '1';
ledUsable <= '1';
doorOpenEngine <= '1';
doorCloseEngine <= '1';
current_s <= s3;
end if;
-- verifica se vi sono state richieste nei vari piani ad ogni ciclo di clock assegnando a df (desired floor) il piano della richiesta
if (clk'event and clk='1') then
if (zero = '1') then df <= "0000";
elsif (one = '1') then df <= "0001";
elsif (two = '1') then df <= "0010";
elsif (three = '1') then df <= "0011";
elsif (four = '1') then df <= "0100";
end if;
-- lo stato corrente corrisponde allo stato successivo
current_s <= next_s;
end if;
end process;
-- Processo Ascensore
process (current_s, cf, df, clk)
begin
if (clk'event and clk='1') then
case current_s is
-- STATO 0: fase di salita ascensore fino a che il piano desiderato non e' uguale al piano corrente
when s0 =>
if(cf < df) then
upEngine <= '1';
-- se il motore non e' ancora arrivato al piano resta nello Stato 0
if((countMotore= "1001") or (countMotore= "1000") or (countMotore= "0111") or (countMotore= "0110") or (countMotore= "0101") or (countMotore= "0100") or (countMotore = "0011") or (countMotore = "0010") or (countMotore = "0001"))
then then next_s <= s0;
end if;
-- se sono passati 10 sec, siamo arrivati al piano. cf verra' aumentato
if(countMotore = "0000") then
if (cf = "0000") then cf <= "0001";
elsif (cf = "0001") then cf <= "0010";
elsif (cf = "0010") then cf <= "0011";
elsif (cf = "0011") then cf <= "0100";
end if;
end if;
-- se il piano desiderato e' > del corrente fai un altro ciclo dello Stato 0
if(cf < df) then
next_s <= s0;
end if;
-- se il piano desiderato e' = al corrente vai nello Stato 2
if(cf = df) then
ledUp <= '0';
upEngine <= '0';
next_s <= s2;
countPorta <= "100";
end if;
end if;
-- STATO 1: fase di discesa ascensore fino a che il piano desiderato non e' uguale al piano corrente
when s1 =>
if(cf > df) then
downEngine <= '1';
-- se il motore non e' ancora arrivato al piano resta nello Stato 1
if((countMotore= "1001") or (countMotore= "1000") or (countMotore= "0111") or (countMotore= "0110") or (countMotore= "0101") or (countMotore= "0100") or (countMotore = "0011") or (countMotore = "0010") or (countMotore = "0001")) then
elsif(countMotore = "0000") then next_s <= s1;
end if;
-- se sono passati 10 sec, siamo arrivati al piano. cf verra' diminuito
if(countMotore = "0000") then
if (cf = "0100") then cf <= "0011";
elsif (cf = "0011") then cf <= "0010";
elsif (cf = "0010") then cf <= "0001";
elsif (cf = "0001") then cf <= "0000";
else cf <= cf;
end if;
end if;
-- se il piano desiderato e' < del corrente fai un altro ciclo dello Stato 1
if (cf > df) then
next_s <= s1;
end if;
-- se il piano desiderato e' = al corrente vai nello Stato 2
if(cf = df) then
ledDown <= '0';
downEngine <= '0';
next_s <= s2;
countPorta <= "100";
end if;
end if;
-- STATO 2: fase di apertura della porta nel piano desiderato
when s2 =>
if(countPorta = "000") then next_s <= s3;
else next_s <= s2;
end if;
-- STATO 3: ascensore in attesa di richieste con porta aperta
when s3 =>
doorOpenEngine <= '1';
doorCloseEngine <= '0';
ledDoorOpen <= '1';
ledDoorClosed <= '0';
ledReady <= '1';
ledUp <= '0';
ledDown <= '0';
ledBusy <= '0';
ledUsable <= '1';
if(cf = df) then
next_s <= s3;
end if;
if ((cf<df) or (cf>df)) then
countPorta <= "100";
next_s <= s4;
end if;
-- STATO 4: fase di chiusura della porta e selezione dello stato successivo per la salita (Stato 0) o discesa (Stato 1) dell'ascensore
when s4 =>
if((countPorta = "100") or (countPorta = "011") or (countPorta = "010") or (countPorta = "001")) then
next_s <= s4;
elsif((countPorta = "000") and (cf<df)) then
doorOpenEngine <= '0';
doorCloseEngine <= '1';
ledDoorOpen <= '0';
ledDoorClosed <= '1';
ledReady <= '0';
ledUp <= '1';
ledDown <= '0';
ledBusy <= '1';
ledUsable <= '0';
countMotore <= "1001";
next_s <= s0;
elsif((countPorta = "000") and (cf>df)) then
doorOpenEngine <= '0';
doorCloseEngine <= '1';
ledDoorOpen <= '0';
ledDoorClosed <= '1';
ledReady <= '0';
ledUp <= '0';
ledDown <= '1';
ledBusy <= '1';
ledUsable <= '0';
countMotore <= "1001";
next_s <= s1;
end if;
end case;
end if;
end process;
end Ascensore;发布于 2018-01-28 19:00:08
大多数时候,像这样的错误是因为testbench中的端口连接错误而发生的,为了确定这一点,你可以检查连接,但如果你不能发现任何错误,你可以在没有testbench的情况下测试你的模块,并使用力值和力时钟,但如果它仍然未知,你的错误是在波形选择中查看。
祝好运
发布于 2018-02-23 13:19:59
我不确定你在这个设计中处于什么位置,但我希望你在发帖后取得了一些进展。
现在,来谈谈你的问题的核心。信号upEngine、downEngine、...、doorCloseEngine和current_s不是在单个进程中分配的。它们在第三个和第四个process语句中都被驱动,因此构成了一个多驱动网络的情况。
在您的模拟器中,查找将报告任何给定信号的驱动程序的命令。下面是我在Vivado中看到的upEngine信号(行号可能不完全匹配--我正在调整代码):
report_drivers {/Elevator/upEngine}
Drivers for /Elevator/upEngine
U : Net /Elevator/upEngine
U : Driver /Elevator/line__125 at C:/temp/new1.vhd:125
1 : Driver /Elevator/line__82 at C:/temp/new1.vhd:82这有点微妙。当有多个驱动程序时,VHDL使用一个解析函数来决定要做什么。在本例中,由于信号是std_logic类型,因此std_logic_1164库指定了分辨率函数,并指出'U'总是在两个值之间的竞争中获胜。因此,无论在第三个进程中驱动什么,第四个进程中未初始化的信号都将贡献'U'并确定信号状态。(至少在状态机达到将已知值实际驱动到upEngine上的状态之前是这样)。
您可能已经注意到,在模拟中,信号ledUp和ledDown在第一个时钟上升沿之后为'X'。这是因为它们也都是多路驱动的--但是一个驱动程序提供'1',另一个驱动程序提供'0'。在这种情况下,解析函数表示结果是未知的-- 'X'。
检查合成工具的日志输出,因为它应该将这些多驱动网络报告为错误或可能只是警告。(在使用三态信号分配或采用有线和/或逻辑的设计中,存在倍增驱动网络的时间和地点。)
令人高兴的是,解决方案只是将所有内容合并到一个进程中,然后再试一次。我怀疑你会有额外的工作要做,因为在我粗略的检查中,你设计的逻辑功能对我来说并不明显。(作为一个有用的练习,将所有std_logic类型更改为bit并重新分析。倍增驱动的网就像疼痛的拇指一样脱颖而出。)
下面是一些关于你所使用的编码风格的提示:
rising_edge()函数,而不是clk'event and clk='1'。虽然不常见,但如果时钟从'X'或'U'转换到'1',后一种方法可能会导致细微的模拟错误,这可能会导致您认为电路正在工作,但却发现硬件行为differently.Processo Ascensore应该有一个同步或异步的复位信号来清除状态,register.if语句,这些语句似乎正在递减各种信号。if-elsif-elsif复合语句合成到优先级编码器,这将导致更长的组合路径和可能更慢的定时。始终寻找机会使用case语句来实现并行逻辑。unsigned类型的信号来实现设计中各种计数器所需的递减算法。例如,countPorta信号应该声明为unsigned(2减到0),在它上操作的时钟进程应该简单地指定countPorta <= countPorta - "001"; --对于另一个递减counters.process也是如此。错误地(但不是非法的)指定了两个不同的if子句,其中只需要一个子句。事实上,在计算信号df.的赋值时,第二个if子句总是“赢”的
由于您在最初的帖子之后没有按照@user1155120的要求提供测试平台,所以我不能再做下去了。祝好运。
https://stackoverflow.com/questions/45943937
复制相似问题