【问题标题】:VHDL code works in ModelSim but not on FPGAVHDL 代码在 ModelSim 中有效,但在 FPGA 上无效
【发布时间】:2016-01-30 16:32:53
【问题描述】:

我的 VHDL 代码功能正确,在 ModelSim 中一切正常。我对它进行了许多变体测试,代码功能正确。

但是当我把它放在 Altera 板上时,它在 7 段显示器上显示“3”,但它应该显示“0”。 如果我将 RESET 设置为“1”,它会完全中断并仅在顶部显示一行。 我的输入 X、CLK、RESET 连接到开关。 LOAD 连接到一个按钮,DIGIT 连接到 7 段显示器。

当我切换 CLK 开关时,它应该有一个时钟信号。

这是我的完整代码:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY seqdec IS
PORT    (   X:          IN      std_logic_vector(15 DOWNTO 0);
            CLK:        IN      std_logic;
            RESET:  IN      std_logic;
            LOAD:       IN      std_logic;
            DIGIT:  OUT std_logic_vector(6 DOWNTO 0) := "1111110";
            Y:          OUT std_logic);
END seqdec;

ARCHITECTURE SEQ OF seqdec IS
TYPE        statetype IS (s0, s1, s2, s3, s4);
SIGNAL  state: statetype:=s0;
SIGNAL  next_state: statetype;
SIGNAL  counter: std_logic_vector(2 DOWNTO 0) :="000" ;
SIGNAL  temp:   std_logic_vector(15 DOWNTO 0):= (OTHERS => '0');
SIGNAL  so:     std_logic := 'U';

-------------------Aktualisierung des Zustandes--------------------------------
    BEGIN
    STATE_AKT: PROCESS (CLK, RESET)
        BEGIN   
            IF RESET = '1' THEN     
                state <= s0;
            ELSIF CLK = '1' AND CLK'event THEN
                state <= next_state ;
            END IF;
        END PROCESS STATE_AKT;

---------------------Counter---------------------------------------------------
    COUNT:  PROCESS (state, RESET)
        BEGIN   
            IF (RESET = '1') THEN   
                counter <= (OTHERS => '0');
            ELSIF (state = s4) THEN
                counter <= counter + '1';
            END IF;
    END PROCESS COUNT;

