-
Notifications
You must be signed in to change notification settings - Fork 1
/
timer.v
126 lines (107 loc) · 2.86 KB
/
timer.v
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
120
121
122
123
124
125
126
`timescale 1ns/1ns
`define IDLE 2'b00
`define LOAD 2'b01
`define CNTING 2'b10
`define INT 2'b11
`define MODE_0 2'b00
`define MODE_1 2'b01
module coco_timer (clk_i,rst_i,add_i,we_i,dat_i,dat_o,irq);
input [3:2] add_i;
input clk_i,rst_i,we_i;
input [31:0] dat_i;
output [31:0] dat_o;
output irq;
reg [31:0] count;
reg [31:0] preset;
reg [31:0] ctrl;
reg _irq;
reg [1:0] curr_state,next_state;
assign dat_o=(add_i==2'b00)?ctrl:
(add_i==2'b01)?preset:
(add_i==2'b10)?count:
32'h12345678;
assign irq=_irq;
always @(posedge clk_i or posedge rst_i) begin
if (rst_i) begin
count<=31'h0000_0000;
preset<=31'h0000_0000;
ctrl<=31'h0000_0000;
_irq<=0;
curr_state<=`IDLE;
end // if(rst)
else if (we_i) begin
if (add_i==2'b00) begin
ctrl<=dat_i;
curr_state<=next_state;
end // if(dat_i)
else if (add_i==2'b01) begin
preset<=dat_i;
_irq<=0;
next_state<=`LOAD;
end // if(add_i=2'b01)
else if (add_i==2'b10) begin
count<=dat_i;
curr_state<=next_state;
end
else begin
curr_state<=next_state;
end
end // if(we)
else begin
curr_state<=next_state;
end
end // always @ (posedge clk_i or posedge rst_i)
always @(curr_state or ctrl or count) begin
next_state=`IDLE;
if (!ctrl[0]) begin
next_state=`IDLE;
end // if(ctrl[0])
else begin
case (curr_state)
`IDLE: begin
if (ctrl[2:1]==`MODE_1) begin
next_state=`LOAD;
end // if(ctrl[2:1])
//ctrl[2:1]==`MODE_0
else if (ctrl[0] && count>1) begin
next_state=`CNTING;
end
else begin
next_state=`IDLE;
end
end // case: IDLE
`LOAD: begin
next_state=`CNTING;
end
`CNTING: begin
if (count==1) begin
next_state=`INT;
end // if(count==1)
else begin
next_state=`CNTING;
end
end
default: begin
next_state=`IDLE;
end
endcase // case(curr_state)
end
end // always @ (curr_state)
always @(posedge clk_i or posedge rst_i) begin
case (next_state)
`CNTING: begin
count<=count-1;
end
`INT: begin
_irq<=(ctrl[3]&&ctrl[2:1]==`MODE_0);
end
`LOAD: begin
count<=preset;
_irq<=0;
end
default: begin
//do nothing
end
endcase // case(next_state)
end
endmodule // cp0