Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
12 years ago

What should I use here - Need changing value in different processes

Hi, first post here and very poor VHDL knowledge. Tried my best but can't figure this out. Here is my problem:

I have 3 buttons. When any one is pressed I want to reset a corresponding variable/signal AND one (counter) or something to zero, the counter is connected to 3Hz clock. Clock works fine. Another process acts on clock ticks and increment the counter. When counter reaches a certain value the corresponding value which was set at button press gets acted upon. SO, this way I want to create a delay between button press and action (trying to avoid the debouncing and million other errors which were there before).

The problem:

I do not know which type of variable/signal to use for counter and the other corresponding value related to which button is pressed. I tried making both signals, it didn;t worked, error appeared about resolving multiple constant drivers. Tried with variable, same error.

Can some one pleaseeeeee help me?

library ieee;use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity StepperMotorController is
  port(
    stepper_clk_i    :in std_logic;
     Direction_i, Run_i, Halt_i:in std_logic;
    winding1A_o,winding1B_o,winding2A_o,winding2B_o:out std_logic;
    Led7,Led6,Led5,Led4:out std_logic;
    LED7S : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
    );
end entity StepperMotorController;
architecture structure of StepperMotorController is
    signal speed_cntrl : unsigned (1 downto 0):="00";        -- initiaize with value 0
    signal halt_cntrl, direction_cntrl: std_LOGIC:='1';
    shared variable D,R:integer:=0;
    signal clk_12Hz, clk_6Hz, clk_3Hz, stepper_clk:std_logic; -- create a 3Hz clock for 1:2:3 speed
    signal step : unsigned (2 downto 0);    -- Stes go from 0 to 7 steps = TOTAL 8 STEPS
    shared variable count:integer:=0;
    signal windings:std_logic_vector(3 downto 0);
    constant STEP1: std_logic_vector(3 downto 0):="1000"; -- for 15 degrees we need 8 steps which get repeated
    constant STEP2: std_logic_vector(3 downto 0):="1010";
    constant STEP3: std_logic_vector(3 downto 0):="0010";
    constant STEP4: std_logic_vector(3 downto 0):="0110";
    constant STEP5: std_logic_vector(3 downto 0):="0100";
    constant STEP6: std_logic_vector(3 downto 0):="0101";
    constant STEP7: std_logic_vector(3 downto 0):="0001";
    constant STEP8: std_logic_vector(3 downto 0):="1001";
begin
    winding1A_o <=windings(3);
    winding2A_o <=windings(1);
    winding1B_o <=windings(2);
    winding2B_o <=windings(0);
--    led7<=speed_cntrol(1);
--    led6<=speed_cntrol(0);
--    led7<=clk_12Hz;
--    led6<=clk_6Hz;
--    led5<=clk_3Hz;
        SPEED_BOX: process(stepper_clk_i) is
            variable counter:unsigned(2 downto 0):="000";  -- FROM 1 DOWN TO 0 > CHANGE TO 2 DOWN TO 0
            begin
                    if rising_edge(stepper_clk_i) then
                        counter:=counter+1;
                    end if;
                    clk_12Hz <= STD_LOGIC(counter(0));
                    clk_6Hz  <= STD_LOGIC(counter(1));
                    clk_3Hz  <= STD_LOGIC(counter(2));
            end process;
        
        COUNT_DELAY: process (clk_3Hz) is
            begin
                    count:=count+1;
            end process;
            
        COUNT_ACTION: process (clk_3Hz) is
            begin
                    if count=3 then
                            if D=1 then
                                direction_cntrl<=not direction_cntrl;
                            elsif R=1 then
                                speed_cntrl<=speed_cntrl+1;
                            else
                                D:=0;
                                R:=0;
                            end if;
                    end if;
            end process;
            
        SPEED_SELECT: with speed_cntrl select
                        stepper_clk <=    clk_12Hz when "00", 
                                           clk_6Hz  when "01",
                                           clk_3Hz  when others;-- on 2 it will get 3Hz.
        SPEED_DISPLAY: process (halt_cntrl,speed_cntrl) IS
            begin
                    if halt_cntrl='1' then
                                LED7S <=not "01110110"; -- 'H'
                    elsif speed_cntrl="00" then
                                LED7S<= not "01001110";    --'F'
                    elsif speed_cntrl="01" then
                                LED7S<=    not "00111110";--'|-|
                    else
                                LED7S<=    not "01101101";-- 'S'
                    end if;             -----.gfedcba 1low - 0 - high
            end process;
        STEPPER_SEQUENCER: process(stepper_clk) is  
            begin
                    if rising_edge(stepper_clk) then
                        if halt_cntrl='0' then
                            if direction_cntrl='1' then 
                                step <= step+1;
                            else
                                step <= step-1;
                            end if;
                        end if;
                    end if;
            end process;
 
        COIL_DRIVER: with step select
                                    windings <= STEP1  when "000",
                                                    STEP2  when "001",
                                                    STEP3  when "010",
                                                    STEP4  when "011",
                                                    STEP5  when "100",
                                                    STEP6  when "101",
                                                    STEP7  when "110",
                                                    STEP8  when "111",
                                                  "0000" when others;
        
        CONTROL: process(Direction_i,Run_i,Halt_i) is
            begin
                    if Direction_i='1' then
                        if halt_cntrl='0' then
                            count:=0;
                            D:=1;
                        end if;
                    elsif (Run_i='1') then
                        if halt_cntrl='1' then
                                halt_cntrl<='0';
                        else
                            count:=0;
                            R:=1;
                        end if;
                    elsif (Halt_i='1')     then
                            halt_cntrl<='1';
                    end if;
            end process CONTROL;
