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

Subversion Repositories rtf_sprite_controller

[/] [rtf_sprite_controller/] [trunk/] [rtl/] [verilog/] [rfSpriteController.sv] - Diff between revs 7 and 9

Only display areas with differences | Details | Blame | View Log

Rev 7 Rev 9
`timescale 1ns / 1ps
`timescale 1ns / 1ps
// ============================================================================
// ============================================================================
//        __
//        __
//   \\__/ o\    (C) 2005-2022  Robert Finch, Waterloo
//   \\__/ o\    (C) 2005-2022  Robert Finch, Waterloo
//    \  __ /    All rights reserved.
//    \  __ /    All rights reserved.
//     \/_//     robfinch@finitron.ca
//     \/_//     robfinch@finitron.ca
//       ||
//       ||
//
//
//      rfSpriteController.sv
//      rfSpriteController.sv
//              sprite / hardware cursor controller
//              sprite / hardware cursor controller
//
//
// BSD 3-Clause License
// BSD 3-Clause License
// Redistribution and use in source and binary forms, with or without
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// modification, are permitted provided that the following conditions are met:
//
//
// 1. Redistributions of source code must retain the above copyright notice, this
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//    list of conditions and the following disclaimer.
//
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//    and/or other materials provided with the distribution.
//
//
// 3. Neither the name of the copyright holder nor the names of its
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//    this software without specific prior written permission.
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//
//
//
//      Sprite Controller
//      Sprite Controller
//
//
//      FEATURES
//      FEATURES
//      - parameterized number of sprites 1,2,4,6,8,14,16 or 32
//      - parameterized number of sprites 1,2,4,6,8,14,16 or 32
//      - sprite image cache buffers
//      - sprite image cache buffers
//              - each image cache is capable of holding multiple
//              - each image cache is capable of holding multiple
//                sprite images
//                sprite images
//              - an embedded DMA controller is used for sprite reload
//              - an embedded DMA controller is used for sprite reload
//      - programmable image offset within cache
//      - programmable image offset within cache
//      - programmable sprite width,height, and pixel size
//      - programmable sprite width,height, and pixel size
//              - sprite width and height may vary from 1 to 256 as long
//              - sprite width and height may vary from 1 to 256 as long
//                as the product doesn't exceed 4096.
//                as the product doesn't exceed 4096.
//          - pixels may be programmed to be 1,2,3 or 4 video clocks
//          - pixels may be programmed to be 1,2,3 or 4 video clocks
//            both height and width are programmable
//            both height and width are programmable
//      - programmable sprite position
//      - programmable sprite position
//      - programmable 8, 16 or 32 bits for color
//      - programmable 8, 16 or 32 bits for color
//              eg 32k color + 1 bit alpha blending indicator (1,5,5,5)
//              eg 32k color + 1 bit alpha blending indicator (1,5,5,5)
//      - fixed display and DMA priority
//      - fixed display and DMA priority
//          sprite 0 highest, sprite 31 lowest
//          sprite 0 highest, sprite 31 lowest
//      - graphics plane control
//      - graphics plane control
//
//
//              This core requires an external timing generator to
//              This core requires an external timing generator to
//      provide horizontal and vertical sync signals, but
//      provide horizontal and vertical sync signals, but
//      otherwise can be used as a display controller on it's
//      otherwise can be used as a display controller on it's
//      own. However, normally this core would be embedded
//      own. However, normally this core would be embedded
//      within another core such as a VGA controller. Sprite
//      within another core such as a VGA controller. Sprite
//      positions are referenced to the rising edge of the
//      positions are referenced to the rising edge of the
//      vertical and horizontal sync pulses.
//      vertical and horizontal sync pulses.
//              The core includes an embedded dual port RAM to hold the
//              The core includes an embedded dual port RAM to hold the
//      sprite images. The image RAM is updated using a built in DMA
//      sprite images. The image RAM is updated using a built in DMA
//      controller. The DMA controller uses 32 bit accesses to fill
//      controller. The DMA controller uses 32 bit accesses to fill
//      the sprite buffers. The circuit features an automatic bus
//      the sprite buffers. The circuit features an automatic bus
//  transaction timeout; if the system bus hasn't responded
//  transaction timeout; if the system bus hasn't responded
//  within 20 clock cycles, the DMA controller moves onto the
//  within 20 clock cycles, the DMA controller moves onto the
//  next address.
//  next address.
//              The controller uses a ram underlay to cache the values
//              The controller uses a ram underlay to cache the values
//      of the registers. This is a lot cheaper resource wise than
//      of the registers. This is a lot cheaper resource wise than
//      using a 32 to 1 multiplexor (well at least for an FPGA).
//      using a 32 to 1 multiplexor (well at least for an FPGA).
//
//
//      All registers are 32 bits wide
//      All registers are 32 bits wide
//
//
//      These registers repeat in incrementing block of four registers
//      These registers repeat in incrementing block of four registers
//      and pertain to each sprite
//      and pertain to each sprite
//      00:     - position register
//      00:     - position register
//              HPOS    [11: 0] horizontal position (hctr value)
//              HPOS    [11: 0] horizontal position (hctr value)
//          VPOS        [27:16] vertical position (vctr value)
//          VPOS        [27:16] vertical position (vctr value)
//
//
//      04:     SZ      - size register
//      04:     SZ      - size register
//                      bits
//                      bits
//                      [ 7: 0] width of sprite in pixels - 1
//                      [ 7: 0] width of sprite in pixels - 1
//                      [15: 8] height of sprite in pixels -1
//                      [15: 8] height of sprite in pixels -1
//                      [19:16] size of horizontal pixels - 1 in clock cycles
//                      [19:16] size of horizontal pixels - 1 in clock cycles
//                      [23:20] size of vertical pixels in scan-lines - 1
//                      [23:20] size of vertical pixels in scan-lines - 1
//                              * the product of width * height cannot exceed 2048 !
//                              * the product of width * height cannot exceed 2048 !
//                              if it does, the display will begin repeating
//                              if it does, the display will begin repeating
//                      [27:24] output plane
//                      [27:24] output plane
//                      [31:30] color depth 01=RGB332,10=RGB555+A,11=RGB888+A
//                      [31:30] color depth 01=RGB332,10=RGB555+A,11=RGB888+A
//
//
//      08: ADR [31:12] 20 bits sprite image address bits
//      08: ADR [31:12] 20 bits sprite image address bits
//                      This registers contain the high order address bits of the
//                      This registers contain the high order address bits of the
//          location of the sprite image in system memory.
//          location of the sprite image in system memory.
//                      The DMA controller will assign the low order 12 bits
//                      The DMA controller will assign the low order 12 bits
//                      during DMA.
//                      during DMA.
//                  [11:0] image offset bits [11:0]
//                  [11:0] image offset bits [11:0]
//                      offset of the sprite image within the sprite image cache
//                      offset of the sprite image within the sprite image cache
//                      typically zero
//                      typically zero
//
//
//      0C: TC  [23:0]  transparent color
//      0C: TC  [23:0]  transparent color
//                      This register identifies which color of the sprite
//                      This register identifies which color of the sprite
//                      is transparent
//                      is transparent
//
//
//
//
//
//
//      0C-1FC: registers reserved for up to thirty-one other sprites
//      0C-1FC: registers reserved for up to thirty-one other sprites
//
//
//      200:            DMA burst reg sprite 0
//      200:            DMA burst reg sprite 0
//                              [8:0]  burst start
//                              [8:0]  burst start
//                              [24:16] burst end
//                              [24:16] burst end
//      ...
//      ...
//      27C:            DMA burst reg sprite 31
//      27C:            DMA burst reg sprite 31
//
//
//  280:        [ 7: 0] Frame size, multiples of 16 pixels
//  280:        [ 7: 0] Frame size, multiples of 16 pixels
//                              [15: 8] Number of frames of animation
//                              [15: 8] Number of frames of animation
//        [25:16] Animation Rate
//        [25:16] Animation Rate
//                              [29:26] Frame size, LSBs 0 to 3
//                              [29:26] Frame size, LSBs 0 to 3
//                              [30]            Auto repeat
//                              [30]            Auto repeat
//                              [31]    Enable animation
//                              [31]    Enable animation
//  ...
//  ...
//      2FC:    Animation register sprite #31
//      2FC:    Animation register sprite #31
//
//
//      Global status and control
//      Global status and control
//      3C0: EN [31:0] sprite enable register
//      3C0: EN [31:0] sprite enable register
//  3C4: IE     [31:0] sprite interrupt enable / status
//  3C4: IE     [31:0] sprite interrupt enable / status
//      3C8: SCOL       [31:0] sprite-sprite collision register
//      3C8: SCOL       [31:0] sprite-sprite collision register
//      3CC: BCOL       [31:0] sprite-background collision register
//      3CC: BCOL       [31:0] sprite-background collision register
//      3D0: DT         [31:0] sprite DMA trigger on
//      3D0: DT         [31:0] sprite DMA trigger on
//      3D4: DT         [31:0] sprite DMA trigger off
//      3D4: DT         [31:0] sprite DMA trigger off
//      3D8: VDT        [31:0] sprite vertical sync DMA trigger
//      3D8: VDT        [31:0] sprite vertical sync DMA trigger
//      3EC: BC   [29:0] background color
//      3EC: BC   [29:0] background color
//  3FC: ADDR   [31:0] sprite DMA address bits [63:32]
//  3FC: ADDR   [31:0] sprite DMA address bits [63:32]
//
//
 
