Skip to content

Final project - RO module

Code

`timescale 1ns/1ps

module ro (   
    input  wire        enable,     // to enable the inverters chain
    // verilator lint_off UNOPTFLAT
    output wire        endOfChain  // The output of the selected RO for that challenge
    // verilator lint_on UNOPTFLAT
);

    localparam num_inv = 7;          // number of inverters in a chain
    genvar i;

    wire[num_inv:0] inter_wire;      // connections between the inverters

    // build a chain of inverters
    generate
        for (i = 0; i < num_inv; i = i+1) begin           
            `ifndef SYNTHESIS
            assign #5 inter_wire[i+1] = ~inter_wire[i];
            `else
                sky130_fd_sc_hd__inv_2 inv (
                .A    (inter_wire[i]),
                .Y    (inter_wire[i+1])
            );           
            `endif
        end
    endgenerate

    // First inverter input = enable signal AND a feed-back from the last inverter
    // First inverter output = a wire to the second inverter
    `ifndef SYNTHESIS
        and #5 beginOfChain(inter_wire[0], endOfChain, enable);
    `else
        sky130_fd_sc_hd__and2_2 beginOfChain (
            .A    (endOfChain),
            .B    (enable),
            .Y    (inter_wire[0])
        );
    `endif

    // Connect the last inverter to the end of chain
    assign endOfChain = inter_wire[num_inv];

endmodule 

Lint

verilator --lint-only -Wall -Ilib puf/ro.v config.vlt
- V e r i l a t i o n   R e p o r t: Verilator 5.044 2026-01-01 rev v5.044
- Verilator: Built from 0.037 MB sources in 2 modules, into 0.074 MB in 3 C++ files needing 0.000 MB
- Verilator: Walltime 0.009 s (elab=0.000, cvt=0.004, bld=0.000); cpu 0.009 s on 1 threads; alloced 30.348 MB

Test harness

`timescale 1ns/1ps

module test_ro;
    // Inputs are reg (we drive them)
    reg enable;

    // Outputs are wire (DUT drives them)
    wire endOfChain;

    // Instantiate Device Under Test
    ro myRo (
        .enable(enable),
        .endOfChain(endOfChain)
    );


    // Test stimulus
    initial begin
        $dumpfile("waves.vcd");
        $dumpvars(0, test_ro);

        // Initialize
        $display("Initialize");        
        enable = 0;  
        #50;  

        // Start oscillating
        $display("==> Test case 1");       
        enable = 1; 
        #500;               
        enable = 0;  // stop
        #100;

        $finish;
    end

    // measure frequency (optional)
    real period, last_rise;
    initial begin
        last_rise = 0;
        forever begin
            @(posedge endOfChain);
            if (last_rise > 0) begin
                period = $realtime - last_rise;
                $display("Period = %0.1f ns | Freq = %0.2f MHz", 
                          period, 1000.0/period);
            end
            last_rise = $realtime;
        end
    end   


endmodule

Test run in simulation

Initialize
==> Test case 1
Period = 90.0 ns | Freq = 11.11 MHz
Period = 80.0 ns | Freq = 12.50 MHz
Period = 80.0 ns | Freq = 12.50 MHz
Period = 80.0 ns | Freq = 12.50 MHz
Period = 80.0 ns | Freq = 12.50 MHz
Period = 80.0 ns | Freq = 12.50 MHz
Period = 60.0 ns | Freq = 16.67 MHz
puf/test_ro.v:34: $finish called at 650000 (1ps)