【发布时间】: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