OpenCores
URL https://opencores.org/ocsvn/sparc64soc/sparc64soc/trunk

Subversion Repositories sparc64soc

[/] [sparc64soc/] [trunk/] [T1-common/] [common/] [ucb_noflow.v] - Blame information for rev 6

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dmitryr
// ========== Copyright Header Begin ==========================================
2
// 
3
// OpenSPARC T1 Processor File: ucb_noflow.v
4
// Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
5
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6
// 
7
// The above named program is free software; you can redistribute it and/or
8
// modify it under the terms of the GNU General Public
9
// License version 2 as published by the Free Software Foundation.
10
// 
11
// The above named program is distributed in the hope that it will be 
12
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
// General Public License for more details.
15
// 
16
// You should have received a copy of the GNU General Public
17
// License along with this work; if not, write to the Free Software
18
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19
// 
20
// ========== Copyright Header End ============================================
21
////////////////////////////////////////////////////////////////////////
22
/*
23
//  Module Name:        ucb_noflow
24
//      Description:    Unit Control Block
25
//                      - supports 64 or 128-bit read with flow control
26
//                      - supports 64-bit write without flow control
27
//                      - automactically drops non-64-bit writes
28
//                      - supports interrupt return to IO Bridge
29
//                      - provides only single buffer at each interface
30
//
31
//                      This module is intended for units that have
32
//                      both 64 and 128 bit registers.
33
//
34
//                      Data bus width to and from the IO Bridge is
35
//                      configured through parameters UCB_IOB_WIDTH and
36
//                      IOB_UCB_WIDTH.  Supported widths are:
37
//
38
//                      IOB_UCB_WIDTH  UCB_IOB_WIDTH
39
//                      ----------------------------
40
//                      32             8
41
//                      16             8
42
//                       8             8
43
//                       4             4
44
 */
45
////////////////////////////////////////////////////////////////////////
46
// Global header file includes
47
////////////////////////////////////////////////////////////////////////
48
`include        "sys.h" // system level definition file which 
49
                        // contains the time scale definition
50
 
51
`include        "iop.h"
52
 
53
////////////////////////////////////////////////////////////////////////
54
// Local header file includes / local defines
55
////////////////////////////////////////////////////////////////////////
56
 
57
module ucb_noflow (/*AUTOARG*/
58
   // Outputs
59
   ucb_iob_stall, rd_req_vld, wr_req_vld, thr_id_in, buf_id_in,
60
   size_in, addr_in, data_in, int_busy, ucb_iob_vld, ucb_iob_data,
61
   // Inputs
62
   clk, rst_l, iob_ucb_vld, iob_ucb_data, rd_ack_vld, rd_nack_vld,
63
   thr_id_out, buf_id_out, data128, data_out, int_vld, int_typ,
64
   int_thr_id, dev_id, int_stat, int_vec, iob_ucb_stall
65
   );
66
 
67
   // synopsys template
68
 
69
   parameter IOB_UCB_WIDTH = 32;  // data bus width from IOB to UCB
70
   parameter UCB_IOB_WIDTH = 8;   // data bus width from UCB to IOB
71
   parameter REG_WIDTH = 64;      // set this to 128 if unit needs to
72
                                  // return 128-bit data
73
 
74
 
75
   // Globals
76
   input                                clk;
77
   input                                rst_l;
78
 
79
   // Request from IO Bridge
80
   input                                iob_ucb_vld;
81
   input [IOB_UCB_WIDTH-1:0]             iob_ucb_data;
82
   output                               ucb_iob_stall;
83
 
84
   // Request to local unit
85
   output                               rd_req_vld;
86
   output                               wr_req_vld;
87
   output [`UCB_THR_HI-`UCB_THR_LO:0]   thr_id_in;
88
   output [`UCB_BUF_HI-`UCB_BUF_LO:0]   buf_id_in;
89
   output [`UCB_SIZE_HI-`UCB_SIZE_LO:0] size_in;   // only pertinent to PCI
90
   output [`UCB_ADDR_HI-`UCB_ADDR_LO:0] addr_in;
91
   output [`UCB_DATA_HI-`UCB_DATA_LO:0] data_in;
92
 
93
   // Ack/Nack from local unit
94
   input                                rd_ack_vld;
95
   input                                rd_nack_vld;
96
   input [`UCB_THR_HI-`UCB_THR_LO:0]     thr_id_out;
