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

Subversion Repositories rtf68ksys

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 robfinch
/* ===============================================================
2
        (C) 2005  Robert Finch
3
        All rights reserved.
4
        robfinch@opencores.org
5
 
6
        rtfSpriteController.v
7
                sprite / hardware cursor controller
8
 
9
        This source code is free for use and modification for
10
        non-commercial or evaluation purposes, provided this
11
        copyright statement and disclaimer remains present in
12
        the file.
13
 
14
        If you do modify the code, please state the origin and
15
        note that you have modified the code.
16
 
17
        NO WARRANTY.
18
        THIS Work, IS PROVIDED "AS IS" WITH NO WARRANTIES OF
19
        ANY KIND, WHETHER EXPRESS OR IMPLIED. The user must assume
20
        the entire risk of using the Work.
21
 
22
        IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23
        ANY INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES
24
        WHATSOEVER RELATING TO THE USE OF THIS WORK, OR YOUR
25
        RELATIONSHIP WITH THE AUTHOR.
26
 
27
        IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU
28
        TO USE THE WORK IN APPLICATIONS OR SYSTEMS WHERE THE
29
        WORK'S FAILURE TO PERFORM CAN REASONABLY BE EXPECTED
30
        TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN LOSS
31
        OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK,
32
        AND YOU AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS
33
        FROM ANY CLAIMS OR LOSSES RELATING TO SUCH UNAUTHORIZED
34
        USE.
35
 
36
 
37
        Sprite Controller
38
 
39
        FEATURES
40
        - parameterized number of sprites
41
        - eight sprite image cache buffers
42
                - each image cache is capable of holding multiple
43
                  sprite images
44
                - cache may be accessed like a memory by the processor
45
                - an embedded DMA controller may also be used for
46
                        sprite reload
47
        - programmable image offset within cache
48
        - programmable sprite width,height, and pixel size
49
                - sprite width and height may vary from 1 to 64 as long
50
                  as the product doesn't exceed 1024.
51
            - pixels may be programmed to be 1,2,3 or 4 video clocks
52
              both height and width are programmable
53
        - programmable sprite position
54
        - 16 bits for color
55
                eg 32k color + 1 bit alpha blending indicator (1,5,5,5)
56
        - fixed display and DMA priority
57
            sprite 0 highest, sprite 7 lowest
58
 
59
                This core requires an external timing generator to
60
        provide horizontal and vertical sync signals, but
61
        otherwise can be used as a display controller on it's
62
        own. However, normally this core would be embedded
63
        within another core such as a VGA controller. Sprite
64
        positions are referenced to the rising edge of the
65
        vertical and horizontal sync pulses.
66
                The core includes an embedded dual port RAM to hold the
67
        sprite images. The image RAM is updated using a built in DMA
68
        controller. The DMA controller uses 16 bit accesses to fill
69
        the sprite buffers, as the sprite buffers are only 16 bits
70
        wide. The circuit features an automatic bus transaction
71
        timeout; if the system bus hasn't responded within 20 clock
72
        cycles, the DMA controller moves onto the next address.
73
                The controller uses a ram underlay to cache the values
74
        of the registers. This is a lot cheaper resource wise than
75
        using a 32 to 1 multiplexor (well at least for an FPGA).
76
 
77
        All registers are 16 bits wide
78
 
79
        These registers repeat in incrementing block of four registers
80
        and pertain to each sprite
81
        0:      HPOS    - position register
82
                        [15: 0] horizontal position (hctr value)
83
        1:      VPOS    [15:0]  vertical position (vctr value)
84
 
85
        2:      SZ      - size register
86
                        bits
87
                        [ 5: 0] width of sprite in pixels - 1
88
                        [ 7: 6] size of horizontal pixels - 1 in clock cycles
89
                        [13: 8] height of sprite in pixels -1
90
                        [15:14] size of vertical pixels in scan-lines - 1
91
                                * the product of width * height cannot exceed 1024 !
92
                                if it does, the display will begin repeating
93
 
94
        3: OFFS [9:0] image offset
95
                        offset of the sprite image within the sprite image cache
96
                        typically zero
97
 
98
        4: ADRH [15:0] sprite image address bits [42:27]
99
        5: ADRL [15:0] sprite image address bits [26:11]
100
                        These registers contain the location of the sprite image
101
                        in system memory.
102
                        The low order 11 bits are fixed at zero. The DMA
103
                        controller will assign the low order 11 bits
104
                        during DMA.
105
 
106
        6: TC   [15:0]  transparent color
107
                        This register identifies which color of the sprite
108
                        is transparent
109
 
110
 
111
        8-63:   registers for seven other sprites
112
 
113
        Global status and control
114
        116: BTC        [23:0] background transparent color
115
        117: BTC
116
        118: BC [23:0] background color
117
        119: BC
118
        120: EN [15:0] sprite enable register
119
        121: IE [15:0] sprite interrupt enable / status
120
        122: SCOL       [15:0] sprite-sprite collision register
121
        123: BCOL       [15:0] sprite-background collision register
122
        124: DT         [ 7:0] sprite DMA trigger
123
 
124
 
125
        1635 LUTs/ 1112 slices/ 82MHz - Spartan3e-4
126
        3 8x8 multipliers (for alpha blending)
127
        8 block rams
128
=============================================================== */
129
 
