Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16606 Discussions

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

Altera_Forum
Honored Contributor II
2,154 Views

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.
0 Kudos
5 Replies
Altera_Forum
Honored Contributor II
654 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
654 Views

 

--- 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.
0 Kudos
Altera_Forum
Honored Contributor II
654 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
654 Views

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;
0 Kudos
Altera_Forum
Honored Contributor II
654 Views

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.
0 Kudos
Reply