Search code examples
verilogsystem-verilogasicsoc

Why is the following clock multiplication Verilog code not working for me?


I am trying to generate a clock which is (3/16) of the system clock. So, I have decided to generate a 3x clock from the system clk and then (1/16)x clock from that. Right now, I am stuck at generating just the 3x clock. I am doing this by calculating the time period of the system clock and then toggling the 3x clock every 1/6th of that period. But my simulation just stalls forever with that. I have not used the forever block anywhere, I have checked. Hence no timing construct. Following is the code that I am working on.

module eec_clk_gen (
    input logic arst,
    input logic sys_clk,
    output logic eec_clk
);

real t0;
real t1;
real sys_clk_tp;


logic eec_clk_x3;


//Calculating clock period of sys_clk
initial
begin
    @(posedge sys_clk) t0 = $realtime;
    @(posedge sys_clk) t1 = $realtime;
    sys_clk_tp = t1 - t0;
end



//Generating clock at 3 times sys_clk freq

initial
begin
    @(posedge sys_clk) eec_clk_x3 = 1'b1;
end

always
begin
    #(sys_clk_tp/6) eec_clk_x3 <= ~eec_clk_x3;
end

endmodule: eec_clk_gen

I am not concerned about the arst signal which is missing from my code. It will be implemented once the eec_clk is functional. Some help please?


Solution

  • There 2, possibly 3 problems with your code.

    1. The initial value of sys_clk_tp is 0.0. So your always block goes into an infinite 0-delay loop. Time cannot advance
    2. You are using non-blocking assignment to t1,t2, so t2 is still 0 when evaluating t1-t2
    3. You are using $time instead of $realtime If your input clock has any fractional delay due to different timescales, $time truncates. I would do

    `

    initial
         begin
            @(posedge sys_clk) t0 = $realtime;
            @(posedge sys_clk) t1 = $realtime;
            sys_clk_tp = t1 - t0;
            forever  #(sys_clk_tp/6) eec_clk_x3 = ~eec_clk_x3;
        end