Jump to content
  • 0

Nexys 4 Ring Oscillator


Shahin

Question

Hey guys,

I want to implement a ring oscillator on my Nexys 4. Below is an image of the structure I want to implement and the code is also attached:

 

image.thumb.png.33a3dbe6fd3ce0047ff459e9

 

Is it possible to just synthesize this and read the output of the counter or simply attach the output of the CUT to an oscilloscope and read the frequency?

 

Thanks,

Shahin

source.zip

Link to comment
Share on other sites

20 answers to this question

Recommended Posts

Hi again Shalin.

I got this design up and running on my Spartan 6 board, sadly I included an error to add to your frustration:

 

process(reset_count,signals(signals'high))
   begin
      if reset_count = '1' then
         pulse_counter <= (others =>'0');
      elsif rising_edge(signals(signals'high)) then
         pulse_counter <= pulse_counter+1;   -- ERROR WAS HERE
      end if;
   end process;

I can't go back and updated the original post - drat!

On my spartan 6, with the reference clock of 32MHz I get 0x2D = 46 cycles per hundred 32MHz clock cycles =3125ns/46 = approx 68 ns per oscillation, or about 0.90 ns per LUT (and the routing delay) in the counter. 

A few randomly selected route had routing delays of between 0.3ns and 0.9ns, and the chip datasheet has a LUT delay of between 0.26ns, so it sounds like the right number.

Here's a picture of the ring oscillator from the FPGA floorplan editor.

Ring.png.

I've also added a full writeup on my wiki at http://hamsterworks.co.nz/mediawiki/index.php/Ring_Oscillator

Link to comment
Share on other sites

12 hours ago, xc6lx45 said:

This is actually cool stuff

I agree completely.

12 hours ago, xc6lx45 said:

My main concern with "innovative" approaches is that we can never prove that it works reliably

This comment set off the nerve right next to the one that's been buzzing since I started reading this thread. It's true that once in a 'blue moon' an innovation destroys current thinking of an idea. But there seems to be some areas where such innovation is very unlikely. As xc6lx45 points out there's a lot that the user can't control in an FPGA implementation. Worse, digital means for generating random numbers have come and gone over that many decades that I've been in the industry.

This is just a thought but if I were assigned to do such an investigation and it had to do with digital logic** I'd gravitate toward ECL, CML or PECL MSI logic ( briefly there was GaAs logic). You have reasonably well known and quantifiable blocks to play with and an opportunity to exploit the analog nature of very high slewing logic with consistent logic structures; but with the ability to wedge your own 'magic sauce' between them. But, even of you can remove most of the uncontrollable aspects it seems to me that the domain of digital logic, for this line of design, is like the sirens that called to Jason and the Argonauts...  but causing a slightly different type of craziness; inviting you to see things that aren't there and get 'wrapped-around the axle' so to speak. I do know this; many have sailed this sea and not returned. There's a reason why digital random number generators aren't available at your favorite distributor.

To anyone thinking that such advise is silly, all I can say is, your best revenge is to prove me wrong. Sometimes being proven wrong is great! Been there; done that. ( I was convinced that IBM's venture into a 'PC' for individuals and small businesses was a very expensive and short lived experiment; as long as they controlled it. Somehow, the most powerful computing company in the world managed to screw up that monopoly ( perhaps with a little help from a partnership with Mr. Gates and associates ) and, as they say, the rest is history...)

** Digital logic doesn't exist in the physical realm if it ever switches state, but is really old fashioned, complicated  analog. Fortunately, we can pretend it is to a great extent most of the time.

Link to comment
Share on other sites

This is actually cool stuff. Please take this as constructive input on academic research:

A very straightforward problem is that P&R isn't fully under user control (even if I constrain the sites). There's a risk that performance tested on an empty device is optimal (shortest routes, highest frequency) but degrades as design density goes up and path lengths increase.

My main concern with "innovative" approaches is that we can never prove that it works reliably, in all device process corners and across the life span of the device. The basic, advertised features (e.g. the LC oscillator in an MMCM) are validated extensively, both in theory (e.g. sufficient margin for the loop stability factor, to pick one parameter out of a very long list) and hardware validation (say, "high temperature operating life" HTOL testing. Ovens full of tightly packed devices that are then tortured for weeks or even months).

For the chaotic oscillator, we have to rely on a "cowboy proof" - it worked yesterday, it works today, it'll probably still work tomorrow :)

Here's a random link about CMOS reliability, relatively recent (2016). The question I'd ask is, are we subjecting the device to stress that will cause it to change over time. Or more precisely (any semiconductor changes with time => Avogadro's law, e.g. diffusions wander), that will detectably change the analog behavior. For digital operation, your chip is designed to be maximally robust. But this is not a digital circuit, so there may be nasty surprises when for example previously independent random processes suddenly get correlated, say via supply line coupling. Deterministic post-processing cannot add entropy, suddenly my RNG leaves finger prints...

Example for stress, Fig. 1.2, change in threshold voltage (which will obviously have some impact on this pseudo-analog circuit). I'd also keep an eye on current consumption (electromigration) when chip-internal signals are becoming ill-defined in continuous operation on a large scale.

Bad cryptography kills people - maybe I wouldn't consider it for (Xilinx paper) "... probably the most demanding cryptographic applications"...

But, it's a cool little circuit, shows what FPGAs can do besides "mainstream synchronous logic" .

 

 

Link to comment
Share on other sites

So I went different way, described in following paper: https://forums.xilinx.com/xlnx/attachments/xlnx/NewUser/35703/1/High Speed True Random Number Generators in Xilinx FPGAs.pdf

 

With quite a simple and short code (God bless the authors of 'generate' statement in VHDL! :)) I've generated 32-channel source of high frequency noise that looks very promising on my oscilloscope.

Now it is time to sample it with D-type flip-flops, create AXI IP core and send a stream of random numbers to my PS to test it with DieHarder. :)

Link to comment
Share on other sites

15 hours ago, Zygmunt said:

As you see strategy of solvina a problmem by avoiding it and assuming that this problem is not worth solving won't work in this case.

Fair enough, and honestly I wish you good fortune. There are a lot of ghosts in the house that you've chosen to occupy.

Link to comment
Share on other sites

I am doing this to statistically evaluate such a generator (in fact - to test TRNGs using RO) and compare its results with other generators. As you see strategy of solvina a problmem by avoiding it and assuming that this problem is not worth solving won't work in this case. ;)

Link to comment
Share on other sites

24 minutes ago, Zygmunt said:

I need it to generate jitter as a source of entropy for true random number generator

Interesting.... There are ( I'm assuming ) much better, analog techniques for 'true' random generators. I've seen a few. Whether or not they work reliably or are immune to outside influence I can't say. Personally, I put this line of investigation into the same bucket as cryptology... not so difficult that anyone can't implement a concept but way too complicated to pull off correctly ( or perhaps I should say avoid all the ways of failing where it counts ). Why do you assume that such a scheme, if you get it to work, is independent of everything else in an FPGA design that would use it? I wouldn't want to be the person responsible for proving that your 'random' numbers are truly appropriate for any particular application. Then there's the problem of repeatability across implementation generations. Perhaps your entropy is more of a signature?  Let's face it pseudo-random number generators have their place but any application requiring 'true' random number generators that I can think of have pretty high standards to meet. None of this is to say that it can't be done, just that I'm very skeptical ( not that this should bother anyone). My bet is that poking holes in any implementation anyone come's up with will be easier than developing the implementation. I am for certain no expert in the matter.  

Link to comment
Share on other sites

2 hours ago, zygot said:

 I need someone to tell me why they need a ring oscillator instead of using a PLL that can create clocks well above what the device can support

I need it to generate jitter as a source of entropy for true random number generator. PLL won't do the job.

Link to comment
Share on other sites

I have a few comments on creating ring oscillators in FPGA devices.

About using oscilloscopes: By default most digital scopes use sin(x)/x interpolation when displaying a signal. This presentation can create a false impression as to what the actual signal looks like. There are a number of ways to get an oscilloscope to trick you into thinking that a signal looks like something that it isn't. That's the nature of tools. A garden hoe is just as happy to slice off one of your toes as it is to slice off the top of a weed. You have to be in control.

To me a ring oscillator is an oscillation caused by a race condition of combinatorial logic with feedback. There are a number of reasons why synthesis and simulation tools aren't designed to support such designs. Still, you can fool the synthesis tool into creating a logic structure by using the 'event or rising_edge syntax using logic signals instead of a real clock. I'm really not sure exactly what it is that you get from doing this. Tricking the simulator into doing an RTL simulation will require a lot more effort.

But, let's say that you can get the tool to synthesize a logic implementation and have also taken the time to create location constraints that place specific logic elements into specific LUT locations. Let's assume that you have a signal in your FPGA that oscillates more or less reliably at some very high rate ( I need someone to tell me why they need a ring oscillator instead of using a PLL that can create clocks well above what the device can support ), what good is it? I'm assuming that you want to see a sine wave on an IO pin. Understand that you need to go though some IOSTANDARD driver structure first which is not likely to pass such a signal into a load. Of course if all you want to do is see a sinewave on an FPGA output you can set up your scope to show you that.... and that brings us back to lab test equipment.

This is all fun stuff to think about. Frankly, I think that it's a waste of time to work on ( at least in the FPGA world ).

 

Link to comment
Share on other sites

Hi!

I have programmed my ZedBoard with code above (Shahin successfully used it on his Nexys4), but there is no oscillating signal on output (checked with  my oscilloscope).

My constraints (generated by Vivado):
 

set_property PACKAGE_PIN W11 [get_ports osc_out]
set_property IOSTANDARD LVCMOS33 [get_ports osc_out]
set_property PACKAGE_PIN P16 [get_ports reset]

set_property SLEW SLOW [get_ports osc_out]

set_property IOSTANDARD LVCMOS33 [get_ports reset]

set_property PULLDOWN true [get_ports reset]

Any ideas what went wrong?

I guess that I should find better source of reset signal, but I don't know any good source of this signal in PL.

Link to comment
Share on other sites

 

​Hi Hamster,

 

Your lastest post is deleted for some reason...I wanted to thank you again for the great response. The world needs more people like you :)

 

Also, I have another code now to implement the ring oscillator using hard LUTs and I just tested it on the Nexys 4 board and it works! Results are attached for a 5/7 stage ring oscillator. It would be great to combine this with your code, where we could have the counter at the output of my oscillator and display the results after a number of cycles on the 7segment display/LEDs and wait for a reset button to display the results for the next number of cycles.

 

My code is as follows:


--
-- Library declarations
--
-- The Unisim Library is used to define Xilinx primitives. It is also used during
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library unisim;
use unisim.vcomponents.all;
--
------------------------------------------------------------------------------------
--
-- Main Entity for ring_osc
--
entity ring_osc is
  port(   osc_out : out std_logic;
            reset : in std_logic   );
  end ring_osc;
--
------------------------------------------------------------------------------------
--
-- Start of Main Architecture for ring_osc
--     
architecture low_level_definition of ring_osc is
--
------------------------------------------------------------------------------------
--
-- Signals used in RING_OSC
--
------------------------------------------------------------------------------------
--
signal ring_delay1      : std_logic;
signal ring_delay2      : std_logic;
signal ring_delay3      : std_logic;
signal ring_delay4      : std_logic;
signal ring_delay5      : std_logic;
signal ring_delay6      : std_logic;
signal ring_invert      : std_logic;
signal toggle           : std_logic;
signal clk_div2         : std_logic;

signal resetn : std_logic;

--
-- Attributes to stop delay logic from being optimised.
--
attribute KEEP : string; 
attribute KEEP of ring_delay1 : signal is "true"; 
attribute KEEP of ring_delay2 : signal is "true"; 
attribute KEEP of ring_delay3 : signal is "true"; 
attribute KEEP of ring_delay4 : signal is "true"; 
attribute KEEP of ring_delay5 : signal is "true"; 
attribute KEEP of ring_delay6 : signal is "true";
--
------------------------------------------------------------------------------------
--
-- Attributes to define LUT contents during implementation for primitives not 
-- contained within generate loops. In each case the information is repeated
-- in the generic map for functional simulation
--
attribute INIT : string; 
attribute INIT of div2_lut              : label is "1"; 
attribute INIT of delay1_lut            : label is "4"; 
attribute INIT of delay2_lut            : label is "4"; 
attribute INIT of delay3_lut            : label is "4"; 
attribute INIT of delay4_lut            : label is "4"; 
attribute INIT of delay5_lut            : label is "4"; 
attribute INIT of delay6_lut            : label is "4"; 

attribute INIT of invert_lut            : label is "B"; 
--
------------------------------------------------------------------------------------
--    
-- Circuit description
--
------------------------------------------------------------------------------------
--    
begin
  --
  --Output is the ring oscillator divided by 2 to provide a square wave.
  --
  osc_out <= clk_div2;

  resetn <= NOT reset;

  toggle_flop: FD
  port map ( D => toggle,
             Q => clk_div2,
             C => ring_invert);

  div2_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"1")
  --synthesis translate_on
  port map( I0 => resetn,
            I1 => clk_div2,
             O => toggle );

  --
  --Ring oscillator is formed of 5 levels of logic of which one is an inverter.
  --

  delay1_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"4")
  --synthesis translate_on
  port map( I0 => resetn,
            I1 => ring_invert,
             O => ring_delay1 );

  delay2_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"4")
  --synthesis translate_on
  port map( I0 => resetn,
            I1 => ring_delay1,
             O => ring_delay2 );

  delay3_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"4")
  --synthesis translate_on
  port map( I0 => resetn,
            I1 => ring_delay2,
             O => ring_delay3 );

  delay4_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"4")
  --synthesis translate_on
  port map( I0 => resetn,
            I1 => ring_delay3,
             O => ring_delay4 );


  delay5_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"4")
  --synthesis translate_on
  port map( I0 => resetn,
            I1 => ring_delay4,
             O => ring_delay5 );
             
  delay6_lut: LUT2
             --synthesis translate_off
               generic map (INIT => X"4")
             --synthesis translate_on
             port map( I0 => resetn,
                       I1 => ring_delay5,
                        O => ring_delay6 );             
             
  invert_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"B")
  --synthesis translate_on
  port map( I0 => resetn,
            I1 => ring_delay6,
             O => ring_invert );


