Forum Discussion

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

Synchronization on falling and rising edges

Hi, I need help .

I need to synchronize to the falling and rising edge encoder signal "A" .

Both these edges need to work with the signal "count".

I have this error : Error (10028): Can't resolve multiple constant drivers for net "number[0]" at encoder.vhd(62)

My code:

library ieee;

use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

entity encoder is

port( clk:in std_logic;

A:in std_logic;

B:in std_logic;

number:buffer unsigned(11 downto 0):=(others=>'0'));

end encoder;

architecture main of encoder is

signal count: unsigned(11 downto 0):=(others=>'0');

begin

ld:process(A)

begin

if rising_edge(A) then

if B='0' then

number<=number + 1;

end if;

if B='1' then

number<=number - 1 ;

end if;

end if;

end process;

ld1:process(A)

begin

if falling_edge(A) then

if B='1' then

number<=number + 1;

end if;

if B='0' then

number<=number - 1 ;

end if;

end if;

end process;

end main;

this is signal of encoder

http://3.bp.blogspot.com/_qwqti0pxucw/tjbvdoimaxi/aaaaaaaaauk/m6on7fybr0o/s1600/encoding.png

9 Replies

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

    multiple drivers are not allowed in fpga design(or digital design but possible in analogue domain).

    you can use two counters then mux the result but I don't see why you will ever need that as it looks like DDR signal
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello Tomsik,

    I had a similar problem some time ago.

    The trick i used is to generate the flank detections on an internal FPGA clock.

    This clock is normally a lot faster than the ecoder timing, so it should not be a problem.

    wire a;

    wire b;

    assign a = KEY[0];

    assign b = KEY[1];

    reg aPrev;

    reg bPrev;

    always @(posedge CLOCK_50)

    begin

    // mounting flank on A

    if (a > aPrev)

    begin

    if (b==0)

    r <= r+1;

    else

    r <= r-1;

    end

    // descending flank on a

    if (a < aPrev)

    begin

    if (b==1)

    r <= r + 1;

    else

    r <= r - 1;

    end

    aPrev<=a;

    bPrev<=b;

    end

    Best Regards,

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

    This is not VHDL.

    Works only on second turn encoder.

    But I need capture the falling edge and affect the signal.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    OK problem resolved!

    library ieee;

    use ieee.std_logic_1164.all;

    use ieee.numeric_std.all;

    entity encoder is

    port( clk:in std_logic;

    state_A:in std_logic;

    B:in std_logic;

    number:buffer unsigned(11 downto 0):=(others=>'0'));

    end encoder;

    architecture main of encoder is

    signal number1:unsigned (11 downto 0):=(others=>'0');

    signal number2:unsigned (11 downto 0):=(others=>'0');

    signal cislo:unsigned (11 downto 0):=(others=>'0');

    signal NOTstate_A: std_logic;

    begin

    ld:process(state_A,NOTstate_A)

    begin

    if rising_edge(state_A) then

    if B='0' then

    number1<=number1 + 1;

    end if;

    if B='1' then

    number1<=number1 - 1;

    end if;

    end if;

    if rising_edge(NOTstate_A) then

    if B='1' then

    number2<=number2 + 1;

    end if;

    if B='0' then

    number2<=number2 - 1;

    end if;

    end if;

    end process;

    NOTstate_A<=not state_A;

    cislo<=number1+number2;

    number<=not cislo;

    end main;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    This is unlikely to work in real hardware. You have generated a logic clock and the timing between the two clocks is likely to be variable.

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

    --- Quote Start ---

    This is unlikely to work in real hardware. You have generated a logic clock and the timing between the two clocks is likely to be variable.

    --- Quote End ---

    My program works excellently. The outputs of the rotary encoder are routed on capacitor and schmitt gate .
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello, please How to my code takes 756 total logic elements. Can I somehow save the data to an external RAM or internal RAM . How?

    library ieee;

    use ieee.std_logic_1164.all;

    use ieee.numeric_std.all;

    entity Number_converter is

    port( INPUT12bit: in unsigned (11 downto 0);

    digit1: out unsigned (11 downto 0);

    digit2: out unsigned (11 downto 0);

    digit3: out unsigned (11 downto 0);

    digit4: out unsigned (11 downto 0));

    end entity;

    architecture main of Number_converter is

    signal INPUT12bit_INT:integer range 0 to 4096;

    attribute ramstyle: string;

    attribute ramstyle of digit4 : signal is "M9K";

    begin

    digit1<=(INPUT12bit rem 10)/1;

    digit2<=(INPUT12bit rem 100)/10;

    digit3<=(INPUT12bit rem 1000)/100;

    digit4<=(INPUT12bit/1000);

    end main;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    divide and remainder take a lot of logic to implement when the denominator is not 2^n.

    You also cannot turn an output into a ram.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    divide and remainder take a lot of logic to implement when the denominator is not 2^n.

    You also cannot turn an output into a ram.

    --- Quote End ---

    Please, How?