FPGA/Verilog study

[Verilog] FSM 설계 스탑워치 구현

섭섭입니다 2021. 5. 17. 14:47

 

무어 머신 : 상태머신이 현재 상태에만 영향을 받음

 

 

- 초기 상태에서 클럭의 에지에서 i가 '0' 이면 s0 상태 유지, '1'이면 s1으로 천이

- 출력 y는 s0에서 항상 입력 m을 출력하고, s1에서 항상 입력 n을 출력

 

 

 

 

밀리 머신 : 상태머신이 현재 상태와 입력에 영향을 받음 

 

 

- 초기 상태에서 클럭의 에지에서 i가'0'이면 s0상태 유지, '1'이면 s1으로 천이

- 출력 y는 s0에서 s1으로 천이될 때 입력 n을 출력, s1에서 s0로 천이될 때 입력 m을 출력 

 

 

 

 

idle, running, stop 상태에서 버튼에 따라서 각각의 다른 출력 값을 내보내는 것이다.

 

 

 

동작설명

 

스탑와치의 동작은 초기 상태에서 Start 버튼을 누르면 시간이 증가하다가 Stop 버튼을 누르면 정지하고 Reset 버튼을 누르면 시간이 0으로 초기화 됩니다. 이것을 FSM으로 나타내려면 3개의 상태 (0으로 초기화 되어 있는 상태, 카운트 하고 있는 상태, 정지되어 있는 상태) 와 각 상태 간 천이를 일으키는 버튼 입력 조건으로 나타낼 수 있습니다.

 

 

 

< design.v >

`timescale 1ns/1ns
module stopwatch(Button_Start, Button_Stop, Button_Reset,reset, clk, clk_count,  sec_count);

input Button_Start, Button_Stop, Button_Reset, reset, clk;
output [8:0] sec_count;
reg [8:0] sec_count;
output [1:0] clk_count;
reg [1:0] clk_count;

parameter [1:0]
 s_idle = 2'd0,
 s_running = 2'd1,
 s_stop = 2'd2;

reg [1:0] state;

always @(posedge clk)
	if(!reset) 
		state <= s_idle;
	else
		case(state)
			s_idle : state <= s_running;
				
			s_running : state <= s_stop;
				
			s_stop : state <= s_idle;
				
			default : 
				state <= s_idle;
		endcase

always @( posedge clk )
	if(!reset) 
		begin
			clk_count <= 0;
			sec_count <= 0;
		end 
	else if(state == s_idle) 
		begin
			clk_count <= 0;
			sec_count <= 0;
		end 
	else if(state == s_running) 
		begin
			if(clk_count < 3)  
				begin
					clk_count <= clk_count + 1;
//clk_count가 3보다 작을 경우 1씩 증가하도록 하여 시간의 지연을 나타냄
				end 
	
			else 
				begin
					clk_count <= 0;
					if(sec_count < 500)
						sec_count <= sec_count + 1;
					else
						sec_count <= 0;
				end
		end 
	
	else if(state == s_stop)
		begin
			clk_count <= clk_count;
			sec_count <= sec_count;
		end

	else 
		begin
			clk_count <= 0;
			sec_count <= 0;
		end 
endmodule

 

 

< testbench.v >

`timescale 1ns/1ns
module testbench;
  
  wire [8:0] Second;
  wire [1:0] CLK_count;
  reg B_Start, B_Stop, B_Reset,Reset, CLOCK;


  stopwatch ex1(B_Start, B_Stop, B_Reset, Reset, CLOCK, CLK_count,Second);

  initial 
     begin 
         $dumpfile("dump.vcd");
         $dumpvars(1);
	  
         CLOCK = 1; 
         forever #5 CLOCK = ~CLOCK; 
      end   

   initial 
      begin 
	 Reset = 1'b0; 
         repeat (3) @(negedge CLOCK); 
	 Reset = 1'b1; 
      end 

    initial
      begin
        B_Start=0; B_Stop=0; B_Reset=0; #25;
        B_Start=1; B_Stop=0; B_Reset=0; #10;
        B_Start=0; B_Stop=0; B_Reset=0; #200;
        B_Start=0; B_Stop=1; B_Reset=0; #10;
        B_Start=0; B_Stop=0; B_Reset=0; #100;
        B_Start=0; B_Stop=0; B_Reset=1; #10;
        B_Start=0; B_Stop=0; B_Reset=0; #200;        
        $finish;
      end  
endmodule

 

 

 

시뮬레이션 결과