I have the following module:
module test1(
input en,
input clk,
input burst,
output out_clk
);
reg [1:0] cpt = 0;
localparam burst_beg = 0;
localparam burst_end = 1;
localparam burst_init = 2;
reg [0:1] state = burst_init;
assign out_clk = (cpt <= 1) && state != burst_init ? clk : 1'b0;
always @(negedge clk) begin
if (en) begin
case (state)
burst_init: begin
if (burst) begin
state <= burst_end;
cpt <= 2;
end
end
burst_beg: begin
if (!burst) begin
state <= burst_end;
cpt <= 2;
end
else if (cpt == 1) begin
cpt <= 2;
end
else if (cpt != 2)begin
cpt <= 1;
end
end
burst_end: begin
if (burst) begin
state <= burst_beg;
cpt <= 0;
end
end
default: ;
endcase
end
end
endmodule
Its functionality is pretty simple, it lets the clk signal pass only during 2 ticks, after what it just sends a zero on the out_clk wire.
I also have a very simple module:
module test2 (
input clk,
output reg [0:3] cpt
);
initial begin
cpt = 0;
end
always @(posedge clk) begin
cpt <= cpt + 1;
end
endmodule
A simple counter that increments on every clock posedge
In sum this gives us the following top module:
module test (
input clk,
input en,
input burst,
output [0:3] cpt
);
test1 t1(
.en(en),
.clk(clk),
.burst(burst)
);
test2 t2 (
.clk(t1.out_clk),
.cpt(cpt)
);
endmodule
Once enabled, on every burst the cpt should normally increment by 2, since only 2 clock cycles of the clk are allowed through to the out_clk. Which is what happens with the current code, here is a GtkWave screenshot to better visualise.
However here is what happends when I change the negedge in the module test1 to posedge.
Why does my counter increment once more? I do not seem to understand how that is possible since there have only been 2 clock cycles on the out_clk.
This question does seem to give a clue: Timing of Writing at clock edge
Thanks in advance!
This is only possible if clk_out has a glitch. There might be a way to see it on your trace, but in any case it results from using 'clk' in the assign statement. The following scenario could have happened:
As a result you have a glitch not visible in a simple trace. It could be detected by alwayse @* $display...
or by a special mode of the tracer (if exists). But nevertheless it produces a clock edge which triggers your counter.
The way to work around this issue is to make sure that the gating signals are calculated before the clock edge, or make a delay in calculation of out_clk. In your original code you calculated those signal at the negedge, way before the posedge of the clk.