// 7200
//=============================================================================
//=============================================================================
import wishbone_pkg::*;
import wishbone_pkg::*;
module rfSpriteController(
module rfSpriteController(
// Bus Slave interface
// Bus Slave interface
//------------------------------
//------------------------------
// Slave signals
// Slave signals
input rst_i,                    // reset
input rst_i,                    // reset
input s_clk_i,          // clock
input s_clk_i,          // clock
input s_cs_i,
input s_cs_i,
input   wb_write_request32_t wbs_req,
input   wb_write_request32_t wbs_req,
output wb_read_response32_t wbs_resp,
output wb_read_response32_t wbs_resp,
//------------------------------
//------------------------------
// Bus Master Signals
// Bus Master Signals
input m_clk_i,                          // clock
input m_clk_i,                          // clock
output wb_write_request128_t wbm_req,
output wb_write_request128_t wbm_req,
input wb_read_response128_t wbm_resp,
input wb_read_response128_t wbm_resp,
output [4:0] m_spriteno_o,
output [4:0] m_spriteno_o,
//--------------------------
//--------------------------
input dot_clk_i,                // video dot clock
input dot_clk_i,                // video dot clock
input hsync_i,                  // horizontal sync pulse
input hsync_i,                  // horizontal sync pulse
input vsync_i,                  // vertical sync pulse
input vsync_i,                  // vertical sync pulse
input blank_i,                  // blanking signal
input blank_i,                  // blanking signal
input [39:0] zrgb_i,                    // input pixel stream
input [39:0] zrgb_i,                    // input pixel stream
output [39:0] zrgb_o,   // output pixel stream 12-12-12-4
output [39:0] zrgb_o,   // output pixel stream 12-12-12-4
output irq,                                     // interrupt request
output irq,                                     // interrupt request
input test,
input test,
input xonoff_i
input xonoff_i
);
);
reg m_soc_o;
reg m_soc_o;
wire vclk = dot_clk_i;
wire vclk = dot_clk_i;
wire hSync = hsync_i;
wire hSync = hsync_i;
wire vSync = vsync_i;
wire vSync = vsync_i;
reg [39:0] zrgb_o;
reg [39:0] zrgb_o;
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Core Parameters
// Core Parameters
//--------------------------------------------------------------------
//--------------------------------------------------------------------
parameter pnSpr = 32;           // number of sprites
parameter pnSpr = 32;           // number of sprites
parameter phBits = 12;          // number of bits in horizontal timing counter
parameter phBits = 12;          // number of bits in horizontal timing counter
parameter pvBits = 12;          // number of bits in vertical timing counter
parameter pvBits = 12;          // number of bits in vertical timing counter
localparam pnSprm = pnSpr-1;
localparam pnSprm = pnSpr-1;
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Variable Declarations
// Variable Declarations
//--------------------------------------------------------------------
//--------------------------------------------------------------------
reg ce;                                                                         // controller enable
reg ce;                                                                         // controller enable
wb_write_request32_t wb_reqs;   // synchronized request
wb_write_request32_t wb_reqs;   // synchronized request
wire [4:0] sprN = wb_reqs.adr[8:4];
wire [4:0] sprN = wb_reqs.adr[8:4];
reg [phBits-1:0] hctr;          // horizontal reference counter (counts dots since hSync)
reg [phBits-1:0] hctr;          // horizontal reference counter (counts dots since hSync)
reg [pvBits-1:0] vctr;          // vertical reference counter (counts scanlines since vSync)
reg [pvBits-1:0] vctr;          // vertical reference counter (counts scanlines since vSync)
reg sprSprIRQ;
reg sprSprIRQ;
reg sprBkIRQ;
reg sprBkIRQ;
reg [31:0] out;                 // sprite output
reg [31:0] out;                 // sprite output
reg outact;                             // sprite output is active
reg outact;                             // sprite output is active
reg [3:0] outplane;
reg [3:0] outplane;
reg [pnSprm:0] bkCollision;             // sprite-background collision
reg [pnSprm:0] bkCollision;             // sprite-background collision
reg [29:0] bgTc;                        // background transparent color
reg [29:0] bgTc;                        // background transparent color
reg [29:0] bkColor;             // background color
reg [29:0] bkColor;             // background color
reg [pnSprm:0] sprWe;   // block ram write enable for image cache update
reg [pnSprm:0] sprWe;   // block ram write enable for image cache update
reg [pnSprm:0] sprRe;   // block ram read enable for image cache update
reg [pnSprm:0] sprRe;   // block ram read enable for image cache update
// Global control registers
// Global control registers
reg [31:0] sprEn;       // enable sprite
reg [31:0] sprEn;       // enable sprite
reg [pnSprm:0] sprCollision;        // sprite-sprite collision
reg [pnSprm:0] sprCollision;        // sprite-sprite collision
reg sprSprIe;                   // sprite-sprite interrupt enable
reg sprSprIe;                   // sprite-sprite interrupt enable
reg sprBkIe;            // sprite-background interrupt enable
reg sprBkIe;            // sprite-background interrupt enable
reg sprSprIRQPending;   // sprite-sprite collision interrupt pending
reg sprSprIRQPending;   // sprite-sprite collision interrupt pending
reg sprBkIRQPending;    // sprite-background collision interrupt pending
reg sprBkIRQPending;    // sprite-background collision interrupt pending
reg sprSprIRQPending1;  // sprite-sprite collision interrupt pending
reg sprSprIRQPending1;  // sprite-sprite collision interrupt pending
reg sprBkIRQPending1;   // sprite-background collision interrupt pending
reg sprBkIRQPending1;   // sprite-background collision interrupt pending
reg sprSprIRQ1;                 // vclk domain regs
reg sprSprIRQ1;                 // vclk domain regs
reg sprBkIRQ1;
reg sprBkIRQ1;
// Sprite control registers
// Sprite control registers
reg [31:0] sprSprCollision;
reg [31:0] sprSprCollision;
reg [pnSprm:0] sprSprCollision1;
reg [pnSprm:0] sprSprCollision1;
reg [31:0] sprBkCollision;
reg [31:0] sprBkCollision;
reg [pnSprm:0] sprBkCollision1;
reg [pnSprm:0] sprBkCollision1;
reg [23:0] sprTc [pnSprm:0];            // sprite transparent color code
reg [23:0] sprTc [pnSprm:0];            // sprite transparent color code
// How big the pixels are:
// How big the pixels are:
// 1 to 16 video clocks
// 1 to 16 video clocks
reg [3:0] hSprRes [pnSprm:0];           // sprite horizontal resolution
reg [3:0] hSprRes [pnSprm:0];           // sprite horizontal resolution
reg [3:0] vSprRes [pnSprm:0];           // sprite vertical resolution
reg [3:0] vSprRes [pnSprm:0];           // sprite vertical resolution
reg [7:0] sprWidth [pnSprm:0];          // number of pixels in X direction
reg [7:0] sprWidth [pnSprm:0];          // number of pixels in X direction
reg [7:0] sprHeight [pnSprm:0];         // number of vertical pixels
reg [7:0] sprHeight [pnSprm:0];         // number of vertical pixels
reg [3:0] sprPlane [pnSprm:0];          // output plane sprite is in
reg [3:0] sprPlane [pnSprm:0];          // output plane sprite is in
reg [1:0] sprColorDepth [pnSprm:0];
reg [1:0] sprColorDepth [pnSprm:0];
reg [1:0] colorBits;
reg [1:0] colorBits;
// Sprite DMA control
// Sprite DMA control
reg [8:0] sprBurstStart [pnSprm:0];
reg [8:0] sprBurstStart [pnSprm:0];
reg [8:0] sprBurstEnd   [pnSprm:0];
reg [8:0] sprBurstEnd   [pnSprm:0];
reg [31:0] vSyncT;                                                              // DMA on vSync
reg [31:0] vSyncT;                                                              // DMA on vSync
// display and timing signals
// display and timing signals
reg [31:0] hSprReset;   // horizontal reset
reg [31:0] hSprReset;   // horizontal reset
reg [31:0] vSprReset;   // vertical reset
reg [31:0] vSprReset;   // vertical reset
reg [31:0] hSprDe;              // sprite horizontal display enable
reg [31:0] hSprDe;              // sprite horizontal display enable
reg [31:0] vSprDe;              // sprite vertical display enable
reg [31:0] vSprDe;              // sprite vertical display enable
reg [31:0] sprDe;                       // display enable
reg [31:0] sprDe;                       // display enable
reg [phBits-1:0] hSprPos [pnSprm:0];    // sprite horizontal position
reg [phBits-1:0] hSprPos [pnSprm:0];    // sprite horizontal position
reg [pvBits-1:0] vSprPos [pnSprm:0];    // sprite vertical position
reg [pvBits-1:0] vSprPos [pnSprm:0];    // sprite vertical position
reg [7:0] hSprCnt [pnSprm:0];   // sprite horizontal display counter
reg [7:0] hSprCnt [pnSprm:0];   // sprite horizontal display counter
reg [7:0] vSprCnt [pnSprm:0];   // vertical display counter
reg [7:0] vSprCnt [pnSprm:0];   // vertical display counter
reg [11:0] sprImageOffs [pnSprm:0];     // offset within sprite memory
reg [11:0] sprImageOffs [pnSprm:0];     // offset within sprite memory
reg [12:0] sprAddr [pnSprm:0];  // index into sprite memory (pixel number)
reg [12:0] sprAddr [pnSprm:0];  // index into sprite memory (pixel number)
reg [9:0] sprAddr1 [pnSprm:0];  // index into sprite memory
reg [9:0] sprAddr1 [pnSprm:0];  // index into sprite memory
reg [2:0] sprAddr2 [pnSprm:0];  // index into sprite memory
reg [2:0] sprAddr2 [pnSprm:0];  // index into sprite memory
reg [2:0] sprAddr3 [pnSprm:0];  // index into sprite memory
reg [2:0] sprAddr3 [pnSprm:0];  // index into sprite memory
reg [2:0] sprAddr4 [pnSprm:0];  // index into sprite memory
reg [2:0] sprAddr4 [pnSprm:0];  // index into sprite memory
reg [2:0] sprAddr5 [pnSprm:0];  // index into sprite memory
reg [2:0] sprAddr5 [pnSprm:0];  // index into sprite memory
reg [11:0] sprAddrB [pnSprm:0]; // backup address cache for rescan
reg [11:0] sprAddrB [pnSprm:0]; // backup address cache for rescan
wire [31:0] sprOut4 [pnSprm:0]; // sprite image data output
wire [31:0] sprOut4 [pnSprm:0]; // sprite image data output
reg [31:0] sprOut [pnSprm:0];   // sprite image data output
reg [31:0] sprOut [pnSprm:0];   // sprite image data output
reg [31:0] sprOut5 [pnSprm:0];  // sprite image data output
reg [31:0] sprOut5 [pnSprm:0];  // sprite image data output
 
wire [5:0] actcnt;      // count of sprites active at a given pixel location of the screen
 
 
// Animation
// Animation
reg [11:0] sprFrameSize [pnSprm:0];
reg [11:0] sprFrameSize [pnSprm:0];
reg [7:0] sprFrames [pnSprm:0];
reg [7:0] sprFrames [pnSprm:0];
reg [7:0] sprCurFrame [pnSprm:0];
reg [7:0] sprCurFrame [pnSprm:0];
reg [9:0] sprRate [pnSprm:0];
reg [9:0] sprRate [pnSprm:0];
reg [9:0] sprCurRateCount [pnSprm:0];
reg [9:0] sprCurRateCount [pnSprm:0];
reg [pnSprm:0] sprEnableAnimation;
reg [pnSprm:0] sprEnableAnimation;
reg [pnSprm:0] sprAutoRepeat;
reg [pnSprm:0] sprAutoRepeat;
 
reg [11:0] sprFrameProd [pnSprm:0];
 
 
// DMA access
// DMA access
reg [31:12] sprSysAddr [pnSprm:0];      // system memory address of sprite image (low bits)
reg [31:12] sprSysAddr [pnSprm:0];      // system memory address of sprite image (low bits)
reg [4:0] dmaOwner;                     // which sprite has the DMA channel
reg [4:0] dmaOwner;                     // which sprite has the DMA channel
reg [31:0] sprDt;               // DMA trigger register
reg [31:0] sprDt;               // DMA trigger register
reg dmaActive;                          // this flag indicates that a block DMA transfer is active
reg dmaActive;                          // this flag indicates that a block DMA transfer is active
genvar g;
genvar g;
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// DMA control / bus interfacing
// DMA control / bus interfacing
//--------------------------------------------------------------------
//--------------------------------------------------------------------
reg cs_regs;
reg cs_regs;
always_ff @(posedge s_clk_i)
always_ff @(posedge s_clk_i)
        cs_regs <= wbs_req.cyc & wbs_req.stb & s_cs_i;
        cs_regs <= wbs_req.cyc & wbs_req.stb & s_cs_i;
always_ff @(posedge s_clk_i)
always_ff @(posedge s_clk_i)
        wb_reqs <= wbs_req;
        wb_reqs <= wbs_req;
