Stepper-Motor-Control  v3.0.0
System on a Chip 2014 - Group 04
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
signal_generator.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 --! @file signal_generator.vhd
3 --! @author Marc Kossmann
4 --! @author Michael Riedel
5 --! @version v1.0.0
6 --! @date 05.12.2014
7 --!
8 --! @brief Signal Generator for Stepper-Motor-PWM
9 --! @details Generates the pulse-width and enable signals accordingly.
10 --! @details Motor State-Machine
11 --! @par History:
12 --! @details v0.1.0 25.11.2014 Riedel & Kossmann
13 --! - first draft
14 --! @details v0.1.1 26.11.2014 Riedel
15 --! - implemented signal-generator logic
16 --! @details v0.1.2 27.11.2014 Riedel
17 --! - added speed-statemachine to determine the correct
18 --! speed-integer when changes occur on the speed-bus
19 --! - added new CONSTANT `UNLIMITED_STEPS` for CR and IDLE, now
20 --! the IR won't be triggered everytime
21 --! - renamed the input `enable` to `prescaler`
22 --! @details v0.1.3 28.11.2014 Riedel & Kossmann
23 --! - fixed speed'Event, now the user can change the speed and
24 --! the signal_generator directly uses the new value
25 --! - removed wrong synchronization statements
26 --! @details v0.1.4 28.11.2014 Riedel
27 --! - removed `prescaler`-dependency in `pwm_generation`-process
28 --! @details v0.1.5 30.11.2014 Kossmann
29 --! - changed speed to speed_wire transfering process to async
30 --! - changed speed_wire /= old_speed_wire check to async
31 --! - fixed bug of t_pulse (pwm width) being systematical to long
32 --! (have to set pwm_5ms_counter to (speed_wire - 1))
33 --! @details v0.1.6 30.11.2014 Riedel & Kossmann
34 --! - fixed Chain of Steps Bug though evaluating run signal of mcu
35 --! @details v0.1.7 02.12.2014 Riedel & Kossmann
36 --! - changed structure and fixed bugs to get code working on fpga
37 --! @details v0.1.8 02.12.2014 Kossmann
38 --! - small adjustments for fulfill specification
39 --! @details v0.1.9 03.12.2014 Kossmann
40 --! - moved motor driver enable to mode_state machine
41 --! @details v0.1.10 05.12.2014 Riedel
42 --! - added few documentational lines
43 --! - corrected formatting and indention
44 --! @details v1.0.11 05.12.2014 Riedel & Kossmann
45 --! - release milestone 3b
46 --! @details v1.0.12 09.12.2014 Riedel & Kossmann
47 --! - swapped `rising_edge(prescaler)` with
48 --! `rising_edge(clock) AND prescaler = '1'`
49 --! @details v1.0.13 09.12.2014 Riedel
50 --! - restructured state-machine for modes
51 --! - created new process for motor power-management
52 --! - moved ir-logic to renamed `count_steps_and_set_ir`-process
53 --! @details v1.0.14 11.12.2014 Riedel & Kossmann
54 --! - corrected ir wire not being high for one clock
55 --! - corrected versioning mistake
56 -------------------------------------------------------------------------------
57 
58 --! Use Standard Library
59 LIBRARY ieee;
60 --! Use Logic Elements
61 USE ieee.std_logic_1164.all;
62 --! Use Conversion Functions
63 USE ieee.std_logic_arith.all;
64 --! Use Conversion Functions
65 USE ieee.std_logic_signed.all;
66 
67 --! @brief Signal Generator
69  PORT(
70  clock : IN STD_LOGIC; --! component clock
71  run : IN STD_LOGIC; --! run or stop the signal_generator
72  prescaler : IN STD_LOGIC; --! input for minimum time-base
73  reset_n : IN STD_LOGIC; --! resets the component
74  mode : IN STD_LOGIC_VECTOR(3 DOWNTO 0); --! mode to run motor with
75  speed : IN STD_LOGIC_VECTOR(2 DOWNTO 0); --! speed to run moter with
76  direction : IN STD_LOGIC; --! motor direction ('0' is LEFT)
77  ir : OUT STD_LOGIC; --! IR signal set when motor stopped
78  steps : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); --! number of steps motor did
79  motor_pwm : OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --! signal-bus for the motor pulse-width-modulation
80  motor_en : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) --! both enable signals for the motor
81  );
82 END signal_generator;
83 
84 --! @brief Architecture of signal generator
85 ARCHITECTURE my_signal_generator OF signal_generator IS
86 
87 CONSTANT UNLIMITED_STEPS : INTEGER := -1;
88 CONSTANT LEFT : STD_LOGIC := '0';
89 CONSTANT RIGHT : STD_LOGIC := NOT LEFT;
90 
91 TYPE MODE_STATE_TYPE IS (IDLE, CR, COS_1_4, COS_1_2, COS_1, COS_2);
92 TYPE PWM_STATE_TYPE IS (ONE, TWO, THREE, FOUR);
93 
94 SIGNAL mode_state : MODE_STATE_TYPE;
95 SIGNAL pwm_state : PWM_STATE_TYPE;
96 SIGNAL speed_wire : INTEGER RANGE 0 TO 400;
97 SIGNAL old_speed_wire : INTEGER RANGE 0 TO 400;
98 SIGNAL pwm_counter : INTEGER RANGE 0 TO 400;
99 SIGNAL steps_to_run : INTEGER;
100 SIGNAL motor_en_wire : STD_LOGIC_VECTOR(1 DOWNTO 0);
101 SIGNAL motor_pwm_wire : STD_LOGIC_VECTOR(3 DOWNTO 0);
102 SIGNAL ir_wire : STD_LOGIC;
103 SIGNAL steps_output_wire : INTEGER;
104 
105 BEGIN
106  --- MODE's
107  mode_state_machine : PROCESS (reset_n, clock, mode)
108  BEGIN
109  IF(reset_n = '0') THEN
110  mode_state <= IDLE;
111  ELSIF(rising_edge(clock) AND ir_wire = '0') THEN
112  CASE mode IS
113  WHEN "0010" =>
114  mode_state <= COS_1_4;
115  WHEN "0110" =>
116  mode_state <= COS_1_2;
117  WHEN "1010" =>
118  mode_state <= COS_1;
119  WHEN "1110" =>
120  mode_state <= COS_2;
121  WHEN OTHERS =>
122  IF (mode(1 DOWNTO 0) = "01") THEN
123  mode_state <= CR;
124  ELSE
125  mode_state <= IDLE;
126  END IF;
127  END CASE;
128  END IF;
129  END PROCESS;
130 
131  mode_processing : PROCESS (mode_state)
132  BEGIN
133  CASE mode_state IS
134  WHEN IDLE =>
135  steps_to_run <= UNLIMITED_STEPS;
136  WHEN CR =>
137  steps_to_run <= UNLIMITED_STEPS;
138  WHEN COS_1_4 =>
139  steps_to_run <= 199;
140  WHEN COS_1_2 =>
141  steps_to_run <= 399;
142  WHEN COS_1 =>
143  steps_to_run <= 799;
144  WHEN COS_2 =>
145  steps_to_run <= 1599;
146  WHEN others =>
147  steps_to_run <= 0;
148  END CASE;
149  END PROCESS;
150 
151  --- SPEED's
152  --- this block generates 9 combinational loops with latches
153  speed_converting : PROCESS (reset_n, clock, speed)
154  BEGIN
155  old_speed_wire <= speed_wire;
156  CASE speed IS
157  WHEN "000" =>
158  speed_wire <= 399;
159  WHEN "001" =>
160  speed_wire <= 199;
161  WHEN "010" =>
162  speed_wire <= 99;
163  WHEN "011" =>
164  speed_wire <= 49;
165  WHEN "100" =>
166  speed_wire <= 19;
167  WHEN "101" =>
168  speed_wire <= 9;
169  WHEN "110" =>
170  speed_wire <= 4;
171  WHEN "111" =>
172  speed_wire <= 1;
173  WHEN others =>
174  speed_wire <= 399;
175  END CASE;
176  END PROCESS;
177 
178  --- PWM's
179  pulse_generation : PROCESS (reset_n, clock, prescaler, speed_wire, old_speed_wire)
180  BEGIN
181  IF(reset_n = '0') THEN
182  pwm_counter <= speed_wire;
183  ELSIF(speed_wire /= old_speed_wire) THEN
184  pwm_counter <= speed_wire;
185  ELSIF(rising_edge(clock) AND prescaler = '1') THEN
186  IF(pwm_counter = 0) THEN
187  pwm_counter <= speed_wire;
188  ELSE
189  pwm_counter <= pwm_counter - 1;
190  END IF;
191  END IF;
192  END PROCESS;
193 
194  pwm_state_machine : PROCESS (reset_n, clock, prescaler, pwm_counter, direction)
195  BEGIN
196  IF(reset_n = '0') THEN
197  pwm_state <= ONE;
198  ELSIF(rising_edge(clock) AND prescaler = '1' AND pwm_counter = 0) THEN
199  IF(direction = LEFT) THEN
200  CASE pwm_state IS
201  WHEN FOUR =>
202  pwm_state <= THREE;
203  WHEN THREE =>
204  pwm_state <= TWO;
205  WHEN TWO =>
206  pwm_state <= ONE;
207  WHEN ONE =>
208  pwm_state <= FOUR;
209  END CASE;
210  ELSE
211  CASE pwm_state IS
212  WHEN ONE =>
213  pwm_state <= TWO;
214  WHEN TWO =>
215  pwm_state <= THREE;
216  WHEN THREE =>
217  pwm_state <= FOUR;
218  WHEN FOUR =>
219  pwm_state <= ONE;
220  END CASE;
221  END IF;
222  END IF;
223  END PROCESS;
224 
225  pwm_output : PROCESS (pwm_state)
226  BEGIN
227  CASE pwm_state IS
228  WHEN ONE =>
229  motor_pwm_wire <= "1100";
230  WHEN TWO =>
231  motor_pwm_wire <= "0110";
232  WHEN THREE =>
233  motor_pwm_wire <= "0011";
234  WHEN FOUR =>
235  motor_pwm_wire <= "1001";
236  END CASE;
237  END PROCESS;
238 
239  power_motor : PROCESS (run, ir_wire)
240  BEGIN
241  IF(run = '0' OR ir_wire = '1') THEN
242  motor_en_wire <= "00";
243  ELSE
244  motor_en_wire <= "11";
245  END IF;
246  END PROCESS;
247 
248  --- STEPS's
249  count_steps_and_set_ir : PROCESS (reset_n, steps_to_run, clock, run, prescaler, pwm_counter, mode_state)
250  VARIABLE steps_counter : INTEGER := 0;
251  BEGIN
252  IF(reset_n = '0') THEN
253  steps_counter := 0;
254  steps_output_wire <= 0;
255  ir_wire <= '0';
256  ELSIF(run = '0') then
257  steps_counter := 0;
258  steps_output_wire <= 0;
259  ir_wire <= '0';
260  ELSIF(rising_edge(clock) AND prescaler = '1' AND pwm_counter = 0 AND mode_state /= CR AND mode_state /= IDLE) THEN
261  IF(steps_counter = steps_to_run) THEN
262  steps_counter := 0;
263  ir_wire <= '1';
264  END IF;
265  IF(direction = LEFT) THEN
266  steps_output_wire <= steps_output_wire - 1;
267  ELSE
268  steps_output_wire <= steps_output_wire + 1;
269  END IF;
270  steps_counter := steps_counter + 1;
271  END IF;
272  END PROCESS;
273 
274  motor_en <= motor_en_wire;
275  motor_pwm <= motor_pwm_wire;
276  ir <= ir_wire;
277  steps <= conv_std_logic_vector(steps_output_wire, 32);
278 END my_signal_generator;
in speedSTD_LOGIC_VECTOR(2 DOWNTO0)
speed to run moter with
in modeSTD_LOGIC_VECTOR(3 DOWNTO0)
mode to run motor with
in reset_nSTD_LOGIC
resets the component
out motor_enSTD_LOGIC_VECTOR(1 DOWNTO0)
both enable signals for the motor
out irSTD_LOGIC
IR signal set when motor stopped.
out motor_pwmSTD_LOGIC_VECTOR(3 DOWNTO0)
signal-bus for the motor pulse-width-modulation
in clockSTD_LOGIC
component clock
in runSTD_LOGIC
run or stop the signal_generator
out stepsSTD_LOGIC_VECTOR(31 DOWNTO0)
number of steps motor did
in prescalerSTD_LOGIC
input for minimum time-base
_library_ ieeeieee
Use Standard Library.
in directionSTD_LOGIC
motor direction ('0' is LEFT)
Signal Generator.