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

Subversion Repositories rtf_sprite_controller

[/] [rtf_sprite_controller/] [trunk/] [rtl/] [verilog/] [rtfSpriteController.v] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 robfinch
`timescale 1ns / 1ps
2
// ============================================================================
3
//        __
4
//   \\__/ o\    (C) 2005-2013  Robert Finch, Stratford
5
//    \  __ /    All rights reserved.
6
//     \/_//     robfinch<remove>@opencores.org
7
//       ||
8
//
9
//      rtfSpriteController.v
10
//              sprite / hardware cursor controller
11
//
12
// This source file is free software: you can redistribute it and/or modify 
13
// it under the terms of the GNU Lesser General Public License as published 
14
// by the Free Software Foundation, either version 3 of the License, or     
15
// (at your option) any later version.                                      
16
//                                                                          
17
// This source file is distributed in the hope that it will be useful,      
18
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
19
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
20
// GNU General Public License for more details.                             
21
//                                                                          
22
// You should have received a copy of the GNU General Public License        
23
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
24
//
25
//
26
//      Sprite Controller
27
//
28
//      FEATURES
29
//      - parameterized number of sprites 1,2,4,6,8 or 14
30
//      - sprite image cache buffers
31
//              - each image cache is capable of holding multiple
32
//                sprite images
33
//              - cache may be accessed like a memory by the processor
34
//              - an embedded DMA controller may also be used for
35
//                      sprite reload
36
//      - programmable image offset within cache
37
//      - programmable sprite width,height, and pixel size
38
//              - sprite width and height may vary from 1 to 64 as long
39
//                as the product doesn't exceed 2048.
40
//          - pixels may be programmed to be 1,2,3 or 4 video clocks
41
//            both height and width are programmable
42
//      - programmable sprite position
43
//      - 8 or 16 bits for color
44
//              eg 32k color + 1 bit alpha blending indicator (1,5,5,5)
45
//      - fixed display and DMA priority
46
//          sprite 0 highest, sprite 13 lowest
47
//
48
//              This core requires an external timing generator to
49
//      provide horizontal and vertical sync signals, but
50
//      otherwise can be used as a display controller on it's
51
//      own. However, normally this core would be embedded
52
//      within another core such as a VGA controller. Sprite
53
//      positions are referenced to the rising edge of the
54
//      vertical and horizontal sync pulses.
55
//              The core includes an embedded dual port RAM to hold the
56
//      sprite images. The image RAM is updated using a built in DMA
57
//      controller. The DMA controller uses 32 bit accesses to fill
58
//      the sprite buffers. The circuit features an automatic bus
59
//  transaction timeout; if the system bus hasn't responded
60
//  within 20 clock cycles, the DMA controller moves onto the
61
//  next address.
62
//              The controller uses a ram underlay to cache the values
63
//      of the registers. This is a lot cheaper resource wise than
64
//      using a 32 to 1 multiplexor (well at least for an FPGA).
65
//
66
//      All registers are 32 bits wide
67
//
68
//      These registers repeat in incrementing block of four registers
69
//      and pertain to each sprite
70
//      00:     - position register
71
//              HPOS    [11: 0] horizontal position (hctr value)
72
//          VPOS        [27:16] vertical position (vctr value)
73
//
74
//      04:     SZ      - size and offset register
75
//                      bits
76
//                      [ 5: 0] width of sprite in pixels - 1
77
//                      [ 7: 6] size of horizontal pixels - 1 in clock cycles
78
//                      [13: 8] height of sprite in pixels -1
79
//                      [15:14] size of vertical pixels in scan-lines - 1
80
//                              * the product of width * height cannot exceed 2048 !
81
//                              if it does, the display will begin repeating
82
//                              
83
//              OFFS    [26:16] image offset bits [10:0]
84
//                      offset of the sprite image within the sprite image cache
85
//                      typically zero
86
//
87
//      08: ADR 21 bits sprite image address bits [31:11]
88
//                      This registers contain the low order address bits of the
89
//          location of the sprite image in system memory.
90
//                      The DMA controller will assign the low order 11 bits
91
//                      during DMA.
92
//      
93
//      0C: TC  [7:0]   transparent color
94
//                      This register identifies which color of the sprite
95
//                      is transparent
96
//
97
//
98
//      0C-DC:  registers reserved for up to thirteen other sprites
99
//
100
//      Global status and control
101
//      E8: BTC [23:0] background transparent color
102
//      EC: BC  [23:0] background color
103
//      F0: EN  [13:0] sprite enable register
104
//              IE      [29:16] sprite interrupt enable / status
105
//      F4: SCOL        [13:0] sprite-sprite collision register
106
//              BCOL    [29:16] sprite-background collision register
107
//      F8: DT          [13:0] sprite DMA trigger
108
//  FC: ADDR    [31:0] sprite DMA address bits [63:32]
109
//
110
//
111
//      1635 LUTs/ 1112 slices/ 82MHz - Spartan3e-4 (8 sprites)
112
//      3 8x8 multipliers (for alpha blending)
113
//      14 block rams
114
//=============================================================== */
115
 
116
`define VENDOR_XILINX   // block ram vendor (only one defined for now)
117
 