wire s_ack_o;
wire s_ack_o;
ack_gen #(
ack_gen #(
        .READ_STAGES(3),
        .READ_STAGES(3),
        .WRITE_STAGES(1),
        .WRITE_STAGES(1),
        .REGISTER_OUTPUT(1)
        .REGISTER_OUTPUT(1)
)
)
uag1 (
uag1 (
        .clk_i(s_clk_i),
        .clk_i(s_clk_i),
        .ce_i(1'b1),
        .ce_i(1'b1),
        .i(cs_regs),
        .i(cs_regs),
        .we_i(cs_regs & wb_reqs.we),
        .we_i(cs_regs & wb_reqs.we),
        .o(s_ack_o),
        .o(s_ack_o),
        .rid_i(0),
        .rid_i(0),
        .wid_i(0),
        .wid_i(0),
        .rid_o(),
        .rid_o(),
        .wid_o()
        .wid_o()
);
);
always_comb
always_comb
begin
begin
        wbs_resp.ack = s_ack_o & wbs_req.cyc & wbs_req.stb;
        wbs_resp.ack = s_ack_o & wbs_req.cyc & wbs_req.stb;
        wbs_resp.next = s_ack_o & wbs_req.cyc & wbs_req.stb;
        wbs_resp.next = s_ack_o & wbs_req.cyc & wbs_req.stb;
end
end
assign irq = sprSprIRQ|sprBkIRQ;
assign irq = sprSprIRQ|sprBkIRQ;
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// DMA control / bus interfacing
// DMA control / bus interfacing
//--------------------------------------------------------------------
//--------------------------------------------------------------------
reg [5:0] dmaStart;
reg [5:0] dmaStart;
reg [8:0] cob;  // count of burst cycles
reg [8:0] cob;  // count of burst cycles
assign wbm_req.bte = LINEAR;
assign wbm_req.bte = LINEAR;
assign wbm_req.cti = CLASSIC;
assign wbm_req.cti = CLASSIC;
 
assign wbm_req.blen = 6'd63;
assign wbm_req.stb = wbm_req.cyc;
assign wbm_req.stb = wbm_req.cyc;
assign wbm_req.sel = 16'hFFFF;
assign wbm_req.sel = 16'hFFFF;
assign wbm_req.cid = 4'd5;
assign wbm_req.cid = 4'd5;
assign m_spriteno_o = dmaOwner;
assign m_spriteno_o = dmaOwner;
reg [2:0] mstate;
reg [2:0] mstate;
parameter IDLE = 3'd0;
parameter IDLE = 3'd0;
parameter ACTIVE = 3'd1;
parameter ACTIVE = 3'd1;
parameter ACK = 3'd2;
parameter ACK = 3'd2;
parameter NACK = 3'd3;
parameter NACK = 3'd3;
wire pe_m_ack_i;
wire pe_m_ack_i;
edge_det ued2 (.rst(rst_i), .clk(m_clk_i), .ce(1'b1), .i(wbm_resp.ack), .pe(pe_m_ack_i), .ne(), .ee());
edge_det ued2 (.rst(rst_i), .clk(m_clk_i), .ce(1'b1), .i(wbm_resp.ack), .pe(pe_m_ack_i), .ne(), .ee());
 
 
 
reg [11:0] tocnt;
 
always_ff @(posedge m_clk_i)
 
if (rst_i)
 
        tocnt <= 'd0;
 
else begin
 
        if (wbm_req.cyc)
 
                tocnt <= tocnt + 2'd1;
 
        else
 
                tocnt <= 'd0;
 
end
 
 
always_ff @(posedge m_clk_i)
always_ff @(posedge m_clk_i)
if (rst_i)
if (rst_i)
        mstate <= IDLE;
        mstate <= IDLE;
else begin
else begin
        case(mstate)
        case(mstate)
        IDLE:
        IDLE:
                if (|sprDt & ce)
                if (|sprDt & ce)
                        mstate <= ACTIVE;
                        mstate <= ACTIVE;
        ACTIVE:
        ACTIVE:
                mstate <= ACK;
                mstate <= ACK;
        ACK:
        ACK:
                if (wbm_resp.ack | wbm_resp.err)
                if (wbm_resp.ack | wbm_resp.err | tocnt[10])
                        mstate <= NACK;
                        mstate <= NACK;
        NACK:
        NACK:
                if (~(wbm_resp.ack|wbm_resp.err))
                if (~(wbm_resp.ack|wbm_resp.err))
                        mstate <= cob==sprBurstEnd[dmaOwner] ? IDLE : ACTIVE;
                        mstate <= cob==sprBurstEnd[dmaOwner] ? IDLE : ACTIVE;
        default:
        default:
                mstate <= IDLE;
                mstate <= IDLE;
        endcase
        endcase
end
end
integer n30;
integer n30;
always_ff @(posedge m_clk_i)
always_ff @(posedge m_clk_i)
begin
begin
        case(mstate)
        case(mstate)
        IDLE:
        IDLE:
                begin
                begin
                        dmaOwner <= 5'd0;
                        dmaOwner <= 5'd0;
                        for (n30 = pnSprm; n30 >= 0; n30 = n30 - 1)
                        for (n30 = pnSprm; n30 >= 0; n30 = n30 - 1)
                                if (sprDt[n30])
                                if (sprDt[n30])
                                        dmaOwner <= n30;
                                        dmaOwner <= n30;
                end
                end
        default:        ;
        default:        ;
        endcase
        endcase
end
end
always_ff @(posedge m_clk_i)
always_ff @(posedge m_clk_i)
if (rst_i)
if (rst_i)
        dmaStart <= 6'b0;
        dmaStart <= 6'b0;
else begin
else begin
        dmaStart <= {dmaStart[4:0],1'b0};
        dmaStart <= {dmaStart[4:0],1'b0};
        case(mstate)
        case(mstate)
        IDLE:
        IDLE:
                if (|sprDt & ce)
                if (|sprDt & ce)
                        dmaStart <= 6'h3F;
                        dmaStart <= 6'h3F;
        default:        ;
        default:        ;
        endcase
        endcase
end
end
integer n32;
integer n32;
always_ff @(posedge m_clk_i)
always_ff @(posedge m_clk_i)
begin
begin
        case(mstate)
        case(mstate)
        IDLE:
        IDLE:
                for (n32 = pnSprm; n32 >= 0; n32 = n32 - 1)
                for (n32 = pnSprm; n32 >= 0; n32 = n32 - 1)
                        if (sprDt[n32])
                        if (sprDt[n32] & ce)
                                cob <= sprBurstStart[n32];
                                cob <= sprBurstStart[n32];
        ACTIVE:
        ACTIVE:
                cob <= cob + 2'd2;
                cob <= cob + 2'd2;
        default:        ;
        default:        ;
        endcase
        endcase
end
end
always_ff @(posedge m_clk_i)
always_ff @(posedge m_clk_i)
if (rst_i)
if (rst_i)
        wb_m_nack();
        wb_m_nack();
else begin
else begin
        case(mstate)
        case(mstate)
        IDLE:
        IDLE:
                wb_m_nack();
                wb_m_nack();
        ACTIVE:
        ACTIVE:
                begin
                begin
                        wbm_req.cyc <= 1'b1;
                        wbm_req.cyc <= 1'b1;
                        wbm_req.adr <= {sprSysAddr[dmaOwner],cob[8:1],4'h0};
                        wbm_req.adr <= {sprSysAddr[dmaOwner],cob[8:1],4'h0};
                end
                end
        ACK:
        ACK:
                if (wbm_resp.ack|wbm_resp.err)
                if (wbm_resp.ack|wbm_resp.err|tocnt[10])
                        wb_m_nack();
                        wb_m_nack();
        endcase
        endcase
end
end
task wb_m_nack;
task wb_m_nack;
begin
begin
        wbm_req.cyc <= 1'b0;
        wbm_req.cyc <= 1'b0;
end
end
endtask
endtask
// generate a write enable strobe for the sprite image memory
// generate a write enable strobe for the sprite image memory
integer n1;
integer n1;
reg [8:0] m_adr_or;
reg [8:0] m_adr_or;             // 64-bit value address
reg [127:0] m_dat_ir;
reg [127:0] m_dat_ir;
reg ack1;
reg ack1;
always_ff @(posedge m_clk_i)
always_ff @(posedge m_clk_i)
for (n1 = 0; n1 < pnSpr; n1 = n1 + 1)
for (n1 = 0; n1 < pnSpr; n1 = n1 + 1)
        sprWe[n1] <= (dmaOwner==n1 && (pe_m_ack_i||ack1));
        sprWe[n1] <= (dmaOwner==n1 && (pe_m_ack_i||ack1));
always_ff @(posedge m_clk_i)
always_ff @(posedge m_clk_i)
        ack1 <= pe_m_ack_i;
        ack1 <= pe_m_ack_i;
always_ff @(posedge m_clk_i)
always_ff @(posedge m_clk_i)
if (pe_m_ack_i|ack1)
if (pe_m_ack_i|ack1)
        m_adr_or <= {wbm_req.adr[11:4],ack1};
        m_adr_or <= {wbm_req.adr[11:4],ack1};
always_ff @(posedge m_clk_i)
always_ff @(posedge m_clk_i)
if (pe_m_ack_i) begin
if (pe_m_ack_i) begin
        if (test)
        if (test)
                m_dat_ir <= {8{1'b0,dmaOwner,10'b0}};
                m_dat_ir <= {8{1'b0,dmaOwner,10'b0}};
        else
        else
                m_dat_ir <= {wbm_resp.dat[63:0],wbm_resp.dat[127:64]};
                m_dat_ir <= {wbm_resp.dat[63:0],wbm_resp.dat[127:64]};
end
end
else if (ack1)
else if (ack1)
        m_dat_ir <= {64'd0,m_dat_ir[127:64]};
        m_dat_ir <= {64'd0,m_dat_ir[127:64]};
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------
reg [31:0] reg_shadow [0:255];
reg [31:0] reg_shadow [0:255];
reg [7:0] radr;
reg [7:0] radr;
always_ff @(posedge s_clk_i)
always_ff @(posedge s_clk_i)
begin
begin
    if (cs_regs & wb_reqs.we & wb_reqs.sel[0])  reg_shadow[wb_reqs.adr[9:2]][7:0] <= wb_reqs.dat[7:0];
    if (cs_regs & wb_reqs.we & wb_reqs.sel[0])  reg_shadow[wb_reqs.adr[9:2]][7:0] <= wb_reqs.dat[7:0];
    if (cs_regs & wb_reqs.we & wb_reqs.sel[1])  reg_shadow[wb_reqs.adr[9:2]][15:8] <= wb_reqs.dat[15:8];
    if (cs_regs & wb_reqs.we & wb_reqs.sel[1])  reg_shadow[wb_reqs.adr[9:2]][15:8] <= wb_reqs.dat[15:8];
    if (cs_regs & wb_reqs.we & wb_reqs.sel[2])  reg_shadow[wb_reqs.adr[9:2]][23:16] <= wb_reqs.dat[23:16];
    if (cs_regs & wb_reqs.we & wb_reqs.sel[2])  reg_shadow[wb_reqs.adr[9:2]][23:16] <= wb_reqs.dat[23:16];
    if (cs_regs & wb_reqs.we & wb_reqs.sel[3])  reg_shadow[wb_reqs.adr[9:2]][31:24] <= wb_reqs.dat[31:24];
    if (cs_regs & wb_reqs.we & wb_reqs.sel[3])  reg_shadow[wb_reqs.adr[9:2]][31:24] <= wb_reqs.dat[31:24];
end
end
always @(posedge s_clk_i)
always @(posedge s_clk_i)
  radr <= wb_reqs.adr[9:2];
  radr <= wb_reqs.adr[9:2];
wire [31:0] reg_shadow_o = reg_shadow[radr];
wire [31:0] reg_shadow_o = reg_shadow[radr];
// register/sprite memory output mux
// register/sprite memory output mux
always_ff @(posedge s_clk_i)
always_ff @(posedge s_clk_i)
        if (cs_regs)
        if (cs_regs)
                case (wb_reqs.adr[9:2])         // synopsys full_case parallel_case
                case (wb_reqs.adr[9:2])         // synopsys full_case parallel_case
                8'b11110000:    wbs_resp.dat <= sprEn;
                8'b11110000:    wbs_resp.dat <= sprEn;
                8'b11110001:    wbs_resp.dat <= {sprBkIRQPending|sprSprIRQPending,5'b0,sprBkIRQPending,sprSprIRQPending,6'b0,sprBkIe,sprSprIe};
                8'b11110001:    wbs_resp.dat <= {sprBkIRQPending|sprSprIRQPending,5'b0,sprBkIRQPending,sprSprIRQPending,6'b0,sprBkIe,sprSprIe};
                8'b11110010:    wbs_resp.dat <= sprSprCollision;
                8'b11110010:    wbs_resp.dat <= sprSprCollision;
                8'b11110011:    wbs_resp.dat <= sprBkCollision;
                8'b11110011:    wbs_resp.dat <= sprBkCollision;
                8'b11110100:    wbs_resp.dat <= sprDt;
                8'b11110100:    wbs_resp.dat <= sprDt;
                default:        wbs_resp.dat <= reg_shadow_o;
                default:        wbs_resp.dat <= reg_shadow_o;
                endcase
                endcase
        else
        else
                wbs_resp.dat <= 32'h0;
                wbs_resp.dat <= 32'h0;
// vclk -> clk_i
// vclk -> clk_i
always @(posedge s_clk_i)
always @(posedge s_clk_i)
begin
begin
        sprSprIRQ <= sprSprIRQ1;
        sprSprIRQ <= sprSprIRQ1;
        sprBkIRQ <= sprBkIRQ1;
        sprBkIRQ <= sprBkIRQ1;
        sprSprIRQPending <= sprSprIRQPending1;
        sprSprIRQPending <= sprSprIRQPending1;
        sprBkIRQPending <= sprBkIRQPending1;
        sprBkIRQPending <= sprBkIRQPending1;
        sprSprCollision <= sprSprCollision1;
        sprSprCollision <= sprSprCollision1;
        sprBkCollision <= sprBkCollision1;
        sprBkCollision <= sprBkCollision1;
end
end
// register updates
// register updates
// on the clk_i domain
// on the clk_i domain
reg vSync1;
reg vSync1;
integer n33;
integer n33;
always_ff @(posedge s_clk_i)
always_ff @(posedge s_clk_i)
if (rst_i) begin
if (rst_i) begin
        vSyncT <= 32'hFFFF0000;//FFFFFFFF;
        vSyncT <= 32'hFFFFFFFF;//FFFFFFFF;
        sprEn <= 32'hFFFFFFFF;
        sprEn <= 32'hFFFFFFFF;
        sprDt <= 0;
        sprDt <= 0;
  for (n33 = 0; n33 < pnSpr; n33 = n33 + 1) begin
  for (n33 = 0; n33 < pnSpr; n33 = n33 + 1) begin
                sprSysAddr[n33] <= 20'b0000_0000_0011_0000_0000 + n33;  //0030_0000
                sprSysAddr[n33] <= 20'b0000_0000_0011_0000_0000 + n33;  //0030_0000
        end
        end
        sprSprIe <= 0;
        sprSprIe <= 0;
        sprBkIe  <= 0;
        sprBkIe  <= 0;
  // Set reasonable starting positions on the screen
  // Set reasonable starting positions on the screen
  // so that the sprites might be visible for testing
  // so that the sprites might be visible for testing
  for (n33 = 0; n33 < pnSpr; n33 = n33 + 1) begin
  for (n33 = 0; n33 < pnSpr; n33 = n33 + 1) begin
    hSprPos[n33] <= 200 + (n33 & 7) * 70;
    hSprPos[n33] <= 200 + (n33 & 7) * 70;
    vSprPos[n33] <= 100 + (n33 >> 3) * 100;
    vSprPos[n33] <= 100 + (n33 >> 3) * 100;
    sprTc[n33] <= 24'h7FFF;             // White 16 bpp
    sprTc[n33] <= 24'h7FFF;             // White 16 bpp
                sprWidth[n33] <= 8'd16;         // 16x16 sprites
                sprWidth[n33] <= 8'd24;         // 16x16 sprites
                sprHeight[n33] <= 8'd16;
                sprHeight[n33] <= 8'd21;
                hSprRes[n33] <= 2;      // our standard display
                hSprRes[n33] <= 2'd2;   // our standard display
                vSprRes[n33] <= 2;
                vSprRes[n33] <= 2'd2;
                sprImageOffs[n33] <= 0;
                sprImageOffs[n33] <= 12'h0;
                sprPlane[n33] <= 4'hF;//n[3:0];
                sprPlane[n33] <= 4'h7;//n[3:0];
                sprBurstStart[n33] <= 9'h000;
                sprBurstStart[n33] <= 9'h000;
                sprBurstEnd[n33] <= 9'h1FE;
                sprBurstEnd[n33] <= 9'h1FE;
                sprColorDepth[n33] <= 2'b10;
                sprColorDepth[n33] <= 2'b10;
                sprFrameSize[n33] <= 12'd256;
                if (n33 >= 5'd29) begin
                sprFrames[n33] <= 8'd5;
                        sprFrameSize[n33] <= 12'd1936;
 
                        sprFrames[n33] <= 8'd0;
 
                end
 
                else begin
 
                        sprFrameSize[n33] <= 12'd504;
 
                        sprFrames[n33] <= 8'd3;
 
                end
                sprRate[n33] <= 12'd10;
                sprRate[n33] <= 12'd10;
                sprEnableAnimation[n33] <= 1'b1;
                sprEnableAnimation[n33] <= n33 < 5'd29;
                sprAutoRepeat[n33] <= 1'b1;
                sprAutoRepeat[n33] <= 1'b1;
        end
        end
  hSprPos[0] <= 210;
  hSprPos[0] <= 210;
  vSprPos[0] <= 72;
  vSprPos[0] <= 72;
  bgTc <= 24'h08_08_08;
  bgTc <= 24'h08_08_08;
  bkColor <= 24'hFF_FF_60;
  bkColor <= 24'hFF_FF_60;
end
end
else begin
else begin
        ce <= xonoff_i;
        ce <= xonoff_i;
        vSync1 <= vSync;
        vSync1 <= vSync;
        if (vSync & ~vSync1)
        if (vSync & ~vSync1)
                sprDt <= sprDt | vSyncT;
                sprDt <= sprDt | vSyncT;
        // clear DMA trigger bit once DMA is recognized
        // clear DMA trigger bit once DMA is recognized
        if (dmaStart[5])
        if (dmaStart[5])
                sprDt[dmaOwner] <= 1'b0;
                sprDt[dmaOwner] <= 1'b0;
        // Disable animation after frame count expired, if not auto-repeat.
        // Disable animation after frame count expired, if not auto-repeat.
  for (n33 = 0; n33 < pnSpr; n33 = n33 + 1)
  for (n33 = 0; n33 < pnSpr; n33 = n33 + 1)
                if (sprCurFrame[n33] >= sprFrames[n33] && !sprAutoRepeat[n33])
                if (sprCurFrame[n33] >= sprFrames[n33] && !sprAutoRepeat[n33])
                        sprEnableAnimation[n33] <= 1'b0;
                        sprEnableAnimation[n33] <= 1'b0;
        if (cs_regs & wb_reqs.we) begin
        if (cs_regs & wb_reqs.we) begin
                casez (wb_reqs.adr[9:2])
                casez (wb_reqs.adr[9:2])
                8'b100?????:
                8'b100?????:
                        begin
                        begin
                                if (&wb_reqs.sel[1:0]) sprBurstStart[wb_reqs.adr[6:2]] <= {wb_reqs.dat[8:1],1'b0};
                                if (&wb_reqs.sel[1:0]) sprBurstStart[wb_reqs.adr[6:2]] <= {wb_reqs.dat[8:1],1'b0};
                                if (&wb_reqs.sel[3:2]) sprBurstEnd[wb_reqs.adr[6:2]] <= {wb_reqs.dat[24:17],1'b0};
                                if (&wb_reqs.sel[3:2]) sprBurstEnd[wb_reqs.adr[6:2]] <= {wb_reqs.dat[24:17],1'b0};
                        end
                        end
                8'b101?????:
                8'b101?????:
                        begin
                        begin
                                if (wb_reqs.sel[0]) sprFrameSize[wb_reqs.adr[6:2]][11:4] <= wb_reqs.dat[7:0];
                                if (wb_reqs.sel[0]) sprFrameSize[wb_reqs.adr[6:2]][11:4] <= wb_reqs.dat[7:0];
                                if (wb_reqs.sel[1]) sprFrames[wb_reqs.adr[6:2]] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[1]) sprFrames[wb_reqs.adr[6:2]] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[2]) sprRate[wb_reqs.adr[6:2]][7:0] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[2]) sprRate[wb_reqs.adr[6:2]][7:0] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[3])
                                if (wb_reqs.sel[3])
                                        begin
                                        begin
                                                sprRate[wb_reqs.adr[6:2]][9:8] <= wb_reqs.dat[25:24];
                                                sprRate[wb_reqs.adr[6:2]][9:8] <= wb_reqs.dat[25:24];
                                                sprFrameSize[wb_reqs.adr[6:2]][3:0] <= wb_reqs.dat[29:26];
                                                sprFrameSize[wb_reqs.adr[6:2]][3:0] <= wb_reqs.dat[29:26];
                                                sprAutoRepeat[wb_reqs.adr[6:2]] <= wb_reqs.dat[30];
                                                sprAutoRepeat[wb_reqs.adr[6:2]] <= wb_reqs.dat[30];
                                                sprEnableAnimation[wb_reqs.adr[6:2]] <= wb_reqs.dat[31];
                                                sprEnableAnimation[wb_reqs.adr[6:2]] <= wb_reqs.dat[31];
                                        end
                                        end
                        end
                        end
                8'b11110000:    // 3C0
                8'b11110000:    // 3C0
                        begin
                        begin
                                if (wb_reqs.sel[0]) sprEn[7:0] <= wb_reqs.dat[7:0];
                                if (wb_reqs.sel[0]) sprEn[7:0] <= wb_reqs.dat[7:0];
                                if (wb_reqs.sel[1]) sprEn[15:8] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[1]) sprEn[15:8] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[2]) sprEn[23:16] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[2]) sprEn[23:16] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[3]) sprEn[31:24] <= wb_reqs.dat[31:24];
                                if (wb_reqs.sel[3]) sprEn[31:24] <= wb_reqs.dat[31:24];
                        end
                        end
                8'b11110001:    // 3C4
                8'b11110001:    // 3C4
                        if (wb_reqs.sel[0]) begin
                        if (wb_reqs.sel[0]) begin
                                sprSprIe <= wb_reqs.dat[0];
                                sprSprIe <= wb_reqs.dat[0];
                                sprBkIe <= wb_reqs.dat[1];
                                sprBkIe <= wb_reqs.dat[1];
                        end
                        end
                // update DMA trigger
                // update DMA trigger
                // s_wb_reqs.dat[7:0] indicates which triggers to set  (1=set,0=ignore)
                // s_wb_reqs.dat[7:0] indicates which triggers to set  (1=set,0=ignore)
                // s_wb_reqs.dat[7:0] indicates which triggers to clear (1=clear,0=ignore)
                // s_wb_reqs.dat[7:0] indicates which triggers to clear (1=clear,0=ignore)
                8'b11110100:    // 3D0
                8'b11110100:    // 3D0
                        begin
                        begin
                                if (wb_reqs.sel[0])     sprDt[7:0] <= sprDt[7:0] | wb_reqs.dat[7:0];
                                if (wb_reqs.sel[0])     sprDt[7:0] <= sprDt[7:0] | wb_reqs.dat[7:0];
                                if (wb_reqs.sel[1]) sprDt[15:8] <= sprDt[15:8] | wb_reqs.dat[15:8];
                                if (wb_reqs.sel[1]) sprDt[15:8] <= sprDt[15:8] | wb_reqs.dat[15:8];
                                if (wb_reqs.sel[2]) sprDt[23:16] <= sprDt[23:16] | wb_reqs.dat[23:16];
                                if (wb_reqs.sel[2]) sprDt[23:16] <= sprDt[23:16] | wb_reqs.dat[23:16];
                                if (wb_reqs.sel[3])     sprDt[31:24] <= sprDt[31:24] | wb_reqs.dat[31:24];
                                if (wb_reqs.sel[3])     sprDt[31:24] <= sprDt[31:24] | wb_reqs.dat[31:24];
                        end
                        end
                8'b11110101:    // 3D4
                8'b11110101:    // 3D4
                        begin
                        begin
                                if (wb_reqs.sel[0])     sprDt[7:0] <= sprDt[7:0] & ~wb_reqs.dat[7:0];
                                if (wb_reqs.sel[0])     sprDt[7:0] <= sprDt[7:0] & ~wb_reqs.dat[7:0];
                                if (wb_reqs.sel[1]) sprDt[15:8] <= sprDt[15:8] & ~wb_reqs.dat[15:8];
                                if (wb_reqs.sel[1]) sprDt[15:8] <= sprDt[15:8] & ~wb_reqs.dat[15:8];
                                if (wb_reqs.sel[2]) sprDt[23:16] <= sprDt[23:16] & ~wb_reqs.dat[23:16];
                                if (wb_reqs.sel[2]) sprDt[23:16] <= sprDt[23:16] & ~wb_reqs.dat[23:16];
                                if (wb_reqs.sel[3])     sprDt[31:24] <= sprDt[31:24] & ~wb_reqs.dat[31:24];
                                if (wb_reqs.sel[3])     sprDt[31:24] <= sprDt[31:24] & ~wb_reqs.dat[31:24];
                        end
                        end
                8'b11110110:    // 3D8
                8'b11110110:    // 3D8
                        begin
                        begin
                                if (wb_reqs.sel[0])     vSyncT[7:0] <= wb_reqs.dat[7:0];
                                if (wb_reqs.sel[0])     vSyncT[7:0] <= wb_reqs.dat[7:0];
                                if (wb_reqs.sel[1]) vSyncT[15:8] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[1]) vSyncT[15:8] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[2]) vSyncT[23:16] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[2]) vSyncT[23:16] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[3])     vSyncT[31:24] <= wb_reqs.dat[31:24];
                                if (wb_reqs.sel[3])     vSyncT[31:24] <= wb_reqs.dat[31:24];
                        end
                        end
                8'b11111010:    // 3E8
                8'b11111010:    // 3E8
                        begin
                        begin
                                if (wb_reqs.sel[0])     bgTc[7:0] <= wb_reqs.dat[7:0];
                                if (wb_reqs.sel[0])     bgTc[7:0] <= wb_reqs.dat[7:0];
                                if (wb_reqs.sel[1])     bgTc[15:8] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[1])     bgTc[15:8] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[2])     bgTc[23:16] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[2])     bgTc[23:16] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[3])     bgTc[29:24] <= wb_reqs.dat[29:24];
                                if (wb_reqs.sel[3])     bgTc[29:24] <= wb_reqs.dat[29:24];
                        end
                        end
                8'b11111011:    // 3EC
                8'b11111011:    // 3EC
                        begin
                        begin
                                if (wb_reqs.sel[0]) bkColor[7:0] <= wb_reqs.dat[7:0];
                                if (wb_reqs.sel[0]) bkColor[7:0] <= wb_reqs.dat[7:0];
                                if (wb_reqs.sel[1]) bkColor[15:8] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[1]) bkColor[15:8] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[2]) bkColor[23:16] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[2]) bkColor[23:16] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[3]) bkColor[29:24] <= wb_reqs.dat[29:24];
                                if (wb_reqs.sel[3]) bkColor[29:24] <= wb_reqs.dat[29:24];
                        end
                        end
