3
\$\begingroup\$

I'm designing a finite state machine (FSM) to detect the sequence "10001" in Verilog.

I'm having a similar problem to that described in this question in that my FSM does not tick when the sequence is seen but the solution to that problem does not apply in my case.

This is my FSM design: enter image description here

Here is my verilog code for the FSM.

module fsm_detector(
input wire clk, reset,
input wire sequence,
output reg tick
);
// FSM state declarations
parameter A = 3'b000;
parameter B = 3'b001;
parameter C = 3'b010;
parameter D = 3'b011;
parameter E = 3'b100;
//signal declaration
reg [2:0] state_reg;
reg [2:0] state_next;
// state register logic
// asynchrous reset
always @(posedge clk, posedge reset)
 if(reset)
 state_reg <= A;
 else
 state_reg <= state_next;
//next-state logic and output logic
always @ *
begin
 state_next = state_reg; // default state: the same
 tick = 1'b0; // default tick = 0
 case(state_reg)
 A: if(sequence) // sequence = 1
 state_next = B;
 // else stay in A
 B: if (~sequence)
 state_next = C;
 // else stay in B
 C: 
 if (~sequence)
 state_next = D;
 else
 state_next = B;
 D: 
 if(~sequence)
 state_next = E;
 else
 state_next = B;
 E: if(sequence)
 begin
 tick = 1'b1;
 state_next = B;
 end
 else
 state_next = A;
 default: 
 state_next = A;
 endcase
end
endmodule

And testbench:

`timescale 1ns / 1ns
module fsm_detector_tb();
 //declerations
 parameter T = 20; //clock period in nanoseconds
 reg clk, reset;
 reg test_input;
 wire test_tick;
 fsm_detector uut(
 .clk(clk),
 .reset(reset),
 .sequence(test_input),
 .tick(test_tick)
 );
 // clock
 // 20 ns clock running forever
 always
 begin
 clk = 1'b1; //high
 #(T/2); // delay half a period
 clk = 1'b0; //low
 #(T/2); // delay half a period
 end
 initial
 begin
 reset = 1'b1;
 test_input = 1'b0;
 #(2*T); // delay two clock cycle
 reset = 1'b0;
 test_input = 1'b0;
 #(T); // delay one clock cycle
 test_input = 1'b0;
 #(T); // delay one clock cycle
 test_input = 1'b1;
 #(T); // delay one clock cycle
 test_input = 1'b0;
 #(T); // delay one clock cycle
 test_input = 1'b0;
 #(T); // delay one clock cycle
 test_input = 1'b0;
 #(T); // delay one clock cycle
 test_input = 1'b1;
 #(T); // delay one clock cycle
 test_input = 1'b1;
 #(T); // delay one clock cycle
 test_input = 1'b0;
 #(T); // delay one clock cycle
 $finish;
 end
endmodule

The FSM should tick high at the point marked below:

Simulation output

Any suggestions?

Simulation output showing state transitions: enter image description here

asked Apr 10, 2019 at 22:11
\$\endgroup\$
12
  • \$\begingroup\$ Look at the internal signals to see if the state is changing at all. \$\endgroup\$ Commented Apr 10, 2019 at 22:27
  • \$\begingroup\$ @Matt The internal 'state_reg' signal changes as follows: state_reg = X 0 0 1 1 2 3 4 4 1 . sequence = 0 0 1 1 0 0 0 0 1 1 \$\endgroup\$ Commented Apr 10, 2019 at 22:33
  • \$\begingroup\$ So you did go from E back to B (4 to 1) which should trigger your output. I don't know. Did you confirm that tick didn't assert inside the dut (just to make sure your connections are sound)? \$\endgroup\$ Commented Apr 10, 2019 at 22:43
  • 1
    \$\begingroup\$ Wait you stayed in E for 2 consecutive cycles. That's impossible according to your verilog. Are you sure you're looking at the latest waves? \$\endgroup\$ Commented Apr 10, 2019 at 22:45
  • \$\begingroup\$ In the tb you use blocking assignments for both clk and signal. I don't remember offhand but I think I use nonblocking for signals and blocking for clk. You might have a classic verilog race condition. \$\endgroup\$ Commented Apr 10, 2019 at 22:47

2 Answers 2

4
\$\begingroup\$

Signal (non clock) assignments in a testbench should generally be non blocking (<= operator). Clock assignments should be blocking (= operator). Otherwise there's a race condition.

There are probably exceptions to this rule, but it works for me. Beyond that you need a good understanding of the verilog simulation phases. This rule of thumb will work for you 95% of the time.

answered Apr 10, 2019 at 23:12
\$\endgroup\$
0
-1
\$\begingroup\$

This is due to the race condition in your code at state assignment , usually people will use #TCQ in NBA assignment and to look similar to hardware transiton.

module fsm_detector(
 input wire clk, reset,
 input wire sequence,
 output reg tick
);
 // FSM state declarations
 parameter A = 3'b000;
 parameter B = 3'b001;
 parameter C = 3'b010;
 parameter D = 3'b011;
 parameter E = 3'b100;
 //signal declaration
 reg [2:0] state;
 reg [2:0] next;
 // state register logic
 // asynchrous reset
 always @(posedge clk, posedge reset)
 if(reset) state <= #10 A;
 else state <= #10 next;
 //next-state logic and output logic
 always @ * begin
 next = state; // default state: the same
 tick = 1'b0; // default tick = 0
 case(state)
 A: if ( sequence) next = B;
 B: if (~sequence) next = C;
 C: if (~sequence) next = D;
 else next = B;
 D: if (~sequence) next = E;
 else next = B;
 E: if ( sequence) begin
 tick = 1'b1;
 next = B;
 end else next = A;
 default: next = A;
 endcase
 end
endmodule

Simulation output with modified code and adding #TCQ to NBA(Non-Blocking Assignments) assignments enter image description here

answered Mar 3, 2020 at 15:50
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.