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);
// ...