//              8'b11111100:    // 3F0
//              8'b11111100:    // 3F0
//                      if (wb_reqs.sel[0]) ce <= wb_reqs[0];
//                      if (wb_reqs.sel[0]) ce <= wb_reqs[0];
                8'b0?????00:
                8'b0?????00:
                         begin
                         begin
                        if (wb_reqs.sel[0]) hSprPos[sprN][ 7:0] <= wb_reqs.dat[ 7: 0];
                        if (wb_reqs.sel[0]) hSprPos[sprN][ 7:0] <= wb_reqs.dat[ 7: 0];
                        if (wb_reqs.sel[1]) hSprPos[sprN][11:8] <= wb_reqs.dat[11: 8];
                        if (wb_reqs.sel[1]) hSprPos[sprN][11:8] <= wb_reqs.dat[11: 8];
                        if (wb_reqs.sel[2]) vSprPos[sprN][ 7:0] <= wb_reqs.dat[23:16];
                        if (wb_reqs.sel[2]) vSprPos[sprN][ 7:0] <= wb_reqs.dat[23:16];
                        if (wb_reqs.sel[3]) vSprPos[sprN][11:8] <= wb_reqs.dat[27:24];
                        if (wb_reqs.sel[3]) vSprPos[sprN][11:8] <= wb_reqs.dat[27:24];
                end
                end
    8'b0?????01:
    8'b0?????01:
                        begin
                        begin
                if (wb_reqs.sel[0]) begin
                if (wb_reqs.sel[0]) begin
                                        sprWidth[sprN] <= wb_reqs.dat[7:0];
                                        sprWidth[sprN] <= wb_reqs.dat[7:0];
        end
        end
                if (wb_reqs.sel[1]) begin
                if (wb_reqs.sel[1]) begin
                                        sprHeight[sprN] <= wb_reqs.dat[15:8];
                                        sprHeight[sprN] <= wb_reqs.dat[15:8];
        end
        end
                                if (wb_reqs.sel[2]) begin
                                if (wb_reqs.sel[2]) begin
                hSprRes[sprN] <= wb_reqs.dat[19:16];
                hSprRes[sprN] <= wb_reqs.dat[19:16];
                vSprRes[sprN] <= wb_reqs.dat[23:20];
                vSprRes[sprN] <= wb_reqs.dat[23:20];
                                end
                                end
                                if (wb_reqs.sel[3]) begin
                                if (wb_reqs.sel[3]) begin
                                        sprPlane[sprN] <= wb_reqs.dat[27:24];
                                        sprPlane[sprN] <= wb_reqs.dat[27:24];
                                        sprColorDepth[sprN] <= wb_reqs.dat[31:30];
                                        sprColorDepth[sprN] <= wb_reqs.dat[31:30];
                                end
                                end
                        end
                        end
                8'b0?????10:
                8'b0?????10:
                        begin   // DMA address set on clk_i domain
                        begin   // DMA address set on clk_i domain
        if (wb_reqs.sel[0]) sprImageOffs[sprN][ 7:0] <= wb_reqs.dat[7:0];
        if (wb_reqs.sel[0]) sprImageOffs[sprN][ 7:0] <= wb_reqs.dat[7:0];
        if (wb_reqs.sel[1]) sprImageOffs[sprN][11:8] <= wb_reqs.dat[11:8];
        if (wb_reqs.sel[1]) sprImageOffs[sprN][11:8] <= wb_reqs.dat[11:8];
                                if (wb_reqs.sel[1]) sprSysAddr[sprN][15:12] <= wb_reqs.dat[15:12];
                                if (wb_reqs.sel[1]) sprSysAddr[sprN][15:12] <= wb_reqs.dat[15:12];
                                if (wb_reqs.sel[2]) sprSysAddr[sprN][23:16] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[2]) sprSysAddr[sprN][23:16] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[3]) sprSysAddr[sprN][31:24] <= wb_reqs.dat[31:24];
                                if (wb_reqs.sel[3]) sprSysAddr[sprN][31:24] <= wb_reqs.dat[31:24];
                        end
                        end
                8'b0?????11:
                8'b0?????11:
                        begin
                        begin
                                if (wb_reqs.sel[0]) sprTc[sprN][ 7:0] <= wb_reqs.dat[ 7:0];
                                if (wb_reqs.sel[0]) sprTc[sprN][ 7:0] <= wb_reqs.dat[ 7:0];
                                if (wb_reqs.sel[1]) sprTc[sprN][15:8] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[1]) sprTc[sprN][15:8] <= wb_reqs.dat[15:8];
                                if (wb_reqs.sel[2]) sprTc[sprN][23:16] <= wb_reqs.dat[23:16];
                                if (wb_reqs.sel[2]) sprTc[sprN][23:16] <= wb_reqs.dat[23:16];
                        end
                        end
                default:        ;
                default:        ;
                endcase
                endcase
        end
        end
