I studied Verilog and do my exercises on HDLBits. I came up with a question when trying to solve this problem: https://hdlbits.01xz.net/wiki/Exams/2014_q3fsm
I wrote the following codes according to this State transition diagram.
I submit my code:
module top_module(
input clk,
input reset, // Synchronous reset
input s,
input w,
output reg z
);
// State encoding
parameter A = 3'd0, B1 = 3'd1, B2 = 3'd2, B3 = 3'd3, B = 3'd4;
reg [2:0] state, next_state;
reg [2:0] count;
//reg z;
// Next-state logic
always @(*) begin
case (state)
A: next_state = s ? B : A;
B1: next_state = B2;
B2: next_state = B3;
B3: next_state = B;
B: next_state = B1;
default: next_state = A;
endcase
end
// Sequential logic
always @(posedge clk) begin
if (reset) begin
state <= A;
count <= 0;
z <= 0;
end else begin
state <= next_state;
z <= 0;
// Count update
case (next_state)
B : count <= 0;
B1 : count <= w;
B2: count <= count + w;
B3: begin
count <= count + w;
z <= (count + w == 2);
end
default: count <= 0;
endcase
end
end
endmodule
Then I got those messages:
From the result, we can see my z become 1 when t = 120, but the refs become 1 at time = 110.
But when I execute this code in Vivado, the waveform is as below:
The testbench code is:
module fsm1_tb;
reg s, w, clk, reset;
wire out, out2;
top_module dut(clk, reset, s, w, out);
always
#5 clk = ~clk;
initial begin
clk = 1;
reset = 1;
s = 0;
w = 0;
#20 reset = 0;
#20 s = 1;
#10 w = 1;
#30 w = 0;
#5 w = 1;
#10 w = 0;
#5 w = 1;
#10 w = 0;
#5 w = 1;
#5 w = 0;
#5 w = 1;
#5 w = 0;
#5 w = 1;
#10 w = 0;
#25 $finish;
end
always @(posedge clk) begin
$strobe("t=%0t: state=%d, next_state=%d, in=%b, count=%d", $time, dut.state, dut.next_state, w, dut.count);
end
endmodule
The waveforms Vivado show that my z become 1 at 110ns.
I don't know why this happens. Are there any problems with my state transition diagram or codes?
I think there is a problem with the HDLBits question. When I follow your link, I see sample waveforms which show the input signals s
and w
being synchronous to the clock. The text does not explicitly say they are synchronous, but it is a reasonable assumption for anyone to make.
However, when you post your code in the site, then run the simulation there, the input waveforms they used show w
as an asynchronous signal because it is changing on both edges of the clock. I consider this a problem because they did not give you a complete specification for the design. This HDLBits exercise is faulty, and you should not bother using it.
That being said, if you assume all inputs should be synchronous to the clock, you should change your testbench to drive the inputs the same as how you drive output signals inside the module, namely:
@(posedge clk)
For example:
initial begin
clk = 1;
reset = 1;
s = 0;
w = 0;
repeat (2) @(posedge clk);
reset <= 0;
repeat (2) @(posedge clk);
s <= 1;
// etc.
This avoids the simulation race conditions in your testbench code. Due to the races, simulation results between 2 simulators are not guaranteed to match each other.
Note: at time=0, it doesn't matter if you use blocking or nonblocking assignments.
Another issue with HDLBits is that you can't see their testbench code, nor do you have any visibility into internal signals. The site is very useful for trivial designs, but it is not very useful for more complex designs like this example.
Someone posted a solution to Q3a: FSM that shows a passing result on HDLBits, although it uses poor coding style.