118
module rtfSpriteController(
119
// Bus Slave interface
120
//------------------------------
121
// Slave signals
122
input rst_i,                    // reset
123
input clk_i,                    // clock
124
input         s_cyc_i,  // cycle valid
125
input         s_stb_i,  // data transfer
126
output        s_ack_o,  // transfer acknowledge
127
input         s_we_i,   // write
128
input  [ 3:0] s_sel_i,   // byte select
129
input  [23:0] s_adr_i,   // address
130
input  [31:0] s_dat_i,   // data input
131
output reg [31:0] s_dat_o,       // data output
132
output vol_o,                   // volatile register
133
//------------------------------
134
// Bus Master Signals
135
output reg [1:0] m_bte_o,        // burst type
136
output reg [2:0] m_cti_o,        // cycle type
137
output reg [5:0] m_bl_o, // burst length
138
output reg    m_cyc_o,  // cycle is valid
139
output reg    m_stb_o,  // strobe output
140
input         m_ack_i,  // input data is ready
141
output reg    m_we_o,           // write (always inactive)
142
output reg [ 3:0] m_sel_o,       // byte select
143
output reg [63:0] m_adr_o,       // DMA address
144
input  [31:0] m_dat_i,   // data input
145
output reg [31:0] m_dat_o,       // data output (always zero)
146
//--------------------------
147
input vclk,                                     // video dot clock
148
input hSync,                            // horizontal sync pulse
149
input vSync,                            // vertical sync pulse
150
input blank,                            // blanking signal
151
input [24:0] rgbIn,                      // input pixel stream
152
output reg [23:0] rgbOut,        // output pixel stream
153
output irq                                      // interrupt request
154
);
155
 
156
reg m_soc_o;
157
 
158
//--------------------------------------------------------------------
159
// Core Parameters
160
//--------------------------------------------------------------------
161
parameter pnSpr = 8;            // number of sprites
162
parameter phBits = 11;          // number of bits in horizontal timing counter
163
parameter pvBits = 11;          // number of bits in vertical timing counter
164
parameter pColorBits = 16;      // number of bits used for color data
165
localparam pnSprm = pnSpr-1;
166
 
167
 
168
//--------------------------------------------------------------------
169
// Variable Declarations
170
//--------------------------------------------------------------------
171
 
172
wire [3:0] sprN = s_adr_i[7:4];
173
 
174
reg [phBits-1:0] hctr;           // horizontal reference counter (counts dots since hSync)
175
reg [pvBits-1:0] vctr;           // vertical reference counter (counts scanlines since vSync)
176
reg sprSprIRQ;
177
reg sprBkIRQ;
178
 
179
reg [15:0] out;                  // sprite output
180
reg outact;                             // sprite output is active
181
wire bkCollision;               // sprite-background collision
182
reg [23:0] bgTc;         // background transparent color
183
reg [23:0] bkColor;              // background color
184
 
185
 
186
reg [pnSprm:0] sprWe;    // block ram write enable for image cache update
187
reg [pnSprm:0] sprRe;    // block ram read enable for image cache update
188
 
189
// Global control registers
190
reg [15:0] sprEn;        // enable sprite
191
reg [pnSprm:0] sprCollision;         // sprite-sprite collision
192
reg sprSprIe;                   // sprite-sprite interrupt enable
193
reg sprBkIe;            // sprite-background interrupt enable
194
reg sprSprIRQPending;   // sprite-sprite collision interrupt pending
195
reg sprBkIRQPending;    // sprite-background collision interrupt pending
196
reg sprSprIRQPending1;  // sprite-sprite collision interrupt pending
197
reg sprBkIRQPending1;   // sprite-background collision interrupt pending
198
reg sprSprIRQ1;                 // vclk domain regs
199
reg sprBkIRQ1;
200
 
201
// Sprite control registers
202
reg [15:0] sprSprCollision;
203
reg [pnSprm:0] sprSprCollision1;
204
reg [15:0] sprBkCollision;
205
reg [pnSprm:0] sprBkCollision1;
206
reg [pColorBits-1:0] sprTc [pnSprm:0];            // sprite transparent color code
207
// How big the pixels are:
208
// 1,2,3,or 4 video clocks
209
reg [1:0] hSprRes [pnSprm:0];             // sprite horizontal resolution
210
reg [1:0] vSprRes [pnSprm:0];             // sprite vertical resolution
211
reg [5:0] sprWidth [pnSprm:0];            // number of pixels in X direction
212
reg [5:0] sprHeight [pnSprm:0];           // number of vertical pixels
213
 
214
// display and timing signals
215
reg [13:0] hSprReset;   // horizontal reset
216
reg [13:0] vSprReset;   // vertical reset
217
reg [13:0] hSprDe;               // sprite horizontal display enable
218
reg [13:0] vSprDe;               // sprite vertical display enable
219
reg [13:0] sprDe;                        // display enable
220
reg [phBits-1:0] hSprPos [pnSprm:0];      // sprite horizontal position
221
reg [pvBits-1:0] vSprPos [pnSprm:0];      // sprite vertical position
222
reg [5:0] hSprCnt [pnSprm:0];     // sprite horizontal display counter
223
reg [5:0] vSprCnt [pnSprm:0];     // vertical display counter
224
reg [10:0] sprImageOffs [pnSprm:0];       // offset within sprite memory
225
reg [10:0] sprAddr [pnSprm:0];    // index into sprite memory
226
reg [10:0] sprAddrB [pnSprm:0];   // backup address cache for rescan
227
wire [pColorBits-1:0] sprOut [pnSprm:0];  // sprite image data output
228
 
