【问题标题】:VHDL simulation hangs even though it shows no error即使没有显示错误,VHDL 仿真也会挂起
【发布时间】:2018-05-04 20:19:24
【问题描述】:

我是 VHDL 语言的新手,现在我正在尝试制作可控制的步进电机。应该是 this 之类的东西(我实际上是从我和 Tina 的代码中得到这张图片的)

这是我的代码:

LIBRARY ieee;                
USE ieee.std_logic_1164.ALL;            
USE ieee.std_logic_signed.ALL;         
ENTITY state_stepper_halfstep IS         
PORT(clk, plus, minus, start: IN    STD_LOGIC;
     q0,q1,q2,q3: OUT STD_LOGIC;
         a7,b7,c7,d7,e7,f7,g7,h7: OUT std_logic);
END state_stepper_halfstep;

ARCHITECTURE arc OF state_stepper_halfstep IS
    TYPE state_type IS (s0, s1, s2, s3, s4, s5, s6, s7);
    SIGNAL state: state_type;
        SIGNAL q: STD_LOGIC_VECTOR(3 downto 0);
        SIGNAL counter: integer range 0 to 21 :=11;
        SIGNAL digit: std_logic_vector (7 downto 0);
BEGIN

PROCESS (plus, minus, start, clk)
BEGIN 

IF rising_edge(plus) THEN  --  + Rotation value
    counter <= counter+1;
    IF counter > 20 THEN
        counter <= 20;
    END IF; 

ELSIF rising_edge(minus) THEN  --  - Rotation Value
    counter <= counter-1;
    IF counter < 2 THEN
        counter <= 2;
    END IF;
END IF;

    IF start = '1' THEN
        IF counter > 11 THEN  -- When value > 0
            WHILE counter > 11 LOOP  -- Clockwise looping
                EXIT WHEN counter = 11;
                IF rising_edge(clk) THEN        -- Clockwise Steps
                    CASE state IS
                        WHEN s0 => state <= s1;
                        WHEN s1 => state <= s2;
                        WHEN s2 => state <= s3;
                        WHEN s3 => state <= s4;
                        WHEN s4 => state <= s5;
                        WHEN s5 => state <= s6;
                        WHEN s6 => state <= s7;
                                   counter <= counter-1;
                        WHEN s7 => state <= s0;
                    END CASE;
                END IF;
            END LOOP;

        ELSIF counter < 11 THEN  -- When value < 0
            WHILE counter < 11 LOOP -- Counter-clockwise looping
                EXIT WHEN counter = 11;             
                IF rising_edge(clk) THEN        -- Counter-clockwise Steps
                    CASE state IS
                        WHEN s0 => state <= s7;
                        WHEN s7 => state <= s6;
                        WHEN s6 => state <= s5;
                        WHEN s5 => state <= s4;
                        WHEN s4 => state <= s3;
                        WHEN s3 => state <= s2;
                        WHEN s2 => state <= s1;
                                   counter <= counter+1;
                        WHEN s1 => state <= s0;
                    END CASE;
                END IF;
            END LOOP;

        ELSIF counter = 11 THEN -- When value = 0
            counter <= counter;

        END IF;

    ELSE state <= state;

    END IF;

END PROCESS;

WITH state SELECT
    q   <=  "0001"  WHEN    s0,
            "0011"  WHEN    s1,
            "0010"  WHEN    s2,
            "0110"  WHEN    s3,
            "0100"  WHEN    s4,
            "1100"  WHEN    s5,
            "1000"  WHEN    s6,
            "1001"  WHEN    s7;

q0 <= q(0);
q1 <= q(1);
q2 <= q(2);
q3 <= q(3);

    with counter select
digit<= "11000000" when 11,
    "11111001" when 12,
    "10100100" when 13,
    "10110000" when 14,
    "10011001" when 15,
    "10010010" when 16,
    "10000010" when 17,
    "11111000" when 18,
    "10000000" when 19,
    "10010000" when 20,
    "01111001" when 10,
    "00100100" when 9,
    "00110000" when 8,
    "00011001" when 7,
    "00010010" when 6,
    "00000010" when 5,
    "01111000" when 4,
    "00000000" when 3,
    "00010000" when 2;
    a7 <= digit(0);
b7 <= digit(1);
c7 <= digit(2);
d7 <= digit(3);
e7 <= digit(4);
f7 <= digit(5);
g7 <= digit(6);
h7 <= digit(7);
END arc;


这实际上应该如何工作:
1. 我可以选择步进电机(用 LED 指示)通过“加号”和“减号”开关旋转多少次(可以从 -9 计数到 9)
2. 7段的点是显示数字的负号
3. 正值会使电机顺时针旋转
4. 负值(用7段点表示)会使电机逆时针方向旋转
5.电机每转一圈,7段数减1个
6.步进电机只有在我启动时才会开始旋转(给“启动”输入一个高逻辑)


