Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] FSM in Verilog - Help needed in Debugging/ Logic

Status
Not open for further replies.

graphene

Full Member level 2
Full Member level 2
Joined
Mar 22, 2012
Messages
129
Helped
4
Reputation
8
Reaction score
3
Trophy points
1,298
Location
Germany
Activity points
2,181
Dear Friends,
I am a Verilog code for a FSM.
>> Its a simple Car window with 4 states 00,01,10,11(fullyopen, partially closed, partially opened, fully closed). I am sure you can understand.

>>Here I have 2 options, UP or DOWN. and the position with the action cannot be expressed in bubble diagram.

>>UP and DOWN are mutually exclusive events.

>> the start condition and the final condition is reset, which is nothing but fully closed state.

>>In the output here I am unable to get the states changed mov, posi are the variables (registers), I have used in this code.

I am lagging behind in some register initation or wrongly coded loops. Can some one help me out with this ?? I am also pasting the test benches alongside.
: Sorry if you find the code unorthodox.

Thank you for your times.

Code:
module glass(
//win1,win2,//window1 and window2
clk,rst,//clock and reset
up,down,// upward or downward action
val,// input referring the present state of the window
mov,tmp,// output registers
posi,// current position ina 2 bit representation
incr,decr// junk registers
);

input /*win1, win2,*/clk,rst;
input up,down;//up or down 

input [1:0] val;
output [1:0] mov;

//reg up, down;
output reg [1:0] posi,incr, decr,tmp;
reg [1:0] mov;// for using in case

parameter [1:0] s1=2'b00, s2=2'b01, s3=2'b10, s4=2'b11;

always@(posedge clk) begin

if (rst) begin
    mov<=2'b11;
    posi<=2'b11;
    incr<=2'b11;
    decr<=2'b11;
