- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm trying to set up a small demo to make a stepper motor move in various ways in which I'll need a series of buttons to control the action of the motors.
To do this I'm using a state machine to perform the required actions depending on the button press, however some of the states aren't continuous and need to drop to another state after completion of the action. The trouble is I'm getting errors. I kinda understand why the compiler doesn't like it, but I don't know how to circumvent the issue, so suggestions welcome. Also, it would appear that I'm not getting the desired clock signal on my step_clk output, which also confuses me greatly.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity motor_demo is
port( clk: in std_logic;
RST, EN, CTRL, HALF, CW, Step_clk: out std_logic;
sw: in std_logic_vector(0 to 4)
);
end motor_demo;
architecture stm of motor_demo is
type motor_action is (STOP, CWISE, CCWISE, CW_45, CCW_180);
signal motor_state: motor_action := CWISE;
signal stepcount: integer := 0;
signal clk_div: std_logic;
begin
-- Clock divider for stepper action
clk_divider: entity work.clk_divide port map(clk, clk_div);
process(sw) is
begin
case sw is
when "01111" =>
motor_state <= CWISE;
when "10111" =>
motor_state <= CCWISE;
when "11011" =>
motor_state <= STOP;
when "11101" =>
motor_state <= CW_45;
when "00001" =>
motor_state <= CCW_180;
when others =>
motor_state <= STOP;
end case;
end process;
process(clk_div, motor_state) is
begin
if rising_edge(clk_div) then
case motor_state is
when STOP =>
step_clk <= '0';
stepcount <= 0;
when CWISE =>
step_clk <= clk_div;
CW <= '1';
when CCWISE =>
Step_clk <= clk_div;
CW <= '0';
when CW_45 =>
CW <= '1';
if(stepcount < 49) then
step_clk <= clk_div;
else
motor_state <= STOP;
end if;
stepcount <= stepcount + 1;
when CCW_180 =>
CW <= '0';
if(stepcount < 199) then
step_clk <= clk_div;
else
motor_state <= STOP;
end if;
stepcount <= stepcount + 1;
end case;
end if;
end process;
end stm;
Error (10028): Can't resolve multiple constant drivers for net "motor_state.STOP" at motor_demo.vhd(52)
Error (10029): Constant driver at motor_demo.vhd(31)
Error (10028): Can't resolve multiple constant drivers for net "motor_state.CWISE" at motor_demo.vhd(52)
Error (10028): Can't resolve multiple constant drivers for net "motor_state.CCWISE" at motor_demo.vhd(52)
Error (10028): Can't resolve multiple constant drivers for net "motor_state.CW_45" at motor_demo.vhd(52)
Error (10028): Can't resolve multiple constant drivers for net "motor_state.CCW_180" at motor_demo.vhd(52)
Error (12153): Can't elaborate top-level user hierarchy
Error: Quartus II 32-bit Analysis & Synthesis was unsuccessful. 7 errors, 5 warnings
Edit: So apparently if I put the 'sw' case statement within 'if rising_edge(clk_div)' statement I don't have a problem, but the only downside is that's not ideal if the clock were to be going a few Hz.
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Only one process should generate "motor_state" but you get "motor_state <= stop;" in your 2nd process ! It seems you are new to VHDL, I suggest you to first describe completely your finite state machine by a schema : inputs and transitions to select which state, outputs for each state. and then simply transcode to VHDL.look for "moore machine", "mealy machine".
more secure like this.
else you will spend hours and get headache to "debug" a bad conception. EDIT : "Multiple drivers" means that tour "motor_state" is driven by more than one source and the synthesizer don't know how to resolve this signal, beacause this signal is declared as unresolved. "Unresolved signal" declaration is a good thing to early catch this error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Hi, Only one process should generate "motor_state" but you get "motor_state <= stop;" in your 2nd process ! --- Quote End --- I realise that, and I realise that's where the error is from. What I was confused about was how else I'm supposed to drop out of that state automatically after a number of cycles without that assignment there? I NEED two constant drivers as far as I can see. EDIT: I think I found a solution, but it's giving me a weird error and I can't see any problem. argh! Code is in my post below.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You dont need two constant drivers. Yoy just need to signal to your state machine when to stop. You probably need another signal for this.
Your new code should work as it's a single process. Remember that a signal takes the last thing assigned to it.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok, so here's my new code. Hopefully this is more appropriately written.
EDIT: This doesn't work, obviously. It doesn't drive the motor because cw_45 and ccw_180 are low to begin so it just throws it into the STOP state during the 'else' of the second if statement and keeps it there. Suggestions on how to fix?
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity motor_demo is
port( clk: in std_logic;
RST, EN, CTRL, HALF, CW, Step_clk: out std_logic;
sw: in std_logic_vector(0 to 4);
sw_check: out std_logic_vector(0 to 4)
);
end motor_demo;
architecture stm of motor_demo is
type motor_action is (STOP, CWISE, CCWISE);
signal motor_state: motor_action := CWISE;
signal stepcount: integer := 0;
signal clk_div: std_logic;
signal drive: std_logic := '0';
signal cw_45, ccw_180: std_logic := '0';
begin
-- Clock divider for stepper action
clk_divider: entity work.clk_divide port map(clk, clk_div);
-- Motor control lines
EN <= '1';
RST <= '1';
CTRL <= '1';
HALF <= '1';
-- switch debugging
sw_check <= sw;
-- driving the step clock
with drive select
step_clk <= clk_div when '1',
'0' when '0',
'0' when others;
process(clk_div, motor_state, sw) is
begin
if rising_edge(clk_div) then
if sw(0) = '0' then
motor_state <= CWISE;
elsif sw(1) = '0' then
motor_state <= CCWISE;
elsif sw(2) = '0' then
motor_state <= STOP;
elsif sw(3) = '0' then
motor_state <= CWISE;
cw_45 <= '1';
elsif sw(4) = '0' then
motor_state <= CCWISE;
ccw_180 <= '1';
end if;
-- counter conditions
if cw_45 = '1' AND stepcount < 49 then
stepcount <= stepcount + 1;
elsif ccw_180 = '1' AND stepcount < 199 then
stepcount <= stepcount + 1;
else
ccw_180 <= '0';
cw_45 <= '0';
motor_state <= STOP;
end if;
case motor_state is
when STOP =>
drive <= '0';
stepcount <= 0;
when CWISE =>
drive <= '1';
CW <= '1';
when CCWISE =>
drive <= '1';
CW <= '0';
end case;
end if;
end process;
end stm;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What exactly doesnt work? what errros are you getting? in simulation or on hardware? have you got a testbench?
You have a clock divider - if this is done in logic and not a PLL then you could have timing problems on a real circuit.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page