97
   input [`UCB_BUF_HI-`UCB_BUF_LO:0]     buf_id_out;
98
   input                                data128;   // set to 1 if data returned is 128 bit
99
   input [REG_WIDTH-1:0]                 data_out;
100
 
101
   // Interrupt from local unit
102
   input                                int_vld;
103
   input [`UCB_PKT_HI-`UCB_PKT_LO:0]     int_typ;          // interrupt type
104
   input [`UCB_THR_HI-`UCB_THR_LO:0]     int_thr_id;       // interrupt thread ID
105
   input [`UCB_INT_DEV_HI-`UCB_INT_DEV_LO:0] dev_id;      // interrupt device ID
106
   input [`UCB_INT_STAT_HI-`UCB_INT_STAT_LO:0] int_stat;  // interrupt status
107
   input [`UCB_INT_VEC_HI-`UCB_INT_VEC_LO:0]   int_vec;   // interrupt vector
108
   output                               int_busy;         // interrupt buffer busy
109
 
110
   // Output to IO Bridge
111
   output                               ucb_iob_vld;
112
   output [UCB_IOB_WIDTH-1:0]            ucb_iob_data;
113
   input                                iob_ucb_stall;
114
 
115
   // Local signals
116
   wire                                 indata_buf_vld;
117
   wire [127:0]                  indata_buf;
118
   wire                                 ucb_iob_stall_a1;
119
 
120
   wire                                 read_pending;
121
   wire                                 read_outstanding;
122
   wire                                 read_outstanding_next;
123
   wire                                 write_pending;
124
   wire                                 illegal_write_size;
125
 
126
   wire                                 ack_buf_rd;
127
   wire                                 ack_buf_wr;
128
   wire                                 ack_buf_vld;
129
   wire                                 ack_buf_vld_next;
130
   wire                                 ack_buf_is_nack;
131
   wire                                 ack_buf_is_data128;
132
   wire [`UCB_PKT_HI-`UCB_PKT_LO:0]      ack_typ_out;
133
   wire [REG_WIDTH+`UCB_BUF_HI-`UCB_PKT_LO:0] ack_buf_in;
134
   wire [REG_WIDTH+`UCB_BUF_HI-`UCB_PKT_LO:0] ack_buf;
135
   wire [(REG_WIDTH+64)/UCB_IOB_WIDTH-1:0] ack_buf_vec;
136
 
137
   wire                                 int_buf_rd;
138
   wire                                 int_buf_wr;
139
   wire                                 int_buf_vld;
140
   wire                                 int_buf_vld_next;
141
   wire [`UCB_INT_VEC_HI-`UCB_PKT_LO:0] int_buf_in;
142
   wire [`UCB_INT_VEC_HI-`UCB_PKT_LO:0] int_buf;
143
   wire [(REG_WIDTH+64)/UCB_IOB_WIDTH-1:0] int_buf_vec;
144
 
145
   wire                                 int_last_rd;
146
   wire                                 outdata_buf_busy;
147
   wire                                 outdata_buf_wr;
148
   wire [REG_WIDTH+63:0]                 outdata_buf_in;
149
   wire [(REG_WIDTH+64)/UCB_IOB_WIDTH-1:0] outdata_vec_in;
150
 
151
 
152
////////////////////////////////////////////////////////////////////////
153
// Code starts here
154
////////////////////////////////////////////////////////////////////////
155
   /************************************************************
156
    * Inbound Data
157
    ************************************************************/
158
   // Register size is hardcoded to 64 bits here because all
159
   // units using the UCB module will only write to 64 bit registers.
160
   ucb_bus_in #(IOB_UCB_WIDTH,64) ucb_bus_in (.rst_l(rst_l),
161
                                              .clk(clk),
162
                                              .vld(iob_ucb_vld),
163
                                              .data(iob_ucb_data),
164
                                              .stall(ucb_iob_stall),
165
                                              .indata_buf_vld(indata_buf_vld),
166
                                              .indata_buf(indata_buf),
167
                                              .stall_a1(ucb_iob_stall_a1));
168
 
169
 
170
   /************************************************************
171
    * Decode inbound packet type
172
    ************************************************************/