229
// DMA access
230
reg [63:32] sprSysAddrHx;       // high order 32 bits of sprite memory address
231
reg [26:11] sprSysAddrL [pnSprm:0];      // system memory address of sprite image (low bits)
232
reg [31:27] sprSysAddrH [pnSprm:0];      // system memory address of sprite image (high bits)
233
reg [3:0] dmaOwner;                      // which sprite has the DMA channel
234
reg [15:0] sprDt;                // DMA trigger register
235
reg dmaActive;                          // this flag indicates that a block DMA transfer is active
236
 
237
integer n;
238
 
239
//--------------------------------------------------------------------
240
// DMA control / bus interfacing
241
//--------------------------------------------------------------------
242
wire cs_ram = s_cyc_i && s_stb_i && (s_adr_i[23:16]==8'hD8);
243
wire cs_regs = s_cyc_i && s_stb_i && (s_adr_i[23:8]==16'hDA_D0);
244
 
245
reg sprRdy;
246
always @(posedge clk_i)
247
        sprRdy = (cs_ram|cs_regs);
248
 
249
//assign s_ack_o = cs_regs ? 1'b1 : cs_ram ? (s_we_i ? 1 : sprRamRdy) : 0;
250
assign s_ack_o = (cs_regs|cs_ram) ? (s_we_i ? 1'b1 : sprRdy) : 1'b0;
251
assign vol_o = cs_regs & s_adr_i[8:2]>7'd111;
252
assign irq = sprSprIRQ|sprBkIRQ;
253
 
254
//--------------------------------------------------------------------
255
// DMA control / bus interfacing
256
//--------------------------------------------------------------------
257
reg dmaStart;
258
 
259
wire btout;
260
wire sbi_rdy1 = m_ack_i|btout;
261
busTimeoutCtr #(20) br0(
262
        .rst(rst_i),
263
        .crst(1'b0),
264
        .clk(clk_i),
265
        .ce(1'b1),
266
        .req(m_soc_o),
267
        .rdy(m_ack_i),
268
        .timeout(btout)
269
);
270
 
271
reg [4:0] cob;   // count of burst cycles
272
 
273
always @(posedge clk_i)
274
if (rst_i) begin
275
        dmaStart <= 1'b0;
276
        dmaActive <= 1'b0;
277
        dmaOwner <= 4'd0;
278
        m_bte_o <= 2'b00;
279
        m_cti_o <= 3'b000;
280
        m_bl_o <= 6'd63;
281
        m_soc_o <= 1'b0;
282
        m_cyc_o <= 1'b0;
283
        m_stb_o <= 1'b0;
284
        m_we_o <= 1'b0;
285
        m_sel_o <= 4'h0;
286
        m_adr_o <= 44'd0;
287
        m_dat_o <= 32'd0;
288
        cob <= 5'd0;
289
end
290
else begin
291
        dmaStart <= 1'b0;
292
        m_soc_o <= 1'b0;
293
        if (!dmaActive) begin
294
                cob <= 5'd0;
295
                dmaStart <= |sprDt;
296
                dmaActive <= |sprDt;
297
                dmaOwner  <= 0;
298
                for (n = pnSprm; n >= 0; n = n - 1)
299
                        if (sprDt[n]) dmaOwner <= n;
300
        end
301
        else begin
302
                if (!m_cyc_o) begin
303
                        m_bte_o <= 2'b00;
304
                        m_cti_o <= 3'b010;
305
                        m_cyc_o <= 1'b1;
306
                        m_stb_o <= 1'b1;
307
                        m_sel_o <= 4'b1111;
308
                        m_bl_o <= 6'd63;
309
                        m_adr_o <= {sprSysAddrHx,sprSysAddrH[dmaOwner],sprSysAddrL[dmaOwner],cob[2:0],8'h00};
310
                        m_soc_o <= 1'b1;
311
                        cob <= cob + 5'd1;
312
                end
313
                else if (m_ack_i|btout) begin
314
                        m_soc_o <= 1'b1;
315
                        m_adr_o[7:0] <= m_adr_o[7:0] + 8'd4;
316
                        // Flag last cycle of burst
317
                        if (m_adr_o[7:0]==8'hF8)
318
                                m_cti_o <= 3'b111;
319
                        if (m_adr_o[7:0]==8'hFC) begin
320
                                m_soc_o <= 1'b0;
321
                                m_cyc_o <= 1'b0;
322
                                m_stb_o <= 1'b0;
323
                                m_sel_o <= 4'b0000;
324
                                m_cti_o <= 3'b000;
325
                                m_adr_o <= 44'd0;
326
                                if (cob==5'd8)
327
                                        dmaActive <= 1'b0;
328
                        end
329
                end
330
        end
331
end
332
 
333
// generate a write enable strobe for the sprite image memory
334
always @(dmaOwner, dmaActive, s_adr_i, cs_ram, s_we_i, m_ack_i)
335
for (n = 0; n < pnSpr; n = n + 1)
336
        sprWe[n] = (dmaOwner==n && dmaActive && m_ack_i)||(cs_ram && s_we_i && s_adr_i[14:11]==n);
337
 
338
always @(cs_ram, s_adr_i)
339
for (n = 0; n < pnSpr; n = n + 1)
340
        sprRe[n] = cs_ram && s_adr_i[14:11]==n;
341
 
342
wire [31:0] sr_dout [pnSprm:0];
343
reg [31:0] sr_dout_all;
344
 
345
generate
346
begin : gSrDout
347
always @(pnSpr)
348
if (pnSpr==1)
349
        sr_dout_all <= sr_dout[0];
350
else if (pnSpr==2)
351
        sr_dout_all <= sr_dout[0]|sr_dout[1];
352
else if (pnSpr==4)
353
        sr_dout_all <= sr_dout[0]|sr_dout[1]|sr_dout[2]|sr_dout[3];
354
else if (pnSpr==6)
355
        sr_dout_all <= sr_dout[0]|sr_dout[1]|sr_dout[2]|sr_dout[3]|sr_dout[4]|sr_dout[5];
356
else if (pnSpr==8)
357
        sr_dout_all <= sr_dout[0]|sr_dout[1]|sr_dout[2]|sr_dout[3]|sr_dout[4]|sr_dout[5]|sr_dout[6]|sr_dout[7];//|
358
else if (pnSpr==14)
359
        sr_dout_all <= sr_dout[0]|sr_dout[1]|sr_dout[2]|sr_dout[3]|sr_dout[4]|sr_dout[5]|sr_dout[6]|sr_dout[7]|
360
                                                        sr_dout[8]|sr_dout[9]|sr_dout[10]|sr_dout[11]|sr_dout[12]|sr_dout[13];
361
end
362
endgenerate
363
 
364
// register/sprite memory output mux
365
always @(posedge clk_i)
366
        if (cs_ram)
367
                s_dat_o <= sr_dout_all;
368
        else if (cs_regs)
369
                case (s_adr_i[7:1])             // synopsys full_case parallel_case
370
                7'd120: s_dat_o <= {2{sprEn}};
371
                7'd121: s_dat_o <= {2{sprBkIRQPending|sprSprIRQPending,5'b0,sprBkIRQPending,sprSprIRQPending,6'b0,sprBkIe,sprSprIe}};
372
                7'd122: s_dat_o <= {2{sprSprCollision}};
373
                7'd123: s_dat_o <= {2{sprBkCollision}};
374
                7'd124: s_dat_o <= {2{sprDt}};
375
                default:        s_dat_o <= 0;
376
                endcase
377
        else
378
                s_dat_o <= 32'd0;
379
 
380
 
381
// vclk -> clk_i
382
always @(posedge clk_i)
383
begin
384
        sprSprIRQ <= sprSprIRQ1;
385
        sprBkIRQ <= sprBkIRQ1;
386
        sprSprIRQPending <= sprSprIRQPending1;
387
        sprBkIRQPending <= sprBkIRQPending1;
388
        sprSprCollision <= sprSprCollision1;
389
        sprBkCollision <= sprBkCollision1;
390
end
391
 
392
 
393
// register updates
394
// on the clk_i domain
395
always @(posedge clk_i)
396
if (rst_i) begin
397
        sprEn <= {pnSpr{1'b1}};
398
        sprDt <= 0;
399
    for (n = 0; n < pnSpr; n = n + 1) begin
400
                sprSysAddrL[n] <= 5'b0100_0 + n;        //xxxx_4000
401
                sprSysAddrH[n] <= 16'h0000;                     //0000_xxxx
402
        end
403
        sprSprIe <= 0;
404
        sprBkIe  <= 0;
405
 
406
    // Set reasonable starting positions on the screen
407
    // so that the sprites might be visible for testing
408
    for (n = 0; n < pnSpr; n = n + 1) begin
409
        hSprPos[n] <= 440 + n * 50;
410
        vSprPos[n] <= 200;
411
        sprTc[n] <= 16'h6739;
412
                sprWidth[n] <= 47;  // 48x42 sprites
413
                sprHeight[n] <= 41;
414
                hSprRes[n] <= 0; // our standard display
415
                vSprRes[n] <= 0;
416
                sprImageOffs[n] <= 0;
417
        end
418
    hSprPos[0] <= 290;
419
    vSprPos[0] <= 72;
420
 
421
    bgTc <= 24'h00_00_00;
422
    bkColor <= 24'hFF_FF_60;
423
end
424
else begin
425
        // clear DMA trigger bit once DMA is recognized
426
        if (dmaStart)
427
                sprDt[dmaOwner] <= 1'b0;
428
 
429
        if (cs_regs & s_we_i) begin
430
 
431
                casex (s_adr_i[8:1])
432
 
433
                8'd116,8'd117:
434
                        begin
435
                                if (s_sel_i[0]) bgTc[7:0] <= s_dat_i[7:0];
436
                                if (s_sel_i[1]) bgTc[15:8] <= s_dat_i[15:8];
437
                                if (s_sel_i[2]) bgTc[23:16] <= s_dat_i[23:16];
438
                        end
439
                8'd118,8'd119:
440
                        begin
441
                                if (s_sel_i[0]) bkColor[7:0] <= s_dat_i[7:0];
442
                                if (s_sel_i[1]) bkColor[15:8] <= s_dat_i[15:8];
443
                                if (s_sel_i[2]) bkColor[23:16] <= s_dat_i[23:16];
444
                        end
445
                8'd120,8'd121:
446
                        begin
447
                                if (s_sel_i[0]) sprEn[7:0] <= s_dat_i[7:0];
448
                                if (s_sel_i[1]) sprEn[13:8] <= s_dat_i[13:8];
449
                                if (s_sel_i[2]) begin
450
                                        sprSprIe <= s_dat_i[16];
451
                                        sprBkIe <= s_dat_i[17];
452
                                end
453
                        end
454
                // update DMA trigger
455
                // s_dat_i[7:0] indicates which triggers to set  (1=set,0=ignore)
456
                // s_dat_i[7:0] indicates which triggers to clear (1=clear,0=ignore)
457
                8'd124,8'd125:
458
                        begin
459
                                if (s_sel_i[0])  sprDt[7:0] <= sprDt[7:0] | s_dat_i[7:0];
460
                                if (s_sel_i[1]) sprDt[13:8] <= sprDt[13:8] | s_dat_i[13:8];
461
                                if (s_sel_i[2]) sprDt[7:0] <= sprDt[7:0] & ~s_dat_i[23:16];
462
                                if (s_sel_i[3]) sprDt[13:8] <= sprDt[13:8] & ~s_dat_i[29:24];
463
                        end
464
                8'd126,8'd127:
465
                        begin
466
                                if (sel_i[0]) sprSysAddrHx[39:32] <= s_dat_i[ 7: 0];
467
                                if (sel_i[1]) sprSysAddrHx[47:40] <= s_dat_i[15: 8];
468
                                if (sel_i[2]) sprSysAddrHx[55:48] <= s_dat_i[23:16];
469
                                if (sel_i[3]) sprSysAddrHx[63:56] <= s_dat_i[31:24];
470
                        end
471
                8'b0xxxx00x:
472
                         begin
473
                        if (s_sel_i[0]) hSprPos[sprN][ 7:0] <= s_dat_i[ 7: 0];
474
                        if (s_sel_i[1]) hSprPos[sprN][10:8] <= s_dat_i[10: 8];
475
                        if (s_sel_i[2]) vSprPos[sprN][ 7:0] <= s_dat_i[23:16];
476
                        if (s_sel_i[3]) vSprPos[sprN][10:8] <= s_dat_i[26:24];
477
                end
478
        8'b0xxxx01x:
479
                        begin
480
                        if (s_sel_i[0]) begin
481
                                        sprWidth[sprN] <= s_dat_i[5:0];
482
                        hSprRes[sprN] <= s_dat_i[7:6];
483
                    end
484
                        if (s_sel_i[1]) begin
485
                                        sprHeight[sprN] <= s_dat_i[13:8];
486
                        vSprRes[sprN] <= s_dat_i[15:14];
487
                    end
488
                    if (s_sel_i[2]) sprImageOffs[sprN][ 7:0] <= s_dat_i[23:16];
489
                    if (s_sel_i[3]) sprImageOffs[sprN][10:8] <= s_dat_i[26:24];
490
                        end
491
                8'b0xxxx10x:
492
                        begin   // DMA address set on clk_i domain
493
                                if (s_sel_i[0]) sprSysAddrL[sprN][18:11] <= s_dat_i[ 7: 0];
494
                                if (s_sel_i[1]) sprSysAddrL[sprN][26:19] <= s_dat_i[15: 8];
495
                                if (s_sel_i[2]) sprSysAddrH[sprN][34:27] <= s_dat_i[23:16];
496
                                if (s_sel_i[3]) sprSysAddrH[sprN][42:35] <= s_dat_i[31:24];
497
                        end
498
                8'b0xxxx11x:
499
                        begin
500
                                if (s_sel_i[0]) sprTc[sprN][ 7:0] <= s_dat_i[ 7:0];
501
                                if (pColorBits>8)
502
                                        if (s_sel_i[1]) sprTc[sprN][15:8] <= s_dat_i[15:8];
503
                        end
504
 
505
                default:        ;
506
                endcase
507
 
508
        end
509
end
510
 
511
//-------------------------------------------------------------
512
// Sprite Image Cache RAM
513
// This RAM is dual ported with an SoC side and a display
514
// controller side.
515
//-------------------------------------------------------------
516
wire [10:2] sr_adr = m_cyc_o ? m_adr_o[10:2] : s_adr_i[10:2];
517
wire [31:0] sr_din = m_cyc_o ? m_dat_i[31:0] : s_dat_i[31:0];
518
wire sr_ce = m_cyc_o ? sbi_rdy1 : cs_ram;
519
 
520
// Note: the sprite output can't be zeroed out using the rst input!!!
521
// We need to know what the output is to determine if it's the 
522
// transparent color.
523
genvar g;
524
generate
525
        for (g = 0; g < pnSpr; g = g + 1)
526
        begin : genSpriteRam
527
                if (pColorBits==8)
528
                        rtfSpriteRam8 sprRam0
529
                        (
530
                                .clka(vclk),
531
                                .adra(sprAddr[g]),
532
                                .doa(sprOut[g]),
533
                                .cea(1'b1),
534
 
535
                                .clkb(~clk_i),
536
                                .adrb(sr_adr),
537
                                .dib(sr_din),
538
                                .dob(sr_dout[g]),
539
                                .ceb(sr_ce),
540
                                .web(sprWe[g]),
541
                                .rstb(!sprRe[g])
542
                        );
543
                else if (pColorBits==16)
544
                        rtfSpriteRam16 sprRam0
545
                        (
546
                                .clka(vclk),
547
                                .adra(sprAddr[g]),
548
                                .doa(sprOut[g]),
549
                                .cea(1'b1),
550
 
551
                                .clkb(~clk_i),
552
                                .adrb(sr_adr),
553
                                .dib(sr_din),
554
                                .dob(sr_dout[g]),
555
                                .ceb(sr_ce),
556
                                .web(sprWe[g]),
557
                                .rstb(!sprRe[g])
558
                        );
559
        end
560
endgenerate
561
 
562
 
563
 
564
//-------------------------------------------------------------
565
// Timing counters and addressing
566
// Sprites are like miniature bitmapped displays, they need
567
// all the same timing controls.
568
//-------------------------------------------------------------
569
 
570
// Create a timing reference using horizontal and vertical
571
// sync
572
wire hSyncEdge, vSyncEdge;
573
edge_det ed0(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(hSync), .pe(hSyncEdge), .ne(), .ee() );
574
edge_det ed1(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(vSync), .pe(vSyncEdge), .ne(), .ee() );
575
 
576
always @(posedge vclk)
577
if (rst_i)              hctr <= 0;
578
else if (hSyncEdge) hctr <= 0;
579
else                    hctr <= hctr + 1;
580
 
581
always @(posedge vclk)
582
if (rst_i)              vctr <= 0;
583
else if (vSyncEdge) vctr <= 0;
584
else if (hSyncEdge) vctr <= vctr + 1;
585
 
586
// track sprite horizontal reset
587
always @(posedge vclk)
588
for (n = 0; n < pnSpr; n = n + 1)
589
        hSprReset[n] <= hctr==hSprPos[n];
590
 
591
// track sprite vertical reset
592
always @(posedge vclk)
593
for (n = 0; n < pnSpr; n = n + 1)
594
        vSprReset[n] <= vctr==vSprPos[n];
595
 
596
always @(hSprDe, vSprDe)
597
for (n = 0; n < 14; n = n + 1)
598
        sprDe[n] <= hSprDe[n] & vSprDe[n];
599
 
600
 
601
// take care of sprite size scaling
602
// video clock division
603
reg [13:0] hSprNextPixel;
604
reg [13:0] vSprNextPixel;
605
reg [1:0] hSprPt [13:0];   // horizontal pixel toggle
606
reg [1:0] vSprPt [13:0];   // vertical pixel toggle
607
always @(n)
608
for (n = 0; n < pnSpr; n = n + 1)
609
    hSprNextPixel[n] = hSprPt[n]==hSprRes[n];
610
always @(n)
611
for (n = 0; n < pnSpr; n = n + 1)
612
    vSprNextPixel[n] = vSprPt[n]==vSprRes[n];
613
 
614
// horizontal pixel toggle counter
615
always @(posedge vclk)
616
for (n = 0; n < pnSpr; n = n + 1)
617
        if (hSprReset[n])
618
                hSprPt[n] <= 0;
619
    else if (hSprNextPixel[n])
620
        hSprPt[n] <= 0;
621
    else
622
        hSprPt[n] <= hSprPt[n] + 1;
623
 
624
// vertical pixel toggle counter
625
always @(posedge vclk)
626
for (n = 0; n < pnSpr; n = n + 1)
627
    if (hSprReset[n]) begin
628
        if (vSprReset[n])
629
                vSprPt[n] <= 0;
630
        else if (vSprNextPixel[n])
631
            vSprPt[n] <= 0;
632
        else
633
            vSprPt[n] <= vSprPt[n] + 1;
634
    end
635
 
636
 
637
// clock sprite image address counters
638
always @(posedge vclk)
639
for (n = 0; n < pnSpr; n = n + 1) begin
640
    // hReset and vReset - top left of sprite,
641
    // reset address to image offset
642
        if (hSprReset[n] & vSprReset[n]) begin
643
                sprAddr[n]  <= sprImageOffs[n];
644
                sprAddrB[n] <= sprImageOffs[n];
645
        end
646
        // hReset:
647
        //  If the next vertical pixel
648
        //      set backup address to current address
649
        //  else
650
        //      set current address to backup address
651
        //      in order to rescan the line
652
        else if (hSprReset[n]) begin
653
                if (vSprNextPixel[n])
654
                        sprAddrB[n] <= sprAddr[n];
655
                else
656
                        sprAddr[n]  <= sprAddrB[n];
657
        end
658
        // Not hReset or vReset - somewhere on the sprite scan line
659
        // just advance the address when the next pixel should be
660
        // fetched
661
        else if (sprDe[n] & hSprNextPixel[n])
662
                sprAddr[n] <= sprAddr[n] + 1;
663
end
664
 
665
 
666
// clock sprite column (X) counter
667
always @(posedge vclk)
668
for (n = 0; n < pnSpr; n = n + 1)
669
        if (hSprReset[n])
670
                hSprCnt[n] <= 0;
671
        else if (hSprNextPixel[n])
672
                hSprCnt[n] <= hSprCnt[n] + 1;
673
 
674
 
675
// clock sprite horizontal display enable
676
always @(posedge vclk)
677
for (n = 0; n < pnSpr; n = n + 1) begin
678
        if (hSprReset[n])
679
                hSprDe[n] <= 1;
680
        else if (hSprNextPixel[n]) begin
681
                if (hSprCnt[n] == sprWidth[n])
682
                        hSprDe[n] <= 0;
683
        end
684
end
685
 
686
 
687
// clock the sprite row (Y) counter
688
always @(posedge vclk)
689
for (n = 0; n < pnSpr; n = n + 1)
690
        if (hSprReset[n]) begin
691
                if (vSprReset[n])
692
                        vSprCnt[n] <= 0;
693
                else if (vSprNextPixel[n])
694
                        vSprCnt[n] <= vSprCnt[n] + 1;
695
        end
696
 
697
 
698
// clock sprite vertical display enable
699
always @(posedge vclk)
700
for (n = 0; n < pnSpr; n = n + 1) begin
701
        if (hSprReset[n]) begin
702
                if (vSprReset[n])
703
                        vSprDe[n] <= 1;
704
                else if (vSprNextPixel[n]) begin
705
                        if (vSprCnt[n] == sprHeight[n])
706
                                vSprDe[n] <= 0;
707
                end
708
        end
709
end
710
 
711
 
712
//-------------------------------------------------------------
713
// Output stage
714
//-------------------------------------------------------------
715
 
716
// function used for color blending
717
// given an alpha and a color component, determine the resulting color
718
// this blends towards black or white
719
// alpha is eight bits ranging between 0 and 1.999...
720
// 1 bit whole, 7 bits fraction
721
function [7:0] fnBlend;
722
input [7:0] alpha;
723
input [7:0] colorbits;
724
 
725
begin
726
        fnBlend = (({8'b0,colorbits} * alpha) >> 7);
727
end
728
endfunction
729
 
730
 
731
// pipeline delays for display enable
732
reg [14:0] sprDe1;
733
reg [14:0] sproact;
734
always @(posedge vclk)
735
for (n = 0; n < pnSpr; n = n + 1) begin
736
        sprDe1[n] <= sprDe[n];
737
end
738
 
739
 
740
// Detect which sprite outputs are active
741
// The sprite output is active if the current display pixel
742
// address is within the sprite's area, the sprite is enabled,
743
// and it's not a transparent pixel that's being displayed.
744
always @(n, sprEn, sprDe1)
745
for (n = 0; n < pnSpr; n = n + 1)
746
        sproact[n] <= sprEn[n] && sprDe1[n] && sprTc[n]!=sprOut[n];
747
 
748
// register sprite activity flag
749
// The image combiner uses this flag to know what to do with
750
// the sprite output.
751
always @(posedge vclk)
752
outact = |sproact;
753
 
754
// Display data comes from the active sprite with the
755
// highest display priority.
756
// Make sure that alpha blending is turned off when
757
// no sprite is active.
758
always @(posedge vclk)
759
begin
760
        out = 16'h0080; // alpha blend max (and off)
761
        for (n = pnSprm; n >= 0; n = n - 1)
762
                if (sproact[n]) out = sprOut[n];
763
end
764
 
765
 
766
// combine the text / graphics color output with sprite color output
767
// blend color output
768
wire [23:0] blendedColor = {
769
        fnBlend(out[7:0],rgbIn[23:16]),          // R
770
        fnBlend(out[7:0],rgbIn[15: 8]),          // G
771
        fnBlend(out[7:0],rgbIn[ 7: 0])};  // B
772
 
773
 
774
// display color priority bit [24] 1=display is over sprite
775
always @(posedge vclk)
776
if (blank)
777
        rgbOut <= 0;
778
else begin
779
        if (rgbIn[24] && rgbIn[23:0] != bgTc)    // color is in front of sprite
780
                rgbOut <= rgbIn[23:0];
781
        else if (outact) begin
782
                if (!out[15]) begin                     // a sprite is displayed without alpha blending
783
                        if (pColorBits==8)
784
                                rgbOut <= {out[7:5],5'b0,out[4:2],5'b0,out[1:0],6'b0};
785
                        else
786
                                rgbOut <= {out[14:10],3'b0,out[9:5],3'b0,out[4:0],3'b0};
787
                end
788
                else
789
                        rgbOut <= blendedColor;
790
        end else
791
                rgbOut <= rgbIn[23:0];
792
end
793
 
794
 
795
//--------------------------------------------------------------------
796
// Collision logic
797
//--------------------------------------------------------------------
798
 
799
// Detect when a sprite-sprite collision has occurred. The criteria
800
// for this is that a pixel from the sprite is being displayed, while
801
// there is a pixel from another sprite that could be displayed at the
802
// same time.
803
 
804
//--------------------------------------------------------------------
805
// Note this case has to be modified for the number of sprites
806
//--------------------------------------------------------------------
807
generate
808
begin : gSprsColliding
809
always @(pnSpr or sproact)
810
if (pnSpr==1)
811
        sprCollision = 0;
812
else if (pnSpr==2)
813
        case (sproact)
814
        2'b00,
815
        2'b01,
816
        2'b10:  sprCollision = 0;
817
        2'b11:  sprCollision = 1;
818
        endcase
819
else if (pnSpr==4)
820
        case (sproact)
821
        4'b0000,
822
        4'b0001,
823
        4'b0010,
824
        4'b0100,
825
        4'b1000:        sprCollision = 0;
826
        default:        sprCollision = 1;
827
        endcase
828
else if (pnSpr==6)
829
        case (sproact)
830
        6'b000000,
831
        6'b000001,
832
        6'b000010,
833
        6'b000100,
834
        6'b001000,
835
        6'b010000,
836
        8'b100000:      sprCollision = 0;
837
        default:        sprCollision = 1;
838
        endcase
839
else if (pnSpr==8)
840
        case (sproact)
841
        8'b00000000,
842
        8'b00000001,
843
        8'b00000010,
844
        8'b00000100,
845
        8'b00001000,
846
        8'b00010000,
847
        8'b00100000,
848
        8'b01000000,
849
        8'b10000000:    sprCollision = 0;
850
        default:                sprCollision = 1;
851
        endcase
852
else if (pnSpr==14)
853
        case (sproact)
854
        14'b00000000000000,
855
        14'b00000000000001,
856
        14'b00000000000010,
857
        14'b00000000000100,
858
        14'b00000000001000,
859
        14'b00000000010000,
860
        14'b00000000100000,
861
        14'b00000001000000,
862
        14'b00000010000000,
863
        14'b00000100000000,
864
        14'b00001000000000,
865
        14'b00010000000000,
866
        14'b00100000000000,
867
        14'b01000000000000,
868
        14'b10000000000000:     sprCollision = 0;
869
        default:                        sprCollision = 1;
870
        endcase
871
end
872
endgenerate
873
 
874
// Detect when a sprite-background collision has occurred
875
assign bkCollision = (rgbIn[24] && rgbIn[23:0] != bgTc) ? 0 :
876
                outact && rgbIn[23:0] != bkColor;
877
 
878
// Load the sprite collision register. This register continually
879
// accumulates collision bits until reset by reading the register.
880
// Set the collision IRQ on the first collision and don't set it
881
// again until after the collision register has been read.
882
always @(posedge vclk)
883
if (rst_i) begin
884
        sprSprIRQPending1 <= 0;
885
        sprSprCollision1 <= 0;
886
        sprSprIRQ1 <= 0;
887
end
888
else if (sprCollision) begin
889
        // isFirstCollision
890
        if ((sprSprCollision1==0)||(cs_regs && s_sel_i[0] && s_adr_i[7:1]==7'd122)) begin
891
                sprSprIRQPending1 <= 1;
892
                sprSprIRQ1 <= sprSprIe;
893
                sprSprCollision1 <= sproact;
894
        end
895
        else
896
                sprSprCollision1 <= sprSprCollision1|sproact;
897
end
898
else if (cs_regs && s_sel_i[0] && s_adr_i[7:1]==7'd122) begin
899
        sprSprCollision1 <= 0;
900
        sprSprIRQPending1 <= 0;
901
        sprSprIRQ1 <= 0;
902
end
903
 
904
 
905
// Load the sprite background collision register. This register
906
// continually accumulates collision bits until reset by reading
907
// the register.
908
// Set the collision IRQ on the first collision and don't set it
909
// again until after the collision register has been read.
910
// Note the background collision indicator is externally supplied,
911
// it will come from the color processing logic.
912
always @(posedge vclk)
913
if (rst_i) begin
914
        sprBkIRQPending1 <= 0;
915
        sprBkCollision1 <= 0;
916
        sprBkIRQ1 <= 0;
917
end
918
else if (bkCollision) begin
919
        // Is the register being cleared at the same time
920
        // a collision occurss ?
921
        // isFirstCollision
922
        if ((sprBkCollision1==0) || (cs_regs && s_sel_i[0] && s_adr_i[7:1]==7'd123)) begin
923
                sprBkIRQ1 <= sprBkIe;
924
                sprBkCollision1 <= sproact;
925
                sprBkIRQPending1 <= 1;
926
        end
927
        else
928
                sprBkCollision1 <= sprBkCollision1|sproact;
929
end
930
else if (cs_regs && s_sel_i[0] && s_adr_i[7:1]==7'd123) begin
931
        sprBkCollision1 <= 0;
932
        sprBkIRQPending1 <= 0;
933
        sprBkIRQ1 <= 0;
934
end
935
 
936
endmodule
937
 
938
// Sprite RAM for eight bit color depth
939
module rtfSpriteRam8 (
940
        clka, adra, doa, cea,
941
        clkb, adrb, dib, dob, ceb, web, rstb
942
);
943
input clka;
944
input [10:0] adra;
945
output [7:0] doa;
946
reg [7:0] doa;
947
input cea;
948
input clkb;
949
input [8:0] adrb;
950
input [31:0] dib;
951
output [31:0] dob;
952
input ceb;
953
input web;
954
input rstb;
955
 
956
reg [31:0] mem [0:511];
957
reg [10:0] radra;
958
reg [8:0] radrb;
959
 
960
always @(posedge clka)  if (cea) radra <= adra;
961
always @(posedge clkb)  if (ceb) radrb <= adrb;
962
always @(radra)
963
        case(radra[1:0])
964
        2'b00:  doa <= mem[radra[10:2]][ 7: 0];
965
        2'b01:  doa <= mem[radra[10:2]][15: 8];
966
        2'b10:  doa <= mem[radra[10:2]][23:16];
967
        2'b11:  doa <= mem[radra[10:2]][31:24];
968
        endcase
969
assign dob = rstb ? 32'd0 : mem [radrb];
970
always @(posedge clkb)
971
        if (ceb & web) mem[adrb] <= dib;
972
 
973
endmodule
974
 
975
// Sprite RAM for sixteen bit color depth
976
module rtfSpriteRam16 (
977
        clka, adra, doa, cea,
978
        clkb, adrb, dib, dob, ceb, web, rstb
979
);
980
input clka;
981
input [9:0] adra;
982
output [15:0] doa;
983
reg [15:0] doa;
984
input cea;
985
input clkb;
986
input [8:0] adrb;
987
input [31:0] dib;
988
output [31:0] dob;
989
input ceb;
990
input web;
991
input rstb;
992
 
993
reg [31:0] mem [0:511];
994
reg [9:0] radra;
995
reg [8:0] radrb;
996
 
997
always @(posedge clka)  if (cea) radra <= adra;
998
always @(posedge clkb)  if (ceb) radrb <= adrb;
999
always @(radra)
1000
        case(radra[1])
1001
        1'b0:   doa <= mem[radra[9:1]][15: 0];
1002
        1'b1:   doa <= mem[radra[9:1]][31:16];
1003
        endcase
1004
assign dob = rstb ? 32'd0 : mem [radrb];
1005
always @(posedge clkb)
1006
        if (ceb & web) mem[adrb] <= dib;
1007
 
1008
endmodule
1009
 

powered by: WebSVN 2.1.0

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