0

I'm creating an architecture to drive a stepper motor using an FPGA board with a L297 controller. So in order to change the speed i created a clock divider to change the clock frequency taken by the L297. The clock divider works just fine. My problem is that I created mutiple clock outputs, one of which will be selected using Push-buttons on the board, so when i connect those signals to the MUX the output is not tottaly correct when it comes to clock input signals but it works fine with STD_LOGIC. This is the code i used for the MUX

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;

entity TEST_MUX is
Port ( A : in  STD_LOGIC;
       B : in  STD_LOGIC;
       C : in  STD_LOGIC;
       D : in  STD_LOGIC;
       E : in  STD_LOGIC;
       choice_select : in  STD_LOGIC;
       choice_valid : in  STD_LOGIC;
       choice_reset : in  STD_LOGIC;
       Choice : out  STD_LOGIC);
  end TEST_MUX;

 architecture Behavioral of TEST_MUX is

signal count : integer  := 0;
signal S_out : STD_LOGIC ;

 begin

 process ( choice_select , choice_valid, choice_reset,A,B,C,D,E)
   begin
if (choice_reset = '0') THEN
            count <=0;
            S_out <= 'Z';
            else
            if (choice_select'event) and (choice_select ='1')  THEN
                    count <= count + 1;
                        if (choice_valid = '1')  THEN
                            case count is
                            when  1=>  S_out<=A ; 
                            when  2=>  S_out<=B ;  
                            when  3=>  S_out<=C ; 
                            when  4=>  S_out<=D; 
                            when  5=>  S_out<=E ;   
                            when others =>   S_out <= 'Z';
                            end case;
                        end if;
           end if;
end if;                                         
end process;

Choice<=S_out;

end Behavioral;

Here is the correct simulation result when the input are STD_LOGIC : enter image description here

Here with inputs forced as clock: enter image description here Thank you for you help

  • What a mess. I recommend you try and separate the combinatorial and sequential part of the process you have right now. Also avoid using ieee.std_arith. Use ieee.numeric_std instead. And most important do not use both at the same time. – andrsmllr Jun 27 '17 at 09:25
  • do you mean separate the combinatorial and sequential part. aren't the if and case statement supposed to be inside the process – Med Khalil Jun 27 '17 at 09:48
  • Why are you using `'Z'` = tristate in your code? This is not supported on internal FPGA signals. Also: I hope you are aware that you need to put clock domain synchronizers on external inputs (push buttons) to be able to use them? Else they will screw up internal logic by violating setup-and-hold times – JHBonarius Jun 27 '17 at 11:42

1 Answers1

0

Let's look at the contents of your process more closely:

process ( choice_select , choice_valid, choice_reset,A,B,C,D,E)
begin
  if (choice_reset = '0') THEN
    -- Reset things
  else
    if (choice_select'event) and (choice_select ='1')  THEN
      -- Counter and multiplexer here
    end if;
  end if;                                         
end process;

You have put a lot of signals in your sensitivity list, but the only two signals that can actually cause your process to do anything are choice_reset and choice_select. Crucially, the block where your multiplexer and counter are is only executed if there is an event (i.e. a transition) in your choice_select signal. Changes in A, B, etc, do not enable this block, and so you do not see your multiplexer doing anything if only these signals have changed.

What you need to do is to move your multiplexer into another, unclocked process:

process (count, choice_valid, choice_reset, A, B, C, D, E)
begin
  if (choice_reset = '0') THEN
      S_out <= 'Z';
  elsif (choice_valid = '1')  THEN
    case count is
      when 1 => S_out <=A; 
      when 2 => S_out <=B;  
      when 3 => S_out <=C; 
      when 4 => S_out <=D; 
      when 5 => S_out <=E;   
      when others => S_out <= 'Z';
    end case;
  end if;                                         
end process;

Having said all that, the correct way to implement clock multiplexers in most FPGA devices is to make use of whatever dedicated clock multiplexers the device might have. This ensures that clocks stay on clock routing networks, and may even provide glitch-free switching between clocks. You may be able to establish that a LUT-based multiplexer is sufficient for your application, but this should not be the starting assumption.


You can use the functions rising_edge() or falling_edge() as a better alternative to the 'event style used in your code, i.e. if rising_edge(choice_select) then.

Per the comment, you should also not use ieee.std_logic_arith.all; or use ieee.std_logic_unsigned.all;.

scary_jeff
  • 4,314
  • 13
  • 27
  • what you said does make alot more sens and it's more logical than what i did, I think i can fix it now by sperating the the multiplexer and the case stament, thank you very much sir i really appreciate the help – Med Khalil Jun 27 '17 at 10:48