end low_level_definition;

 

 

 

5_stages.PNG

7_stages.PNG

Link to comment
Share on other sites

Oh, and once again.... if you want to simulate it it won't work due to the combinatorial loop. To get around this you can insert a short delay:

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity my_not is
    Port ( a : in  STD_LOGIC;
           o : out  STD_LOGIC);
end my_not;
architecture Behavioral of my_not is
begin
   o <= not a after 2 ns;
end Behavioral;

​Thanks Hamster for the code!

 

I did synthesized that and tried mapping "count_output" to the LEDs to see if there is any output, but none. Only LED 0 and LED2 light up and that's about it.

 

I also mapped the "a" input of the AND gate to one of the switches on the board to make sure the oscillation has turned on.

 

Link to comment
Share on other sites

Is it possible to just synthesize this and read the output of the counter or simply attach the output of the CUT to an oscilloscope and read the frequency?

Shahin,

​Yes for both of these. You can create a test bench and view the output waveform, or if you attach the output to a pin you can scope the output with an oscilloscope. 

Kaitlyn

Link to comment
Share on other sites

This isn't directly related to this particular post topic, but you can always upload an image to our Gallery and then link to it from the forum post if you're out of space to upload photos directly.

Granted, this isn't quite the same as dragging a photo that you can see within the post, but at least it's something.

