Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Button press to change state machine - "Can't resolve multiple constant drivers..."

Status
Not open for further replies.

kureigu

Member level 2
Joined
Jan 14, 2013
Messages
49
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Location
Scotland
Activity points
1,779
Button press to change state machine - "Can't resolve multiple constant drivers..."

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.

Code:
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;

Code:
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.
 
Last edited:

Re: Button press to change state machine - "Can't resolve multiple constant drivers.

You can't have a signal being driven from more than one process which is the reason for the error since 'motor_state' is assigned in both. As you have discovered, one solution is to embed the two into one process, the other is to recognize that your clocked process has no business modifying motor_state, simply commenting out the else branch as shown below will work.

Code:
if(stepcount < 49) then
    step_clk <= clk_div;
    stepcount <= stepcount + 1;  -- Moved inside the branch
-- else
--    motor_state <= STOP;
end if;

Part of your problem is conceptual. What you're calling 'motor_state' is not any sort of 'state', but what it really represents is a decoding of an input command (i.e. 'sw'). Since 'sw' is your input command, does it make sense then that the design would be able to generate it's own command? (Hint: the answer is 'no'). What the design can do is act on that input command, it cannot change the input command. Viewed in that light, it should make sense then why 'motor_state' should not be driven from within the clocked process.

Kevin Jennings
 

Re: Button press to change state machine - "Can't resolve multiple constant drivers.

So the problem is, I want the motor 'state' to be able to drop out of that state after so many cycles, as you can probably tell. How would I go about this if not counting within the state machine?

EDIT: I think I see what you're saying now. Perhaps I'd be best using the state machine to do purely the driving CW/CCW/stopping, and doing the timing and logic outside the case statement but still in the same process...?

EDIT 2: I attempted to make the state machine more like a state machine, but I'm struggling to make the push buttons do what I want in a sensible manner.

First two buttons need to make it latch in cw/ccw respectively, 3 needs to make it stop... that's easy enough.
Where I struggle: Buttons 4 and 5 need to make it spin a certain number of steps then stop, and below is my best attempt to do that.

Is there a better way than below? am I missing something? Sample/example code would be greatly appreciated to help clarify any points made, I'm trying hard to learn here.

EDIT3: 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. I need a way to stop it driving the motor after the counter reaches it's value, without affecting the other stuff.

New code:

Code:
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;
 
Last edited:

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top