I implemented a very simple counter with preset functionality (code reproduced below).
module counter
#(
parameter mod = 4
) (
input wire clk,
input wire rst,
input wire pst,
input wire en,
input wire [mod - 1:0] data,
output reg [mod - 1:0] out,
output reg rco
);
parameter max = (2 ** mod) - 1;
always @* begin
if(out == max) begin
rco = 1;
end else begin
rco = 0;
end
end
always @(posedge clk) begin
if(rst) begin
out <= 0;
end else if(pst) begin
out <= data;
end else if(en) begin
out <= out + 1;
end else begin
out <= out;
end
end
endmodule
I am having trouble understanding the following simulation result. With pst
asserted and data
set to 7 on a rising clock edge, the counter's out
is set to data
, as expected (first image below. out
is the last signal, data
is the signal just above, and above that is pst
.). On the next rising edge, I kept preset asserted and set data
to 0. However, out
does not follow data
this time. What is the cause of this behavior?
My thoughts
On the rising clock edge where I set data
to 0, I notice that out
stays at 7, and doesn't increment to 8. So I believe that the counter is presetting, but with the value 7, not 0. If I move the data
transition from 7 to 0 up in time, out
gets set to 0 as expected (image below). Am I encountering a race condition?
Testbenches
My initial testbench code that produced the first image is reproduced below. I show the changes I made to get coherent results as comments.
parameter mod = 4;
// ...
reg pst;
reg [mod - 1:0] data;
// ...
@(posedge clk); // ==> @(negedge clk)
data = 7;
pst = 1;
@(posedge clk); // ==> @(negedge clk)
data 0;
pst = 1;
@(posedge clk); // ==> @(negedge clk)
pst = 0;
@(posedge clk);
// ...