Search code examples
vhdl

Ring Oscillator


I'm having some trouble implementing a ring oscillator. I don't care about it working on an FPGA. I only want to simulate using Xilinx ISE. Is the code below acceptable? I also addded the test bench. Thanks!

Code


library ieee;
use ieee.std_logic_1164.all;

-- 5 Ring Oscillator

entity ring_osc is
    port (ro_en : in std_logic;
            delay : in time;
            ro_out : out std_logic);
end ring_osc;

architecture behavioral of ring_osc is
    signal gate_out : std_logic_vector(5 downto 0) := (others => '0');

begin
    process
    begin
        gate_out(0) <= ro_en and gate_out(5);
        wait for delay;
        gate_out(1) <= not(gate_out(0));
        wait for delay;
        gate_out(2) <= not(gate_out(1));
        wait for delay;
        gate_out(3) <= not(gate_out(2));
        wait for delay;
        gate_out(4) <= not(gate_out(3));
        wait for delay;
        gate_out(5) <= not(gate_out(4));
        wait for delay;
        ro_out <= gate_out(5);
    end process;

end behavioral;

Test Bench


library ieee;
use ieee.std_logic_1164.all;

entity ring_osc_tb is
end ring_osc_tb;

architecture behavior of ring_osc_tb is 

    -- component declaration for the unit under test (uut)

    component ring_osc
        port (ro_en : in  std_logic;
              delay : in time;
              ro_out : out  std_logic);
    end component;


    -- Inputs
    signal ro_en : std_logic := '0';
    signal delay : time := 0.5 ns;

    -- Outputs
    signal ro_out : std_logic;

    signal clk : std_logic := '0';
    constant clk_period : time := 10 ns;

begin

    -- instantiate the unit under test (uut)
    uut: ring_osc port map (
        ro_en => ro_en,
        delay => delay,
        ro_out => ro_out
    );

    -- clock process definitions
    clk_process :process
    begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
    end process;

    -- stimulus process
    stim_proc: process
    begin
        ro_en <= '1';
        delay <= 0.5 ns;
        wait for 10*clk_period;

        delay <= 1 ns;
        wait for 5*clk_period;

        assert false report "End of Simulation" severity failure;
    end process;

end;

Solution

  • The process with sequential wait does not describe the concurrent nature of the gates in the Ring oscillator, since execution is suspended for delay time at each wait, which is not the way a real word design operates.

    A description with concurrent evaluation of all the gates can be:

    gate_out(0) <= ro_en and gate_out(5) after delay;
    
    inv_g : for i in 1 to gate_out'high generate
      gate_out(i) <= not gate_out(i - 1) after delay;
    end generate;
    
    ro_out <= gate_out(5);
    

    This is for simulation only, as also noted in the question, due to the inherent loop nature of a ring oscillator.

    Using test bench, with added disable at start:

    -- Disable at start
    ro_en <= '0';
    delay <= 0.5 ns;
    wait for 10 * 0.5 ns;
    

    Then the resulting waveform is:

    enter image description here