end
end
//-------------------------------------------------------------
//-------------------------------------------------------------
// Sprite Image Cache RAM
// Sprite Image Cache RAM
// This RAM is dual ported with an SoC side and a display
// This RAM is dual ported with an SoC side and a display
// controller side.
// controller side.
//-------------------------------------------------------------
//-------------------------------------------------------------
integer n2;
integer n2;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n2 = 0; n2 < pnSpr; n2 = n2 + 1)
for (n2 = 0; n2 < pnSpr; n2 = n2 + 1)
case(sprColorDepth[n2])
case(sprColorDepth[n2])
2'd1:   sprAddr1[n2] <= {sprAddr[n2][11:3],~sprAddr[n2][2]};
2'd1:   sprAddr1[n2] <= {sprAddr[n2][11:3],~sprAddr[n2][2]};
2'd2:   sprAddr1[n2] <= {sprAddr[n2][10:2],~sprAddr[n2][1]};
2'd2:   sprAddr1[n2] <= {sprAddr[n2][10:2],~sprAddr[n2][1]};
2'd3:   sprAddr1[n2] <= {sprAddr[n2][ 9:1],~sprAddr[n2][0]};
2'd3:   sprAddr1[n2] <= {sprAddr[n2][ 9:1],~sprAddr[n2][0]};
default:        ;
default:        ;
endcase
endcase
// The three LSBs of the image index need to be pipelined so they may be used
// The three LSBs of the image index need to be pipelined so they may be used
// to select the pixel. Output from the SRAM is always 32-bits wide so an
// to select the pixel. Output from the SRAM is always 32-bits wide so an
// additional mux is needed.
// additional mux is needed.
integer n4, n5, n27, n29;
integer n4, n5, n27, n29;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n4 = 0; n4 < pnSpr; n4 = n4 + 1)
for (n4 = 0; n4 < pnSpr; n4 = n4 + 1)
        sprAddr2[n4] <= ~sprAddr[n4][2:0];
        sprAddr2[n4] <= ~sprAddr[n4][2:0];
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n5 = 0; n5 < pnSpr; n5 = n5 + 1)
for (n5 = 0; n5 < pnSpr; n5 = n5 + 1)
        sprAddr3[n5] <= sprAddr2[n5];
        sprAddr3[n5] <= sprAddr2[n5];
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n27 = 0; n27 < pnSpr; n27 = n27 + 1)
for (n27 = 0; n27 < pnSpr; n27 = n27 + 1)
        sprAddr4[n27] <= sprAddr3[n27];
        sprAddr4[n27] <= sprAddr3[n27];
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n29 = 0; n29 < pnSpr; n29 = n29 + 1)
for (n29 = 0; n29 < pnSpr; n29 = n29 + 1)
        sprAddr5[n29] <= sprAddr4[n29];
        sprAddr5[n29] <= sprAddr4[n29];
// The pixels are displayed from most signicant to least signicant bits of the
// The pixels are displayed from most signicant to least signicant bits of the
// word. Display order is opposite to memory storage. So, the least significant
// word. Display order is opposite to memory storage. So, the least significant
// address bits are flipped to get the correct display.
// address bits are flipped to get the correct display.
integer n3;
integer n3;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n3 = 0; n3 < pnSpr; n3 = n3 + 1)
for (n3 = 0; n3 < pnSpr; n3 = n3 + 1)
case(sprColorDepth[n3])
case(sprColorDepth[n3])
2'd1:
2'd1:
        case(sprAddr5[n3][1:0])
        case(sprAddr5[n3][1:0])
        2'd3:   sprOut5[n3] <= sprOut4[n3][31:24];
        2'd3:   sprOut5[n3] <= sprOut4[n3][31:24];
        2'd2:   sprOut5[n3] <= sprOut4[n3][23:16];
        2'd2:   sprOut5[n3] <= sprOut4[n3][23:16];
        2'd1:   sprOut5[n3] <= sprOut4[n3][15:8];
        2'd1:   sprOut5[n3] <= sprOut4[n3][15:8];
        2'd0:   sprOut5[n3] <= sprOut4[n3][7:0];
        2'd0:   sprOut5[n3] <= sprOut4[n3][7:0];
        endcase
        endcase
