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 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 robfinch
`timescale 1ns / 1ps
2
// ============================================================================
3
//        __
4 3 robfinch
//   \\__/ o\    (C) 2005-2015  Robert Finch, Stratford
5 2 robfinch
//    \  __ /    All rights reserved.
6 3 robfinch
//     \/_//     robfinch<remove>@finitron.ca
7 2 robfinch
//       ||
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 3 robfinch
//      - parameterized number of sprites 1,2,4,6,8,14 or 32
30 2 robfinch
//      - 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 3 robfinch
//                as the product doesn't exceed 4096.
40 2 robfinch
//          - 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 3 robfinch
//          sprite 0 highest, sprite 31 lowest
47 2 robfinch
//
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 3 robfinch
//      04:     SZ      - size register
75 2 robfinch
//                      bits
76 3 robfinch
//                      [ 7: 0] width of sprite in pixels - 1
77
//                      [15: 8] height of sprite in pixels -1
78
//                      [19:16] size of horizontal pixels - 1 in clock cycles
79
//                      [23:20] size of vertical pixels in scan-lines - 1
80 2 robfinch
//                              * the product of width * height cannot exceed 2048 !
81
//                              if it does, the display will begin repeating
82
//                              
83 3 robfinch
//      08: ADR [31:12] 20 bits sprite image address bits
84
//                      This registers contain the high order address bits of the
85
//          location of the sprite image in system memory.
86
//                      The DMA controller will assign the low order 12 bits
87
//                      during DMA.
88
//                  [11:0] image offset bits [11:0]
89 2 robfinch
//                      offset of the sprite image within the sprite image cache
90
//                      typically zero
91
//      
92 3 robfinch
//      0C: TC  [15:0]  transparent color
93 2 robfinch
//                      This register identifies which color of the sprite
94
//                      is transparent
95
//
96
//
97
//
98 3 robfinch
//      0C-1FC: registers reserved for up to thirty-one other sprites
99
//
100 2 robfinch
//      Global status and control
101 3 robfinch
//      3C0: EN [31:0] sprite enable register
102
//  3C4: IE     [31:0] sprite interrupt enable / status
103
//      3C8: SCOL       [31:0] sprite-sprite collision register
104
//      3CC: BCOL       [31:0] sprite-background collision register
105
//      3D0: DT         [31:0] sprite DMA trigger on
106
//      3D4: DT         [31:0] sprite DMA trigger off
107
//      3E8: BTC        [23:0] background transparent color
108
//      3EC: BC     [23:0] background color
109
//  3FC: ADDR   [31:0] sprite DMA address bits [63:32]
110 2 robfinch
//
111
//
112 3 robfinch
//      2200 LUTs/ 188MHz - xc7a100t (8 sprites)
113 2 robfinch
//      3 8x8 multipliers (for alpha blending)
114 3 robfinch
//      16 block rams
115 2 robfinch
//=============================================================== */
116
 
117
module rtfSpriteController(
118
// Bus Slave interface
119
//------------------------------
120
// Slave signals
121
input rst_i,                    // reset
122
input clk_i,                    // clock
123
input         s_cyc_i,  // cycle valid
124
input         s_stb_i,  // data transfer
125
output        s_ack_o,  // transfer acknowledge
126
input         s_we_i,   // write
127
input  [ 3:0] s_sel_i,   // byte select
128 3 robfinch
input  [31:0] s_adr_i,   // address
129 2 robfinch
input  [31:0] s_dat_i,   // data input
130
output reg [31:0] s_dat_o,       // data output
131
output vol_o,                   // volatile register
132
//------------------------------
133
// Bus Master Signals
134 3 robfinch
input m_clk_i,                          // clock
135
output [1:0]  m_bte_o,
136
output [2:0]  m_cti_o,
137 2 robfinch
output reg    m_cyc_o,  // cycle is valid
138 3 robfinch
output        m_stb_o,  // strobe output
139 2 robfinch
input         m_ack_i,  // input data is ready
140 3 robfinch
input         m_err_i,
141
output        m_we_o,
142
output reg [31:0] m_adr_o,       // DMA address
143 2 robfinch
input  [31:0] m_dat_i,   // data input
144 3 robfinch
output [31:0] m_dat_o,
145 2 robfinch
//--------------------------
146
input vclk,                                     // video dot clock
147
input hSync,                            // horizontal sync pulse
148
input vSync,                            // vertical sync pulse
149
input blank,                            // blanking signal
150 3 robfinch
input [1:0] rgbPriority,
151
input [23:0] rgbIn,                      // input pixel stream
152 2 robfinch
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 3 robfinch
parameter phBits = 12;          // number of bits in horizontal timing counter
163
parameter pvBits = 12;          // number of bits in vertical timing counter
164 2 robfinch
parameter pColorBits = 16;      // number of bits used for color data
165
localparam pnSprm = pnSpr-1;
166
 
167
 
168
//--------------------------------------------------------------------
169
// Variable Declarations
170
//--------------------------------------------------------------------
171
 
172 3 robfinch
wire [4:0] sprN = s_adr_i[8:4];
173 2 robfinch
 
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 3 robfinch
reg [31:0] sprEn;        // enable sprite
191 2 robfinch
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 3 robfinch
reg [31:0] sprSprCollision;
203 2 robfinch
reg [pnSprm:0] sprSprCollision1;
204 3 robfinch
reg [31:0] sprBkCollision;
205 2 robfinch
reg [pnSprm:0] sprBkCollision1;
206
reg [pColorBits-1:0] sprTc [pnSprm:0];            // sprite transparent color code
207
// How big the pixels are:
208 3 robfinch
// 1 to 16 video clocks
209
reg [3:0] hSprRes [pnSprm:0];             // sprite horizontal resolution
210
reg [3:0] vSprRes [pnSprm:0];             // sprite vertical resolution
211
reg [7:0] sprWidth [pnSprm:0];            // number of pixels in X direction
212
reg [7:0] sprHeight [pnSprm:0];           // number of vertical pixels
213 2 robfinch
 
214
// display and timing signals
215 3 robfinch
reg [31:0] hSprReset;   // horizontal reset
216
reg [31:0] vSprReset;   // vertical reset
217
reg [31:0] hSprDe;               // sprite horizontal display enable
218
reg [31:0] vSprDe;               // sprite vertical display enable
219
reg [31:0] sprDe;                        // display enable
220 2 robfinch
reg [phBits-1:0] hSprPos [pnSprm:0];      // sprite horizontal position
221
reg [pvBits-1:0] vSprPos [pnSprm:0];      // sprite vertical position
222 3 robfinch
reg [7:0] hSprCnt [pnSprm:0];     // sprite horizontal display counter
223
reg [7:0] vSprCnt [pnSprm:0];     // vertical display counter
224
reg [11:0] sprImageOffs [pnSprm:0];       // offset within sprite memory
225
reg [11:0] sprAddr [pnSprm:0];    // index into sprite memory
226
reg [11:0] sprAddrB [pnSprm:0];   // backup address cache for rescan
227 2 robfinch
wire [pColorBits-1:0] sprOut [pnSprm:0];  // sprite image data output
228
 
229
// DMA access
230 3 robfinch
reg [31:12] sprSysAddr [pnSprm:0];       // system memory address of sprite image (low bits)
231
reg [4:0] dmaOwner;                      // which sprite has the DMA channel
232
reg [31:0] sprDt;                // DMA trigger register
233 2 robfinch
reg dmaActive;                          // this flag indicates that a block DMA transfer is active
234
 
235
integer n;
236
 
237
//--------------------------------------------------------------------
238
// DMA control / bus interfacing
239
//--------------------------------------------------------------------
240 3 robfinch
wire cs_ram = s_cyc_i && s_stb_i && (s_adr_i[31:16]==16'hFFD8 || s_adr_i[31:16]==16'hFFD9);
241
wire cs_regs = s_cyc_i && s_stb_i && (s_adr_i[31:12]==20'hFFDAD);
242 2 robfinch
 
243
reg sprRdy;
244
always @(posedge clk_i)
245
        sprRdy = (cs_ram|cs_regs);
246
 
247
//assign s_ack_o = cs_regs ? 1'b1 : cs_ram ? (s_we_i ? 1 : sprRamRdy) : 0;
248
assign s_ack_o = (cs_regs|cs_ram) ? (s_we_i ? 1'b1 : sprRdy) : 1'b0;
249 3 robfinch
assign vol_o = cs_regs & s_adr_i[9:2]>=8'b11110000;
250 2 robfinch
assign irq = sprSprIRQ|sprBkIRQ;
251
 
252
//--------------------------------------------------------------------
253
// DMA control / bus interfacing
254
//--------------------------------------------------------------------
255
reg dmaStart;
256
 
257 3 robfinch
wire sbi_rdy1 = m_ack_i|m_err_i;
258 2 robfinch
 
259 3 robfinch
reg [7:0] cob;   // count of burst cycles
260 2 robfinch
 
261 3 robfinch
assign m_bte_o = 2'b00;
262
assign m_cti_o = 3'b000;
263
assign m_stb_o = 1'b1;
264
assign m_we_o = 1'b0;
265
assign m_dat_o = 32'h00000;
266
 
267
always @(posedge m_clk_i)
268 2 robfinch
if (rst_i) begin
269
        dmaStart <= 1'b0;
270
        dmaActive <= 1'b0;
271
        dmaOwner <= 4'd0;
272 3 robfinch
        wb_m_nack();
273
        cob <= 8'd0;
274 2 robfinch
end
275
else begin
276
        dmaStart <= 1'b0;
277
        m_soc_o <= 1'b0;
278
        if (!dmaActive) begin
279 3 robfinch
                cob <= 8'd0;
280 2 robfinch
                dmaStart <= |sprDt;
281
                dmaActive <= |sprDt;
282
                dmaOwner  <= 0;
283
                for (n = pnSprm; n >= 0; n = n - 1)
284
                        if (sprDt[n]) dmaOwner <= n;
285
        end
286
        else begin
287
                if (!m_cyc_o) begin
288
                        m_cyc_o <= 1'b1;
289 3 robfinch
                        m_adr_o <= {sprSysAddr[dmaOwner],cob[7:0],4'h0};
290 2 robfinch
                        m_soc_o <= 1'b1;
291 3 robfinch
                        cob <= cob + 8'd1;
292 2 robfinch
                end
293 3 robfinch
                else if (m_ack_i|m_err_i) begin
294 2 robfinch
                        m_soc_o <= 1'b1;
295 3 robfinch
                        m_adr_o[3:0] <= m_adr_o[3:0] + 8'd4;
296
                        if (m_adr_o[3:0]==4'hC) begin
297
                                wb_m_nack();
298
                                if (cob==8'd255)
299 2 robfinch
                                        dmaActive <= 1'b0;
300
                        end
301
                end
302
        end
303
end
304
 
305 3 robfinch
task wb_m_nack;
306
begin
307
        m_soc_o <= 1'b0;
308
        m_cyc_o <= 1'b0;
309
end
310
endtask
311
 
312 2 robfinch
// generate a write enable strobe for the sprite image memory
313
always @(dmaOwner, dmaActive, s_adr_i, cs_ram, s_we_i, m_ack_i)
314
for (n = 0; n < pnSpr; n = n + 1)
315 3 robfinch
        sprWe[n] = (dmaOwner==n && dmaActive && m_ack_i)||(cs_ram && s_we_i && s_adr_i[16:12]==n);
316 2 robfinch
 
317
always @(cs_ram, s_adr_i)
318
for (n = 0; n < pnSpr; n = n + 1)
319 3 robfinch
        sprRe[n] = cs_ram && s_adr_i[16:12]==n;
320 2 robfinch
 
321 3 robfinch
//--------------------------------------------------------------------
322
//--------------------------------------------------------------------
323
 
324 2 robfinch
wire [31:0] sr_dout [pnSprm:0];
325
reg [31:0] sr_dout_all;
326
 
327
generate
328
begin : gSrDout
329
always @(pnSpr)
330
if (pnSpr==1)
331
        sr_dout_all <= sr_dout[0];
332
else if (pnSpr==2)
333
        sr_dout_all <= sr_dout[0]|sr_dout[1];
334
else if (pnSpr==4)
335
        sr_dout_all <= sr_dout[0]|sr_dout[1]|sr_dout[2]|sr_dout[3];
336
else if (pnSpr==6)
337
        sr_dout_all <= sr_dout[0]|sr_dout[1]|sr_dout[2]|sr_dout[3]|sr_dout[4]|sr_dout[5];
338
else if (pnSpr==8)
339
        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];//|
340
else if (pnSpr==14)
341
        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]|
342
                                                        sr_dout[8]|sr_dout[9]|sr_dout[10]|sr_dout[11]|sr_dout[12]|sr_dout[13];
343 3 robfinch
else if (pnSpr==32)
344
        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]|
345
                                   sr_dout[8]|sr_dout[9]|sr_dout[10]|sr_dout[11]|sr_dout[12]|sr_dout[13]|sr_dout[14]|sr_dout[15]|
346
                                   sr_dout[16]|sr_dout[17]|sr_dout[18]|sr_dout[19]|sr_dout[20]|sr_dout[21]|sr_dout[22]|sr_dout[23]|
347
                                   sr_dout[24]|sr_dout[25]|sr_dout[26]|sr_dout[27]|sr_dout[28]|sr_dout[29]|sr_dout[30]|sr_dout[31]
348
                                   ;
349 2 robfinch
end
350
endgenerate
351
 
352
// register/sprite memory output mux
353
always @(posedge clk_i)
354
        if (cs_ram)
355
                s_dat_o <= sr_dout_all;
356
        else if (cs_regs)
357 3 robfinch
                case (s_adr_i[9:2])             // synopsys full_case parallel_case
358
                8'b11110000:    s_dat_o <= sprEn;
359
                8'b11110001:    s_dat_o <= {sprBkIRQPending|sprSprIRQPending,5'b0,sprBkIRQPending,sprSprIRQPending,6'b0,sprBkIe,sprSprIe};
360
                8'b11110010:    s_dat_o <= sprSprCollision;
361
                8'b11110011:    s_dat_o <= sprBkCollision;
362
                8'b11110100:    s_dat_o <= sprDt;
363
                default:        s_dat_o <= 32'd0;
364 2 robfinch
                endcase
365
        else
366
                s_dat_o <= 32'd0;
367
 
368
 
369
// vclk -> clk_i
370
always @(posedge clk_i)
371
begin
372
        sprSprIRQ <= sprSprIRQ1;
373
        sprBkIRQ <= sprBkIRQ1;
374
        sprSprIRQPending <= sprSprIRQPending1;
375
        sprBkIRQPending <= sprBkIRQPending1;
376
        sprSprCollision <= sprSprCollision1;
377
        sprBkCollision <= sprBkCollision1;
378
end
379
 
380
 
381
// register updates
382
// on the clk_i domain
383
always @(posedge clk_i)
384
if (rst_i) begin
385
        sprEn <= {pnSpr{1'b1}};
386
        sprDt <= 0;
387
    for (n = 0; n < pnSpr; n = n + 1) begin
388 3 robfinch
                sprSysAddr[n] <= 20'b0001_0000_0000_0100 + n;    //1000_4000
389 2 robfinch
        end
390
        sprSprIe <= 0;
391
        sprBkIe  <= 0;
392
 
393
    // Set reasonable starting positions on the screen
394
    // so that the sprites might be visible for testing
395
    for (n = 0; n < pnSpr; n = n + 1) begin
396 3 robfinch
        hSprPos[n] <= 400 + (n & 15) * 60;
397
        vSprPos[n] <= 200 + (n > 16 ? 100 : 0);
398 2 robfinch
        sprTc[n] <= 16'h6739;
399 3 robfinch
                sprWidth[n] <= 56;  // 56x36 sprites
400
                sprHeight[n] <= 36;
401 2 robfinch
                hSprRes[n] <= 0; // our standard display
402
                vSprRes[n] <= 0;
403
                sprImageOffs[n] <= 0;
404
        end
405
    hSprPos[0] <= 290;
406
    vSprPos[0] <= 72;
407
 
408
    bgTc <= 24'h00_00_00;
409
    bkColor <= 24'hFF_FF_60;
410
end
411
else begin
412
        // clear DMA trigger bit once DMA is recognized
413
        if (dmaStart)
414
                sprDt[dmaOwner] <= 1'b0;
415
 
416
        if (cs_regs & s_we_i) begin
417
 
418 3 robfinch
                casex (s_adr_i[9:2])
419
                8'b11110000:    // 3C0
420 2 robfinch
                        begin
421 3 robfinch
                                if (s_sel_i[0]) sprEn[7:0] <= s_dat_i[7:0];
422
                                if (s_sel_i[1]) sprEn[15:8] <= s_dat_i[15:8];
423
                                if (s_sel_i[2]) sprEn[23:16] <= s_dat_i[23:16];
424
                                if (s_sel_i[3]) sprEn[31:24] <= s_dat_i[31:24];
425 2 robfinch
                        end
426 3 robfinch
                8'b11110001:    // 3C4
427
                        if (s_sel_i[0]) begin
428
                                sprSprIe <= s_dat_i[0];
429
                                sprBkIe <= s_dat_i[1];
430 2 robfinch
                        end
431
                // update DMA trigger
432
                // s_dat_i[7:0] indicates which triggers to set  (1=set,0=ignore)
433
                // s_dat_i[7:0] indicates which triggers to clear (1=clear,0=ignore)
434 3 robfinch
                8'b11110100:    // 3D0
435 2 robfinch
                        begin
436
                                if (s_sel_i[0])  sprDt[7:0] <= sprDt[7:0] | s_dat_i[7:0];
437 3 robfinch
                                if (s_sel_i[1]) sprDt[15:8] <= sprDt[15:8] | s_dat_i[15:8];
438
                                if (s_sel_i[2]) sprDt[23:16] <= sprDt[23:16] | s_dat_i[23:16];
439
                                if (s_sel_i[3]) sprDt[31:24] <= sprDt[31:24] | s_dat_i[31:24];
440 2 robfinch
                        end
441 3 robfinch
                8'b11110101:    // 3D4
442 2 robfinch
                        begin
443 3 robfinch
                                if (s_sel_i[0])  sprDt[7:0] <= sprDt[7:0] & ~s_dat_i[7:0];
444
                                if (s_sel_i[1]) sprDt[15:8] <= sprDt[15:8] & ~s_dat_i[15:8];
445
                                if (s_sel_i[2]) sprDt[23:16] <= sprDt[23:16] & ~s_dat_i[23:16];
446
                                if (s_sel_i[3]) sprDt[31:24] <= sprDt[31:24] & ~s_dat_i[31:24];
447 2 robfinch
                        end
448 3 robfinch
                8'b11111010:    // 3E8
449
                        begin
450
                                if (s_sel_i[0])  bgTc[7:0] <= s_dat_i[7:0];
451
                                if (s_sel_i[1]) bgTc[15:8] <= s_dat_i[15:8];
452
                                if (s_sel_i[2]) bgTc[23:16] <= s_dat_i[23:16];
453
                        end
454
                8'b11111011:    // 3EC
455
                        begin
456
                                if (s_sel_i[0]) bkColor[7:0] <= s_dat_i[7:0];
457
                                if (s_sel_i[1]) bkColor[15:8] <= s_dat_i[15:8];
458
                                if (s_sel_i[2]) bkColor[23:16] <= s_dat_i[23:16];
459
                        end
460
                8'b0xxxxx00:
461 2 robfinch
                         begin
462
                        if (s_sel_i[0]) hSprPos[sprN][ 7:0] <= s_dat_i[ 7: 0];
463
                        if (s_sel_i[1]) hSprPos[sprN][10:8] <= s_dat_i[10: 8];
464
                        if (s_sel_i[2]) vSprPos[sprN][ 7:0] <= s_dat_i[23:16];
465
                        if (s_sel_i[3]) vSprPos[sprN][10:8] <= s_dat_i[26:24];
466
                end
467 3 robfinch
        8'b0xxxxx01:
468 2 robfinch
                        begin
469
                        if (s_sel_i[0]) begin
470 3 robfinch
                                        sprWidth[sprN] <= s_dat_i[7:0];
471 2 robfinch
                    end
472
                        if (s_sel_i[1]) begin
473 3 robfinch
                                        sprHeight[sprN] <= s_dat_i[15:8];
474 2 robfinch
                    end
475 3 robfinch
                                if (s_sel_i[2]) begin
476
                        hSprRes[sprN] <= s_dat_i[19:16];
477
                        vSprRes[sprN] <= s_dat_i[23:20];
478
                                end
479 2 robfinch
                        end
480 3 robfinch
                8'b0xxxxx10:
481 2 robfinch
                        begin   // DMA address set on clk_i domain
482 3 robfinch
                    if (s_sel_i[0]) sprImageOffs[sprN][ 7:0] <= s_dat_i[7:0];
483
                    if (s_sel_i[1]) sprImageOffs[sprN][10:8] <= s_dat_i[11:8];
484
                                if (s_sel_i[1]) sprSysAddr[sprN][15:12] <= s_dat_i[15:12];
485
                                if (s_sel_i[2]) sprSysAddr[sprN][23:16] <= s_dat_i[23:16];
486
                                if (s_sel_i[3]) sprSysAddr[sprN][31:24] <= s_dat_i[31:24];
487 2 robfinch
                        end
488 3 robfinch
                8'b0xxxxx11:
489 2 robfinch
                        begin
490
                                if (s_sel_i[0]) sprTc[sprN][ 7:0] <= s_dat_i[ 7:0];
491
                                if (pColorBits>8)
492
                                        if (s_sel_i[1]) sprTc[sprN][15:8] <= s_dat_i[15:8];
493
                        end
494
 
495
                default:        ;
496
                endcase
497
 
498
        end
499
end
500
 
501
//-------------------------------------------------------------
502
// Sprite Image Cache RAM
503
// This RAM is dual ported with an SoC side and a display
504
// controller side.
505
//-------------------------------------------------------------
506 3 robfinch
wire [11:2] sr_adr = m_cyc_o ? m_adr_o[11:2] : s_adr_i[11:2];
507 2 robfinch
wire [31:0] sr_din = m_cyc_o ? m_dat_i[31:0] : s_dat_i[31:0];
508
wire sr_ce = m_cyc_o ? sbi_rdy1 : cs_ram;
509
 
510
// Note: the sprite output can't be zeroed out using the rst input!!!
511
// We need to know what the output is to determine if it's the 
512
// transparent color.
513
genvar g;
514
generate
515
        for (g = 0; g < pnSpr; g = g + 1)
516
        begin : genSpriteRam
517
                if (pColorBits==8)
518
                        rtfSpriteRam8 sprRam0
519
                        (
520
                                .clka(vclk),
521
                                .adra(sprAddr[g]),
522
                                .doa(sprOut[g]),
523
                                .cea(1'b1),
524
 
525
                                .clkb(~clk_i),
526
                                .adrb(sr_adr),
527
                                .dib(sr_din),
528
                                .dob(sr_dout[g]),
529
                                .ceb(sr_ce),
530
                                .web(sprWe[g]),
531
                                .rstb(!sprRe[g])
532
                        );
533
                else if (pColorBits==16)
534
                        rtfSpriteRam16 sprRam0
535
                        (
536
                                .clka(vclk),
537 3 robfinch
                                .adra(sprAddr[g][10:0]),
538 2 robfinch
                                .doa(sprOut[g]),
539
                                .cea(1'b1),
540
 
541
                                .clkb(~clk_i),
542
                                .adrb(sr_adr),
543
                                .dib(sr_din),
544
                                .dob(sr_dout[g]),
545
                                .ceb(sr_ce),
546
                                .web(sprWe[g]),
547
                                .rstb(!sprRe[g])
548
                        );
549
        end
550
endgenerate
551
 
552
 
553
 
554
//-------------------------------------------------------------
555
// Timing counters and addressing
556
// Sprites are like miniature bitmapped displays, they need
557
// all the same timing controls.
558
//-------------------------------------------------------------
559
 
560
// Create a timing reference using horizontal and vertical
561
// sync
562
wire hSyncEdge, vSyncEdge;
563
edge_det ed0(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(hSync), .pe(hSyncEdge), .ne(), .ee() );
564
edge_det ed1(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(vSync), .pe(vSyncEdge), .ne(), .ee() );
565
 
566
always @(posedge vclk)
567
if (rst_i)              hctr <= 0;
568
else if (hSyncEdge) hctr <= 0;
569
else                    hctr <= hctr + 1;
570
 
571
always @(posedge vclk)
572
if (rst_i)              vctr <= 0;
573
else if (vSyncEdge) vctr <= 0;
574
else if (hSyncEdge) vctr <= vctr + 1;
575
 
576
// track sprite horizontal reset
577
always @(posedge vclk)
578
for (n = 0; n < pnSpr; n = n + 1)
579
        hSprReset[n] <= hctr==hSprPos[n];
580
 
581
// track sprite vertical reset
582
always @(posedge vclk)
583
for (n = 0; n < pnSpr; n = n + 1)
584
        vSprReset[n] <= vctr==vSprPos[n];
585
 
586
always @(hSprDe, vSprDe)
587 3 robfinch
for (n = 0; n < pnSpr; n = n + 1)
588 2 robfinch
        sprDe[n] <= hSprDe[n] & vSprDe[n];
589
 
590
 
591
// take care of sprite size scaling
592
// video clock division
593 3 robfinch
reg [31:0] hSprNextPixel;
594
reg [31:0] vSprNextPixel;
595
reg [3:0] hSprPt [31:0];   // horizontal pixel toggle
596
reg [3:0] vSprPt [31:0];   // vertical pixel toggle
597 2 robfinch
always @(n)
598
for (n = 0; n < pnSpr; n = n + 1)
599
    hSprNextPixel[n] = hSprPt[n]==hSprRes[n];
600
always @(n)
601
for (n = 0; n < pnSpr; n = n + 1)
602
    vSprNextPixel[n] = vSprPt[n]==vSprRes[n];
603
 
604
// horizontal pixel toggle counter
605
always @(posedge vclk)
606
for (n = 0; n < pnSpr; n = n + 1)
607
        if (hSprReset[n])
608
                hSprPt[n] <= 0;
609
    else if (hSprNextPixel[n])
610
        hSprPt[n] <= 0;
611
    else
612
        hSprPt[n] <= hSprPt[n] + 1;
613
 
614
// vertical pixel toggle counter
615
always @(posedge vclk)
616
for (n = 0; n < pnSpr; n = n + 1)
617
    if (hSprReset[n]) begin
618
        if (vSprReset[n])
619
                vSprPt[n] <= 0;
620
        else if (vSprNextPixel[n])
621
            vSprPt[n] <= 0;
622
        else
623
            vSprPt[n] <= vSprPt[n] + 1;
624
    end
625
 
626
 
627
// clock sprite image address counters
628
always @(posedge vclk)
629
for (n = 0; n < pnSpr; n = n + 1) begin
630
    // hReset and vReset - top left of sprite,
631
    // reset address to image offset
632
        if (hSprReset[n] & vSprReset[n]) begin
633
                sprAddr[n]  <= sprImageOffs[n];
634
                sprAddrB[n] <= sprImageOffs[n];
635
        end
636
        // hReset:
637
        //  If the next vertical pixel
638
        //      set backup address to current address
639
        //  else
640
        //      set current address to backup address
641
        //      in order to rescan the line
642
        else if (hSprReset[n]) begin
643
                if (vSprNextPixel[n])
644
                        sprAddrB[n] <= sprAddr[n];
645
                else
646
                        sprAddr[n]  <= sprAddrB[n];
647
        end
648
        // Not hReset or vReset - somewhere on the sprite scan line
649
        // just advance the address when the next pixel should be
650
        // fetched
651
        else if (sprDe[n] & hSprNextPixel[n])
652
                sprAddr[n] <= sprAddr[n] + 1;
653
end
654
 
655
 
656
// clock sprite column (X) counter
657
always @(posedge vclk)
658
for (n = 0; n < pnSpr; n = n + 1)
659
        if (hSprReset[n])
660
                hSprCnt[n] <= 0;
661
        else if (hSprNextPixel[n])
662
                hSprCnt[n] <= hSprCnt[n] + 1;
663
 
664
 
665
// clock sprite horizontal display enable
666
always @(posedge vclk)
667
for (n = 0; n < pnSpr; n = n + 1) begin
668
        if (hSprReset[n])
669
                hSprDe[n] <= 1;
670
        else if (hSprNextPixel[n]) begin
671
                if (hSprCnt[n] == sprWidth[n])
672
                        hSprDe[n] <= 0;
673
        end
674
end
675
 
676
 
677
// clock the sprite row (Y) counter
678
always @(posedge vclk)
679
for (n = 0; n < pnSpr; n = n + 1)
680
        if (hSprReset[n]) begin
681
                if (vSprReset[n])
682
                        vSprCnt[n] <= 0;
683
                else if (vSprNextPixel[n])
684
                        vSprCnt[n] <= vSprCnt[n] + 1;
685
        end
686
 
687
 
688
// clock sprite vertical display enable
689
always @(posedge vclk)
690
for (n = 0; n < pnSpr; n = n + 1) begin
691
        if (hSprReset[n]) begin
692
                if (vSprReset[n])
693
                        vSprDe[n] <= 1;
694
                else if (vSprNextPixel[n]) begin
695
                        if (vSprCnt[n] == sprHeight[n])
696
                                vSprDe[n] <= 0;
697
                end
698
        end
699
end
700
 
701
 
702
//-------------------------------------------------------------
703
// Output stage
704
//-------------------------------------------------------------
705
 
706
// function used for color blending
707
// given an alpha and a color component, determine the resulting color
708
// this blends towards black or white
709
// alpha is eight bits ranging between 0 and 1.999...
710
// 1 bit whole, 7 bits fraction
711
function [7:0] fnBlend;
712
input [7:0] alpha;
713
input [7:0] colorbits;
714
 
715
begin
716
        fnBlend = (({8'b0,colorbits} * alpha) >> 7);
717
end
718
endfunction
719
 
720
 
721
// pipeline delays for display enable
722 3 robfinch
reg [31:0] sprDe1;
723
reg [31:0] sproact;
724 2 robfinch
always @(posedge vclk)
725
for (n = 0; n < pnSpr; n = n + 1) begin
726
        sprDe1[n] <= sprDe[n];
727
end
728
 
729
 
730
// Detect which sprite outputs are active
731
// The sprite output is active if the current display pixel
732
// address is within the sprite's area, the sprite is enabled,
733
// and it's not a transparent pixel that's being displayed.
734
always @(n, sprEn, sprDe1)
735
for (n = 0; n < pnSpr; n = n + 1)
736
        sproact[n] <= sprEn[n] && sprDe1[n] && sprTc[n]!=sprOut[n];
737
 
738
// register sprite activity flag
739
// The image combiner uses this flag to know what to do with
740
// the sprite output.
741
always @(posedge vclk)
742
outact = |sproact;
743
 
744
// Display data comes from the active sprite with the
745
// highest display priority.
746
// Make sure that alpha blending is turned off when
747
// no sprite is active.
748
always @(posedge vclk)
749
begin
750
        out = 16'h0080; // alpha blend max (and off)
751
        for (n = pnSprm; n >= 0; n = n - 1)
752
                if (sproact[n]) out = sprOut[n];
753
end
754
 
755
 
756
// combine the text / graphics color output with sprite color output
757
// blend color output
758
wire [23:0] blendedColor = {
759
        fnBlend(out[7:0],rgbIn[23:16]),          // R
760
        fnBlend(out[7:0],rgbIn[15: 8]),          // G
761
        fnBlend(out[7:0],rgbIn[ 7: 0])};  // B
762
 
763
 
764
// display color priority bit [24] 1=display is over sprite
765
always @(posedge vclk)
766
if (blank)
767
        rgbOut <= 0;
768
else begin
769 3 robfinch
        if (rgbPriority==2'b10 && rgbIn[23:0] != bgTc)   // color is in front of sprite
770 2 robfinch
                rgbOut <= rgbIn[23:0];
771
        else if (outact) begin
772
                if (!out[15]) begin                     // a sprite is displayed without alpha blending
773
                        if (pColorBits==8)
774
                                rgbOut <= {out[7:5],5'b0,out[4:2],5'b0,out[1:0],6'b0};
775
                        else
776
                                rgbOut <= {out[14:10],3'b0,out[9:5],3'b0,out[4:0],3'b0};
777
                end
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
 
794
//--------------------------------------------------------------------
795
// Note this case has to be modified for the number of sprites
796
//--------------------------------------------------------------------
797
generate
798
begin : gSprsColliding
799
always @(pnSpr or sproact)
800
if (pnSpr==1)
801
        sprCollision = 0;
802
else if (pnSpr==2)
803
        case (sproact)
804
        2'b00,
805
        2'b01,
806
        2'b10:  sprCollision = 0;
807
        2'b11:  sprCollision = 1;
808
        endcase
809
else if (pnSpr==4)
810
        case (sproact)
811
        4'b0000,
812
        4'b0001,
813
        4'b0010,
814
        4'b0100,
815
        4'b1000:        sprCollision = 0;
816
        default:        sprCollision = 1;
817
        endcase
818
else if (pnSpr==6)
819
        case (sproact)
820
        6'b000000,
821
        6'b000001,
822
        6'b000010,
823
        6'b000100,
824
        6'b001000,
825
        6'b010000,
826
        8'b100000:      sprCollision = 0;
827
        default:        sprCollision = 1;
828
        endcase
829
else if (pnSpr==8)
830
        case (sproact)
831
        8'b00000000,
832
        8'b00000001,
833
        8'b00000010,
834
        8'b00000100,
835
        8'b00001000,
836
        8'b00010000,
837
        8'b00100000,
838
        8'b01000000,
839
        8'b10000000:    sprCollision = 0;
840
        default:                sprCollision = 1;
841
        endcase
842
else if (pnSpr==14)
843
        case (sproact)
844
        14'b00000000000000,
845
        14'b00000000000001,
846
        14'b00000000000010,
847
        14'b00000000000100,
848
        14'b00000000001000,
849
        14'b00000000010000,
850
        14'b00000000100000,
851
        14'b00000001000000,
852
        14'b00000010000000,
853
        14'b00000100000000,
854
        14'b00001000000000,
855
        14'b00010000000000,
856
        14'b00100000000000,
857
        14'b01000000000000,
858
        14'b10000000000000:     sprCollision = 0;
859
        default:                        sprCollision = 1;
860
        endcase
861 3 robfinch
else if (pnSpr==32)
862
        case (sproact)
863
        32'h00000000,
864
        32'h00000001,
865
        32'h00000002,
866
        32'h00000004,
867
        32'h00000008,
868
        32'h00000010,
869
        32'h00000020,
870
        32'h00000040,
871
        32'h00000080,
872
        32'h00000100,
873
        32'h00000200,
874
        32'h00000400,
875
        32'h00000800,
876
        32'h00001000,
877
        32'h00002000,
878
        32'h00004000,
879
        32'h00008000,
880
        32'h00010000,
881
        32'h00020000,
882
        32'h00040000,
883
        32'h00080000,
884
        32'h00100000,
885
        32'h00200000,
886
        32'h00400000,
887
        32'h00800000,
888
        32'h01000000,
889
        32'h02000000,
890
        32'h04000000,
891
        32'h08000000,
892
        32'h10000000,
893
        32'h20000000,
894
        32'h40000000,
895
        32'h80000000:           sprCollision = 0;
896
        default:                        sprCollision = 1;
897
        endcase
898 2 robfinch
end
899
endgenerate
900
 
901
// Detect when a sprite-background collision has occurred
902 3 robfinch
assign bkCollision = //(rgbIn[24] && rgbIn[23:0] != bgTc) ? 0 :
903
                outact && rgbPriority==2'b01;//rgbIn[23:0] != bkColor;
904 2 robfinch
 
905
// Load the sprite collision register. This register continually
906
// accumulates collision bits until reset by reading the register.
907
// Set the collision IRQ on the first collision and don't set it
908
// again until after the collision register has been read.
909
always @(posedge vclk)
910
if (rst_i) begin
911
        sprSprIRQPending1 <= 0;
912
        sprSprCollision1 <= 0;
913
        sprSprIRQ1 <= 0;
914
end
915
else if (sprCollision) begin
916
        // isFirstCollision
917 3 robfinch
        if ((sprSprCollision1==0)||(cs_regs && s_sel_i[0] && s_adr_i[9:2]==8'b11110010)) begin
918 2 robfinch
                sprSprIRQPending1 <= 1;
919
                sprSprIRQ1 <= sprSprIe;
920
                sprSprCollision1 <= sproact;
921
        end
922
        else
923
                sprSprCollision1 <= sprSprCollision1|sproact;
924
end
925 3 robfinch
else if (cs_regs && s_sel_i[0] && s_adr_i[9:2]==8'b11110010) begin
926 2 robfinch
        sprSprCollision1 <= 0;
927
        sprSprIRQPending1 <= 0;
928
        sprSprIRQ1 <= 0;
929
end
930
 
931
 
932
// Load the sprite background collision register. This register
933
// continually accumulates collision bits until reset by reading
934
// the register.
935
// Set the collision IRQ on the first collision and don't set it
936
// again until after the collision register has been read.
937
// Note the background collision indicator is externally supplied,
938
// it will come from the color processing logic.
939
always @(posedge vclk)
940
if (rst_i) begin
941
        sprBkIRQPending1 <= 0;
942
        sprBkCollision1 <= 0;
943
        sprBkIRQ1 <= 0;
944
end
945
else if (bkCollision) begin
946
        // Is the register being cleared at the same time
947
        // a collision occurss ?
948
        // isFirstCollision
949 3 robfinch
        if ((sprBkCollision1==0) || (cs_regs && s_sel_i[0] && s_adr_i[9:2]==8'b11110011)) begin
950 2 robfinch
                sprBkIRQ1 <= sprBkIe;
951
                sprBkCollision1 <= sproact;
952
                sprBkIRQPending1 <= 1;
953
        end
954
        else
955
                sprBkCollision1 <= sprBkCollision1|sproact;
956
end
957 3 robfinch
else if (cs_regs && s_sel_i[0] && s_adr_i[9:2]==8'b11110011) begin
958 2 robfinch
        sprBkCollision1 <= 0;
959
        sprBkIRQPending1 <= 0;
960
        sprBkIRQ1 <= 0;
961
end
962
 
963
endmodule
964
 
965
// Sprite RAM for eight bit color depth
966
module rtfSpriteRam8 (
967
        clka, adra, doa, cea,
968
        clkb, adrb, dib, dob, ceb, web, rstb
969
);
970
input clka;
971 3 robfinch
input [11:0] adra;
972 2 robfinch
output [7:0] doa;
973
reg [7:0] doa;
974
input cea;
975
input clkb;
976 3 robfinch
input [9:0] adrb;
977 2 robfinch
input [31:0] dib;
978
output [31:0] dob;
979
input ceb;
980
input web;
981
input rstb;
982
 
983 3 robfinch
reg [31:0] mem [0:1023];
984
reg [11:0] radra;
985
reg [9:0] radrb;
986 2 robfinch
 
987
always @(posedge clka)  if (cea) radra <= adra;
988
always @(posedge clkb)  if (ceb) radrb <= adrb;
989
always @(radra)
990
        case(radra[1:0])
991 3 robfinch
        2'b00:  doa <= mem[radra[11:2]][ 7: 0];
992
        2'b01:  doa <= mem[radra[11:2]][15: 8];
993
        2'b10:  doa <= mem[radra[11:2]][23:16];
994
        2'b11:  doa <= mem[radra[11:2]][31:24];
995 2 robfinch
        endcase
996
assign dob = rstb ? 32'd0 : mem [radrb];
997
always @(posedge clkb)
998
        if (ceb & web) mem[adrb] <= dib;
999
 
1000
endmodule
1001
 
1002
// Sprite RAM for sixteen bit color depth
1003
module rtfSpriteRam16 (
1004
        clka, adra, doa, cea,
1005
        clkb, adrb, dib, dob, ceb, web, rstb
1006
);
1007
input clka;
1008 3 robfinch
input [10:0] adra;
1009 2 robfinch
output [15:0] doa;
1010
reg [15:0] doa;
1011
input cea;
1012
input clkb;
1013 3 robfinch
input [9:0] adrb;
1014 2 robfinch
input [31:0] dib;
1015
output [31:0] dob;
1016
input ceb;
1017
input web;
1018
input rstb;
1019
 
1020 3 robfinch
reg [31:0] mem [0:1023];
1021
reg [10:0] radra;
1022
reg [9:0] radrb;
1023 2 robfinch
 
1024
always @(posedge clka)  if (cea) radra <= adra;
1025
always @(posedge clkb)  if (ceb) radrb <= adrb;
1026
always @(radra)
1027
        case(radra[1])
1028 3 robfinch
        1'b0:   doa <= mem[radra[10:1]][15: 0];
1029
        1'b1:   doa <= mem[radra[10:1]][31:16];
1030 2 robfinch
        endcase
1031
assign dob = rstb ? 32'd0 : mem [radrb];
1032
always @(posedge clkb)
1033
        if (ceb & web) mem[adrb] <= dib;
1034
 
1035
endmodule
1036
 

powered by: WebSVN 2.1.0

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