Forum Discussion

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

Synthesizable delay with VHDL (One single output pulses)

Thanks in advance for your nice instructions.

What I am doing is producing a single output pulse. It is a simple output but due my little knowledge it becomes complicated for me.

What I want in output is like this [SUB]--------0-------[/SUB][SUP]-------1-------[/SUP][SUB]---------0-------[/SUB]

It is simple but there are some points, As the pulse width (When pulse is "1") is important for my experiment, I have used counters to count clock cycles and make output "1" for a certain clock cycles make output "0" after certain clock cycles.

But the problem is at the starting point. When I connect it to Oscilloscope the output is "1" before my commands.

I have attached the Oscilloscope waveform. The waveform is always "1" before my real command. I want 0 and 1 and then 0 again without any other repetition.

Please look at the code and help me for correction.

As I write in the code, After 2 clock pulse (Constant a) output become "1" and after 3 clock pulse (Constant b) output become "0" again, This is for controlling the output pulse width. But the problem is about before starting. As you see in the attachment picture, output of FPGA already is "1" and then my codes acts.

I am sure there are some mistake in the code, please help me to correct it.

library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;
entity ltd_auto is
port    (        clk : in std_logic;
        data_out: out std_logic    );
end ltd_auto;
Architecture behavioral of ltd_auto is
signal         c : integer:= 0;
constant     a : integer:= 2;
constant        b : integer:= 3;
type state_type is (idle, delay, zero);
signal  next_s: state_type;
begin
     process (clk)
        begin            if (rising_edge(clk))then
                case next_s is
                    when idle =>
                        c <= c + 1;
                        next_s <= delay; 
                   when delay =>
                        if (c = a) then
                            data_out <= '1';
                        end if;
                        if (c = b) then
                        data_out <= '0';
                        next_s <= zero;
                        else
                        c <= c + 1;
                        end if;
                    when zero => 
                   c <= 0;
                end case;
            end if;
    end process;
end behavioral;

another code that i wrote with the same problem


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ltd_1 is
port    (        clk : in std_logic; 
       data_out: out std_logic    );
end ltd_1;
Architecture behavioral of ltd_1 is
signal         c : integer:= 0;
constant     a : integer:= 1;
constant        b : integer:= 2;
begin 
    process (clk) 
       begin  
          if (falling_edge(clk))then 
               c <= c + 1;
                    if (c = a) then 
                   data_out <= '1';
                    elsif (c = b) then
                    data_out <= '0';
                    end if;
            end if;
    end process;
end behavioral; 
               

Thank you in Advance for your help.

10 Replies

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

    You're inferring a register on data_out. You may assign a default value '0' to it, when conditions ( c = a ) and ( c = b ) don't match.

    process..

    begin

    if( rising_edge(clk)) then

    data_out <= '0';

    case ....

    a reset condition it helps too:

    begin

    if(clr='1') then

    data_out <= '0';

    elsif(rising_edge(clk)...
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi,

    one more to mention is, that the FPGA Output Pins are tri-state as long as the FPGA has not configured. Thus in case you do not pull the Signal down by an external resistor, there will always be a high Signal till the FPGA has configured and started to execute programming...
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Another point, In the below mentioned code I have a pulse like this [SUB]----0---[/SUB][SUB]----0---[/SUB][SUB]---0----[/SUB][SUP]-----1----[/SUP][SUB]----0---[/SUB][SUB]----0---[/SUB][SUB]---0----[/SUB][SUP]-----1----[/SUP]. The point is that I need only the first "1", I do not need any pulses any more. But as I have to control the pulse width of my signal (When the output is "1") therefore I need to use counter.

    I have used the type command and two state (idle and delay). After idle state it goes to delay state and if it was (c=a) output become 1 and if it was (c=b) output become 0 (Because I need to control the pulse width). After it becomes 0 it goes again to delay state. I have tried many other options to don't let goes to idle after delay state. What is your suggestion for rejection of repetition.

    I mean, only one pulse in output with width controllability??

    library ieee;

    use ieee.std_logic_1164.all;

    use ieee.numeric_std.all;

    entity delay_auto is

    port

    (

    clk : in std_logic;

    data_out: out std_logic

    );

    end delay_auto;

    Architecture behavioral of delay_auto is

    signal c : integer:= 0;

    constant a : integer:= 5;

    constant b : integer:= 6;

    type state_type is (idle, delay);

    signal next_s: state_type;

    begin

    process (clk)

    begin

    if (rising_edge(clk))then

    case next_s is

    when idle =>

    c <= c + 1;

    next_s <= delay;

    when delay =>

    if (c = a) then

    data_out <= '1';

    end if;

    if (c = b) then

    data_out <= '0';

    next_s <= idle;

    c <= 0;

    else

    c <= c + 1;

    end if;

    end case;

    end if;

    end process;

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

    You get repeated pulses because you set the state machine back to the IDLE state after the delay state, and hence it loops forever.

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

    Tricky: Thanks for the reply.

    I have mentioned this state machine makes a loop. (Idle to delay to idle to delay etc). As I said I want to cancel the loop. Any idea how to cancel the loop for only one output pulse with width controbillity? I tried to describe another state with name of "zaro" to make the counter c <=0 but it won't help.

    This is what I mean [SUB]----0----[/SUB][SUP]--------1-------[/SUP][SUB]------------------0------------------[/SUB]
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    remove the return to the idle state from the 2nd state.

    --- Quote End ---

    I did before. Please go up and read the thread from the first. When I remove idle from the 2nd state output become 1 before my original code. I attached the image also.

    Anyway Thank you foe follow up. I really need help for this.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Try this. It has a new state that hangs the state machine:

    begin

    process (clk)

    begin

    if (rising_edge(clk))then

    data_out <= '0';

    case next_s is

    when idle =>

    c <= c + 1;

    next_s <= delay;

    when delay =>

    if (c = a) then

    data_out <= '1';

    c <= c + 1;

    end if;

    if (c = b) then

    data_out <= '0';

    next_s <= stopped;

    c <= 0;

    else

    c <= c + 1;

    end if;

    when stopped =>

    data_out <= '0';

    end case;

    end if;

    end process;

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

    I might have not got the clue on your Intention, but in case you just Need one pulse when the FPGA goes online, this should be possible by just implementing a Counter that starts couting with every rising edge of clk as Long as the final value is not reached. the Output can be set high for countervalue being higher than x (this is the number of clocks delaying the high pulse) and being lower than y (with y-x defining the pulse width):

    signal Counter : integer range 0 to 1023;

    signal start_delay : integer range 0 to 1023;

    signal pulse_width: integer range 0 to 1023;

    process(clk,POR)

    begin

    if (POR='1') then

    Counter <= 0;

    Output <= '0';

    elsif rising_edge(clk) then

    if (Counter < 1023)

    then

    Counter <= Counter+1;

    end if;

    if (Counter < start_delay)

    then

    Output <= '0';

    elsif (Counter < (start_delay+pulse_width))

    then

    Output <= '1';

    else

    Output <= '0';

    end if;

    end if;

    end process;

    The POR signal is a internally generated (or external applied) PowerOnReset signal - not functionally necessary...

    I just wrote this here - did not check for Syntax in QII yet, thus excuse any typo...