Given the following FSM:
I am trying to model it using Verilog, and here is my trial:
module fsm (u,d,clr,clk,inc,dec,c);
input u,d, clr,clk;
output reg inc,dec,c ;
// the state variables
reg y,Y; // y is the present state and Y is the next state
reg S0,S1;
// next state and output specifications
always @ (y,u,d) begin
case (y)
S0 : if (u==1) begin
Y= S1;
inc=1;
dec=0;
c=1;
end
else if (u==0) begin
c=0;
end
S1 : if (d==1) begin
Y= S0;
inc=0;
dec=1;
c=0;
end
else if (d==0) begin
c=1;
end
endcase
end
// state update
always @(posedge clk,clr) begin
if (clr)
y=S0;
else
y=Y;
end
endmodule
Please let me know if my code correctly describes this FSM, and if there is any enhancement in the code please let me know it.
Here is an initial test bench code:
module tb();
reg u,d, clr,clk;
reg inc,dec,c,y ;
fsm ttb (.u(u),.d(d),.clk(clk),.clr(clr),.inc(inc),.dec(dec),.c(c));
initial begin
$dumpfile("dump.vcd");
$dumpvars;
end
initial begin //{
clk=0 ; clr=0; #10
clk=1; u=0 ; clr=0 ; d=0; #10
clk = 0;#10
u=1; clk=1; #10
$finish;
end //}
endmodule
The testbench code shows that there is something wrong. The present state variable y
shows an undefined value 'X'. I don't know why. The same for the output variables inc
and dec
.
There are several causes for the X
's.
In the design, you declared S0
and S1
as reg
, but then you never assigned values to them. A Verilog reg
is initialized to X
. An FSM is conventionally coded using constant parameter
values. For example, change:
reg S0,S1;
to:
parameter S0=0, S1=1;
Your next state logic needs to assign values to Y
in all cases (refer to <---
):
always @ (y,u,d) begin
case (y)
S0 : if (u==1) begin
Y= S1;
inc=1;
dec=0;
c=1;
end
else if (u==0) begin
c=0;
Y= S0; // <-----
end
S1 : if (d==1) begin
Y= S0;
inc=0;
dec=1;
c=0;
end
else if (d==0) begin
c=1;
Y= S1; // <-----
end
endcase
end
In your testbench, you need to assert the reset (clr
=1):
initial begin
u=0; d=0;
clk=0 ; clr=1; #10
clk=1; u=0 ; d=0; #10
clk = 0;#10
u=1; clk=1; clr=0; #10
$finish;
end
Addressing the comments on your Question regarding the asynchronous clear, you should change:
always @(posedge clk,clr) begin
to:
always @(posedge clk, posegde clr) begin