END structure;

18 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    have you written a testbench to test it in modelsim?

    --- Quote End ---

    I tried this the whole day. But I could not do it properly. Can someone test it for me please?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Finally some results. PLease see the attached pic. Run_i is LOW, but R stays High and keeps reading Run_i as HIGH continually. I don't know why this is happening.

    library ieee;use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    entity StepperMotorController is
      port(
        stepper_clk_i    :in std_logic;
    	 Direction_i, Run_i, Halt_i:in std_logic;
        winding1A_o,winding1B_o,winding2A_o,winding2B_o:out std_logic;
        Led7,Led6,Led5,Led4:out std_logic;
        LED7S : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
    	);
    end entity StepperMotorController;
    architecture structure of StepperMotorController is
    	signal speed_cntrl : unsigned (1 downto 0):="00";		-- initiaize with value 0
    	signal halt_cntrl, direction_cntrl: std_LOGIC:='0';
    	signal D,R,H,Done:std_LOGIC:='0';
    	signal counter:unsigned(2 downto 0):="000";  -- FROM 1 DOWN TO 0 > CHANGE TO 2 DOWN TO 0
    	signal clk_12Hz, clk_6Hz, clk_3Hz, stepper_clk:std_logic; -- create a 3Hz clock for 1:2:3 speed
    	signal step : unsigned (2 downto 0):="000";	-- Step go from 0 to 7 steps = TOTAL 8 STEPS
    	signal count:integer:=0;
    	signal windings:std_logic_vector(3 downto 0);
    	constant STEP1: std_logic_vector(3 downto 0):="1000"; -- for 15 degrees we need 8 steps which get repeated
    	constant STEP2: std_logic_vector(3 downto 0):="1010";
    	constant STEP3: std_logic_vector(3 downto 0):="0010";
    	constant STEP4: std_logic_vector(3 downto 0):="0110";
    	constant STEP5: std_logic_vector(3 downto 0):="0100";
    	constant STEP6: std_logic_vector(3 downto 0):="0101";
    	constant STEP7: std_logic_vector(3 downto 0):="0001";
    	constant STEP8: std_logic_vector(3 downto 0):="1001";
    begin
    	winding1A_o <=windings(3);
    	winding2A_o <=windings(1);
    	winding1B_o <=windings(2);
    	winding2B_o <=windings(0);
    	clk_12Hz <= STD_LOGIC(counter(0));
    	clk_6Hz  <= STD_LOGIC(counter(1));
    	clk_3Hz  <= STD_LOGIC(counter(2));
    					
    --	led7<=speed_cntrol(1);
    --	led6<=speed_cntrol(0);
    --	led7<=clk_12Hz;
    --	led6<=clk_6Hz;
    --	led5<=clk_3Hz;
    		SPEED_BOX: process(stepper_clk_i) is
    			begin
    					if rising_edge(stepper_clk_i) then
    						counter<=counter+1;
    					end if;
    			end process;
    		
    		SPEED_SELECT: with speed_cntrl select
    						stepper_clk <=	clk_12Hz when "00", 
    										   clk_6Hz  when "01",
    										   clk_3Hz  when others;-- on 2 it will get 3Hz.
    		SPEED_DISPLAY: process (halt_cntrl,speed_cntrl) IS
    			begin
    					if halt_cntrl='1' then
    								LED7S <=not "01110110"; -- 'H'
    					elsif speed_cntrl="00" then
    								LED7S<= not "01001110";	--'F'
    					elsif speed_cntrl="01" then
    								LED7S<=	not "00111110";--'|-|
    					else
    								LED7S<=	not "01101101";-- 'S'
    					end if;	         -----.gfedcba 1low - 0 - high
    			end process;
    		STEPPER_SEQUENCER: process(stepper_clk) is  
    			begin
    					if rising_edge(stepper_clk) then
    						if halt_cntrl='0' then
    							if direction_cntrl='1' then 
    								step <= step+1;
    							else
    								step <= step-1;
    							end if;
    						end if;
    					end if;
    			end process;
     
    		COIL_DRIVER: with step select
    									windings <= STEP1  when "000",
    													STEP2  when "001",
    													STEP3  when "010",
    													STEP4  when "011",
    													STEP5  when "100",
    													STEP6  when "101",
    													STEP7  when "110",
    													STEP8  when "111",
    												  "0000" when others;
    		
    		CONTROL: process(stepper_clk_i,Direction_i,halt_i,run_i) is
    			begin
    --				if rising_edge(stepper_clk_i) then
    --					if (clk_12Hz='1') then
    							if Run_i<='1' then
    								  count<='0';
    								  R<='1';
    							elsif Direction_i='1' and halt_cntrl='0' then
    									count<=0;
    									D<='1';
    							elsif Halt_i='1' then
    									count<=0;
    									H<='1';
    							else
    									if Done='1' then
    										if D='1' OR R='1' OR H='1' then
    											D<='0';
    											R<='0';
    											H<='0';
    										end if;
    									end if;
    									count<=count+1;
    							end if;
    --					end if;
    --				end if;
    			end process CONTROL;
    			
    			ACTION: process (stepper_clk_i) is
    				begin
    						if count=4 then
    							if D='1' then
    										direction_cntrl<=not direction_cntrl;
    										Done<='1';
    							elsif R='1' then
    										if halt_cntrl='1' then
    											halt_cntrl<='0';
    											Done<='1';
    										else
    											speed_cntrl<=speed_cntrl+1;
    											Done<='1';
    										end if;
    							elsif H='1' then
    										Halt_cntrl<='1';
    										Done<='1';
    							end if;
    						end if;
    						if D='0' and R='0' and H='0' then
    										Done<='0';
    						end if;
    				end process;
    END structure;
    

    The test bench code is here:

    
          
        Main_Clock : Process is
          Begin
            stepper_clk_i<='1';
            wait for 5 ns;
            stepper_clk_i<='0';
            wait for 5 ns;
          End process;
          
        Run_But: Process is
          Begin
            wait for 20 ns;
            Run_i<='1';
            wait for 20 ns;
            Run_i<='0';
            wait for 300 ns;
          end process;
          
          Halt_But: Process is
            Begin
              Halt_i<='0';
              wait;
          end process;
    END ; 
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You picture is too small to see the signal names.

    R will get set high as soon as run_i goes high. It wont go low again until done is '1'.

    and I just noticed that the ACTION process uses the stepper clock in the sensitivity list, but it is NOT a clocked process. So therefore its all wrong. You need to remove stepper_clk_i from the sensitivity list and add count, D, derection_cntrl, R, halt_cntrl, speed+cntrol, H. THis process will also create latches, as you have incomplete if statements.

    ACTION : process(R, D, H, count,derection_cntrl, halt_cntrl, speed_cntrl)

    Plus, putting adders in asynchronous processes is a bad idea.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    You picture is too small to see the signal names.

    R will get set high as soon as run_i goes high. It wont go low again until done is '1'.

    --- Quote End ---

    This is not happening. Run_i is being read as high all the time. I don't know why, even though it is low.

    --- Quote Start ---

    and I just noticed that the ACTION process uses the stepper clock in the sensitivity list, but it is NOT a clocked process. So therefore its all wrong. You need to remove stepper_clk_i from the sensitivity list and add count, D, derection_cntrl, R, halt_cntrl, speed+cntrol, H. THis process will also create latches, as you have incomplete if statements.

    ACTION : process(R, D, H, count,derection_cntrl, halt_cntrl, speed_cntrl)

    --- Quote End ---

    If I do not do this then how will I update the count at set intervals. Count is the one creating the delay after the button is released. I was looking at this as a helper signal to avoid debouncing of switches.

    --- Quote Start ---

    Plus, putting adders in asynchronous processes is a bad idea.

    --- Quote End ---

    What do you mean by this. Can you please explain pointing to the code? Thanks (I will try uploading a bigger picture when I reach home for you, not sure why it came so small.)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    This is not happening. Run_i is being read as high all the time. I don't know why, even though it is low.

    --- Quote End ---

    How do you know it is being read as high? There is no way you know something is being read - its all down to your code. Plus the testbench you posted only shows the inputs for run, clk and halt. What about direction?

    --- Quote Start ---

    If I do not do this then how will I update the count at set intervals. Count is the one creating the delay after the button is released. I was looking at this as a helper signal to avoid debouncing of switches.

    --- Quote End ---

    Synthesis ignores sensitivity lists, and will build the logic by whats in the process. But simulation works by whatever is in the code. So, from your code, the ACTION process only updates when the clock changes (so it will activate on rising AND falling edges of the clock). This means you will get a simulation/synthesis missmathc. If you want a delay, you need to use a clocked process.

    --- Quote Start ---

    What do you mean by this. Can you please explain pointing to the code? Thanks (I will try uploading a bigger picture when I reach home for you, not sure why it came so small.)

    --- Quote End ---

    If you have an asynchronous process with an adder, the adder feeds back into itself, so when you +1, it then needs to +1 again, and so on and so on. It makes a logic loop with the adder trying to add 1 to itself in 0 time. Using a clock prevents this by determining when the adder should be updated.

    I really suggest you read a logic tutorlal. Are you usually a software engineer?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Are you usually a software engineer?

    --- Quote End ---

    Unfortunately, Yes I am. I write for PICs/Avrs etc.

    I have uploaded a better picture. I hope this will make clear my previous questions.

    I appreciate your attempt to help but this seems complicated. I will really appreciate if you can make changes in the code and I can understand it /test it as I go along. Many thanks.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I am not going to do your work for you. But, R is not changing because Done never goes high, because the count never increases. You need to learn to debug your own code.