Link to comment
Share on other sites

Oh, and once again.... if you want to simulate it it won't work due to the combinatorial loop. To get around this you can insert a short delay:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity my_not is
    Port ( a : in  STD_LOGIC;
           o : out  STD_LOGIC);
end my_not;
architecture Behavioral of my_not is
begin
   o <= not a after 2 ns;
end Behavioral;
Link to comment
Share on other sites

Oh, and the timing will change depending on the placement of the logic blocks and the routing choices made by the tools. You might end up needing to use manual placement to get everything to work consistently.

I was going to upload an image but I'm out of quota :-(

Link to comment
Share on other sites

Hi Shahin,

I compiled your design, and then had a look under the "view technology schematic" process under implement design. It doesn't look as it should to reflect the intent of your code.

So I quickly bashed up a solution that looks right for what you are trying. The solution might be to use the "keep hierarchy" mapping option, preventing it from being optimized away.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;
entity ring_test is
    Port ( clk          : in  STD_LOGIC;
           count_output : out  STD_LOGIC_VECTOR (9 downto 0));
end ring_test;
architecture Behavioral of ring_test is
    COMPONENT my_and
    PORT(
        a : IN std_logic;
        b : IN std_logic;          
        o : OUT std_logic
        );
    END COMPONENT;
    COMPONENT my_not
    PORT(
        a : IN std_logic;
        o : OUT std_logic
        );
    END COMPONENT;
   signal signals       : std_logic_vector(75 downto 0) := (others => '0');
   signal reset_count   : std_logic := '0';
   signal enable        : std_logic := '0';
   signal ref_counter   : unsigned(9 downto 0) := (others => '0');
   signal pulse_counter : unsigned(9 downto 0) := (others => '0');