2'd2:
2'd2:
        case(sprAddr5[n3][0])
        case(sprAddr5[n3][0])
        1'd0:   sprOut5[n3] <= {sprOut4[n3][15],16'h0000,sprOut4[n3][14:0]};
        1'd0:   sprOut5[n3] <= {sprOut4[n3][15],16'h0000,sprOut4[n3][14:0]};
        1'd1:   sprOut5[n3] <= {sprOut4[n3][31],16'h0000,sprOut4[n3][30:16]};
        1'd1:   sprOut5[n3] <= {sprOut4[n3][31],16'h0000,sprOut4[n3][30:16]};
        endcase
        endcase
2'd3:
2'd3:
        sprOut5[n3] <= sprOut4[n3];
        sprOut5[n3] <= sprOut4[n3];
default:        ;
default:        ;
endcase
endcase
generate
generate
for (g = 0; g < pnSpr; g = g + 1) begin : sprRam
for (g = 0; g < pnSpr; g = g + 1) begin : sprRam
        SpriteRam sprRam0
        SpriteRam sprRam0
        (
        (
                .clka(m_clk_i),
                .clka(m_clk_i),
                .addra(m_adr_or),
                .addra(m_adr_or),
                .dina(m_dat_ir[63:0]),
                .dina(m_dat_ir[63:0]),
                .ena(sprWe[g]),
                .ena(sprWe[g]),
                .wea(sprWe[g]),
                .wea(sprWe[g]),
                // Core reg and output reg 3 clocks from read address
                // Core reg and output reg 3 clocks from read address
                .clkb(vclk),
                .clkb(vclk),
                .addrb(sprAddr1[g]),
                .addrb(sprAddr1[g]),
                .doutb(sprOut4[g]),
                .doutb(sprOut4[g]),
                .enb(1'b1)
                .enb(1'b1)
        );
        );
        end
        end
endgenerate
endgenerate
//-------------------------------------------------------------
//-------------------------------------------------------------
// Timing counters and addressing
// Timing counters and addressing
// Sprites are like miniature bitmapped displays, they need
// Sprites are like miniature bitmapped displays, they need
// all the same timing controls.
// all the same timing controls.
//-------------------------------------------------------------
//-------------------------------------------------------------
// Create a timing reference using horizontal and vertical
// Create a timing reference using horizontal and vertical
// sync
// sync
wire hSyncEdge, vSyncEdge;
wire hSyncEdge, vSyncEdge;
edge_det ed0(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(hSync), .pe(hSyncEdge), .ne(), .ee() );
edge_det ed0(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(hSync), .pe(hSyncEdge), .ne(), .ee() );
edge_det ed1(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(vSync), .pe(vSyncEdge), .ne(), .ee() );
edge_det ed1(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(vSync), .pe(vSyncEdge), .ne(), .ee() );
always_ff @(posedge vclk)
always_ff @(posedge vclk)
if (hSyncEdge) hctr <= {phBits{1'b0}};
if (hSyncEdge) hctr <= {phBits{1'b0}};
else hctr <= hctr + 2'd1;
else hctr <= hctr + 2'd1;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
if (vSyncEdge) vctr <= {pvBits{1'b0}};
if (vSyncEdge) vctr <= {pvBits{1'b0}};
else if (hSyncEdge) vctr <= vctr + 2'd1;
else if (hSyncEdge) vctr <= vctr + 2'd1;
// track sprite horizontal reset
// track sprite horizontal reset
integer n19;
integer n19;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n19 = 0; n19 < pnSpr; n19 = n19 + 1)
for (n19 = 0; n19 < pnSpr; n19 = n19 + 1)
        hSprReset[n19] <= hctr==hSprPos[n19];
        hSprReset[n19] <= hctr==hSprPos[n19];
// track sprite vertical reset
// track sprite vertical reset
integer n20;
integer n20;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n20 = 0; n20 < pnSpr; n20 = n20 + 1)
for (n20 = 0; n20 < pnSpr; n20 = n20 + 1)
        vSprReset[n20] <= vctr==vSprPos[n20];
        vSprReset[n20] <= vctr==vSprPos[n20];
integer n21;
integer n21;
always_comb
always_comb
for (n21 = 0; n21 < pnSpr; n21 = n21 + 1)
for (n21 = 0; n21 < pnSpr; n21 = n21 + 1)
        sprDe[n21] <= hSprDe[n21] & vSprDe[n21];
        sprDe[n21] <= hSprDe[n21] & vSprDe[n21];
// take care of sprite size scaling
// take care of sprite size scaling
// video clock division
// video clock division
reg [31:0] hSprNextPixel;
reg [31:0] hSprNextPixel;
reg [31:0] vSprNextPixel;
reg [31:0] vSprNextPixel;
reg [3:0] hSprPt [31:0];   // horizontal pixel toggle
reg [3:0] hSprPt [31:0];   // horizontal pixel toggle
reg [3:0] vSprPt [31:0];   // vertical pixel toggle
reg [3:0] vSprPt [31:0];   // vertical pixel toggle
integer n17;
integer n17;
always_comb
always_comb
for (n17 = 0; n17 < pnSpr; n17 = n17 + 1)
for (n17 = 0; n17 < pnSpr; n17 = n17 + 1)
    hSprNextPixel[n17] = hSprPt[n17]==hSprRes[n17];
    hSprNextPixel[n17] = hSprPt[n17]==hSprRes[n17];
integer n18;
integer n18;
always_comb
always_comb
for (n18 = 0; n18 < pnSpr; n18 = n18 + 1)
for (n18 = 0; n18 < pnSpr; n18 = n18 + 1)
    vSprNextPixel[n18] = vSprPt[n18]==vSprRes[n18];
    vSprNextPixel[n18] = vSprPt[n18]==vSprRes[n18];
// horizontal pixel toggle counter
// horizontal pixel toggle counter
integer n6;
integer n6;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n6 = 0; n6 < pnSpr; n6 = n6 + 1)
for (n6 = 0; n6 < pnSpr; n6 = n6 + 1)
        if (hSprReset[n6])
        if (hSprReset[n6])
                hSprPt[n6] <= 4'd0;
                hSprPt[n6] <= 4'd0;
  else if (hSprNextPixel[n6])
  else if (hSprNextPixel[n6])
    hSprPt[n6] <= 4'd0;
    hSprPt[n6] <= 4'd0;
  else
  else
    hSprPt[n6] <= hSprPt[n6] + 2'd1;
    hSprPt[n6] <= hSprPt[n6] + 2'd1;
// vertical pixel toggle counter
// vertical pixel toggle counter
integer n7;
integer n7;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n7 = 0; n7 < pnSpr; n7 = n7 + 1)
for (n7 = 0; n7 < pnSpr; n7 = n7 + 1)
  if (hSprReset[n7]) begin
  if (hSprReset[n7]) begin
        if (vSprReset[n7])
        if (vSprReset[n7])
                vSprPt[n7] <= 4'd0;
                vSprPt[n7] <= 4'd0;
    else if (vSprNextPixel[n7])
    else if (vSprNextPixel[n7])
      vSprPt[n7] <= 4'd0;
      vSprPt[n7] <= 4'd0;
    else
    else
      vSprPt[n7] <= vSprPt[n7] + 2'd1;
      vSprPt[n7] <= vSprPt[n7] + 2'd1;
  end
  end
// Animation rate count and frame increment.
// Animation rate count and frame increment.
integer n28;
integer n28;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
        if (vSyncEdge) begin
        if (vSyncEdge) begin
                for (n28 = 0; n28 < pnSpr; n28 = n28 + 1) begin
                for (n28 = 0; n28 < pnSpr; n28 = n28 + 1) begin
                        if (sprEnableAnimation[n28]) begin
                        if (sprEnableAnimation[n28]) begin
                                sprCurRateCount[n28] <= sprCurRateCount[n28] + 2'd1;
                                sprCurRateCount[n28] <= sprCurRateCount[n28] + 2'd1;
                                if (sprCurRateCount[n28] >= sprRate[n28]) begin
                                if (sprCurRateCount[n28] >= sprRate[n28]) begin
                                        sprCurRateCount[n28] <= 'd0;
                                        sprCurRateCount[n28] <= 'd0;
                                        sprCurFrame[n28] <= sprCurFrame[n28] + 2'd1;
                                        sprCurFrame[n28] <= sprCurFrame[n28] + 2'd1;
                                        if (sprCurFrame[n28] >= sprFrames[n28])
                                        sprFrameProd[n28] <= sprFrameProd[n28] + sprFrameSize[n28];
 
                                        if (sprCurFrame[n28] >= sprFrames[n28]) begin
                                                sprCurFrame[n28] <= 'd0;
                                                sprCurFrame[n28] <= 'd0;
 
                                                sprFrameProd[n28] <= 'd0;
                                end
                                end
                        end
                        end
                        else
                        end
 
                        else begin
                                sprCurFrame[n28] <= 'd0;
                                sprCurFrame[n28] <= 'd0;
 
                                sprFrameProd[n28] <= 'd0;
 
                        end
                end
                end
        end
        end
// clock sprite image address counters
// clock sprite image address counters
integer n8;
integer n8;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n8 = 0; n8 < pnSpr; n8 = n8 + 1) begin
for (n8 = 0; n8 < pnSpr; n8 = n8 + 1) begin
    // hReset and vReset - top left of sprite,
    // hReset and vReset - top left of sprite,
    // reset address to image offset
    // reset address to image offset
        if (hSprReset[n8] & vSprReset[n8]) begin
        if (hSprReset[n8] & vSprReset[n8]) begin
                sprAddr[n8]  <= sprImageOffs[n8] + sprCurFrame[n8] * sprFrameSize[n8];
                sprAddr[n8]  <= sprImageOffs[n8] + sprFrameProd[n8];
                sprAddrB[n8] <= sprImageOffs[n8] + sprCurFrame[n8] * sprFrameSize[n8];
                sprAddrB[n8] <= sprImageOffs[n8] + sprFrameProd[n8];
        end
        end
        // hReset:
        // hReset:
        //  If the next vertical pixel
        //  If the next vertical pixel
        //      set backup address to current address
        //      set backup address to current address
        //  else
        //  else
        //      set current address to backup address
        //      set current address to backup address
        //      in order to rescan the line
        //      in order to rescan the line
        else if (hSprReset[n8]) begin
        else if (hSprReset[n8]) begin
                if (vSprNextPixel[n8])
                if (vSprNextPixel[n8])
                        sprAddrB[n8] <= sprAddr[n8];
                        sprAddrB[n8] <= sprAddr[n8];
                else
                else
                        sprAddr[n8]  <= sprAddrB[n8];
                        sprAddr[n8]  <= sprAddrB[n8];
        end
        end
        // Not hReset or vReset - somewhere on the sprite scan line
        // Not hReset or vReset - somewhere on the sprite scan line
        // just advance the address when the next pixel should be
        // just advance the address when the next pixel should be
        // fetched
        // fetched
        else if (hSprDe[n8] & hSprNextPixel[n8])
        else if (hSprDe[n8] & hSprNextPixel[n8])
                sprAddr[n8] <= sprAddr[n8] + 2'd1;
                sprAddr[n8] <= sprAddr[n8] + 2'd1;
end
end
// clock sprite column (X) counter
// clock sprite column (X) counter
integer n9;
integer n9;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n9 = 0; n9 < pnSpr; n9 = n9 + 1)
for (n9 = 0; n9 < pnSpr; n9 = n9 + 1)
        if (hSprReset[n9])
        if (hSprReset[n9])
                hSprCnt[n9] <= 8'd1;
                hSprCnt[n9] <= 8'd1;
        else if (hSprNextPixel[n9])
        else if (hSprNextPixel[n9])
                hSprCnt[n9] <= hSprCnt[n9] + 2'd1;
                hSprCnt[n9] <= hSprCnt[n9] + 2'd1;
// clock sprite horizontal display enable
// clock sprite horizontal display enable
integer n10;
integer n10;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n10 = 0; n10 < pnSpr; n10 = n10 + 1) begin
for (n10 = 0; n10 < pnSpr; n10 = n10 + 1) begin
        if (hSprReset[n10])
        if (hSprReset[n10])
                hSprDe[n10] <= 1'b1;
                hSprDe[n10] <= 1'b1;
        else if (hSprNextPixel[n10]) begin
        else if (hSprNextPixel[n10]) begin
                if (hSprCnt[n10] == sprWidth[n10])
                if (hSprCnt[n10] == sprWidth[n10])
                        hSprDe[n10] <= 1'b0;
                        hSprDe[n10] <= 1'b0;
        end
        end
end
end
// clock the sprite row (Y) counter
// clock the sprite row (Y) counter
integer n11;
integer n11;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n11 = 0; n11 < pnSpr; n11 = n11 + 1)
for (n11 = 0; n11 < pnSpr; n11 = n11 + 1)
        if (hSprReset[n11]) begin
        if (hSprReset[n11]) begin
                if (vSprReset[n11])
                if (vSprReset[n11])
                        vSprCnt[n11] <= 8'd1;
                        vSprCnt[n11] <= 8'd1;
                else if (vSprNextPixel[n11])
                else if (vSprNextPixel[n11])
                        vSprCnt[n11] <= vSprCnt[n11] + 2'd1;
                        vSprCnt[n11] <= vSprCnt[n11] + 2'd1;
        end
        end
// clock sprite vertical display enable
// clock sprite vertical display enable
integer n12;
integer n12;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n12 = 0; n12 < pnSpr; n12 = n12 + 1) begin
for (n12 = 0; n12 < pnSpr; n12 = n12 + 1) begin
        if (hSprReset[n12]) begin
        if (hSprReset[n12]) begin
                if (vSprReset[n12])
                if (vSprReset[n12])
                        vSprDe[n12] <= 1'b1;
                        vSprDe[n12] <= 1'b1;
                else if (vSprNextPixel[n12]) begin
                else if (vSprNextPixel[n12]) begin
                        if (vSprCnt[n12] == sprHeight[n12])
                        if (vSprCnt[n12] == sprHeight[n12])
                                vSprDe[n12] <= 1'b0;
                                vSprDe[n12] <= 1'b0;
                end
                end
        end
        end
end
end
//-------------------------------------------------------------
//-------------------------------------------------------------
// Output stage
// Output stage
//-------------------------------------------------------------
//-------------------------------------------------------------
// function used for color blending
// function used for color blending
// given an alpha and a color component, determine the resulting color
// given an alpha and a color component, determine the resulting color
// this blends towards black or white
// this blends towards black or white
// alpha is eight bits ranging between 0 and 1.999...
// alpha is eight bits ranging between 0 and 1.999...
// 1 bit whole, 7 bits fraction
// 1 bit whole, 7 bits fraction
function [11:0] fnBlend;
function [11:0] fnBlend;
input [7:0] alpha;
input [7:0] alpha;
input [11:0] color1bits;
input [11:0] color1bits;
input [11:0] color2bits;
input [11:0] color2bits;
begin
begin
        fnBlend = (({8'b0,color1bits} * alpha) >> 7) + (({8'h00,color2bits} * (9'h100 - alpha)) >> 7);
        fnBlend = (({8'b0,color1bits} * alpha) >> 7) + (({8'h00,color2bits} * (9'h100 - alpha)) >> 7);
end
end
endfunction
endfunction
// pipeline delays for display enable
// pipeline delays for display enable
reg [31:0] sprDe1, sprDe2, sprDe3, sprDe4, sprDe5, sprDe6;
reg [31:0] sprDe1, sprDe2, sprDe3, sprDe4, sprDe5, sprDe6;
reg [31:0] sproact;
reg [31:0] sproact;
integer n13;
integer n13;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n13 = 0; n13 < pnSpr; n13 = n13 + 1)
for (n13 = 0; n13 < pnSpr; n13 = n13 + 1)
        sprDe1[n13] <= sprDe[n13];
        sprDe1[n13] <= sprDe[n13];
integer n22;
integer n22;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n22 = 0; n22 < pnSpr; n22 = n22 + 1)
for (n22 = 0; n22 < pnSpr; n22 = n22 + 1)
        sprDe2[n22] <= sprDe1[n22];
        sprDe2[n22] <= sprDe1[n22];
integer n23;
integer n23;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n23 = 0; n23 < pnSpr; n23 = n23 + 1)
for (n23 = 0; n23 < pnSpr; n23 = n23 + 1)
        sprDe3[n23] <= sprDe2[n23];
        sprDe3[n23] <= sprDe2[n23];
integer n24;
integer n24;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n24 = 0; n24 < pnSpr; n24 = n24 + 1)
for (n24 = 0; n24 < pnSpr; n24 = n24 + 1)
        sprDe4[n24] <= sprDe3[n24];
        sprDe4[n24] <= sprDe3[n24];
integer n25;
integer n25;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n25 = 0; n25 < pnSpr; n25 = n25 + 1)
for (n25 = 0; n25 < pnSpr; n25 = n25 + 1)
        sprDe5[n25] <= sprDe4[n25];
        sprDe5[n25] <= sprDe4[n25];
integer n26;
integer n26;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n26 = 0; n26 < pnSpr; n26 = n26 + 1)
for (n26 = 0; n26 < pnSpr; n26 = n26 + 1)
        sprDe6[n26] <= sprDe5[n26];
        sprDe6[n26] <= sprDe5[n26];
// Detect which sprite outputs are active
// Detect which sprite outputs are active
// The sprite output is active if the current display pixel
// The sprite output is active if the current display pixel
// address is within the sprite's area, the sprite is enabled,
// address is within the sprite's area, the sprite is enabled,
// and it's not a transparent pixel that's being displayed.
// and it's not a transparent pixel that's being displayed.
integer n14;
integer n14;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n14 = 0; n14 < pnSpr; n14 = n14 + 1)
for (n14 = 0; n14 < pnSpr; n14 = n14 + 1)
        sproact[n14] <= sprEn[n14] && sprDe5[n14] && sprTc[n14]!=sprOut5[n14];
        sproact[n14] <= sprEn[n14] && sprDe5[n14] && sprTc[n14]!=sprOut5[n14];