173
   assign        read_pending = (indata_buf[`UCB_PKT_HI:`UCB_PKT_LO] ==
174
                                 `UCB_READ_REQ) &
175
                                indata_buf_vld;
176
 
177
   // Assertion: rd_req_vld and ack_buf_rd must be
178
   //            mutually exclusive
179
   assign        read_outstanding_next = rd_req_vld ? 1'b1 :
180
                                         ack_buf_rd ? 1'b0 :
181
                                                      read_outstanding;
182
   dffrl_ns #(1) read_outstanding_ff (.din(read_outstanding_next),
183
                                      .clk(clk),
184
                                      .rst_l(rst_l),
185
                                      .q(read_outstanding));
186
 
187
   assign        ucb_iob_stall_a1 = read_pending & read_outstanding;
188
 
189
   assign        write_pending = (indata_buf[`UCB_PKT_HI:`UCB_PKT_LO] ==
190
                                  `UCB_WRITE_REQ) &
191
                                 indata_buf_vld;
192
 
193
   // 3'b011 is the encoding for double word.  All writes have to be
194
   // 64 bits except writes going to PCI.  PCI will instantiate a
195
   // customized version of UCB.
196
   assign        illegal_write_size = (indata_buf[`UCB_SIZE_HI:`UCB_SIZE_LO] !=
197
                                       3'b011);
198
 
199
 
200
   /************************************************************
201
    * Inbound interface to local unit
202
    ************************************************************/
203
   assign        rd_req_vld = read_pending & ~read_outstanding;
204
   assign        wr_req_vld = write_pending & ~illegal_write_size;
205
   assign        thr_id_in = indata_buf[`UCB_THR_HI:`UCB_THR_LO];
206
   assign        buf_id_in = indata_buf[`UCB_BUF_HI:`UCB_BUF_LO];
207
   assign        size_in = indata_buf[`UCB_SIZE_HI:`UCB_SIZE_LO];
208
   assign        addr_in = indata_buf[`UCB_ADDR_HI:`UCB_ADDR_LO];
209
   assign        data_in = indata_buf[`UCB_DATA_HI:`UCB_DATA_LO];
210
 
211
 
212
   /************************************************************
213
    * Outbound Ack/Nack
214
    ************************************************************/
215
   assign        ack_buf_wr = rd_ack_vld | rd_nack_vld;
216
 
217
   assign        ack_buf_vld_next = ack_buf_wr ? 1'b1 :
218
                                    ack_buf_rd ? 1'b0 :
219
                                                 ack_buf_vld;
220
 
221
   dffrl_ns #(1) ack_buf_vld_ff (.din(ack_buf_vld_next),
222
                                 .clk(clk),
223
                                 .rst_l(rst_l),
224
                                 .q(ack_buf_vld));
225
 
226
   dffe_ns #(1) ack_buf_is_nack_ff (.din(rd_nack_vld),
227
                                    .en(ack_buf_wr),
228
                                    .clk(clk),
229
                                    .q(ack_buf_is_nack));
230
 
231
   dffe_ns #(1) ack_buf_is_data128_ff (.din(data128),
232
                                       .en(ack_buf_wr),
233
                                       .clk(clk),
234
                                       .q(ack_buf_is_data128));
235
 
236
   assign        ack_typ_out = rd_ack_vld ? `UCB_READ_ACK:
237
                                            `UCB_READ_NACK;
238
 
239
   assign        ack_buf_in = {data_out,
240
                               buf_id_out,
241
                               thr_id_out,
242
                               ack_typ_out};
243
 
244
   dffe_ns #(REG_WIDTH+`UCB_BUF_HI-`UCB_PKT_LO+1) ack_buf_ff (.din(ack_buf_in),
245
                                                              .en(ack_buf_wr),
246
                                                              .clk(clk),
247
                                                              .q(ack_buf));
248
 