每当我尝试模拟电路并点击“开始”时,就会出现问题。 Tina 会挂起然后“不响应”。老实说,我不确定我在代码中犯了什么错误,因为每当我尝试使用我的 VHDL 代码“输入新宏”时,Tina 都没有显示错误。


我最好的猜测是我在循环命令中犯了错误

    IF start = '1' THEN
        IF counter > 11 THEN  -- When value > 0
            WHILE counter > 11 LOOP  -- Clockwise looping
                EXIT WHEN counter = 11;
                IF rising_edge(clk) THEN        -- Clockwise Steps
                    CASE state IS
                        WHEN s0 => state <= s1;
                        WHEN s1 => state <= s2;
                        WHEN s2 => state <= s3;
                        WHEN s3 => state <= s4;
                        WHEN s4 => state <= s5;
                        WHEN s5 => state <= s6;
                        WHEN s6 => state <= s7;
                                   counter <= counter-1;
                        WHEN s7 => state <= s0;
                    END CASE;
                END IF;
            END LOOP;

        ELSIF counter < 11 THEN  -- When value < 0
            WHILE counter < 11 LOOP -- Counter-clockwise looping
                EXIT WHEN counter = 11;             
                IF rising_edge(clk) THEN        -- Counter-clockwise Steps
                    CASE state IS
                        WHEN s0 => state <= s7;
                        WHEN s7 => state <= s6;
                        WHEN s6 => state <= s5;
                        WHEN s5 => state <= s4;
                        WHEN s4 => state <= s3;
                        WHEN s3 => state <= s2;
                        WHEN s2 => state <= s1;
                                   counter <= counter+1;
                        WHEN s1 => state <= s0;
                    END CASE;
                END IF;
            END LOOP;


如果有人能指出错误,我会很高兴。提前感谢您,祝您有美好的一天!

【问题讨论】:

  • 要使其成为minimal reproducible example,请将您的测试台(或其精简版)添加到问题中。
  • 这段代码根本无法合成:我们没有考虑基本错误,代码需要完全重写。您应该考虑阅读 FPGA 制造商的综合编码指南。
  • 虽然循环不符合合成条件。您的测试台应该重现错误(可验证)。您的计数器的初始值为 11,未包含在包含 while 循环的 if 语句选择中,但被包含在 ELSE 中,它什么都不做。如果十六进制显示正在工作,它应该显示“1000000”(g 下降到 a),带有 h 的减号(数字(7))大概小数点也被点亮(假设驱动器极性为“1”)。 (你不提正负刺激,你的问题不能重复。)
  • rising_edge 函数首先需要一个“0”(或“L”),然后是一个“1”(或“H”)来检测 0 到 1 的转换。这是故意的。
  • 感谢您的所有更正。

标签: vhdl freeze state-machine


【解决方案1】:

您想要实现的是从计算机语言到 VHDL 的直接端口。 HDL 不能以这种方式工作,如果你想实现这种设计,你就必须改变你的范式。以下是一些提示:

  1. 您的实体和架构的描述似乎没问题
  2. 主进程的敏感度列表显示您希望它像线程一样“逐步”运行,但在 HDL 中无法以这种方式进行综合。硬件设计描述的模型是,每次在灵敏度列表中列出的信号上出现一个事件时,整个过程都会运行一次。该进程在等待进一步事件时不能阻塞。如果您的敏感度列表信号经过值测试,这意味着您的过程是组合的(纯逻辑)。这不是你想要得到的(你有一个 clk 信号)。所以你的进程在它的敏感度列表中应该只有一个信号:clk。之后,您的进程主体可以以唯一的IF rising_edge(clk) THEN 开头,该IF rising_edge(clk) THEN 清楚地表明一个时钟进程。
  3. 时钟进程不管理通过当前时钟周期的数据,因此您必须考虑要从一个周期保存到下一个周期的状态并将它们作为信号驱动。
  4. 与变量相比,信号是奇异的野兽,您需要了解它们在事件和时间方面的工作方式。比如counter &lt;= counter;是没用的。
  5. 系统行为的文本规范看起来像状态机的描述。为什么不正式完善它并将其充实为您系统的状态呢?看一个简单的例子here
  6. 通常,对于综合而言,您需要一种复位信号来确保您的所有状态都由硬件初始化。

【讨论】:

  • 谢谢。这对我很有帮助。
猜你喜欢
  • 2016-12-15
  • 1970-01-01
  • 2014-05-02
  • 1970-01-01
  • 2014-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多