end else if (down) begin

	if (posi == 2'b00) begin
		posi=2'b00;
	end else begin
		decr=decr-1;
		posi=decr;
	end

end else if (up) begin

	if (incr == 2'b11) begin
		posi=2'b11;
	end else begin
		incr=incr+1;
		posi=incr;
	end

end else begin
    posi<=val;
end
case(posi)
         
00:if(up) begin
   mov<=01;
   end else begin
   mov<=00; end

01:if(up) begin
   mov<=10;
   end else if (down) begin
   mov<=00;
   end else 
   mov<=01; 

10:if(up) begin
   mov<=11;
   end else if (down) begin
   mov<=01;
   end else 
   mov<=10;

11:if (down) begin
   mov<=10;
   end else 
   mov<=11;

default:mov<=posi;
 
endcase 
//end
end

endmodule

Here is the test bench
Code:
module glass_tb();
    
//reg tb_win1,tb_win2;
reg tb_clk, tb_rst;
reg [1:0] tb_val;
reg tb_up,tb_down;

wire [1:0] tb_mov,tb_posi,tb_incr,tb_decr,tb_tmp;

initial
begin
    fork
    tb_clk=0;
    tb_rst=0;
    tb_val=2'b11;
    tb_up=0;
    tb_down=0;
    join
    
#20 tb_rst=1;
#20 tb_rst=0;

#20 tb_val=2'b00;

#20 tb_up=1;
//#20 tb_var_down=0;
/*
#20 tb_var_up=1;
#20 tb_var_up=0;
#20 tb_var_up=1;
#20 tb_var_up=1;
*/
#2000 $finish;

end

glass glass_tb(/*.win1(tb_win1),.win2(tb_win2),*/.tmp(tb_tmp),.clk(tb_clk), .rst(tb_rst),.val(tb_val),
/*.var_up(tb_var_up),.var_down(tb_var_down),*/.mov(tb_mov),.posi(tb_posi), .incr(tb_incr),.decr(tb_decr)
);

always begin
#10 tb_clk=~tb_clk;
end    
endmodule
 
Last edited:

Hi,

Never use a mixture of blocking and non blocking statements inside always block. Also, there is a specific styles used by coders for inferring FSM in verilog like
1. writing all the combinational logic in one always block
2. writing all the sequential logic in other always block......etc., google it for more details.

from the code if i still want to make up something then it seems like you are applying only "up" signal from your testbench (you have commented out the rest)
and in the main code in always block under if condition for "up" you are checking for incr=2'b11 which is true (after reset) and hence it remains in the same state.....
i think u were trying to write "posi" there instead.....

Anyways, as i said earlier please check some coding example of FSM before u go any further :)

Thanks,
Manoj
 

Thankyou @manojkhandelwal.

I tried the mix for test but your points seriously taken and I have rectified it and classified regarding seq and combinational circuit. You are right, I tried ""posi"" and I am still unable to frame an output logical flow nor define the states.
 

Hi,
You can post your new code if you still have problem as you mentioned

Thanks,
Manoj
 

I think my approach is wrong.. I am unable to sort it down in tersm of gates or using K-Map.... the code is the same,, but I am missing out some logic in looping and certain undefinied states in my code.

For Example, when the car is locked and also before its tried to unlock (say next day), its in reset state, ie window fully closed ... but I am ignorant of framing logic with these,, I mean definig the states...

I thank you for your time, but can you suggest me regarding these ?
 

@manojkhandelwal

here is the new code I've writen... perhaps I find i am missing out something logically


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
module glass(
//win1,win2,
clk,rst,
up,down,
mov//val,
//posi,incr,decr,tmp
);
parameter [1:0] s1=2'b00, s2=2'b01, s3=2'b10, s4=2'b11;
 
input /*win1, win2,*/clk,rst;
input up,down;//up or down 
 
//input [1:0] val;
output reg [1:0] mov;
 
reg [1:0] state;
reg [1:0] next_state;
 
//output reg [1:0] posi,incr, decr,tmp;
reg var_up, var_down;
 
 
 
 
 
// to verify and assign the state and next state on the event of reset or up or down signals
 
always@(state or up or down) begin
 
// condtion to ensure complemency of up and down - 2 mutually exclusive events
 
if(up) begin var_down<=0; var_up<=up;
end else if (down) begin var_up<=0; var_down<=down;
end else begin var_up<=0; var_down<=0;
end 
 
// normal case definitons
 begin 
 next_state=s4;    
 
 case(state)
     s1: if (var_up) begin
         next_state=s2;
     end else if (var_down) begin
         next_state=s1;
     end else 
         next_state=s1;
 
     s2: if (var_up) begin
         next_state=s3;
     end else if (var_down) begin
         next_state=s1;
     end else 
         next_state=s2;
         
     s3: if (var_up) begin
         next_state=s4;
     end else if (var_down) begin
         next_state=s2;
     end else 
         next_state=s3;
         
     s4: if (var_up) begin
         next_state=s4;
     end else if (var_down) begin
         next_state=s3;
     end else 
         next_state=s4;
 
     default:  next_state=s4;
                  
endcase
end
end
 
 
// output condition for variable based on the values of state 
always@ (posedge clk) begin
if (rst)begin
mov=s4;
//state=mov;
end else begin
    state=next_state;
    
case (state)
    s1:begin
        if (state==s4) begin mov=s4;
        end else if (state==s3) begin mov=s3;
        end else if (state==s2) begin mov=s2;
        end else mov=s1;
    end
 
    s2:begin
        if (state==s4) begin mov=s4;
        end else if (state==s3) begin mov=s3;
        end else if (state==s1) begin mov=s1;
        end else mov=s2;
    end
 
    s3:begin
        if (state==s4) begin mov=s4;
        end else if (state==s2) begin mov=s2;
        end else if (state==s1) begin mov=s1;
        end else mov=s3;    
    end
    
    s4:begin
        if (next_state==s3) begin mov=s3;
        end else if (next_state==s2) begin mov=s2;
        end else if (next_state==s1) begin mov=s1;
        end else mov=s4;
    end
 
    default: mov=s4;
    
endcase
end
end
endmodule



Here is my test bench for your verifications


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
module glass_tb();
    
//reg tb_win1,tb_win2;
reg tb_clk, tb_rst;
//reg [1:0] tb_val;
reg tb_up,tb_down;
 
wire [1:0] tb_mov/*,tb_posi,tb_incr,tb_decr,tb_tmp*/;
 
initial
begin
    fork
    tb_clk=0;
    tb_rst=0;
   // tb_val=2'b11;
    tb_up=0;
    tb_down=0;
    join
    
#20 tb_rst=1;
#20 tb_rst=0;
 
//#20 tb_val=2'b00;
 
#20 tb_down=1;
//#20 tb_var_down=0;
/*
#20 tb_var_up=1;
#20 tb_var_up=0;
#20 tb_var_up=1;
#20 tb_var_up=1;
*/
#2000 $finish;
 
end
 
glass glass_tb(/*.win1(tb_win1),.win2(tb_win2),.tmp(tb_tmp),*/.clk(tb_clk), .rst(tb_rst),//.val(tb_val),
.up(tb_up),.down(tb_down),
/*.var_up(tb_var_up),.var_down(tb_var_down),*/.mov(tb_mov)/*.posi(tb_posi), .incr(tb_incr),.decr(tb_decr)*/
);
 
always begin
#10 tb_clk=~tb_clk;
end    
endmodule

 

Code:
module glass(clk,rst,up,down,mov);
  input clk,rst,up,down;
  output  [1:0] mov;
  reg [1:0] state,next_state;
 
  always@ (posedge clk, posedge rst) /*sequential block */
  begin
   if(rst)
    state <= 2'b11;
  else
    state<= next_state;
  end
 
  always@ (*) /*combinational block*/
  begin
      case(state)
        2'b00:
        begin
          if (up)
            next_state= 2'b01;
          else next_state= 2'b00;
        end
          
        2'b01:
        begin
          if(up)
            next_state = 2'b10;
          else if(down)
            next_state = 2'b00;
          else next_state = 2'b01;
        end 
        
        2'b10:
        begin
          if(up)
            next_state = 2'b11;
        else if (down)
            next_state = 2'b01;
        else next_state = 2'b10;
        end
        2'b11:
        begin
          if(down)
            next_state = 2'b10;
          else
            next_state = 2'b11;
        end
       endcase
    end
    
  assign mov = state;/*output logic*/
 
 endmodule

Sorry dont have time to analyze your code
Hope this works for you ...........
also in the testbench try to include as many cases as possible...
i mean you are only applying stimulus for "up"......

00: open
01:partially open
10:partially closed
11:closed...
and "mov" represents output or also state of glass in this case..:)

Thanks,
Manoj
 
@manojkhandelwal.. thanks a lot for yor assistance... this actually works in the way i want and I am able to build upon this further... was just bizzared about few logic and now I got some clear picture abut it.. Thank you and Hats off !!
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top