249
   assign        ack_buf_vec = ack_buf_is_nack    ? {{REG_WIDTH/UCB_IOB_WIDTH{1'b0}},
250
                                                     {64/UCB_IOB_WIDTH{1'b1}}} :
251
                               ack_buf_is_data128 ? {(REG_WIDTH+64)/UCB_IOB_WIDTH{1'b1}} :
252
                                                    {(64+64)/UCB_IOB_WIDTH{1'b1}};
253
 
254
 
255
   /************************************************************
256
    * Outbound Interrupt
257
    ************************************************************/
258
   // Assertion: int_buf_wr shoudn't be asserted if int_buf_busy
259
   assign        int_buf_wr = int_vld;
260
 
261
   assign        int_buf_vld_next = int_buf_wr ? 1'b1 :
262
                                    int_buf_rd ? 1'b0 :
263
                                                 int_buf_vld;
264
 
265
   dffrl_ns #(1) int_buf_vld_ff (.din(int_buf_vld_next),
266
                                 .clk(clk),
267
                                 .rst_l(rst_l),
268
                                 .q(int_buf_vld));
269
 
270
   assign        int_buf_in = {int_vec,
271
                               int_stat,
272
                               dev_id,
273
                               int_thr_id,
274
                               int_typ};
275
 
276
   dffe_ns #(`UCB_INT_VEC_HI-`UCB_PKT_LO+1) int_buf_ff (.din(int_buf_in),
277
                                                        .en(int_buf_wr),
278
                                                        .clk(clk),
279
                                                        .q(int_buf));
280
 
281
   assign        int_buf_vec = {{REG_WIDTH/UCB_IOB_WIDTH{1'b0}},
282
                                {64/UCB_IOB_WIDTH{1'b1}}};
283
 
284
   assign        int_busy = int_buf_vld;
285
 
286
 
287
   /************************************************************
288
    * Outbound ack/interrupt Arbitration
289
    ************************************************************/
290
   dffrle_ns #(1) int_last_rd_ff (.din(int_buf_rd),
291
                                  .en(ack_buf_rd|int_buf_rd),
292
                                  .rst_l(rst_l),
293
                                  .clk(clk),
294
                                  .q(int_last_rd));
295
 
296
   assign        ack_buf_rd = ~outdata_buf_busy & ack_buf_vld &
297
                              (~int_buf_vld | int_last_rd);
298
 
299
   assign        int_buf_rd = ~outdata_buf_busy & int_buf_vld &
300
                              (~ack_buf_vld | ~int_last_rd);
301
 
302
   assign        outdata_buf_wr = ack_buf_rd | int_buf_rd;
303
 
304
   assign        outdata_buf_in = ack_buf_rd ? {ack_buf[REG_WIDTH+`UCB_BUF_HI:`UCB_BUF_HI+1],
305
                                                {(`UCB_RSV_HI-`UCB_RSV_LO+1){1'b0}},
306
                                                {(`UCB_ADDR_HI-`UCB_ADDR_LO+1){1'b0}},
307
                                                {(`UCB_SIZE_HI-`UCB_SIZE_LO+1){1'b0}},
308
                                                ack_buf[`UCB_BUF_HI:`UCB_BUF_LO],
309
                                                ack_buf[`UCB_THR_HI:`UCB_THR_LO],
310
                                                ack_buf[`UCB_PKT_HI:`UCB_PKT_LO]}:
311
                                               {{REG_WIDTH{1'b0}},
312
                                                {(`UCB_INT_RSV_HI-`UCB_INT_RSV_LO+1){1'b0}},
313
                                                int_buf[`UCB_INT_VEC_HI:`UCB_INT_VEC_LO],
314
                                                int_buf[`UCB_INT_STAT_HI:`UCB_INT_STAT_LO],
315
                                                int_buf[`UCB_INT_DEV_HI:`UCB_INT_DEV_LO],
316
                                                int_buf[`UCB_THR_HI:`UCB_THR_LO],
317
                                                int_buf[`UCB_PKT_HI:`UCB_PKT_LO]};
318
 
319
   assign        outdata_vec_in = ack_buf_rd ? ack_buf_vec :
320
                                               int_buf_vec;
321
 
322
   ucb_bus_out #(UCB_IOB_WIDTH, REG_WIDTH) ucb_bus_out (.rst_l(rst_l),
323
                                                        .clk(clk),
324
                                                        .outdata_buf_wr(outdata_buf_wr),
325
                                                        .outdata_buf_in(outdata_buf_in),
326
                                                        .outdata_vec_in(outdata_vec_in),
327
                                                        .outdata_buf_busy(outdata_buf_busy),
328
                                                        .vld(ucb_iob_vld),
329
                                                        .data(ucb_iob_data),
330
                                                        .stall(iob_ucb_stall));
331
 
332
 
333
endmodule // ucb_noflow
334
 
335
 
336
// Local Variables:
337
// verilog-library-directories:(".")
338
// End:
339
 
340
 
341
 
342
 
343
 
344
 
345
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.