首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >( vhdl ) vhdl实体中的输出问题

( vhdl ) vhdl实体中的输出问题
EN

Stack Overflow用户
提问于 2017-08-30 00:19:41
回答 2查看 1.5K关注 0票数 0

我对总是发送U的vhdl实体的输出有问题。我看了各种论坛,但我找不到解决方案。

该项目是一个5层高的电梯,必须等待5秒才能关门,等待10秒才能到达下一架到达目标的飞机。使用Logisim (2.13.22版)和ghdl (0.29.1版)。

有没有人知道问题出在哪里?提前感谢

这是我写的vhdl代码。

代码语言:javascript
复制
    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;
EN

回答 2

Stack Overflow用户

发布于 2018-01-28 19:00:08

大多数时候,像这样的错误是因为testbench中的端口连接错误而发生的,为了确定这一点,你可以检查连接,但如果你不能发现任何错误,你可以在没有testbench的情况下测试你的模块,并使用力值和力时钟,但如果它仍然未知,你的错误是在波形选择中查看。

祝好运

票数 0
EN

Stack Overflow用户

发布于 2018-02-23 13:19:59

我不确定你在这个设计中处于什么位置,但我希望你在发帖后取得了一些进展。

现在,来谈谈你的问题的核心。信号upEnginedownEngine、...、doorCloseEnginecurrent_s不是在单个进程中分配的。它们在第三个和第四个process语句中都被驱动,因此构成了一个多驱动网络的情况。

在您的模拟器中,查找将报告任何给定信号的驱动程序的命令。下面是我在Vivado中看到的upEngine信号(行号可能不完全匹配--我正在调整代码):

代码语言:javascript
复制
 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上的状态之前是这样)。

您可能已经注意到,在模拟中,信号ledUpledDown在第一个时钟上升沿之后为'X'。这是因为它们也都是多路驱动的--但是一个驱动程序提供'1',另一个驱动程序提供'0'。在这种情况下,解析函数表示结果是未知的-- 'X'

检查合成工具的日志输出,因为它应该将这些多驱动网络报告为错误或可能只是警告。(在使用三态信号分配或采用有线和/或逻辑的设计中,存在倍增驱动网络的时间和地点。)

令人高兴的是,解决方案只是将所有内容合并到一个进程中,然后再试一次。我怀疑你会有额外的工作要做,因为在我粗略的检查中,你设计的逻辑功能对我来说并不明显。(作为一个有用的练习,将所有std_logic类型更改为bit并重新分析。倍增驱动的网就像疼痛的拇指一样脱颖而出。)

下面是一些关于你所使用的编码风格的提示:

  • 使用rising_edge()函数,而不是clk'event and clk='1'。虽然不常见,但如果时钟从'X''U'转换到'1',后一种方法可能会导致细微的模拟错误,这可能会导致您认为电路正在工作,但却发现硬件行为differently.
  • You希望您的状态机被重置。因此,Processo Ascensore应该有一个同步或异步的复位信号来清除状态,register.
  • You有几个if语句,这些语句似乎正在递减各种信号。if-elsif-elsif复合语句合成到优先级编码器,这将导致更长的组合路径和可能更慢的定时。始终寻找机会使用case语句来实现并行逻辑。
  • 说过,你的VHDL语言真正需要的是使用unsigned类型的信号来实现设计中各种计数器所需的递减算法。例如,countPorta信号应该声明为unsigned(2减到0),在它上操作的时钟进程应该简单地指定countPorta <= countPorta - "001"; --对于另一个递减counters.
  • The third process也是如此。错误地(但不是非法的)指定了两个不同的if子句,其中只需要一个子句。事实上,在计算信号df.

的赋值时,第二个if子句总是“赢”的

由于您在最初的帖子之后没有按照@user1155120的要求提供测试平台,所以我不能再做下去了。祝好运。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45943937

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档