integer n15;
integer n15;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
for (n15 = 0; n15 < pnSpr; n15 = n15 + 1)
for (n15 = 0; n15 < pnSpr; n15 = n15 + 1)
        sprOut[n15] <= sprOut5[n15];
        sprOut[n15] <= sprOut5[n15];
// register sprite activity flag
// register sprite activity flag
// The image combiner uses this flag to know what to do with
// The image combiner uses this flag to know what to do with
// the sprite output.
// the sprite output.
always_ff @(posedge vclk)
always_ff @(posedge vclk)
        outact <= |sproact & ce;
        outact <= |sproact & ce;
// Display data comes from the active sprite with the
// Display data comes from the active sprite with the
// highest display priority.
// highest display priority.
// Make sure that alpha blending is turned off when
// Make sure that alpha blending is turned off when
// no sprite is active.
// no sprite is active.
integer n16;
integer n16;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
begin
begin
        out <= 32'h0080;        // alpha blend max (and off)
        out <= 32'h0080;        // alpha blend max (and off)
        outplane <= 4'h0;
        outplane <= 4'h0;
        colorBits <= 2'b00;
        colorBits <= 2'b00;
        for (n16 = pnSprm; n16 >= 0; n16 = n16 - 1)
        for (n16 = pnSprm; n16 >= 0; n16 = n16 - 1)
                if (sproact[n16]) begin
                if (sproact[n16]) begin
                        out <= sprOut[n16];
                        out <= sprOut[n16];
                        outplane <= sprPlane[n16];
                        outplane <= sprPlane[n16];
                        colorBits <= sprColorDepth[n16];
                        colorBits <= sprColorDepth[n16];
                end
                end
