Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: niu_smx_timer.v | |
4 | // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
5 | // 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
6 | // | |
7 | // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
8 | // | |
9 | // This program is free software; you can redistribute it and/or modify | |
10 | // it under the terms of the GNU General Public License as published by | |
11 | // the Free Software Foundation; version 2 of the License. | |
12 | // | |
13 | // This program is distributed in the hope that it will be useful, | |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | // GNU General Public License for more details. | |
17 | // | |
18 | // You should have received a copy of the GNU General Public License | |
19 | // along with this program; if not, write to the Free Software | |
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | // | |
22 | // For the avoidance of doubt, and except that if any non-GPL license | |
23 | // choice is available it will apply instead, Sun elects to use only | |
24 | // the General Public License version 2 (GPLv2) at this time for any | |
25 | // software where a choice of GPL license versions is made | |
26 | // available with the language indicating that GPLv2 or any later version | |
27 | // may be used, or where a choice of which version of the GPL is applied is | |
28 | // otherwise unspecified. | |
29 | // | |
30 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
31 | // CA 95054 USA or visit www.sun.com if you need additional information or | |
32 | // have any questions. | |
33 | // | |
34 | // ========== Copyright Header End ============================================ | |
35 | module niu_smx_timer( | |
36 | /*AUTOARG*/ | |
37 | // Outputs | |
38 | resp_rcv_rst, resp_rcv_rst_addr, tid_valid_rst1, | |
39 | tid_valid_rst_addr1, tid_newarr_rst, tid_newarr_rst_addr, | |
40 | timeout_set, timeout_set_addr, | |
41 | // Inputs | |
42 | clk, reset_l, reg_timer_cfg, resp_rcv_rdata_bus, | |
43 | tid_valid_rdata_bus, tid_newarr_rdata_bus, tid_xmited_rdata_bus | |
44 | ); | |
45 | ||
46 | input clk; | |
47 | input reset_l; | |
48 | ||
49 | input [31:0] reg_timer_cfg; | |
50 | // [27:20] -timeout value; use 8 bits for now | |
51 | // [19:0] - tick per table visit | |
52 | ||
53 | // pio_ld_cfg to update cfg ??? | |
54 | ||
55 | input [63:0] resp_rcv_rdata_bus; | |
56 | output resp_rcv_rst; | |
57 | output [5:0] resp_rcv_rst_addr; | |
58 | ||
59 | input [63:0] tid_valid_rdata_bus; | |
60 | output tid_valid_rst1; | |
61 | output [5:0] tid_valid_rst_addr1; | |
62 | ||
63 | input [63:0] tid_newarr_rdata_bus; | |
64 | output tid_newarr_rst; | |
65 | output [5:0] tid_newarr_rst_addr; | |
66 | ||
67 | output timeout_set; | |
68 | output [5:0] timeout_set_addr; | |
69 | ||
70 | input [63:0] tid_xmited_rdata_bus; | |
71 | ||
72 | parameter DATA_WIDTH= 8; // current timeout is 8 bits | |
73 | parameter ADDR_WIDTH= 6; | |
74 | // parameter ENTRY_SIZE= 1<<ADDR_WIDTH; | |
75 | ||
76 | ||
77 | parameter s0= 1'b0, | |
78 | s1= 1'b1; | |
79 | // sm: tid_valid, resprcv, tid_newarr bus& -> snap shot per visit (table) | |
80 | // cycle thru | |
81 | // newarr - ld init timer value | |
82 | ||
83 | reg [27:0] reg_timer_cfg_r; | |
84 | reg pio_ld_cfg; | |
85 | ||
86 | reg [19:0] tick_table_cnt; | |
87 | reg [5:0] cur_tid_addr; | |
88 | ||
89 | wire [19:0] cfg_table= reg_timer_cfg_r[19:0]; // shadow version | |
90 | wire [DATA_WIDTH-1:0] cfg_timeout= reg_timer_cfg_r[DATA_WIDTH+19:20]; | |
91 | ||
92 | wire pio_ld_cfg_n= (reg_timer_cfg_r != reg_timer_cfg[27:0]); | |
93 | // reload shadow whenever differs from pio | |
94 | ||
95 | wire visit_table_n= (tick_table_cnt == 20'h1); | |
96 | wire cfg_table_is_zero_n= ~(|cfg_table); | |
97 | wire all_entry_done_n= &cur_tid_addr; | |
98 | ||
99 | reg timer_cs, timer_ns; | |
100 | reg ld_snap_shot_n, ld_snap_shot; | |
101 | wire rst_snap_shot_n= ld_snap_shot & ~ld_snap_shot_n ; | |
102 | // rst next cycle if pipe and no new entry follow; | |
103 | reg ld_table_cnt_n; | |
104 | reg rst_cur_tid_addr_n; | |
105 | reg inc_cur_tid_addr_n; | |
106 | reg dec_table_cnt_n; | |
107 | reg timer_tb_rd_n; | |
108 | ||
109 | // snap shot; pulse | |
110 | reg ss_tid_valid; | |
111 | reg ss_tid_xmited; | |
112 | reg ss_tid_newarr; | |
113 | reg ss_resprcv; | |
114 | reg [5:0] ss_tid_addr; | |
115 | ||
116 | ||
117 | always @ ( | |
118 | /*AUTOSENSE*/all_entry_done_n or cfg_table_is_zero_n or timer_cs | |
119 | or visit_table_n) begin | |
120 | timer_ns= timer_cs; | |
121 | ld_snap_shot_n= 1'b0; | |
122 | ld_table_cnt_n= 1'b0; | |
123 | dec_table_cnt_n= 1'b0; | |
124 | rst_cur_tid_addr_n= 1'b0; | |
125 | inc_cur_tid_addr_n= 1'b0; | |
126 | timer_tb_rd_n= 1'b0; | |
127 | case(timer_cs) | |
128 | s0: begin // wait table visit | |
129 | if(visit_table_n) begin | |
130 | timer_ns= s1; | |
131 | end | |
132 | else begin | |
133 | dec_table_cnt_n= (~cfg_table_is_zero_n); | |
134 | end | |
135 | end | |
136 | s1: begin // entry visit | |
137 | ld_snap_shot_n= 1'b1; | |
138 | rst_cur_tid_addr_n= all_entry_done_n; | |
139 | inc_cur_tid_addr_n= ~all_entry_done_n; | |
140 | timer_tb_rd_n= 1'b1; | |
141 | timer_ns= (all_entry_done_n)? s0: s1; | |
142 | ld_table_cnt_n= (all_entry_done_n)? 1'b1 : 1'b0; | |
143 | end | |
144 | endcase | |
145 | ||
146 | end | |
147 | ||
148 | always @(posedge clk) begin | |
149 | if(!reset_l) begin | |
150 | reg_timer_cfg_r<= `SMX_PD 28'h0; | |
151 | pio_ld_cfg<= `SMX_PD 1'b0; | |
152 | end | |
153 | else begin | |
154 | if(pio_ld_cfg_n) reg_timer_cfg_r<= `SMX_PD reg_timer_cfg[27:0]; | |
155 | pio_ld_cfg<= `SMX_PD pio_ld_cfg_n; | |
156 | end | |
157 | end | |
158 | ||
159 | always @(posedge clk) begin | |
160 | if(!reset_l) begin | |
161 | tick_table_cnt<= `SMX_PD 20'hff; // default 255 cnt at init | |
162 | // probably overwrite with pio init after reset | |
163 | cur_tid_addr<= `SMX_PD 6'h0; | |
164 | timer_cs<= `SMX_PD s0; | |
165 | end | |
166 | else begin | |
167 | if(ld_table_cnt_n || pio_ld_cfg) tick_table_cnt<= `SMX_PD cfg_table; | |
168 | else if (dec_table_cnt_n) tick_table_cnt<= `SMX_PD tick_table_cnt - 1'b1; | |
169 | ||
170 | if(rst_cur_tid_addr_n) cur_tid_addr<= `SMX_PD 6'h0; | |
171 | else if (inc_cur_tid_addr_n) cur_tid_addr<= `SMX_PD cur_tid_addr + 1'b1; | |
172 | ||
173 | timer_cs<= `SMX_PD timer_ns; | |
174 | end | |
175 | end | |
176 | ||
177 | ||
178 | always @ (posedge clk) begin | |
179 | if(!reset_l) begin | |
180 | ss_tid_valid<= `SMX_PD 1'b0; | |
181 | ss_tid_xmited<= `SMX_PD 1'b0; | |
182 | ss_tid_newarr<= `SMX_PD 1'b0; | |
183 | ss_resprcv<= `SMX_PD 1'b0; | |
184 | ld_snap_shot<= `SMX_PD 1'b0; | |
185 | end | |
186 | else begin | |
187 | if(ld_snap_shot_n) begin | |
188 | ss_tid_valid<= `SMX_PD tid_valid_rdata_bus[cur_tid_addr]; | |
189 | ss_tid_xmited<= `SMX_PD tid_xmited_rdata_bus[cur_tid_addr]; | |
190 | ss_tid_newarr<= `SMX_PD tid_newarr_rdata_bus[cur_tid_addr]; | |
191 | ss_resprcv<= `SMX_PD resp_rcv_rdata_bus[cur_tid_addr]; | |
192 | ld_snap_shot<= `SMX_PD 1'b1; // use this to rst itself | |
193 | end | |
194 | else begin | |
195 | if(rst_snap_shot_n) begin | |
196 | ss_tid_valid<= `SMX_PD 1'b0; | |
197 | ss_tid_xmited<= `SMX_PD 1'b0; | |
198 | ss_tid_newarr<= `SMX_PD 1'b0; | |
199 | ss_resprcv<= `SMX_PD 1'b0; | |
200 | ld_snap_shot<= `SMX_PD 1'b0; | |
201 | end | |
202 | end // snap_shot | |
203 | end // !reset | |
204 | end | |
205 | ||
206 | always @ (posedge clk) begin | |
207 | if(ld_snap_shot_n) begin | |
208 | ss_tid_addr<= `SMX_PD cur_tid_addr; | |
209 | end | |
210 | end | |
211 | ||
212 | // rst timer to init value | |
213 | // ss align with timer_tb_rdata avail | |
214 | wire [DATA_WIDTH-1:0] timer_tb_rdata; | |
215 | wire rst_timer_tb_n= ss_tid_valid & (ss_resprcv | ss_tid_newarr); | |
216 | wire dec_timer_tb_n= ss_tid_valid & ~ss_resprcv & ~ss_tid_newarr & ss_tid_xmited; | |
217 | wire timer_tb_rdata_iszero= ~(|timer_tb_rdata); | |
218 | wire [DATA_WIDTH-1:0] timer_tb_rdata_dec_n= timer_tb_rdata - 1'b1; | |
219 | wire time_out_n= dec_timer_tb_n & (timer_tb_rdata=={{(DATA_WIDTH-1){1'b0}}, 1'b1}); | |
220 | // value of 1 left; waited this '1' already; therefore timeout | |
221 | // wire resp_rcv_rst= rst_timer_tb_n; | |
222 | // wire [5:0] resp_rcv_rst_addr= ss_tid_addr; | |
223 | wire resp_rcv_rst= ld_snap_shot_n; // wanna rst resp_rcv at same time of load, | |
224 | wire [5:0] resp_rcv_rst_addr= cur_tid_addr; // in case 'set' resp rcv happens at same time | |
225 | wire tid_newarr_rst= ss_tid_valid & ss_tid_newarr; | |
226 | wire [5:0] tid_newarr_rst_addr= ss_tid_addr; | |
227 | ||
228 | wire timer_tb_wr_n= rst_timer_tb_n | dec_timer_tb_n; | |
229 | wire [DATA_WIDTH-1:0] timer_tb_wdata_n= | |
230 | (rst_timer_tb_n)? cfg_timeout : | |
231 | ((timer_tb_rdata_iszero)? timer_tb_rdata : timer_tb_rdata_dec_n); | |
232 | reg timer_tb_wr; | |
233 | reg [DATA_WIDTH-1:0] timer_tb_wdata; | |
234 | ||
235 | reg timeout_set; | |
236 | reg [5:0] timeout_set_addr; | |
237 | ||
238 | always @ (posedge clk) begin | |
239 | if(!reset_l) begin | |
240 | timer_tb_wr<= `SMX_PD 1'b0; | |
241 | timeout_set<= `SMX_PD 1'b0; | |
242 | end | |
243 | else begin | |
244 | timer_tb_wr<= `SMX_PD timer_tb_wr_n; | |
245 | timeout_set<= `SMX_PD time_out_n; | |
246 | end | |
247 | end | |
248 | ||
249 | reg [ADDR_WIDTH-1:0] timer_tb_waddr; | |
250 | always @ (posedge clk) begin | |
251 | if(timer_tb_wr_n) begin | |
252 | timer_tb_wdata<= `SMX_PD timer_tb_wdata_n; | |
253 | timer_tb_waddr<= `SMX_PD ss_tid_addr; | |
254 | end | |
255 | if(time_out_n) timeout_set_addr<= `SMX_PD ss_tid_addr; | |
256 | end | |
257 | ||
258 | // rst tid_valid if timeout | |
259 | wire tid_valid_rst1= timeout_set; | |
260 | wire [5:0] tid_valid_rst_addr1= timeout_set_addr; | |
261 | ||
262 | niu_smx_regfl #(DATA_WIDTH,ADDR_WIDTH) timer_tb( | |
263 | .clk (clk), | |
264 | .reset_l (reset_l), | |
265 | .wr (timer_tb_wr), | |
266 | .addr_wr (timer_tb_waddr[ADDR_WIDTH-1:0]), | |
267 | .data_wr (timer_tb_wdata[DATA_WIDTH-1:0]), | |
268 | .rd (timer_tb_rd_n), | |
269 | .addr_rd (cur_tid_addr[ADDR_WIDTH-1:0]), | |
270 | .data_rd (timer_tb_rdata[DATA_WIDTH-1:0]) | |
271 | ); | |
272 | ||
273 | ||
274 | ||
275 | endmodule | |
276 | ||
277 |