I'm new to VHDL language and right now I'm trying to make a controlable stepper motor. It should be something like this (I actually got this picture from my code with Tina)
And this is my code:
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;
This how it actually should work:
1. I can choose how many times the stepper motor (indicated with LEDs) will rotate with the "plus" and "minus" switches (it can counts from -9 to 9)
2. The 7 segment's dot is a negative sign for the number shown in the display
3. Postive value will make the motor rotate in clockwise direction
4. Negative value (shown with dot in 7 segments) will make the motor rotate in counter-clockwise direction
5. Everytime the motor completes 1 rotation, the 7 segments number should be reduced by 1 number
6. Stepper motor will only start to rotate if I start it (with giving a high logic to "start" input)
Problem occurs whenever I'm trying to simulate the circuit and hit "start". Tina will just go hang and then "Not Responding". To be honest, I'm not sure about what mistake I've made in my code because Tina shows no error whenever I try to "Enter New Macro" with my VHDL code.
My best guess is I've made mistake in my looping command
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;
I would really glad if someone could point out the mistake. Thank you in advance and have a good day!
What you are trying to achieve is a direct port from a computer language to VHDL. HDLs don't work this way and you'll have to shift your paradigm if you want to achieve this design. Here are a few tips:
IF rising_edge(clk) THEN
that clearly indicates a clocked process.counter <= counter;
is useless.