How to phase clock in system-verilog?

In System-verilog one can initialize clock and make it tick by code below:

bit clk;
initial begin
    clk <= 0;
end

always #CLOCK_SEMI_PERIOD begin
    clk <= ~clk;
end

But what if I want to make clock ticking with some phase? For example we have two clock, with different semiperiod and I want first one to start ticking from zero, while second one ticking from $urandom_range(6)ns.

         ___     ___     ___     ___     
clk1 ___|   |___|   |___|   |___|   |___   
           ____      ____      ____      
clk2 _____|    |____|    |____|    |____ 

I can't just write something like:

module top(output bit clk1,clk2);
    parameter CLOCK1_SEMI_PERIOD = 10;
    parameter CLOCK2_SEMI_PERIOD = 13;
    int phase;
    initial begin
        clk1 <= 0;
        clk2 <= 0;
        phase = $urandom_range(9);
    end
    always #(CLOCK1_SEMI_PERIOD) begin
        clk1 <= ~clk1;
    end
    always #(CLOCK2_SEMI_PERIOD) begin
        #phase;
        clk2 <= ~clk2;
    end
endmodule

because it will increase second clock period by phase ns.
Then how can I implement this kind of ticking?

Upvotes: 2

Views: 2169

Answers (2)

Sreejin TJ
Sreejin TJ

Reputation: 337

Assignment skew concept can also be applied for introducing the required phase,

module top(output bit clk1,clk2);
parameter CLOCK1_SEMI_PERIOD = 10;
parameter CLOCK2_SEMI_PERIOD = 13;
int phase;

reg  temp_1_clk2;//Added
wire temp_2_clk2;//Added

initial begin
    clk1 <= 0;
    clk2 <= 0;
    phase           = $urandom_range(9);
    temp_1_clk2 = 0;
end
always #(CLOCK1_SEMI_PERIOD) begin
    clk1 <= ~clk1;
end
always #(CLOCK2_SEMI_PERIOD) begin
    temp_1_clk2 <= ~ temp_1_clk2;
end

assign #(phase) temp_2_clk2  =  temp_1_clk2;//Introduces the required phase

always @(temp_2_clk2) begin //Output the clock
     clk2 = ~ temp_2_clk2;
end
endmodule

Also let me know if there is any complication with above code or if any optimisation could be done

Thank you !

Upvotes: 2

dave_59
dave_59

Reputation: 42788

Use an initial/forever loop

initial begin
        clk1 <= 0;
        clk2 <= 0;
        phase = $urandom_range(9);
        fork
           forever #(CLOCK1_SEMI_PERIOD) 
              clk1 <= ~clk1;
           #phase forever #(CLOCK2_SEMI_PERIOD) 
              clk2 <= ~clk2;
       join
end

Upvotes: 5

Related Questions