-------------------PiSo für die Eingabe des zu Prüfenden Vektors---------------
    PISO:       PROCESS (CLK, LOAD, X)
        BEGIN
            IF (LOAD = '1') THEN
                temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
            ELSIF (CLK'event and CLK='1') THEN
                so <= temp(15);
                temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
                temp(0) <= '0';
            END IF;
        END PROCESS PISO;

-------------------Zustandsabfrage und Berechnung------------------------------
    STATE_CAL: PROCESS (so,state)
        BEGIN

            next_state <= state;
            Y <= '0';

            CASE state IS
                WHEN s0 =>  
                    IF so = '1' THEN 
                        next_state <= s0  ;
                    END IF;

                WHEN s1 =>  
                    IF so = '1' THEN 
                        next_state <= s1;
                    END IF;

                WHEN s2 =>  
                    IF so = '0' THEN 
                        next_state <= s3 ;
                    END IF;

                WHEN s3 =>  
                    IF so = '0' THEN 
                        next_state <= s0 ;
                    ELSE
                        next_state <= s4 ;
                    END IF;

                WHEN s4 =>  
                    Y <= '1';
                    IF so = '0' THEN 
                        next_state <= s0;
                    ELSE
                        next_state <= s2 ;
                    END IF;

                WHEN OTHERS => NULL;
            END CASE;
        END PROCESS STATE_CAL;

-------------------7 Segment---------------------------------------------------
    SEVEN_SEG: PROCESS (counter)
        BEGIN
            CASE counter IS
                WHEN "000" => DIGIT <= "1111110";
                WHEN "001" => DIGIT <= "0110000";
                WHEN "010" => DIGIT <= "1101101";
                WHEN "011" => DIGIT <= "1111001";
                WHEN "100" => DIGIT <= "0110011";
                WHEN "101" => DIGIT <= "1011011";
                WHEN OTHERS => NULL;
            END CASE;
        END PROCESS SEVEN_SEG;


END SEQ;

我对 VHDL 很陌生,我很确定它必须对时序做一些事情,因为功能部分应该没问题,如前所述。

希望得到一些提示、技巧甚至解决方案。

编辑:没有 LOAD 的新代码,这是一个有效的想法吗? (尽管整个代码在 FPGA 上都无法运行......)

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY seqdec IS
PORT    (   X:          IN      std_logic_vector(15 DOWNTO 0);
            CLK:        IN      std_logic;
            RESET:  IN      std_logic;
            LOAD:       IN      std_logic;
            DIGIT:  OUT std_logic_vector(0 TO 6) := "0000001";
            Y:          OUT std_logic);
END seqdec;

ARCHITECTURE SEQ OF seqdec IS
TYPE        statetype IS (s0, s1, s2, s3, s4);
SIGNAL  state: statetype:=s0;
SIGNAL  next_state: statetype;
SIGNAL  counter: std_logic_vector(2 DOWNTO 0) :="000" ;
SIGNAL  temp:   std_logic_vector(15 DOWNTO 0):= (OTHERS => '0');
SIGNAL  so:     std_logic := 'U';

-------------------Aktualisierung des Zustandes--------------------------------
    BEGIN
    STATE_AKT: PROCESS (CLK, RESET)
        BEGIN   
            IF RESET = '1' THEN     
                state <= s0;
            ELSIF CLK = '1' AND CLK'event THEN
                state <= next_state ;
            END IF;
        END PROCESS STATE_AKT;

---------------------Counter---------------------------------------------------
    COUNT:  PROCESS (state, RESET)
        BEGIN   
            IF (RESET = '1') THEN   
                counter <= (OTHERS => '0');
            ELSIF (state = s4) THEN
                counter <= counter + '1'; 
            END IF;
    END PROCESS COUNT;

-------------------PiSo für die Eingabe des zu Prüfenden Vektors---------------
    PISO:       PROCESS (CLK, LOAD, X)
        BEGIN
            IF (CLK'event and CLK='1') THEN 
                IF (LOAD = '1') THEN 
                    temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
                ELSE
                    so <= temp(15);
                    temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
                    temp(0) <= '0';
                END IF;
            END IF;
        END PROCESS PISO;

-------------------Zustandsabfrage und Berechnung------------------------------
    STATE_CAL: PROCESS (so,state)
        BEGIN

            next_state <= state;
            Y <= '0';

            CASE state IS
                WHEN s0 =>  
                    IF so = '1' THEN 
                        next_state <= s1  ;
                    END IF;

                WHEN s1 =>  
                    IF so = '1' THEN 
                        next_state <= s2;
                    END IF;

                WHEN s2 =>  
                    IF so = '0' THEN 
                        next_state <= s3 ;
                    END IF;

                WHEN s3 =>  
                    IF so = '0' THEN 
                        next_state <= s0 ;
                    ELSE
                        next_state <= s4 ;
                    END IF;

                WHEN s4 =>  
                    Y <= '1';
                    IF so = '0' THEN 
                        next_state <= s0;
                    ELSE
                        next_state <= s2 ;
                    END IF;

                WHEN OTHERS => NULL;
            END CASE;
        END PROCESS STATE_CAL;

-------------------7 Segment---------------------------------------------------
    SEVEN_SEG: PROCESS (counter)
        BEGIN
            CASE counter IS
                WHEN "000" => DIGIT <= "0000001";
                WHEN "001" => DIGIT <= "1001111";
                WHEN "010" => DIGIT <= "0010010";
                WHEN "011" => DIGIT <= "0000110";
                WHEN "100" => DIGIT <= "1001100";
                WHEN "101" => DIGIT <= "0100100";
                WHEN OTHERS => DIGIT <= "0000001";
            END CASE;
        END PROCESS SEVEN_SEG;


END SEQ;

编辑:这是我现在的版本。 不管我做什么,它仍然会显示一个“0”。

  • 我认为它与 COUNT 和计数器有关。
  • 我也应该意识到这是同步的吗?
  • 数字和无符号真的有那么大的问题吗?我们在大学就是这样做的。
  • 当我将 LOAD 放到滑动开关上时它会起作用吗?

最好的问候 阿德里安

【问题讨论】:

  • 我添加了一个 FSM 示例,它结合了您的两个流程

标签: vhdl


【解决方案1】:

您的代码有几个问题。顺便提一句。运行中的模拟并不意味着您的设计是正确的,因为您可以模拟无法在硬件中实现的动作。

以下是问题列表:

  • 您不能将开关按钮用作时钟信号。按钮不是时钟源!要么实现信号清除电路(至少是去抖电路,这需要另一个时钟),要么使用 clk 信号作为启用。
  • 此外,如果连接到外部开关按钮或切换按钮,您的每个信号都需要一个去抖电路,除非您的测试板有去抖按钮...
  • 您的状态机具有初始化状态(没关系),但您必须将状态分配给 state 而不是 next_state
  • 您的代码使用了已过时的std_logic_unsigned。您应该使用numeric_stdunsigned 类型作为counter 信号。
  • 您的代码为COUT 引入了一个额外的寄存器,这是有意的吗?
  • 您的 PISO 进程使用异步 LOAD 信号,这在硬件中不受支持(假设 FPGA 作为目标设备)。
  • 根据您的综合工具,它可能无法识别 FSM,因为您的 case 语句不符合 FSM 的模式。
  • 看到固定的输出模式可能是由 FSM 故障引起的。如果您的合成器识别出 FSM,您可以转到状态图并识别错误的边缘或错误的终端状态。

更多...

  • 您的 7 段解码器是一个组合过程。无法重置。
  • 而且,这个过程对CLK不敏感,只对counter敏感。这会导致仿真和硬件之间的不匹配。 (综合忽略敏感度列表)

如果你解决了这个问题,你的模拟应该有另一种行为,如果解决了,就可以作为你的硬件工作:)。

FSM

STATE_CAL : process(state, so)
begin
  -- Standardzuweisungen
  next_state  <= state;  -- Bleib im Zustand falls in CASE nichts abweichendes bestimmt wird
  Y <= '0';

  -- Zustandswechsel
  CASE state IS
    WHEN s0 =>
      IF (so = '1' THEN 
        next_state <= s1;
      END IF;

     WHEN s1 =>
       IF (so = '1') THEN
         next_state <= s2;
       END IF;

     WHEN s2 =>
       IF (so = '0') THEN
         next_state <= s3;
       END IF;

     WHEN s3 =>
       IF (so = '0') THEN
         next_state <= s0;
       else
         next_state <= s4;
       END IF;

     WHEN s4 =>
       Y <= '1'; -- Moore-Ausgabe
       IF (so = '0') THEN
         next_state <= s0;
       else
         next_state <= s2;
       END IF;

  END CASE;
END PROCESS;

【讨论】:

  • 这是我的两个进程 STATE_CAL 和 STATE_Y。但是你为什么把 ELSIF 排除在外?是否有必要问“所以='1'”而不是='0'。但是再次感谢,我今天的时间有限,但我明天会试一试,希望明天我也能得到你的一些反馈。
  • (so = '0') 分支使用默认分配处理。我会修复我的复制粘贴错误。 VHDL 有一个 9 值逻辑,你不想测试每个值:)。
  • 好的,我明天看看能不能完成,非常感谢。 privatemessage 的 * 上没有可能性还是? ^^
  • 它是否检测到 FSM 代码模式应该对生成的逻辑没有影响。其他点更重要,所以+1。
  • 好的,现在是同步的,我的网表看起来不错(我认为)。 FSM 也被软件识别并且看起来应该。我把新版本的代码放在第一篇文章中,还有一些问题。
【解决方案2】:

Paebbels 已经描述了您的代码的许多问题。请同时检查您的综合工具的警告。它们通常表明合成器实际输出的逻辑与您在 VHDL 中描述的逻辑不同。

我怀疑你又犯了两个与 VHDL 没有直接关系的错误:

  • 您的 7 段显示控制线似乎处于低活动状态,因为当您按下 RESET 时,您只看到一个活动段。这与您在本例中分配的向量 "1111110" 中唯一的零匹配(通过将 counter 重置为 "000")。
  • 但即使在这种情况下,被点亮的部分也应该位于中间而不是顶部。因此,您的引脚分配似乎是相反的顺序。

【讨论】:

  • 我是如何让它处于低活跃状态的?通常它应该是高度活跃的还是我弄错了? PS:现在显示的是中间部分。我刚刚将 (6 DOWNTO 0) 更改为 (0 TO 6)。
  • @DaPole 然后只分配反转位:"0000001"
  • 是的,我做到了,现在开始显示“0”,这只是一个需要更多知识的问题。我是在决定它是高/低活跃还是董事会如何?软件?还是预定义了其他内容?
  • @DaPole 它由您的董事会定义。看看板子手册就知道了。在 7 段显示说明中,应说明该控件处于低激活状态。
最近更新 更多