---
# System prepended metadata

title: Exams/review2015 fancytimer
tags: [HDLBits]

---

# Exams/review2015 fancytimer
###### tags: `HDLBits`

```=v

module top_module(
input clk,
input reset,
input data,
output reg [3:0] count,
output reg counting,
output reg done,
input ack
);
//parameter 
parameter idle_state=2'd0,
time_set_state=2'd1,
count_state=2'd2,
done_state=2'd3;

//regs
reg [1:0]state,next_state,time_set_counter;
reg [3:0]shift_reg;
reg [9:0]count1000;

//fsm
always@(posedge clk)
begin
	if (reset) state<=idle_state;
		else state<=next_state;
end

always@(*)
begin
	case (state)
	idle_state:
    if (shift_reg==4'b1101) next_state=time_set_state;
	    else next_state=state;
	time_set_state: 
    if (time_set_counter==2'd2) next_state=count_state;
		else next_state=state;
	count_state: 
    if (shift_reg==1'd0 && count1000==10'd999) next_state=done_state;
		else next_state=state;
	done_state:
    if (ack) next_state=idle_state;
		else next_state=state;
	endcase
	end
	
always@(*)
begin
	case(state)
	idle_state:begin
		count=1'd0;
		counting=1'd0;
		done=1'd0;
	end
	time_set_state:begin
		count=1'd0;
		counting=1'd0;
		done=1'd0;
	end
	count_state:begin
		count=shift_reg;
		counting=1'd1;
		done=1'd0;
	end
	done_state:begin
		count=1'd0;
		counting=1'd0;
		done=1'd1;
	end
	endcase
end

//shift_reg_data_in&display
always@(posedge clk)
begin

	if (reset) shift_reg<=1'd0;
	else begin
	
	case (state)
	
	idle_state:begin
		shift_reg[0]<=data;
		shift_reg[1]<=shift_reg[0];
		shift_reg[2]<=shift_reg[1];
		shift_reg[3]<=shift_reg[2];	
	end
	
	time_set_state:begin
		shift_reg[0]<=data;
		shift_reg[1]<=shift_reg[0];
		shift_reg[2]<=shift_reg[1];
		shift_reg[3]<=shift_reg[2];
	end
	
	count_state:begin
		if (count1000==10'd999) shift_reg<=shift_reg-1'd1;
			else shift_reg<=shift_reg;
	end
	
	default:shift_reg<=1'd0;
	endcase
	
	end
end

//count1000

always@(posedge clk)
begin
	case (state)
	count_state:
	
	if (count1000==10'd999) count1000<=1'd0;
		else count1000<=count1000+1'd1;
	
	default count1000<=1'd0;
	endcase
end

//time_set_counter

always@(posedge clk)
begin
	case (state)
	time_set_state: 
    if (time_set_counter==2'd2) time_set_counter<=time_set_counter;
		else time_set_counter<=time_set_counter+1'd1;
	default :time_set_counter<=1'd0;
	endcase
end

endmodule 
```