begin
g1: for i in 1 to signals'high generate
i_my_not : my_not port map ( 
      a => signals(i-1), -- LUT input
      O  => signals(i)    -- LUT general output
   );
end generate;
i_my_and: my_and PORT MAP(
        a => enable,
        b => signals(signals'high),
        o => signals(0)
    );
process(reset_count,signals(signals'high))
   begin
      if reset_count = '1' then
         pulse_counter <= (others =>'0');
      elsif rising_edge(signals(signals'high)) then
         pulse_counter <= ref_counter+1;
      end if;
   end process;
   
control_proc: process(clk)
   begin
      if rising_edge(clk) then
         case to_integer(ref_counter) is
            when      0 => enable       <= '1';
            when    100 => enable       <= '0';
            when    128 => count_output <= std_logic_vector(pulse_counter);
            when    200 => reset_count  <= '1';
            when    230 => reset_count  <= '0';
            when others => NULL;
         end case;
         ref_counter <= ref_counter+1;
      end if;
   end process;
end Behavioral;
and 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity my_not is
    Port ( a : in  STD_LOGIC;
           o : out  STD_LOGIC);
end my_not;
architecture Behavioral of my_not is
begin
   o <= not a;
end Behavioral;
and
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity my_and is
    Port ( a : in  STD_LOGIC;
           b : in  STD_LOGIC;
           o : out  STD_LOGIC);
end my_and;
architecture Behavioral of my_and is
begin
   o <= a and b;
end Behavioral;

The design is a little different from yours - it runs a second counter, which turns the "enable" signal on for 100 cycles of the reference clock. After turning it off it waits a little while for everything to settle, then it outputs the count on the "count_output_signals".

A wee while later it asserts a async reset for the counter, getting it ready for when the next cycle starts.

I had a look in the "View Edit routed design (FPGA editor)" and it looked pretty good. If you highlght the "signal(...)" nets you can track the signal as it runs around. I haven't tested it.I'ld be interested in hearing how you get on!

 

 

 

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...