end
end
// combine the text / graphics color output with sprite color output
// combine the text / graphics color output with sprite color output
// blend color output
// blend color output
wire [35:0] blendedColor32 = {
wire [35:0] blendedColor32 = {
        fnBlend(out[31:24],{out[23:16],4'h0},zrgb_i[35:24]),
        fnBlend(out[31:24],{out[23:16],4'h0},zrgb_i[35:24]),
        fnBlend(out[31:24],{out[15:8],4'h0},zrgb_i[23:12]),
        fnBlend(out[31:24],{out[15:8],4'h0},zrgb_i[23:12]),
        fnBlend(out[31:24],{out[7:0],4'h0},zrgb_i[11: 0])}
        fnBlend(out[31:24],{out[7:0],4'h0},zrgb_i[11: 0])}
        ;
        ;
wire [35:0] blendedColor16 = {
wire [35:0] blendedColor16 = {
        fnBlend(out[7:0],zrgb_i[35:24],12'h0),
        fnBlend(out[7:0],zrgb_i[35:24],12'h0),
        fnBlend(out[7:0],zrgb_i[23:12],12'h0),
        fnBlend(out[7:0],zrgb_i[23:12],12'h0),
        fnBlend(out[7:0],zrgb_i[11: 0],12'h0)}
        fnBlend(out[7:0],zrgb_i[11: 0],12'h0)}
        ;
        ;
always_ff @(posedge vclk)
always_ff @(posedge vclk)
if (blank_i)
if (blank_i)
        zrgb_o <= 0;
        zrgb_o <= 0;
else begin
else begin
        if (outact) begin
        if (outact) begin
                if (zrgb_i[39:36] > outplane) begin                     // rgb input is in front of sprite
                if (zrgb_i[39:36] > outplane) begin                     // rgb input is in front of sprite
                        zrgb_o <= zrgb_i;
                        zrgb_o <= zrgb_i;
                end
                end
                else
                else
                if (!out[31]) begin                     // a sprite is displayed without alpha blending
                if (!out[31]) begin                     // a sprite is displayed without alpha blending
                        case(colorBits)
                        case(colorBits)
                        2'd0:   zrgb_o <= {outplane,out[7:5],9'b0,out[4:2],9'b0,out[1:0],10'b0};
                        2'd0:   zrgb_o <= {outplane,out[7:5],9'b0,out[4:2],9'b0,out[1:0],10'b0};
                        2'd1:   zrgb_o <= {outplane,out[7:5],9'b0,out[4:2],9'b0,out[1:0],10'b0};
                        2'd1:   zrgb_o <= {outplane,out[7:5],9'b0,out[4:2],9'b0,out[1:0],10'b0};
                        2'd2:   zrgb_o <= {outplane,out[14:10],7'b0,out[9:5],7'b0,out[4:0],7'b0};
                        2'd2:   zrgb_o <= {outplane,out[14:10],7'b0,out[9:5],7'b0,out[4:0],7'b0};
                        2'd3:   zrgb_o <= zrgb_o <= {outplane,blendedColor32};  // combine colors {outplane,out[23:16],4'h0,out[15:8],4'h0,out[7:0],4'h0};
                        2'd3:   zrgb_o <= zrgb_o <= {outplane,blendedColor32};  // combine colors {outplane,out[23:16],4'h0,out[15:8],4'h0,out[7:0],4'h0};
                        endcase
                        endcase
                end
                end
                else
                else
                        case(colorBits)
                        case(colorBits)
                        2'd2:   zrgb_o <= {outplane,blendedColor16};    // towards black/white
                        2'd2:   zrgb_o <= {outplane,blendedColor16};    // towards black/white
                        2'd3:   zrgb_o <= {outplane,blendedColor32};    // combine colors
                        2'd3:   zrgb_o <= {outplane,blendedColor32};    // combine colors
                        default:        zrgb_o <= {outplane,out[7:5],9'b0,out[4:2],9'b0,out[1:0],10'b0};        // no blending
                        default:        zrgb_o <= {outplane,out[7:5],9'b0,out[4:2],9'b0,out[1:0],10'b0};        // no blending
                        endcase
                        endcase
        end
        end
        else
        else
                zrgb_o <= zrgb_i;
                zrgb_o <= zrgb_i;
end
end
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Collision logic
// Collision logic
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Detect when a sprite-sprite collision has occurred. The criteria
// Detect when a sprite-sprite collision has occurred. The criteria
// for this is that a pixel from the sprite is being displayed, while
// for this is that a pixel from the sprite is being displayed, while
// there is a pixel from another sprite that could be displayed at the
// there is a pixel from another sprite that could be displayed at the
// same time.
// same time.
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Note this case has to be modified for the number of sprites
 
// ToDo: make collision also depend on plane
// ToDo: make collision also depend on plane
//--------------------------------------------------------------------
//--------------------------------------------------------------------
generate
 
begin : gSprsColliding
cntpop32 ucntp1 (
always @(pnSpr or sproact)
        .i(sproact),
if (pnSpr==1)
        .o(actcnt)
        sprCollision = 0;
);
else if (pnSpr==2)
 
        case (sproact)
 
        2'b00,
 
        2'b01,
 
        2'b10:  sprCollision = 0;
 
        2'b11:  sprCollision = 1;
 
        endcase
 
else if (pnSpr==4)
 
        case (sproact)
 
        4'b0000,
 
        4'b0001,
 
        4'b0010,
 
        4'b0100,
 
        4'b1000:        sprCollision = 0;
 
        default:        sprCollision = 1;
 
        endcase
 
else if (pnSpr==6)
 
        case (sproact)
 
        6'b000000,
 
        6'b000001,
 
        6'b000010,
 
        6'b000100,
 
        6'b001000,
 
        6'b010000,
 
        8'b100000:      sprCollision = 0;
 
        default:        sprCollision = 1;
 
        endcase
 
else if (pnSpr==8)
 
        case (sproact)
 
        8'b00000000,
 
        8'b00000001,
 
        8'b00000010,
 
        8'b00000100,
 
        8'b00001000,
 
        8'b00010000,
 
        8'b00100000,
 
        8'b01000000,
 
        8'b10000000:    sprCollision = 0;
 
        default:                sprCollision = 1;
 
        endcase
 
else if (pnSpr==10)
 
        case (sproact)
 
        10'b0000000000,
 
        10'b0000000001,
 
        10'b0000000010,
 
        10'b0000000100,
 
        10'b0000001000,
 
        10'b0000010000,
 
        10'b0000100000,
 
        10'b0001000000,
 
        10'b0010000000,
 
        10'b0100000000,
 
        10'b1000000000: sprCollision = 0;
 
        default:                sprCollision = 1;
 
        endcase
 
else if (pnSpr==14)
 
        case (sproact)
 
        14'b00000000000000,
 
        14'b00000000000001,
 
        14'b00000000000010,
 
        14'b00000000000100,
 
        14'b00000000001000,
 
        14'b00000000010000,
 
        14'b00000000100000,
 
        14'b00000001000000,
 
        14'b00000010000000,
 
        14'b00000100000000,
 
        14'b00001000000000,
 
        14'b00010000000000,
 
        14'b00100000000000,
 
        14'b01000000000000,
 
        14'b10000000000000:     sprCollision = 0;
 
        default:                        sprCollision = 1;
 
        endcase
 
else if (pnSpr==16)
 
        case (sproact)
 
        16'h0000,
 
        16'h0001,
 
        16'h0002,
 
        16'h0004,
 
        16'h0008,
 
        16'h0010,
 
        16'h0020,
 
        16'h0040,
 
        16'h0080,
 
        16'h0100,
 
        16'h0200,
 
        16'h0400,
 
        16'h0800,
 
        16'h1000,
 
        16'h2000,
 
        16'h4000,
 
        16'h8000:       sprCollision = 0;
 
        default:        sprCollision = 1;
 
        endcase
 
else if (pnSpr==32)
 
        case (sproact)
 
        32'h00000000,
 
        32'h00000001,
 
        32'h00000002,
 
        32'h00000004,
 
        32'h00000008,
 
        32'h00000010,
 
        32'h00000020,
 
        32'h00000040,
 
        32'h00000080,
 
        32'h00000100,
 
        32'h00000200,
 
        32'h00000400,
 
        32'h00000800,
 
        32'h00001000,
 
        32'h00002000,
 
        32'h00004000,
 
        32'h00008000,
 
        32'h00010000,
 
        32'h00020000,
 
        32'h00040000,
 
        32'h00080000,
 
        32'h00100000,
 
        32'h00200000,
 
        32'h00400000,
 
        32'h00800000,
 
        32'h01000000,
 
        32'h02000000,
 
        32'h04000000,
 
        32'h08000000,
 
        32'h10000000,
 
        32'h20000000,
 
        32'h40000000,
 
        32'h80000000:           sprCollision = 0;
 
        default:                        sprCollision = 1;
 
        endcase
 
end
 
endgenerate
 
 
 
// Detect when a sprite-background collision has occurred
// Detect when a sprite-background collision has occurred
integer n31;
integer n31;
always_comb
always_comb
for (n31 = 0; n31 < pnSpr; n31 = n31 + 1)
for (n31 = 0; n31 < pnSpr; n31 = n31 + 1)
        bkCollision[n31] <=
        bkCollision[n31] <=
                sproact[n31] && zrgb_i[39:36]==sprPlane[n31];
                sproact[n31] && zrgb_i[39:36]==sprPlane[n31];
// Load the sprite collision register. This register continually
// Load the sprite collision register. This register continually
// accumulates collision bits until reset by reading the register.
// accumulates collision bits until reset by reading the register.
// Set the collision IRQ on the first collision and don't set it
// Set the collision IRQ on the first collision and don't set it
// again until after the collision register has been read.
// again until after the collision register has been read.
always @(posedge vclk)
always @(posedge vclk)
if (rst_i) begin
if (rst_i) begin
        sprSprIRQPending1 <= 0;
        sprSprIRQPending1 <= 0;
        sprSprCollision1 <= 0;
        sprSprCollision1 <= 0;
        sprSprIRQ1 <= 0;
        sprSprIRQ1 <= 0;
end
end
else if (sprCollision) begin
else if (actcnt > 6'd1) begin
        // isFirstCollision
        // isFirstCollision
        if ((sprSprCollision1==0)||(cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110010)) begin
        if ((sprSprCollision1==0)||(cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110010)) begin
                sprSprIRQPending1 <= 1;
                sprSprIRQPending1 <= 1;
                sprSprIRQ1 <= sprSprIe;
                sprSprIRQ1 <= sprSprIe;
                sprSprCollision1 <= sproact;
                sprSprCollision1 <= sproact;
        end
        end
        else
        else
                sprSprCollision1 <= sprSprCollision1|sproact;
                sprSprCollision1 <= sprSprCollision1|sproact;
end
end
else if (cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110010) begin
else if (cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110010) begin
        sprSprCollision1 <= 0;
        sprSprCollision1 <= 0;
        sprSprIRQPending1 <= 0;
        sprSprIRQPending1 <= 0;
        sprSprIRQ1 <= 0;
        sprSprIRQ1 <= 0;
end
end
// Load the sprite background collision register. This register
// Load the sprite background collision register. This register
// continually accumulates collision bits until reset by reading
// continually accumulates collision bits until reset by reading
// the register.
// the register.
// Set the collision IRQ on the first collision and don't set it
// Set the collision IRQ on the first collision and don't set it
// again until after the collision register has been read.
// again until after the collision register has been read.
// Note the background collision indicator is externally supplied,
// Note the background collision indicator is externally supplied,
// it will come from the color processing logic.
// it will come from the color processing logic.
always @(posedge vclk)
always @(posedge vclk)
if (rst_i) begin
if (rst_i) begin
        sprBkIRQPending1 <= 0;
        sprBkIRQPending1 <= 0;
        sprBkCollision1 <= 0;
        sprBkCollision1 <= 0;
        sprBkIRQ1 <= 0;
        sprBkIRQ1 <= 0;
end
end
else if (|bkCollision) begin
else if (|bkCollision) begin
        // Is the register being cleared at the same time
        // Is the register being cleared at the same time
        // a collision occurss ?
        // a collision occurss ?
        // isFirstCollision
        // isFirstCollision
        if ((sprBkCollision1==0) || (cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110011)) begin
        if ((sprBkCollision1==0) || (cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110011)) begin
                sprBkIRQ1 <= sprBkIe;
                sprBkIRQ1 <= sprBkIe;
                sprBkCollision1 <= bkCollision;
                sprBkCollision1 <= bkCollision;
                sprBkIRQPending1 <= 1;
                sprBkIRQPending1 <= 1;
        end
        end
        else
        else
                sprBkCollision1 <= sprBkCollision1|bkCollision;
                sprBkCollision1 <= sprBkCollision1|bkCollision;
end
end
else if (cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110011) begin
else if (cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110011) begin
        sprBkCollision1 <= 0;
        sprBkCollision1 <= 0;
        sprBkIRQPending1 <= 0;
        sprBkIRQPending1 <= 0;
        sprBkIRQ1 <= 0;
        sprBkIRQ1 <= 0;
end
end
endmodule
endmodule
/*
/*
module SpriteRam32 (
module SpriteRam32 (
        clka, adra, dia, doa, cea, wea,
        clka, adra, dia, doa, cea, wea,
        clkb, adrb, dib, dob, ceb, web
        clkb, adrb, dib, dob, ceb, web
);
);
input clka;
input clka;
input [9:0] adra;
input [9:0] adra;
input [31:0] dia;
input [31:0] dia;
output [31:0] doa;
output [31:0] doa;
input cea;
input cea;
input wea;
input wea;
input clkb;
input clkb;
input [9:0] adrb;
input [9:0] adrb;
input [31:0] dib;
input [31:0] dib;
output [31:0] dob;
output [31:0] dob;
input ceb;
input ceb;
input web;
input web;
reg [31:0] mem [0:1023];
reg [31:0] mem [0:1023];
reg [9:0] radra;
reg [9:0] radra;
reg [9:0] radrb;
reg [9:0] radrb;
always @(posedge clka)  if (cea) radra <= adra;
always @(posedge clka)  if (cea) radra <= adra;
always @(posedge clkb)  if (ceb) radrb <= adrb;
always @(posedge clkb)  if (ceb) radrb <= adrb;
assign doa = mem [radra];
assign doa = mem [radra];
assign dob = mem [radrb];
assign dob = mem [radrb];
always @(posedge clka)
always @(posedge clka)
        if (cea & wea) mem[adra] <= dia;
        if (cea & wea) mem[adra] <= dia;
always @(posedge clkb)
always @(posedge clkb)
        if (ceb & web) mem[adrb] <= dib;
        if (ceb & web) mem[adrb] <= dib;
endmodule
endmodule
*/
*/
 
 

powered by: WebSVN 2.1.0

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