URL
https://opencores.org/ocsvn/rtf_sprite_controller/rtf_sprite_controller/trunk
Subversion Repositories rtf_sprite_controller
Compare Revisions
- This comparison shows the changes necessary to convert path
/rtf_sprite_controller/trunk/rtl
- from Rev 6 to Rev 7
- ↔ Reverse comparison
Rev 6 → Rev 7
/verilog/rfSpriteController.sv
0,0 → 1,1305
`timescale 1ns / 1ps |
// ============================================================================ |
// __ |
// \\__/ o\ (C) 2005-2022 Robert Finch, Waterloo |
// \ __ / All rights reserved. |
// \/_// robfinch<remove>@finitron.ca |
// || |
// |
// rfSpriteController.sv |
// sprite / hardware cursor controller |
// |
// BSD 3-Clause License |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are met: |
// |
// 1. Redistributions of source code must retain the above copyright notice, this |
// list of conditions and the following disclaimer. |
// |
// 2. Redistributions in binary form must reproduce the above copyright notice, |
// this list of conditions and the following disclaimer in the documentation |
// and/or other materials provided with the distribution. |
// |
// 3. Neither the name of the copyright holder nor the names of its |
// contributors may be used to endorse or promote products derived from |
// this software without specific prior written permission. |
// |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
// 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 |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
// |
// |
// Sprite Controller |
// |
// FEATURES |
// - parameterized number of sprites 1,2,4,6,8,14,16 or 32 |
// - sprite image cache buffers |
// - each image cache is capable of holding multiple |
// sprite images |
// - an embedded DMA controller is used for sprite reload |
// - programmable image offset within cache |
// - programmable sprite width,height, and pixel size |
// - sprite width and height may vary from 1 to 256 as long |
// as the product doesn't exceed 4096. |
// - pixels may be programmed to be 1,2,3 or 4 video clocks |
// both height and width are programmable |
// - programmable sprite position |
// - programmable 8, 16 or 32 bits for color |
// eg 32k color + 1 bit alpha blending indicator (1,5,5,5) |
// - fixed display and DMA priority |
// sprite 0 highest, sprite 31 lowest |
// - graphics plane control |
// |
// This core requires an external timing generator to |
// provide horizontal and vertical sync signals, but |
// otherwise can be used as a display controller on it's |
// own. However, normally this core would be embedded |
// within another core such as a VGA controller. Sprite |
// positions are referenced to the rising edge of the |
// vertical and horizontal sync pulses. |
// The core includes an embedded dual port RAM to hold the |
// sprite images. The image RAM is updated using a built in DMA |
// controller. The DMA controller uses 32 bit accesses to fill |
// the sprite buffers. The circuit features an automatic bus |
// transaction timeout; if the system bus hasn't responded |
// within 20 clock cycles, the DMA controller moves onto the |
// next address. |
// The controller uses a ram underlay to cache the values |
// of the registers. This is a lot cheaper resource wise than |
// using a 32 to 1 multiplexor (well at least for an FPGA). |
// |
// All registers are 32 bits wide |
// |
// These registers repeat in incrementing block of four registers |
// and pertain to each sprite |
// 00: - position register |
// HPOS [11: 0] horizontal position (hctr value) |
// VPOS [27:16] vertical position (vctr value) |
// |
// 04: SZ - size register |
// bits |
// [ 7: 0] width of sprite in pixels - 1 |
// [15: 8] height of sprite in pixels -1 |
// [19:16] size of horizontal pixels - 1 in clock cycles |
// [23:20] size of vertical pixels in scan-lines - 1 |
// * the product of width * height cannot exceed 2048 ! |
// if it does, the display will begin repeating |
// [27:24] output plane |
// [31:30] color depth 01=RGB332,10=RGB555+A,11=RGB888+A |
// |
// 08: ADR [31:12] 20 bits sprite image address bits |
// This registers contain the high order address bits of the |
// location of the sprite image in system memory. |
// The DMA controller will assign the low order 12 bits |
// during DMA. |
// [11:0] image offset bits [11:0] |
// offset of the sprite image within the sprite image cache |
// typically zero |
// |
// 0C: TC [23:0] transparent color |
// This register identifies which color of the sprite |
// is transparent |
// |
// |
// |
// 0C-1FC: registers reserved for up to thirty-one other sprites |
// |
// 200: DMA burst reg sprite 0 |
// [8:0] burst start |
// [24:16] burst end |
// ... |
// 27C: DMA burst reg sprite 31 |
// |
// 280: [ 7: 0] Frame size, multiples of 16 pixels |
// [15: 8] Number of frames of animation |
// [25:16] Animation Rate |
// [29:26] Frame size, LSBs 0 to 3 |
// [30] Auto repeat |
// [31] Enable animation |
// ... |
// 2FC: Animation register sprite #31 |
// |
// Global status and control |
// 3C0: EN [31:0] sprite enable register |
// 3C4: IE [31:0] sprite interrupt enable / status |
// 3C8: SCOL [31:0] sprite-sprite collision register |
// 3CC: BCOL [31:0] sprite-background collision register |
// 3D0: DT [31:0] sprite DMA trigger on |
// 3D4: DT [31:0] sprite DMA trigger off |
// 3D8: VDT [31:0] sprite vertical sync DMA trigger |
// 3EC: BC [29:0] background color |
// 3FC: ADDR [31:0] sprite DMA address bits [63:32] |
// |
//============================================================================= |
|
import wishbone_pkg::*; |
|
module rfSpriteController( |
// Bus Slave interface |
//------------------------------ |
// Slave signals |
input rst_i, // reset |
input s_clk_i, // clock |
input s_cs_i, |
input wb_write_request32_t wbs_req, |
output wb_read_response32_t wbs_resp, |
//------------------------------ |
// Bus Master Signals |
input m_clk_i, // clock |
output wb_write_request128_t wbm_req, |
input wb_read_response128_t wbm_resp, |
output [4:0] m_spriteno_o, |
//-------------------------- |
input dot_clk_i, // video dot clock |
input hsync_i, // horizontal sync pulse |
input vsync_i, // vertical sync pulse |
input blank_i, // blanking signal |
input [39:0] zrgb_i, // input pixel stream |
output [39:0] zrgb_o, // output pixel stream 12-12-12-4 |
output irq, // interrupt request |
input test, |
input xonoff_i |
); |
|
reg m_soc_o; |
wire vclk = dot_clk_i; |
wire hSync = hsync_i; |
wire vSync = vsync_i; |
reg [39:0] zrgb_o; |
|
//-------------------------------------------------------------------- |
// Core Parameters |
//-------------------------------------------------------------------- |
parameter pnSpr = 32; // number of sprites |
parameter phBits = 12; // number of bits in horizontal timing counter |
parameter pvBits = 12; // number of bits in vertical timing counter |
localparam pnSprm = pnSpr-1; |
|
|
//-------------------------------------------------------------------- |
// Variable Declarations |
//-------------------------------------------------------------------- |
|
reg ce; // controller enable |
wb_write_request32_t wb_reqs; // synchronized request |
|
wire [4:0] sprN = wb_reqs.adr[8:4]; |
|
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 sprSprIRQ; |
reg sprBkIRQ; |
|
reg [31:0] out; // sprite output |
reg outact; // sprite output is active |
reg [3:0] outplane; |
reg [pnSprm:0] bkCollision; // sprite-background collision |
reg [29:0] bgTc; // background transparent color |
reg [29:0] bkColor; // background color |
|
|
reg [pnSprm:0] sprWe; // block ram write enable for image cache update |
reg [pnSprm:0] sprRe; // block ram read enable for image cache update |
|
// Global control registers |
reg [31:0] sprEn; // enable sprite |
reg [pnSprm:0] sprCollision; // sprite-sprite collision |
reg sprSprIe; // sprite-sprite interrupt enable |
reg sprBkIe; // sprite-background interrupt enable |
reg sprSprIRQPending; // sprite-sprite collision interrupt pending |
reg sprBkIRQPending; // sprite-background collision interrupt pending |
reg sprSprIRQPending1; // sprite-sprite collision interrupt pending |
reg sprBkIRQPending1; // sprite-background collision interrupt pending |
reg sprSprIRQ1; // vclk domain regs |
reg sprBkIRQ1; |
|
// Sprite control registers |
reg [31:0] sprSprCollision; |
reg [pnSprm:0] sprSprCollision1; |
reg [31:0] sprBkCollision; |
reg [pnSprm:0] sprBkCollision1; |
reg [23:0] sprTc [pnSprm:0]; // sprite transparent color code |
// How big the pixels are: |
// 1 to 16 video clocks |
reg [3:0] hSprRes [pnSprm:0]; // sprite horizontal 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] sprHeight [pnSprm:0]; // number of vertical pixels |
reg [3:0] sprPlane [pnSprm:0]; // output plane sprite is in |
reg [1:0] sprColorDepth [pnSprm:0]; |
reg [1:0] colorBits; |
// Sprite DMA control |
reg [8:0] sprBurstStart [pnSprm:0]; |
reg [8:0] sprBurstEnd [pnSprm:0]; |
reg [31:0] vSyncT; // DMA on vSync |
|
// display and timing signals |
reg [31:0] hSprReset; // horizontal reset |
reg [31:0] vSprReset; // vertical reset |
reg [31:0] hSprDe; // sprite horizontal display enable |
reg [31:0] vSprDe; // sprite vertical display enable |
reg [31:0] sprDe; // display enable |
reg [phBits-1:0] hSprPos [pnSprm:0]; // sprite horizontal position |
reg [pvBits-1:0] vSprPos [pnSprm:0]; // sprite vertical position |
reg [7:0] hSprCnt [pnSprm:0]; // sprite horizontal display counter |
reg [7:0] vSprCnt [pnSprm:0]; // vertical display counter |
reg [11:0] sprImageOffs [pnSprm:0]; // offset within sprite memory |
reg [12:0] sprAddr [pnSprm:0]; // index into sprite memory (pixel number) |
reg [9:0] sprAddr1 [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] sprAddr4 [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 |
wire [31:0] sprOut4 [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 |
|
// Animation |
reg [11:0] sprFrameSize [pnSprm:0]; |
reg [7:0] sprFrames [pnSprm:0]; |
reg [7:0] sprCurFrame [pnSprm:0]; |
reg [9:0] sprRate [pnSprm:0]; |
reg [9:0] sprCurRateCount [pnSprm:0]; |
reg [pnSprm:0] sprEnableAnimation; |
reg [pnSprm:0] sprAutoRepeat; |
|
// DMA access |
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 [31:0] sprDt; // DMA trigger register |
reg dmaActive; // this flag indicates that a block DMA transfer is active |
|
genvar g; |
|
//-------------------------------------------------------------------- |
// DMA control / bus interfacing |
//-------------------------------------------------------------------- |
reg cs_regs; |
always_ff @(posedge s_clk_i) |
cs_regs <= wbs_req.cyc & wbs_req.stb & s_cs_i; |
always_ff @(posedge s_clk_i) |
wb_reqs <= wbs_req; |
|
wire s_ack_o; |
ack_gen #( |
.READ_STAGES(3), |
.WRITE_STAGES(1), |
.REGISTER_OUTPUT(1) |
) |
uag1 ( |
.clk_i(s_clk_i), |
.ce_i(1'b1), |
.i(cs_regs), |
.we_i(cs_regs & wb_reqs.we), |
.o(s_ack_o), |
.rid_i(0), |
.wid_i(0), |
.rid_o(), |
.wid_o() |
); |
always_comb |
begin |
wbs_resp.ack = s_ack_o & wbs_req.cyc & wbs_req.stb; |
wbs_resp.next = s_ack_o & wbs_req.cyc & wbs_req.stb; |
end |
|
assign irq = sprSprIRQ|sprBkIRQ; |
|
//-------------------------------------------------------------------- |
// DMA control / bus interfacing |
//-------------------------------------------------------------------- |
|
reg [5:0] dmaStart; |
reg [8:0] cob; // count of burst cycles |
|
assign wbm_req.bte = LINEAR; |
assign wbm_req.cti = CLASSIC; |
assign wbm_req.stb = wbm_req.cyc; |
assign wbm_req.sel = 16'hFFFF; |
assign wbm_req.cid = 4'd5; |
assign m_spriteno_o = dmaOwner; |
|
reg [2:0] mstate; |
parameter IDLE = 3'd0; |
parameter ACTIVE = 3'd1; |
parameter ACK = 3'd2; |
parameter NACK = 3'd3; |
|
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()); |
|
always_ff @(posedge m_clk_i) |
if (rst_i) |
mstate <= IDLE; |
else begin |
case(mstate) |
IDLE: |
if (|sprDt & ce) |
mstate <= ACTIVE; |
ACTIVE: |
mstate <= ACK; |
ACK: |
if (wbm_resp.ack | wbm_resp.err) |
mstate <= NACK; |
NACK: |
if (~(wbm_resp.ack|wbm_resp.err)) |
mstate <= cob==sprBurstEnd[dmaOwner] ? IDLE : ACTIVE; |
default: |
mstate <= IDLE; |
endcase |
end |
|
integer n30; |
always_ff @(posedge m_clk_i) |
begin |
case(mstate) |
IDLE: |
begin |
dmaOwner <= 5'd0; |
for (n30 = pnSprm; n30 >= 0; n30 = n30 - 1) |
if (sprDt[n30]) |
dmaOwner <= n30; |
end |
default: ; |
endcase |
end |
|
always_ff @(posedge m_clk_i) |
if (rst_i) |
dmaStart <= 6'b0; |
else begin |
dmaStart <= {dmaStart[4:0],1'b0}; |
case(mstate) |
IDLE: |
if (|sprDt & ce) |
dmaStart <= 6'h3F; |
default: ; |
endcase |
end |
|
integer n32; |
always_ff @(posedge m_clk_i) |
begin |
case(mstate) |
IDLE: |
for (n32 = pnSprm; n32 >= 0; n32 = n32 - 1) |
if (sprDt[n32]) |
cob <= sprBurstStart[n32]; |
ACTIVE: |
cob <= cob + 2'd2; |
default: ; |
endcase |
end |
|
always_ff @(posedge m_clk_i) |
if (rst_i) |
wb_m_nack(); |
else begin |
case(mstate) |
IDLE: |
wb_m_nack(); |
ACTIVE: |
begin |
wbm_req.cyc <= 1'b1; |
wbm_req.adr <= {sprSysAddr[dmaOwner],cob[8:1],4'h0}; |
end |
ACK: |
if (wbm_resp.ack|wbm_resp.err) |
wb_m_nack(); |
endcase |
end |
|
task wb_m_nack; |
begin |
wbm_req.cyc <= 1'b0; |
end |
endtask |
|
|
// generate a write enable strobe for the sprite image memory |
integer n1; |
reg [8:0] m_adr_or; |
reg [127:0] m_dat_ir; |
reg ack1; |
|
always_ff @(posedge m_clk_i) |
for (n1 = 0; n1 < pnSpr; n1 = n1 + 1) |
sprWe[n1] <= (dmaOwner==n1 && (pe_m_ack_i||ack1)); |
|
always_ff @(posedge m_clk_i) |
ack1 <= pe_m_ack_i; |
always_ff @(posedge m_clk_i) |
if (pe_m_ack_i|ack1) |
m_adr_or <= {wbm_req.adr[11:4],ack1}; |
always_ff @(posedge m_clk_i) |
if (pe_m_ack_i) begin |
if (test) |
m_dat_ir <= {8{1'b0,dmaOwner,10'b0}}; |
else |
m_dat_ir <= {wbm_resp.dat[63:0],wbm_resp.dat[127:64]}; |
end |
else if (ack1) |
m_dat_ir <= {64'd0,m_dat_ir[127:64]}; |
|
|
//-------------------------------------------------------------------- |
//-------------------------------------------------------------------- |
|
reg [31:0] reg_shadow [0:255]; |
reg [7:0] radr; |
always_ff @(posedge s_clk_i) |
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[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[3]) reg_shadow[wb_reqs.adr[9:2]][31:24] <= wb_reqs.dat[31:24]; |
end |
always @(posedge s_clk_i) |
radr <= wb_reqs.adr[9:2]; |
wire [31:0] reg_shadow_o = reg_shadow[radr]; |
|
// register/sprite memory output mux |
always_ff @(posedge s_clk_i) |
if (cs_regs) |
case (wb_reqs.adr[9:2]) // synopsys full_case parallel_case |
8'b11110000: wbs_resp.dat <= sprEn; |
8'b11110001: wbs_resp.dat <= {sprBkIRQPending|sprSprIRQPending,5'b0,sprBkIRQPending,sprSprIRQPending,6'b0,sprBkIe,sprSprIe}; |
8'b11110010: wbs_resp.dat <= sprSprCollision; |
8'b11110011: wbs_resp.dat <= sprBkCollision; |
8'b11110100: wbs_resp.dat <= sprDt; |
default: wbs_resp.dat <= reg_shadow_o; |
endcase |
else |
wbs_resp.dat <= 32'h0; |
|
|
// vclk -> clk_i |
always @(posedge s_clk_i) |
begin |
sprSprIRQ <= sprSprIRQ1; |
sprBkIRQ <= sprBkIRQ1; |
sprSprIRQPending <= sprSprIRQPending1; |
sprBkIRQPending <= sprBkIRQPending1; |
sprSprCollision <= sprSprCollision1; |
sprBkCollision <= sprBkCollision1; |
end |
|
|
// register updates |
// on the clk_i domain |
reg vSync1; |
integer n33; |
always_ff @(posedge s_clk_i) |
if (rst_i) begin |
vSyncT <= 32'hFFFF0000;//FFFFFFFF; |
sprEn <= 32'hFFFFFFFF; |
sprDt <= 0; |
for (n33 = 0; n33 < pnSpr; n33 = n33 + 1) begin |
sprSysAddr[n33] <= 20'b0000_0000_0011_0000_0000 + n33; //0030_0000 |
end |
sprSprIe <= 0; |
sprBkIe <= 0; |
|
// Set reasonable starting positions on the screen |
// so that the sprites might be visible for testing |
for (n33 = 0; n33 < pnSpr; n33 = n33 + 1) begin |
hSprPos[n33] <= 200 + (n33 & 7) * 70; |
vSprPos[n33] <= 100 + (n33 >> 3) * 100; |
sprTc[n33] <= 24'h7FFF; // White 16 bpp |
sprWidth[n33] <= 8'd16; // 16x16 sprites |
sprHeight[n33] <= 8'd16; |
hSprRes[n33] <= 2; // our standard display |
vSprRes[n33] <= 2; |
sprImageOffs[n33] <= 0; |
sprPlane[n33] <= 4'hF;//n[3:0]; |
sprBurstStart[n33] <= 9'h000; |
sprBurstEnd[n33] <= 9'h1FE; |
sprColorDepth[n33] <= 2'b10; |
sprFrameSize[n33] <= 12'd256; |
sprFrames[n33] <= 8'd5; |
sprRate[n33] <= 12'd10; |
sprEnableAnimation[n33] <= 1'b1; |
sprAutoRepeat[n33] <= 1'b1; |
end |
hSprPos[0] <= 210; |
vSprPos[0] <= 72; |
|
bgTc <= 24'h08_08_08; |
bkColor <= 24'hFF_FF_60; |
end |
else begin |
ce <= xonoff_i; |
vSync1 <= vSync; |
if (vSync & ~vSync1) |
sprDt <= sprDt | vSyncT; |
|
// clear DMA trigger bit once DMA is recognized |
if (dmaStart[5]) |
sprDt[dmaOwner] <= 1'b0; |
|
// Disable animation after frame count expired, if not auto-repeat. |
for (n33 = 0; n33 < pnSpr; n33 = n33 + 1) |
if (sprCurFrame[n33] >= sprFrames[n33] && !sprAutoRepeat[n33]) |
sprEnableAnimation[n33] <= 1'b0; |
|
if (cs_regs & wb_reqs.we) begin |
|
casez (wb_reqs.adr[9:2]) |
8'b100?????: |
begin |
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}; |
end |
8'b101?????: |
begin |
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[2]) sprRate[wb_reqs.adr[6:2]][7:0] <= wb_reqs.dat[23:16]; |
if (wb_reqs.sel[3]) |
begin |
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]; |
sprAutoRepeat[wb_reqs.adr[6:2]] <= wb_reqs.dat[30]; |
sprEnableAnimation[wb_reqs.adr[6:2]] <= wb_reqs.dat[31]; |
end |
end |
8'b11110000: // 3C0 |
begin |
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[2]) sprEn[23:16] <= wb_reqs.dat[23:16]; |
if (wb_reqs.sel[3]) sprEn[31:24] <= wb_reqs.dat[31:24]; |
end |
8'b11110001: // 3C4 |
if (wb_reqs.sel[0]) begin |
sprSprIe <= wb_reqs.dat[0]; |
sprBkIe <= wb_reqs.dat[1]; |
end |
// 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 clear (1=clear,0=ignore) |
8'b11110100: // 3D0 |
begin |
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[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]; |
end |
8'b11110101: // 3D4 |
begin |
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[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]; |
end |
8'b11110110: // 3D8 |
begin |
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[2]) vSyncT[23:16] <= wb_reqs.dat[23:16]; |
if (wb_reqs.sel[3]) vSyncT[31:24] <= wb_reqs.dat[31:24]; |
end |
8'b11111010: // 3E8 |
begin |
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[2]) bgTc[23:16] <= wb_reqs.dat[23:16]; |
if (wb_reqs.sel[3]) bgTc[29:24] <= wb_reqs.dat[29:24]; |
end |
8'b11111011: // 3EC |
begin |
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[2]) bkColor[23:16] <= wb_reqs.dat[23:16]; |
if (wb_reqs.sel[3]) bkColor[29:24] <= wb_reqs.dat[29:24]; |
end |
// 8'b11111100: // 3F0 |
// if (wb_reqs.sel[0]) ce <= wb_reqs[0]; |
8'b0?????00: |
begin |
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[2]) vSprPos[sprN][ 7:0] <= wb_reqs.dat[23:16]; |
if (wb_reqs.sel[3]) vSprPos[sprN][11:8] <= wb_reqs.dat[27:24]; |
end |
8'b0?????01: |
begin |
if (wb_reqs.sel[0]) begin |
sprWidth[sprN] <= wb_reqs.dat[7:0]; |
end |
if (wb_reqs.sel[1]) begin |
sprHeight[sprN] <= wb_reqs.dat[15:8]; |
end |
if (wb_reqs.sel[2]) begin |
hSprRes[sprN] <= wb_reqs.dat[19:16]; |
vSprRes[sprN] <= wb_reqs.dat[23:20]; |
end |
if (wb_reqs.sel[3]) begin |
sprPlane[sprN] <= wb_reqs.dat[27:24]; |
sprColorDepth[sprN] <= wb_reqs.dat[31:30]; |
end |
end |
8'b0?????10: |
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[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[2]) sprSysAddr[sprN][23:16] <= wb_reqs.dat[23:16]; |
if (wb_reqs.sel[3]) sprSysAddr[sprN][31:24] <= wb_reqs.dat[31:24]; |
end |
8'b0?????11: |
begin |
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[2]) sprTc[sprN][23:16] <= wb_reqs.dat[23:16]; |
end |
|
default: ; |
endcase |
|
end |
end |
|
//------------------------------------------------------------- |
// Sprite Image Cache RAM |
// This RAM is dual ported with an SoC side and a display |
// controller side. |
//------------------------------------------------------------- |
|
integer n2; |
always_ff @(posedge vclk) |
for (n2 = 0; n2 < pnSpr; n2 = n2 + 1) |
case(sprColorDepth[n2]) |
2'd1: sprAddr1[n2] <= {sprAddr[n2][11:3],~sprAddr[n2][2]}; |
2'd2: sprAddr1[n2] <= {sprAddr[n2][10:2],~sprAddr[n2][1]}; |
2'd3: sprAddr1[n2] <= {sprAddr[n2][ 9:1],~sprAddr[n2][0]}; |
default: ; |
endcase |
|
// 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 |
// additional mux is needed. |
integer n4, n5, n27, n29; |
always_ff @(posedge vclk) |
for (n4 = 0; n4 < pnSpr; n4 = n4 + 1) |
sprAddr2[n4] <= ~sprAddr[n4][2:0]; |
always_ff @(posedge vclk) |
for (n5 = 0; n5 < pnSpr; n5 = n5 + 1) |
sprAddr3[n5] <= sprAddr2[n5]; |
always_ff @(posedge vclk) |
for (n27 = 0; n27 < pnSpr; n27 = n27 + 1) |
sprAddr4[n27] <= sprAddr3[n27]; |
always_ff @(posedge vclk) |
for (n29 = 0; n29 < pnSpr; n29 = n29 + 1) |
sprAddr5[n29] <= sprAddr4[n29]; |
|
// 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 |
// address bits are flipped to get the correct display. |
integer n3; |
always_ff @(posedge vclk) |
for (n3 = 0; n3 < pnSpr; n3 = n3 + 1) |
case(sprColorDepth[n3]) |
2'd1: |
case(sprAddr5[n3][1:0]) |
2'd3: sprOut5[n3] <= sprOut4[n3][31:24]; |
2'd2: sprOut5[n3] <= sprOut4[n3][23:16]; |
2'd1: sprOut5[n3] <= sprOut4[n3][15:8]; |
2'd0: sprOut5[n3] <= sprOut4[n3][7:0]; |
endcase |
2'd2: |
case(sprAddr5[n3][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]}; |
endcase |
2'd3: |
sprOut5[n3] <= sprOut4[n3]; |
default: ; |
endcase |
|
generate |
for (g = 0; g < pnSpr; g = g + 1) begin : sprRam |
SpriteRam sprRam0 |
( |
.clka(m_clk_i), |
.addra(m_adr_or), |
.dina(m_dat_ir[63:0]), |
.ena(sprWe[g]), |
.wea(sprWe[g]), |
// Core reg and output reg 3 clocks from read address |
.clkb(vclk), |
.addrb(sprAddr1[g]), |
.doutb(sprOut4[g]), |
.enb(1'b1) |
); |
end |
endgenerate |
|
//------------------------------------------------------------- |
// Timing counters and addressing |
// Sprites are like miniature bitmapped displays, they need |
// all the same timing controls. |
//------------------------------------------------------------- |
|
// Create a timing reference using horizontal and vertical |
// sync |
wire hSyncEdge, vSyncEdge; |
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() ); |
|
always_ff @(posedge vclk) |
if (hSyncEdge) hctr <= {phBits{1'b0}}; |
else hctr <= hctr + 2'd1; |
|
always_ff @(posedge vclk) |
if (vSyncEdge) vctr <= {pvBits{1'b0}}; |
else if (hSyncEdge) vctr <= vctr + 2'd1; |
|
// track sprite horizontal reset |
integer n19; |
always_ff @(posedge vclk) |
for (n19 = 0; n19 < pnSpr; n19 = n19 + 1) |
hSprReset[n19] <= hctr==hSprPos[n19]; |
|
// track sprite vertical reset |
integer n20; |
always_ff @(posedge vclk) |
for (n20 = 0; n20 < pnSpr; n20 = n20 + 1) |
vSprReset[n20] <= vctr==vSprPos[n20]; |
|
integer n21; |
always_comb |
for (n21 = 0; n21 < pnSpr; n21 = n21 + 1) |
sprDe[n21] <= hSprDe[n21] & vSprDe[n21]; |
|
|
// take care of sprite size scaling |
// video clock division |
reg [31:0] hSprNextPixel; |
reg [31:0] vSprNextPixel; |
reg [3:0] hSprPt [31:0]; // horizontal pixel toggle |
reg [3:0] vSprPt [31:0]; // vertical pixel toggle |
integer n17; |
always_comb |
for (n17 = 0; n17 < pnSpr; n17 = n17 + 1) |
hSprNextPixel[n17] = hSprPt[n17]==hSprRes[n17]; |
integer n18; |
always_comb |
for (n18 = 0; n18 < pnSpr; n18 = n18 + 1) |
vSprNextPixel[n18] = vSprPt[n18]==vSprRes[n18]; |
|
// horizontal pixel toggle counter |
integer n6; |
always_ff @(posedge vclk) |
for (n6 = 0; n6 < pnSpr; n6 = n6 + 1) |
if (hSprReset[n6]) |
hSprPt[n6] <= 4'd0; |
else if (hSprNextPixel[n6]) |
hSprPt[n6] <= 4'd0; |
else |
hSprPt[n6] <= hSprPt[n6] + 2'd1; |
|
// vertical pixel toggle counter |
integer n7; |
always_ff @(posedge vclk) |
for (n7 = 0; n7 < pnSpr; n7 = n7 + 1) |
if (hSprReset[n7]) begin |
if (vSprReset[n7]) |
vSprPt[n7] <= 4'd0; |
else if (vSprNextPixel[n7]) |
vSprPt[n7] <= 4'd0; |
else |
vSprPt[n7] <= vSprPt[n7] + 2'd1; |
end |
|
// Animation rate count and frame increment. |
integer n28; |
always_ff @(posedge vclk) |
if (vSyncEdge) begin |
for (n28 = 0; n28 < pnSpr; n28 = n28 + 1) begin |
if (sprEnableAnimation[n28]) begin |
sprCurRateCount[n28] <= sprCurRateCount[n28] + 2'd1; |
if (sprCurRateCount[n28] >= sprRate[n28]) begin |
sprCurRateCount[n28] <= 'd0; |
sprCurFrame[n28] <= sprCurFrame[n28] + 2'd1; |
if (sprCurFrame[n28] >= sprFrames[n28]) |
sprCurFrame[n28] <= 'd0; |
end |
end |
else |
sprCurFrame[n28] <= 'd0; |
end |
end |
|
// clock sprite image address counters |
integer n8; |
always_ff @(posedge vclk) |
for (n8 = 0; n8 < pnSpr; n8 = n8 + 1) begin |
// hReset and vReset - top left of sprite, |
// reset address to image offset |
if (hSprReset[n8] & vSprReset[n8]) begin |
sprAddr[n8] <= sprImageOffs[n8] + sprCurFrame[n8] * sprFrameSize[n8]; |
sprAddrB[n8] <= sprImageOffs[n8] + sprCurFrame[n8] * sprFrameSize[n8]; |
end |
// hReset: |
// If the next vertical pixel |
// set backup address to current address |
// else |
// set current address to backup address |
// in order to rescan the line |
else if (hSprReset[n8]) begin |
if (vSprNextPixel[n8]) |
sprAddrB[n8] <= sprAddr[n8]; |
else |
sprAddr[n8] <= sprAddrB[n8]; |
end |
// Not hReset or vReset - somewhere on the sprite scan line |
// just advance the address when the next pixel should be |
// fetched |
else if (hSprDe[n8] & hSprNextPixel[n8]) |
sprAddr[n8] <= sprAddr[n8] + 2'd1; |
end |
|
|
// clock sprite column (X) counter |
integer n9; |
always_ff @(posedge vclk) |
for (n9 = 0; n9 < pnSpr; n9 = n9 + 1) |
if (hSprReset[n9]) |
hSprCnt[n9] <= 8'd1; |
else if (hSprNextPixel[n9]) |
hSprCnt[n9] <= hSprCnt[n9] + 2'd1; |
|
|
// clock sprite horizontal display enable |
integer n10; |
always_ff @(posedge vclk) |
for (n10 = 0; n10 < pnSpr; n10 = n10 + 1) begin |
if (hSprReset[n10]) |
hSprDe[n10] <= 1'b1; |
else if (hSprNextPixel[n10]) begin |
if (hSprCnt[n10] == sprWidth[n10]) |
hSprDe[n10] <= 1'b0; |
end |
end |
|
|
// clock the sprite row (Y) counter |
integer n11; |
always_ff @(posedge vclk) |
for (n11 = 0; n11 < pnSpr; n11 = n11 + 1) |
if (hSprReset[n11]) begin |
if (vSprReset[n11]) |
vSprCnt[n11] <= 8'd1; |
else if (vSprNextPixel[n11]) |
vSprCnt[n11] <= vSprCnt[n11] + 2'd1; |
end |
|
|
// clock sprite vertical display enable |
integer n12; |
always_ff @(posedge vclk) |
for (n12 = 0; n12 < pnSpr; n12 = n12 + 1) begin |
if (hSprReset[n12]) begin |
if (vSprReset[n12]) |
vSprDe[n12] <= 1'b1; |
else if (vSprNextPixel[n12]) begin |
if (vSprCnt[n12] == sprHeight[n12]) |
vSprDe[n12] <= 1'b0; |
end |
end |
end |
|
|
//------------------------------------------------------------- |
// Output stage |
//------------------------------------------------------------- |
|
// function used for color blending |
// given an alpha and a color component, determine the resulting color |
// this blends towards black or white |
// alpha is eight bits ranging between 0 and 1.999... |
// 1 bit whole, 7 bits fraction |
function [11:0] fnBlend; |
input [7:0] alpha; |
input [11:0] color1bits; |
input [11:0] color2bits; |
|
begin |
fnBlend = (({8'b0,color1bits} * alpha) >> 7) + (({8'h00,color2bits} * (9'h100 - alpha)) >> 7); |
end |
endfunction |
|
|
// pipeline delays for display enable |
reg [31:0] sprDe1, sprDe2, sprDe3, sprDe4, sprDe5, sprDe6; |
reg [31:0] sproact; |
integer n13; |
always_ff @(posedge vclk) |
for (n13 = 0; n13 < pnSpr; n13 = n13 + 1) |
sprDe1[n13] <= sprDe[n13]; |
integer n22; |
always_ff @(posedge vclk) |
for (n22 = 0; n22 < pnSpr; n22 = n22 + 1) |
sprDe2[n22] <= sprDe1[n22]; |
integer n23; |
always_ff @(posedge vclk) |
for (n23 = 0; n23 < pnSpr; n23 = n23 + 1) |
sprDe3[n23] <= sprDe2[n23]; |
integer n24; |
always_ff @(posedge vclk) |
for (n24 = 0; n24 < pnSpr; n24 = n24 + 1) |
sprDe4[n24] <= sprDe3[n24]; |
integer n25; |
always_ff @(posedge vclk) |
for (n25 = 0; n25 < pnSpr; n25 = n25 + 1) |
sprDe5[n25] <= sprDe4[n25]; |
integer n26; |
always_ff @(posedge vclk) |
for (n26 = 0; n26 < pnSpr; n26 = n26 + 1) |
sprDe6[n26] <= sprDe5[n26]; |
|
|
// Detect which sprite outputs are active |
// The sprite output is active if the current display pixel |
// address is within the sprite's area, the sprite is enabled, |
// and it's not a transparent pixel that's being displayed. |
integer n14; |
always_ff @(posedge vclk) |
for (n14 = 0; n14 < pnSpr; n14 = n14 + 1) |
sproact[n14] <= sprEn[n14] && sprDe5[n14] && sprTc[n14]!=sprOut5[n14]; |
integer n15; |
always_ff @(posedge vclk) |
for (n15 = 0; n15 < pnSpr; n15 = n15 + 1) |
sprOut[n15] <= sprOut5[n15]; |
|
// register sprite activity flag |
// The image combiner uses this flag to know what to do with |
// the sprite output. |
always_ff @(posedge vclk) |
outact <= |sproact & ce; |
|
// Display data comes from the active sprite with the |
// highest display priority. |
// Make sure that alpha blending is turned off when |
// no sprite is active. |
integer n16; |
always_ff @(posedge vclk) |
begin |
out <= 32'h0080; // alpha blend max (and off) |
outplane <= 4'h0; |
colorBits <= 2'b00; |
for (n16 = pnSprm; n16 >= 0; n16 = n16 - 1) |
if (sproact[n16]) begin |
out <= sprOut[n16]; |
outplane <= sprPlane[n16]; |
colorBits <= sprColorDepth[n16]; |
end |
end |
|
|
// combine the text / graphics color output with sprite color output |
// blend color output |
wire [35:0] blendedColor32 = { |
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[7:0],4'h0},zrgb_i[11: 0])} |
; |
|
wire [35:0] blendedColor16 = { |
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[11: 0],12'h0)} |
; |
|
always_ff @(posedge vclk) |
if (blank_i) |
zrgb_o <= 0; |
else begin |
if (outact) begin |
if (zrgb_i[39:36] > outplane) begin // rgb input is in front of sprite |
zrgb_o <= zrgb_i; |
end |
else |
if (!out[31]) begin // a sprite is displayed without alpha blending |
case(colorBits) |
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'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}; |
endcase |
end |
else |
case(colorBits) |
2'd2: zrgb_o <= {outplane,blendedColor16}; // towards black/white |
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 |
endcase |
end |
else |
zrgb_o <= zrgb_i; |
end |
|
|
//-------------------------------------------------------------------- |
// Collision logic |
//-------------------------------------------------------------------- |
|
// Detect when a sprite-sprite collision has occurred. The criteria |
// 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 |
// same time. |
|
//-------------------------------------------------------------------- |
// Note this case has to be modified for the number of sprites |
// ToDo: make collision also depend on plane |
//-------------------------------------------------------------------- |
generate |
begin : gSprsColliding |
always @(pnSpr or sproact) |
if (pnSpr==1) |
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 |
integer n31; |
always_comb |
for (n31 = 0; n31 < pnSpr; n31 = n31 + 1) |
bkCollision[n31] <= |
sproact[n31] && zrgb_i[39:36]==sprPlane[n31]; |
|
// Load the sprite collision register. This register continually |
// accumulates collision bits until reset by reading the register. |
// Set the collision IRQ on the first collision and don't set it |
// again until after the collision register has been read. |
always @(posedge vclk) |
if (rst_i) begin |
sprSprIRQPending1 <= 0; |
sprSprCollision1 <= 0; |
sprSprIRQ1 <= 0; |
end |
else if (sprCollision) begin |
// isFirstCollision |
if ((sprSprCollision1==0)||(cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110010)) begin |
sprSprIRQPending1 <= 1; |
sprSprIRQ1 <= sprSprIe; |
sprSprCollision1 <= sproact; |
end |
else |
sprSprCollision1 <= sprSprCollision1|sproact; |
end |
else if (cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110010) begin |
sprSprCollision1 <= 0; |
sprSprIRQPending1 <= 0; |
sprSprIRQ1 <= 0; |
end |
|
|
// Load the sprite background collision register. This register |
// continually accumulates collision bits until reset by reading |
// the register. |
// Set the collision IRQ on the first collision and don't set it |
// again until after the collision register has been read. |
// Note the background collision indicator is externally supplied, |
// it will come from the color processing logic. |
always @(posedge vclk) |
if (rst_i) begin |
sprBkIRQPending1 <= 0; |
sprBkCollision1 <= 0; |
sprBkIRQ1 <= 0; |
end |
else if (|bkCollision) begin |
// Is the register being cleared at the same time |
// a collision occurss ? |
// isFirstCollision |
if ((sprBkCollision1==0) || (cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110011)) begin |
sprBkIRQ1 <= sprBkIe; |
sprBkCollision1 <= bkCollision; |
sprBkIRQPending1 <= 1; |
end |
else |
sprBkCollision1 <= sprBkCollision1|bkCollision; |
end |
else if (cs_regs && wb_reqs.sel[0] && wb_reqs.adr[9:2]==8'b11110011) begin |
sprBkCollision1 <= 0; |
sprBkIRQPending1 <= 0; |
sprBkIRQ1 <= 0; |
end |
|
endmodule |
|
/* |
module SpriteRam32 ( |
clka, adra, dia, doa, cea, wea, |
clkb, adrb, dib, dob, ceb, web |
); |
input clka; |
input [9:0] adra; |
input [31:0] dia; |
output [31:0] doa; |
input cea; |
input wea; |
input clkb; |
input [9:0] adrb; |
input [31:0] dib; |
output [31:0] dob; |
input ceb; |
input web; |
|
reg [31:0] mem [0:1023]; |
reg [9:0] radra; |
reg [9:0] radrb; |
|
always @(posedge clka) if (cea) radra <= adra; |
always @(posedge clkb) if (ceb) radrb <= adrb; |
assign doa = mem [radra]; |
assign dob = mem [radrb]; |
always @(posedge clka) |
if (cea & wea) mem[adra] <= dia; |
always @(posedge clkb) |
if (ceb & web) mem[adrb] <= dib; |
|
endmodule |
|
*/ |
/verilog/wishbone_pkg.sv
0,0 → 1,612
// ============================================================================ |
// __ |
// \\__/ o\ (C) 2015-2022 Robert Finch, Waterloo |
// \ __ / All rights reserved. |
// \/_// robfinch<remove>@finitron.ca |
// || |
// |
// BSD 3-Clause License |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are met: |
// |
// 1. Redistributions of source code must retain the above copyright notice, this |
// list of conditions and the following disclaimer. |
// |
// 2. Redistributions in binary form must reproduce the above copyright notice, |
// this list of conditions and the following disclaimer in the documentation |
// and/or other materials provided with the distribution. |
// |
// 3. Neither the name of the copyright holder nor the names of its |
// contributors may be used to endorse or promote products derived from |
// this software without specific prior written permission. |
// |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
// 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 |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
// |
// ============================================================================ |
// |
package wishbone_pkg; |
|
typedef logic [31:0] wb_address_t; |
typedef logic [2:0] wb_burst_len_t; // number of beats in a burst -1 |
typedef logic [3:0] wb_channel_t; // channel for devices like system cache |
typedef logic [7:0] wb_tranid_t; // transaction id |
typedef logic [7:0] wb_priv_level_t; // 0=all access, |
typedef logic [3:0] wb_priority_t; // network transaction priority, higher is better |
|
typedef enum logic [2:0] { |
CLASSIC = 3'b000, |
FIXED = 3'b001, // constant data address |
INCR = 3'b010, // incrementing data address |
EOB = 3'b111 // end of data burst |
} wb_cycle_type_t; |
|
typedef enum logic [2:0] { |
DATA = 3'b000, |
STACK = 3'b110, |
CODE = 3'b111 |
} wb_segment_t; |
|
typedef enum logic [2:0] { |
LINEAR = 3'b000, |
WRAP4 = 3'b001, |
WRAP8 = 3'b010, |
WRAP16 = 3'b011, |
WRAP32 = 3'b100, |
WRAP64 = 3'b101, |
WRAP128 = 3'b110 |
} wb_burst_type_t; |
|
// number of byte transferred in a beat |
typedef enum logic [2:0] { |
B8 = 3'd0, |
B16 = 3'd1, |
B32 = 3'd2, |
B64 = 3'd3, |
B128 = 3'd4 |
} wb_size_t; |
|
typedef enum logic [1:0] { |
OKAY = 2'b00, // no error |
DECERR = 2'd01, // decode error |
PROTERR = 2'b10, // security violation |
ERR = 2'b11 // general error |
} wb_error_t; |
|
typedef enum logic [3:0] { |
NC_NB = 4'd0, // Non-cacheable, non-bufferable |
NON_CACHEABLE = 4'd1, |
CACHEABLE_NB = 4'd2, // Cacheable, non-bufferable |
CACHEABLE = 4'd3, // Cacheable, bufferable |
WT_NO_ALLOCATE = 4'd8, // Write Through |
WT_READ_ALLOCATE = 4'd9, |
WT_WRITE_ALLOCATE = 4'd10, |
WT_READWRITE_ALLOCATE = 4'd11, |
WB_NO_ALLOCATE = 4'd12, // Write Back |
WB_READ_ALLOCATE = 4'd13, |
WB_WRITE_ALLOCATE = 4'd14, |
WB_READWRITE_ALLOCATE = 4'd15 |
} wb_cache_t; |
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
// Read requests |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
wb_address_t adr; // address |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic sr; // set reservation |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_read_request8_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
wb_address_t adr; // address |
logic [1:0] sel; // byte lane select |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic sr; // set reservation |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_read_request16_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
wb_address_t adr; // address |
logic [3:0] sel; // byte lane select |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic sr; // set reservation |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_read_request32_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
wb_address_t adr; // address |
logic [7:0] sel; // byte lane select |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic sr; // set reservation |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_read_request64_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
wb_address_t adr; // address |
logic [15:0] sel; // byte lane select |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic sr; // set reservation |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_read_request128_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
wb_address_t adr; // address |
logic [31:0] sel; // byte lane select |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic sr; // set reservation |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_read_request256_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
wb_address_t adr; // address |
logic [63:0] sel; // byte lane select |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic sr; // set reservation |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_read_request512_t; |
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
// Write requests |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
logic we; // write enable |
wb_address_t adr; // address |
logic [7:0] dat; // data |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic csr; // set or clear reservation we:1=clear 0=set |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_write_request8_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
logic we; // write enable |
wb_address_t adr; // address |
logic [1:0] sel; // byte lane selects |
logic [15:0] dat; // data |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic csr; // set or clear reservation we:1=clear 0=set |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_write_request16_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
logic we; // write enable |
wb_address_t adr; // address |
logic [3:0] sel; // byte lane selects |
logic [31:0] dat; // data |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic csr; // set or clear reservation we:1=clear 0=set |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_write_request32_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
logic we; // write enable |
wb_address_t adr; // address |
logic [7:0] sel; // byte lane selects |
logic [63:0] dat; // data |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic csr; // set or clear reservation we:1=clear 0=set |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_write_request64_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
logic we; // write enable |
wb_address_t adr; // address |
logic [15:0] sel; // byte lane selects |
logic [127:0] dat; // data |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic csr; // set or clear reservation we:1=clear 0=set |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_write_request128_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
logic we; // write enable |
wb_address_t adr; // address |
logic [31:0] sel; // byte lane selects |
logic [255:0] dat; // data |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic csr; // set or clear reservation we:1=clear 0=set |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_write_request256_t; |
|
typedef struct packed { |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
logic we; // write enable |
wb_address_t adr; // address |
logic [63:0] sel; // byte lane selects |
logic [511:0] dat; // data |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic csr; // set or clear reservation we:1=clear 0=set |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
} wb_write_request512_t; |
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
// Read responses |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
typedef struct packed { |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic stall; // stall pipeline |
logic next; // advance to next transaction |
logic ack; // response acknowledge |
logic rty; // retry |
logic err; // error |
wb_priority_t pri; // response priority |
logic [7:0] dat; // data |
} wb_read_response8_t; |
|
typedef struct packed { |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic stall; // stall pipeline |
logic next; // advance to next transaction |
logic ack; // response acknowledge |
logic rty; // retry |
logic err; // error |
wb_priority_t pri; // response priority |
logic [15:0] dat; // data |
} wb_read_response16_t; |
|
typedef struct packed { |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic stall; // stall pipeline |
logic next; // advance to next transaction |
logic ack; // response acknowledge |
logic rty; // retry |
logic err; // error |
wb_priority_t pri; // response priority |
logic [31:0] dat; // data |
} wb_read_response32_t; |
|
typedef struct packed { |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic stall; // stall pipeline |
logic next; // advance to next transaction |
logic ack; // response acknowledge |
logic rty; // retry |
logic err; // error |
wb_priority_t pri; // response priority |
logic [31:0] dat; // data |
} wb_response32_t; |
|
typedef struct packed { |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic stall; // stall pipeline |
logic next; // advance to next transaction |
logic ack; // response acknowledge |
logic rty; // retry |
logic err; // error |
wb_priority_t pri; // response priority |
logic [63:0] dat; // data |
} wb_read_response64_t; |
|
typedef struct packed { |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic stall; // stall pipeline |
logic next; // advance to next transaction |
logic ack; // response acknowledge |
logic rty; // retry |
logic err; // error |
wb_priority_t pri; // response priority |
logic [127:0] dat; // data |
} wb_read_response128_t; |
|
typedef struct packed { |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic stall; // stall pipeline |
logic next; // advance to next transaction |
logic ack; // response acknowledge |
logic rty; // retry |
logic err; // error |
wb_priority_t pri; // response priority |
logic [127:0] dat; // data |
} wb_response128_t; |
|
typedef struct packed { |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic stall; // stall pipeline |
logic next; // advance to next transaction |
logic ack; // response acknowledge |
logic rty; // retry |
logic err; // error |
wb_priority_t pri; // response priority |
logic [255:0] dat; // data |
} wb_read_response256_t; |
|
typedef struct packed { |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic stall; // stall pipeline |
logic next; // advance to next transaction |
logic ack; // response acknowledge |
logic rty; // retry |
logic err; // error |
wb_priority_t pri; // response priority |
logic [511:0] dat; // data |
} wb_read_response512_t; |
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
// Write responses |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
// Sometimes write cycles can expect data responses back too. This is typically |
// just a single bit. For instance, the reservation status. Write responses all |
// have a common structure. |
|
typedef struct packed { |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic stall; // stall pipeline |
logic next; // advance to next transaction |
logic ack; // response acknowledge |
logic rty; // retry |
logic err; // error |
wb_priority_t pri; // response priority |
logic [7:0] dat; // data |
} wb_write_response_t; |
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
// read/write requests |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
typedef struct packed |
{ |
wb_read_request8_t read; |
wb_write_request8_t write; |
} wb_readwrite_request8_t; |
|
typedef struct packed |
{ |
wb_read_request16_t read; |
wb_write_request16_t write; |
} wb_readwrite_request16_t; |
|
typedef struct packed |
{ |
wb_read_request32_t read; |
wb_write_request32_t write; |
} wb_readwrite_request32_t; |
|
typedef struct packed |
{ |
wb_read_request64_t read; |
wb_write_request64_t write; |
} wb_readwrite_request64_t; |
|
typedef struct packed |
{ |
wb_read_request128_t read; |
wb_write_request128_t write; |
} wb_readwrite_request128_t; |
|
typedef struct packed |
{ |
wb_read_request256_t read; |
wb_write_request256_t write; |
} wb_readwrite_request256_t; |
|
typedef struct packed |
{ |
wb_read_request512_t read; |
wb_write_request512_t write; |
} wb_readwrite_request512_t; |
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
// read / write responses |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
typedef struct packed |
{ |
wb_read_response8_t read; |
wb_write_response_t write; |
} wb_readwrite_response8_t; |
|
typedef struct packed |
{ |
wb_read_response16_t read; |
wb_write_response_t write; |
} wb_readwrite_response16_t; |
|
typedef struct packed |
{ |
wb_read_response32_t read; |
wb_write_response_t write; |
} wb_readwrite_response32_t; |
|
typedef struct packed |
{ |
wb_read_response64_t read; |
wb_write_response_t write; |
} wb_readwrite_response64_t; |
|
typedef struct packed |
{ |
wb_read_response128_t read; |
wb_write_response_t write; |
} wb_readwrite_response128_t; |
|
typedef struct packed |
{ |
wb_read_response256_t read; |
wb_write_response_t write; |
} wb_readwrite_response256_t; |
|
typedef struct packed |
{ |
wb_read_response512_t read; |
wb_write_response_t write; |
} wb_readwrite_response512_t; |
|
endpackage |
|
interface wb_request_i #(int WID); |
wb_burst_type_t bte; // burst type extension |
wb_cycle_type_t cti; // cycle type indicator |
wb_burst_len_t blen; // length of burst-1 |
wb_segment_t seg; // segment |
logic cyc; // valid cycle |
logic stb; // data strobe |
logic we; // write enable |
wb_address_t adr; // address |
logic [WID/8-1:0] sel; // byte lane selects |
logic [WID-1:0] dat; // data |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic csr; // set or clear reservation we:1=clear 0=set |
wb_priv_level_t pl; // privilege level |
wb_priority_t pri; // transaction priority |
wb_cache_t cache; // cache and buffer properties |
endinterface |
|
interface wb_response_i #(int WID); |
wb_channel_t cid; // channel id |
wb_tranid_t tid; // transaction id |
logic stall; // stall pipeline |
logic next; // advance to next transaction |
logic ack; // response acknowledge |
logic rty; // retry |
logic err; // error |
wb_priority_t pri; // response priority |
logic [WID-1:0] dat; // data |
endinterface |