130
`define VENDOR_XILINX   // block ram vendor (only one defined for now)
131
 
132
module rtfSpriteController(
133
// Bus Slave interface
134
//------------------------------
135
// Slave signals
136
input rst_i,                    // reset
137
input clk_i,                    // clock
138
input         s_cyc_i,  // cycle valid
139
input         s_stb_i,  // data transfer
140
output        s_ack_o,  // transfer acknowledge
141
input         s_we_i,   // write
142
input  [ 1:0] s_sel_i,   // byte select
143
input  [43:0] s_adr_i,   // address
144
input  [15:0] s_dat_i,   // data input
145
output reg [15:0] s_dat_o,       // data output
146
output vol_o,                   // volatile register
147
//------------------------------
148
// Bus Master Signals
149
output reg    m_soc_o,  // start of cycle
150
output        m_cyc_o,  // cycle is valid
151
output            m_stb_o,      // strobe output
152
input         m_ack_i,  // input data is ready
153
output        m_we_o,           // write (always inactive)
154
output [ 1:0] m_sel_o,   // byte select
155
output [43:0] m_adr_o,   // DMA address
156
input  [15:0] m_dat_i,   // data input
157
output [15:0] m_dat_o,   // data output (always zero)
158
//--------------------------
159
input vclk,                                     // video dot clock
160
input hSync,                            // horizontal sync pulse
161
input vSync,                            // vertical sync pulse
162
input blank,                            // blanking signal
163
input [24:0] rgbIn,                      // input pixel stream
164
output reg [23:0] rgbOut,        // output pixel stream
165
output irq                                      // interrupt request
166
);
167
 
168
//--------------------------------------------------------------------
169
// Core Parameters
170
//--------------------------------------------------------------------
171
parameter pnSpr = 8;            // number of sprites
172
parameter phBits = 11;          // number of bits in horizontal timing counter
173
parameter pvBits = 11;          // number of bits in vertical timing counter
174
parameter pColorBits = 16;      // number of bits used for color data
175
localparam pnSprm = pnSpr-1;
176
 
177
 
178
//--------------------------------------------------------------------
179
// Variable Declarations
180
//--------------------------------------------------------------------
181
 
182
wire [2:0] sprN = s_adr_i[6:4];
183
 
184
reg [phBits-1:0] hctr;           // horizontal reference counter (counts dots since hSync)
185
reg [pvBits-1:0] vctr;           // vertical reference counter (counts scanlines since vSync)
186
reg sprSprIRQ;
187
reg sprBkIRQ;
188
 
189
reg [15:0] out;                  // sprite output
190
reg outact;                             // sprite output is active
191
wire bkCollision;               // sprite-background collision
192
reg [23:0] bgTc;         // background transparent color
193
reg [23:0] bkColor;              // background color
194
 
195
 
196
reg [7:0] sprWe; // block ram write enable for image cache update
197
reg [7:0] sprRe; // block ram read enable for image cache update
198
 
199
// Global control registers
200
reg [7:0] sprEn;   // enable sprite
201
reg [7:0] sprCollision;      // sprite-sprite collision
202
reg sprSprIe;                   // sprite-sprite interrupt enable
203
reg sprBkIe;            // sprite-background interrupt enable
204
reg sprSprIRQPending;   // sprite-sprite collision interrupt pending
205
reg sprBkIRQPending;    // sprite-background collision interrupt pending
206
reg sprSprIRQPending1;  // sprite-sprite collision interrupt pending
207
reg sprBkIRQPending1;   // sprite-background collision interrupt pending
208
reg sprSprIRQ1;                 // vclk domain regs
209
reg sprBkIRQ1;
210
 
211
// Sprite control registers
212
reg [7:0] sprSprCollision;
213
reg [7:0] sprSprCollision1;
214
reg [7:0] sprBkCollision;
215
reg [7:0] sprBkCollision1;
216
reg [pColorBits-1:0] sprTc [pnSprm:0];            // sprite transparent color code
217
// How big the pixels are:
218
// 1,2,3,or 4 video clocks
219
reg [1:0] hSprRes [pnSprm:0];             // sprite horizontal resolution
220
reg [1:0] vSprRes [pnSprm:0];             // sprite vertical resolution
221
reg [5:0] sprWidth [pnSprm:0];            // number of pixels in X direction
222
reg [5:0] sprHeight [pnSprm:0];           // number of vertical pixels
223
 
224
// display and timing signals
225
reg [7:0] hSprReset;   // horizontal reset
226
reg [7:0] vSprReset;   // vertical reset
227
reg [7:0] hSprDe;                // sprite horizontal display enable
228
reg [7:0] vSprDe;                // sprite vertical display enable
229
reg [7:0] sprDe;                 // display enable
230
reg [phBits-1:0] hSprPos [7:0];   // sprite horizontal position
231
reg [pvBits-1:0] vSprPos [7:0];   // sprite vertical position
232
reg [5:0] hSprCnt [7:0];  // sprite horizontal display counter
233
reg [5:0] vSprCnt [7:0];  // vertical display counter
234
reg [9:0] sprImageOffs [7:0];     // offset within sprite memory
235
reg [9:0] sprAddr [7:0];  // index into sprite memory
236
reg [9:0] sprAddrB [7:0]; // backup address cache for rescan
237
wire [pColorBits-1:0] sprOut [7:0];       // sprite image data output
238
 
239
// DMA access
240
reg [26:11] sprSysAddrL [7:0];   // system memory address of sprite image (low bits)
241
reg [42:27] sprSysAddrH [7:0];   // system memory address of sprite image (high bits)
242
reg [2:0] dmaOwner;                      // which sprite has the DMA channel
243
reg [7:0] sprDt;         // DMA trigger register
244
wire dmaDone;                           // DMA is finished
245
reg [10:0] dmaCount;             // this counter forms the low order 11 bits of the system address for DMA
246
reg [10:0] dmaCountNext; // next value dmaCount will be loaded with
247
reg [10:0] updAdr;                       // this counter is used to index the sprite image cache
248
reg [10:0] updAdrNext;
249
reg dmaStart;                           // this flag pulses high for a single cycle at the start of a DMA
250
reg dmaActive;                          // this flag indicates that a block DMA transfer is active
251
 
252
integer n;
253
 
254
//--------------------------------------------------------------------
255
// DMA control / bus interfacing
256
//--------------------------------------------------------------------
257
wire cs_ram = s_cyc_i && s_stb_i && (s_adr_i[43:16]==28'hFFF_FFD8);
258
wire cs_regs = s_cyc_i && s_stb_i && (s_adr_i[43:8]==36'hFFF_FFDA_D0);
259
 
260
reg sprRamRdy;
261
always @(posedge clk_i)
262
        sprRamRdy = cs_ram;
263
 
264
 
265
assign m_stb_o = m_cyc_o;
266
assign s_ack_o = cs_regs ? 1'b1 : cs_ram ? (s_we_i ? 1 : sprRamRdy) : 0;
267
assign vol_o = cs_regs & s_adr_i[7:2]>6'd59;
268
assign irq = sprSprIRQ|sprBkIRQ;
269
 
270
//--------------------------------------------------------------------
271
// DMA control / bus interfacing
272
//--------------------------------------------------------------------
273
 
274
wire btout;
275
wire sbi_rdy1 = m_ack_i|btout;
276
busTimeoutCtr #(20) br0(
277
        .rst(rst_i),
278
        .crst(1'b0),
279
        .clk(clk_i),
280
        .ce(1'b1),
281
        .req(m_soc_o),
282
        .rdy(m_ack_i),
283
        .timeout(btout)
284
);
285
 
286
assign m_we_o   = 1'b0;
287
assign m_sel_o  = 2'b11;
288
assign m_adr_o  = {1'b0,sprSysAddrH[dmaOwner],sprSysAddrL[dmaOwner],dmaCount[9:0],1'b0};
289
assign m_dat_o = 32'd0;
290
 
291
// DMA address generator goes based on the requests that have been acknowledged
292
assign dmaDone = dmaCountNext[10] & sbi_rdy1;
293
 
294
always @(dmaCount)
295
dmaCountNext = dmaCount + 1;
296
 
297
always @(posedge clk_i)
298
if (rst_i)
299
        dmaCount = 0;
300
else begin
301
        if (dmaStart)
302
                dmaCount = 0;
303
        else if (sbi_rdy1 && !dmaDone)
304
                dmaCount = dmaCountNext;
305
end
306
 
307
// sprite cache address generator goes based on the responses that are ready
308
wire updDone = updAdrNext[10] & sbi_rdy1;
309
 
310
always @(updAdr)
311
        updAdrNext = updAdr + 1;
312
 
313
always @(posedge clk_i)
314
if (rst_i)
315
        updAdr = 0;
316
else begin
317
        if (dmaStart)
318
                updAdr = 0;
319
        else if (sbi_rdy1 && !updDone)
320
                updAdr = updAdrNext;
321
end
322
 
323
// Arbitrate access to DMA channel - priority ordered
324
always @(posedge clk_i)
325
if (rst_i) begin
326
        dmaActive <= 1'b0;
327
        dmaOwner <= 3'd0;
328
        dmaStart <= 1'b0;
329
        m_soc_o  <= 1'b0;
330
end
331
else begin
332
        dmaStart <= 1'b0;
333
        m_soc_o  <= 1'b0;
334
        if (!dmaActive || updDone) begin
335
                dmaStart  <= |sprDt;
336
                dmaActive <= |sprDt;
337
                m_soc_o   <= |sprDt;
338
                dmaOwner  <= 0;
339
                for (n = 7; n >= 0; n = n - 1)
340
                        if (sprDt[n]) dmaOwner <= n;
341
        end
342
        if (sbi_rdy1 && !updDone)
343
                m_soc_o <= 1'b1;
344
end
345
 
346
assign m_cyc_o = dmaActive & !dmaDone;
347
 
348
// generate a write enable strobe for the sprite image memory
349
always @(dmaOwner, dmaActive, s_adr_i, cs_ram, s_we_i)
350
for (n = 0; n < 8; n = n + 1)
351
        sprWe[n] = (dmaOwner==n && dmaActive)||(cs_ram & s_we_i & s_adr_i[13:11]==n);
352
 
353
always @(cs_ram, s_adr_i)
354
for (n = 0; n < 8; n = n + 1)
355
        sprRe[n] = cs_ram & s_adr_i[13:11]==n;
356
 
357
wire [15:0] sr_dout [7:0];
358
wire [15:0] 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];
359
 
360
// register/sprite memory output mux
361
always @*
362
if (cs_ram)
363
        s_dat_o <= sr_dout_all;
364
else if (cs_regs)
365
        case (s_adr_i[7:1])             // synopsys full_case parallel_case
366
        7'd120: s_dat_o <= {8'b0,sprEn};
367
        7'd121: s_dat_o <= {sprBkIRQPending|sprSprIRQPending,5'b0,sprBkIRQPending,sprSprIRQPending,6'b0,sprBkIe,sprSprIe};
368
        7'd122: s_dat_o <= {8'b0,sprSprCollision};
369
        7'd123: s_dat_o <= sprBkCollision;
370
        7'd124: s_dat_o <= sprDt;
371
        default:        s_dat_o <= 0;
372
        endcase
373
else
374
        s_dat_o <= 32'd0;
375
 
376
 
377
// vclk -> clk_i
378
always @(posedge clk_i)
379
begin
380
        sprSprIRQ <= sprSprIRQ1;
381
        sprBkIRQ <= sprBkIRQ1;
382
        sprSprIRQPending <= sprSprIRQPending1;
383
        sprBkIRQPending <= sprBkIRQPending1;
384
        sprSprCollision <= sprSprCollision1;
385
        sprBkCollision <= sprBkCollision1;
386
end
387
 
388
 
389
// register updates
390
// on the clk_i domain
391
always @(posedge clk_i)
392
if (rst_i) begin
393
        sprEn <= 8'hFF;
394
        sprDt <= 0;
395
    for (n = 0; n < pnSpr; n = n + 1) begin
396
                sprSysAddrL[n] <= 5'b0100_0 + n;        //xxxx_4000
397
                sprSysAddrH[n] <= 16'h0000;                     //0000_xxxx
398
        end
399
        sprSprIe <= 0;
400
        sprBkIe  <= 0;
401
 
402
    // Set reasonable starting positions on the screen
403
    // so that the sprites might be visible for testing
404
    for (n = 0; n < pnSpr; n = n + 1) begin
405
        hSprPos[n] <= 440 + n * 40;
406
        vSprPos[n] <= 200;
407
        sprTc[n] <= 16'h6739;
408
                sprWidth[n] <= 31;  // 32x32 sprites
409
                sprHeight[n] <= 31;
410
                hSprRes[n] <= 0; // our standard display
411
                vSprRes[n] <= 1;
412
                sprImageOffs[n] <= 0;
413
        end
414
    hSprPos[0] <= 290;
415
    vSprPos[0] <= 72;
416
 
417
    bgTc <= 24'h00_00_00;
418
    bkColor <= 24'hFF_FF_60;
419
end
420
else begin
421
        // clear DMA trigger bit once DMA is recognized
422
        if (dmaStart)
423
                sprDt[dmaOwner] <= 1'b0;
424
 
425
        if (cs_regs & s_we_i) begin
426
 
427
                casex (s_adr_i[7:1])
428
 
429
                7'b0xxx000:
430
                         begin
431
                        if (s_sel_i[0]) hSprPos[sprN][ 7:0] <= s_dat_i[ 7:0];
432
                        if (s_sel_i[1]) hSprPos[sprN][10:8] <= s_dat_i[10:8];
433
                end
434
                7'b0xxx001:
435
                         begin
436
                        if (s_sel_i[0]) vSprPos[sprN][ 7:0] <= s_dat_i[ 7:0];
437
                        if (s_sel_i[1]) vSprPos[sprN][10:8] <= s_dat_i[10:8];
438
                end
439
        7'b0xxx010:
440
                        begin
441
                        if (s_sel_i[0]) begin
442
                                        sprWidth[sprN] <= s_dat_i[5:0];
443
                        hSprRes[sprN] <= s_dat_i[7:6];
444
                    end
445
                        if (s_sel_i[1]) begin
446
                                        sprHeight[sprN] <= s_dat_i[13:8];
447
                        vSprRes[sprN] <= s_dat_i[15:14];
448
                    end
449
                        end
450
        7'b0xxx011:
451
                        begin
452
                    if (s_sel_i[0]) sprImageOffs[sprN][ 7:0] <= s_dat_i[ 7:0];
453
                    if (s_sel_i[1]) sprImageOffs[sprN][ 9:8] <= s_dat_i[ 9:8];
454
                        end
455
                7'b0xxx100:
456
                        begin   // DMA address set on clk_i domain
457
                                if (s_sel_i[0]) sprSysAddrH[sprN][34:27] <= s_dat_i[ 7:0];
458
                                if (s_sel_i[1]) sprSysAddrH[sprN][42:35] <= s_dat_i[15:8];
459
                        end
460
                7'b0xxx101:
461
                        begin   // DMA address set on clk_i domain
462
                                if (s_sel_i[0]) sprSysAddrL[sprN][18:11] <= s_dat_i[ 7:0];
463
                                if (s_sel_i[1]) sprSysAddrL[sprN][26:19] <= s_dat_i[15:0];
464
                        end
465
                7'b0xxx110:
466
                        begin
467
                        if (s_sel_i[0]) sprTc[sprN][ 7:0] <= s_dat_i[ 7:0];
468
                        if (s_sel_i[1]) sprTc[sprN][15:8] <= s_dat_i[15:8];
469
                        end
470
 
471
                7'd116:
472
                        begin
473
                                if (s_sel_i[0]) bgTc[7:0] <= s_dat_i[7:0];
474
                                if (s_sel_i[1]) bgTc[15:8] <= s_dat_i[15:8];
475
                        end
476
                7'd117:
477
                        begin
478
                                if (s_sel_i[0]) bgTc[23:16] <= s_dat_i[7:0];
479
                        end
480
                7'd118:
481
                        begin
482
                                if (s_sel_i[0]) bkColor[23:16] <= s_dat_i[7:0];
483
                        end
484
                7'd119:
485
                        begin
486
                                if (s_sel_i[0]) bkColor[7:0] <= s_dat_i[7:0];
487
                                if (s_sel_i[1]) bkColor[15:8] <= s_dat_i[15:8];
488
                        end
489
                7'd120:
490
                        begin
491
                                if (s_sel_i[0]) sprEn <= s_dat_i;
492
                        end
493
                7'd121:
494
                        begin
495
                                if (s_sel_i[0]) begin
496
                                        sprSprIe <= s_dat_i[0];
497
                                        sprBkIe <= s_dat_i[1];
498
                                end
499
                        end
500
                // update DMA trigger
501
                // s_dat_i[7:0] indicates which triggers to set  (1=set,0=ignore)
502
                // s_dat_i[7:0] indicates which triggers to clear (1=clear,0=ignore)
503
                7'd124:
504
                        begin
505
                                if (s_sel_i[0])
506
                                        sprDt <= sprDt | s_dat_i[7:0];
507
                        end
508
                7'd125:
509
                        begin
510
                                if (s_sel_i[0])
511
                                        sprDt <= sprDt & ~s_dat_i[7:0];
512
                        end
513
                default:        ;
514
                endcase
515
 
516
        end
517
end
518
 
519
//-------------------------------------------------------------
520
// Sprite Image Cache RAM
521
// This RAM is dual ported with an SoC side and a display
522
// controller side.
523
//-------------------------------------------------------------
524
wire [10:1] sr_adr = m_cyc_o ? m_adr_o[10:1] : s_adr_i[10:1];
525
wire [15:0] sr_din = m_cyc_o ? m_dat_i[15:0] : s_dat_i[15:0];
526
wire sr_ce = m_cyc_o ? sbi_rdy1 : cs_ram;
527
 
528
// Note: the sprite output can't be zeroed out using the rst input!!!
529
// We need to know what the output is to determine if it's the 
530
// transparent color.
531
genvar g;
532
generate
533
        for (g = 0; g < 8; g = g + 1)
534
        begin : genSpriteRam
535
            rtfSpriteRam #(.pDw(pColorBits)) sprRam0
536
            (
537
                .clka(vclk),
538
                .adra(sprAddr[g]),
539
                .dia(16'hFFFF),
540
                .doa(sprOut[g]),
541
                .cea(1'b1),
542
                .wea(1'b0),
543
                .rsta(1'b0),
544
 
545
                        .clkb(clk_i),
546
                        .adrb(sr_adr),
547
                        .dib(sr_din),
548
                        .dob(sr_dout[g]),
549
                        .ceb(sr_ce),
550
                        .web(sprWe[g]),
551
                        .rstb(!sprRe[g])
552
                );
553
        end
554
endgenerate
555
 
556
 
557
 
558
//-------------------------------------------------------------
559
// Timing counters and addressing
560
// Sprites are like miniature bitmapped displays, they need
561
// all the same timing controls.
562
//-------------------------------------------------------------
563
 
564
// Create a timing reference using horizontal and vertical
565
// soc
566
wire hSyncEdge, vSyncEdge;
567
edge_det ed0(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(hSync), .pe(hSyncEdge), .ne(), .ee() );
568
edge_det ed1(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(vSync), .pe(vSyncEdge), .ne(), .ee() );
569
 
570
always @(posedge vclk)
571
if (rst_i)              hctr <= 0;
572
else if (hSyncEdge) hctr <= 0;
573
else                    hctr <= hctr + 1;
574
 
575
always @(posedge vclk)
576
if (rst_i)              vctr <= 0;
577
else if (vSyncEdge) vctr <= 0;
578
else if (hSyncEdge) vctr <= vctr + 1;
579
 
580
// track sprite horizontal reset
581
always @(posedge vclk)
582
for (n = 0; n < 8; n = n + 1)
583
        hSprReset[n] <= hctr==hSprPos[n];
584
 
585
// track sprite vertical reset
586
always @(posedge vclk)
587
for (n = 0; n < 8; n = n + 1)
588
        vSprReset[n] <= vctr==vSprPos[n];
589
 
590
always @(hSprDe, vSprDe)
591
for (n = 0; n < 8; n = n + 1)
592
        sprDe[n] <= hSprDe[n] & vSprDe[n];
593
 
594
 
595
// take care of sprite size scaling
596
// video clock division
597
reg [7:0] hSprNextPixel;
598
reg [7:0] vSprNextPixel;
599
reg [1:0] hSprPt [7:0];   // horizontal pixel toggle
600
reg [1:0] vSprPt [7:0];   // vertical pixel toggle
601
always @(n)
602
for (n = 0; n < 8; n = n + 1)
603
    hSprNextPixel[n] = hSprPt[n]==hSprRes[n];
604
always @(n)
605
for (n = 0; n < 8; n = n + 1)
606
    vSprNextPixel[n] = vSprPt[n]==vSprRes[n];
607
 
608
// horizontal pixel toggle counter
609
always @(posedge vclk)
610
for (n = 0; n < 8; n = n + 1)
611
        if (hSprReset[n])
612
                hSprPt[n] <= 0;
613
    else if (hSprNextPixel[n])
614
        hSprPt[n] <= 0;
615
    else
616
        hSprPt[n] <= hSprPt[n] + 1;
617
 
618
// vertical pixel toggle counter
619
always @(posedge vclk)
620
for (n = 0; n < 8; n = n + 1)
621
    if (hSprReset[n]) begin
622
        if (vSprReset[n])
623
                vSprPt[n] <= 0;
624
        else if (vSprNextPixel[n])
625
            vSprPt[n] <= 0;
626
        else
627
            vSprPt[n] <= vSprPt[n] + 1;
628
    end
629
 
630
 
631
// clock sprite image address counters
632
always @(posedge vclk)
633
for (n = 0; n < 8; n = n + 1) begin
634
    // hReset and vReset - top left of sprite,
635
    // reset address to image offset
636
        if (hSprReset[n] & vSprReset[n]) begin
637
                sprAddr[n]  <= sprImageOffs[n];
638
                sprAddrB[n] <= sprImageOffs[n];
639
        end
640
        // hReset:
641
        //  If the next vertical pixel
642
        //      set backup address to current address
643
        //  else
644
        //      set current address to backup address
645
        //      in order to rescan the line
646
        else if (hSprReset[n]) begin
647
                if (vSprNextPixel[n])
648
                        sprAddrB[n] <= sprAddr[n];
649
                else
650
                        sprAddr[n]  <= sprAddrB[n];
651
        end
652
        // Not hReset or vReset - somewhere on the sprite scan line
653
        // just advance the address when the next pixel should be
654
        // fetched
655
        else if (sprDe[n] & hSprNextPixel[n])
656
                sprAddr[n] <= sprAddr[n] + 1;
657
end
658
 
659
 
660
// clock sprite column (X) counter
661
always @(posedge vclk)
662
for (n = 0; n < 8; n = n + 1)
663
        if (hSprReset[n])
664
                hSprCnt[n] <= 0;
665
        else if (hSprNextPixel[n])
666
                hSprCnt[n] <= hSprCnt[n] + 1;
667
 
668
 
669
// clock sprite horizontal display enable
670
always @(posedge vclk)
671
for (n = 0; n < 8; n = n + 1) begin
672
        if (hSprReset[n])
673
                hSprDe[n] <= 1;
674
        else if (hSprNextPixel[n]) begin
675
                if (hSprCnt[n] == sprWidth[n])
676
                        hSprDe[n] <= 0;
677
        end
678
end
679
 
680
 
681
// clock the sprite row (Y) counter
682
always @(posedge vclk)
683
for (n = 0; n < 8; n = n + 1)
684
        if (hSprReset[n]) begin
685
                if (vSprReset[n])
686
                        vSprCnt[n] <= 0;
687
                else if (vSprNextPixel[n])
688
                        vSprCnt[n] <= vSprCnt[n] + 1;
689
        end
690
 
691
 
692
// clock sprite vertical display enable
693
always @(posedge vclk)
694
for (n = 0; n < 8; n = n + 1) begin
695
        if (hSprReset[n]) begin
696
                if (vSprReset[n])
697
                        vSprDe[n] <= 1;
698
                else if (vSprNextPixel[n]) begin
699
                        if (vSprCnt[n] == sprHeight[n])
700
                                vSprDe[n] <= 0;
701
                end
702
        end
703
end
704
 
705
 
706
//-------------------------------------------------------------
707
// Output stage
708
//-------------------------------------------------------------
709
 
710
// function used for color blending
711
// given an alpha and a color component, determine the resulting color
712
// this blends towards black or white
713
// alpha is eight bits ranging between 0 and 1.999...
714
// 1 bit whole, 7 bits fraction
715
function [7:0] fnBlend;
716
input [7:0] alpha;
717
input [7:0] colorbits;
718
 
719
begin
720
        fnBlend = (({8'b0,colorbits} * alpha) >> 7);
721
end
722
endfunction
723
 
724
 
725
// pipeline delays for display enable
726
reg [7:0] sprDe1;
727
reg [7:0] sproact;
728
always @(posedge vclk)
729
for (n = 0; n < 8; n = n + 1) begin
730
        sprDe1[n] <= sprDe[n];
731
end
732
 
733
 
734
// Detect which sprite outputs are active
735
// The sprite output is active if the current display pixel
736
// address is within the sprite's area, the sprite is enabled,
737
// and it's not a transparent pixel that's being displayed.
738
always @(n, sprEn, sprDe1)
739
for (n = 0; n < 8; n = n + 1)
740
        sproact[n] <= sprEn[n] && sprDe1[n] && sprTc[n]!=sprOut[n];
741
 
742
// register sprite activity flag
743
// The image combiner uses this flag to know what to do with
744
// the sprite output.
745
always @(posedge vclk)
746
outact = |sproact;
747
 
748
// Display data comes from the active sprite with the
749
// highest display priority.
750
// Make sure that alpha blending is turned off when
751
// no sprite is active.
752
always @(posedge vclk)
753
begin
754
        out = 16'h0080; // alpha blend max (and off)
755
        for (n = 7; n >= 0; n = n - 1)
756
                if (sproact[n]) out = sprOut[n];
757
end
758
 
759
 
760
// combine the text / graphics color output with sprite color output
761
// blend color output
762
wire [23:0] blendedColor = {
763
        fnBlend(out[7:0],rgbIn[23:16]),          // R
764
        fnBlend(out[7:0],rgbIn[15: 8]),          // G
765
        fnBlend(out[7:0],rgbIn[ 7: 0])};  // B
766
 
767
 
768
// display color priority bit [24] 1=display is over sprite
769
always @(posedge vclk)
770
if (blank)
771
        rgbOut <= 0;
772
else begin
773
        if (rgbIn[24] && rgbIn[23:0] != bgTc)    // color is in front of sprite
774
                rgbOut <= rgbIn[23:0];
775
        else if (outact) begin
776
                if (!out[15])                           // a sprite is displayed without alpha blending
777
                        rgbOut <= {out[14:10],3'b0,out[9:5],3'b0,out[4:0],3'b0};
778
                else
779
                        rgbOut <= blendedColor;
780
        end else
781
                rgbOut <= rgbIn[23:0];
782
end
783
 
784
 
785
//--------------------------------------------------------------------
786
// Collision logic
787
//--------------------------------------------------------------------
788
 
789
// Detect when a sprite-sprite collision has occurred. The criteria
790
// for this is that a pixel from the sprite is being displayed, while
791
// there is a pixel from another sprite that could be displayed at the
792
// same time.
793
always @(sproact)
794
case (sproact)
795
8'b00000000,
796
8'b00000001,
797
8'b00000010,
798
8'b00000100,
799
8'b00001000,
800
8'b00010000,
801
8'b00100000,
802
8'b01000000,
803
8'b10000000:    sprCollision = 0;
804
default:                sprCollision = 1;
805
endcase
806
 
807
// Detect when a sprite-background collision has occurred
808
assign bkCollision = (rgbIn[24] && rgbIn[23:0] != bgTc) ? 0 :
809
                outact && rgbIn[23:0] != bkColor;
810
 
811
// Load the sprite collision register. This register continually
812
// accumulates collision bits until reset by reading the register.
813
// Set the collision IRQ on the first collision and don't set it
814
// again until after the collision register has been read.
815
always @(posedge vclk)
816
if (rst_i) begin
817
        sprSprIRQPending1 <= 0;
818
        sprSprCollision1 <= 0;
819
        sprSprIRQ1 <= 0;
820
end
821
else if (sprCollision) begin
822
        // isFirstCollision
823
        if ((sprSprCollision1==0)||(cs_regs && s_sel_i[0] && s_adr_i[7:1]==7'd122)) begin
824
                sprSprIRQPending1 <= 1;
825
                sprSprIRQ1 <= sprSprIe;
826
                sprSprCollision1 <= sproact;
827
        end
828
        else
829
                sprSprCollision1 <= sprSprCollision1|sproact;
830
end
831
else if (cs_regs && s_sel_i[0] && s_adr_i[7:1]==7'd122) begin
832
        sprSprCollision1 <= 0;
833
        sprSprIRQPending1 <= 0;
834
        sprSprIRQ1 <= 0;
835
end
836
 
837
 
838
// Load the sprite background collision register. This register
839
// continually accumulates collision bits until reset by reading
840
// the register.
841
// Set the collision IRQ on the first collision and don't set it
842
// again until after the collision register has been read.
843
// Note the background collision indicator is externally supplied,
844
// it will come from the color processing logic.
845
always @(posedge vclk)
846
if (rst_i) begin
847
        sprBkIRQPending1 <= 0;
848
        sprBkCollision1 <= 0;
849
        sprBkIRQ1 <= 0;
850
end
851
else if (bkCollision) begin
852
        // Is the register being cleared at the same time
853
        // a collision occurss ?
854
        // isFirstCollision
855
        if ((sprBkCollision1==0) || (cs_regs && s_sel_i[0] && s_adr_i[7:1]==7'd123)) begin
856
                sprBkIRQ1 <= sprBkIe;
857
                sprBkCollision1 <= sproact;
858
                sprBkIRQPending1 <= 1;
859
        end
860
        else
861
                sprBkCollision1 <= sprBkCollision1|sproact;
862
end
863
else if (cs_regs && s_sel_i[0] && s_adr_i[7:1]==7'd123) begin
864
        sprBkCollision1 <= 0;
865
        sprBkIRQPending1 <= 0;
866
        sprBkIRQ1 <= 0;
867
end
868
 
869
endmodule

powered by: WebSVN 2.1.0

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