Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Copyright 2006, 2007 Dennis van Weeren
- //
- // This file is part of Minimig
- //
- // Minimig is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 3 of the License, or
- // (at your option) any later version.
- //
- // Minimig is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
- //
- //
- //
- // This is Denise
- // This module is a complete implementation of the Amiga OCS Denise chip
- // It supports all OCS modes including HAM, EHB and interlaced video
- //
- // 11-05-2005 -started coding
- // 15-05-2005 -added local beamcounter
- // -added bitplanes module
- // -added color registers
- // -first experimental version
- // 22-05-2005 -added diwstrt/diwstop
- // 12-06-2005 -started integrating sprites module
- // 21-06-2005 -done more work on integrating sprites module
- // 22-06-2005 -done more work on completing denise
- // 27-06-2005 -added main priority logic (sprites vs playfields)
- // 28-06-2005 -added hold and modify mode
- // -added delay register and video multiplexers
- // -added video output register
- // 29-06-2005 -added collision detection, Denise is now complete! (but untested)
- // -(later this day) Denise works! (hires,interlaced,playfield,sprites)
- // 07-08-2005 -added deniseid register
- // 02-10-2005 -fixed bit 15 of CLXDAT high
- // 19-10-2005 -code now uses sol signal to synchronize local beam counter
- // 11-01-2006 -added blanking circuit
- // 22-01-2006 -added vertical window clipping
- // ----------
- // JB:
- // 2008-07-08 - added hires output (for scandoubler)
- // - changed Denise ID (sometimes Show Config detected wrong chip type)
- // 2008-11-23 - playfield collision detection fix
- // - changed horizontal counter counting range (fixes problems with overscan: Stardust, Forgoten Worlds)
- // - added strhor signal to synchronize local horizontal counter
- // 2009-01-09 - added sprena signal (disables display of sprites until BPL1DAT is written)
- // 2009-03-08 - removed sof and sol inputs as they are no longer used
- // 2009-05-24 - clean-up & renaming
- // 2009-10-04 - implemented DIWHIGH register, pixel pipeline moved to clk28m domain, implemented super hires, changed ID to ECS
- // 2009-12-16 - added ECS enable input (only chip id is affected)
- // 2009-12-20 - DIWHIGH is written only in ECS mode
- // 2010-04-22 - ECS border blank implemented
- module Denise
- (
- input clk28m, // 35ns pixel clock
- input clk, // bus clock / lores pixel clock
- input c1 , // 35ns clock enable signals (for synchronization with clk)
- input c3,
- input cck, // colour clock enable
- input reset, // reset
- input strhor, // horizontal strobe
- input [8:1] reg_address_in, // register address inputs
- input [15:0] data_in, // bus data in
- output [15:0] data_out, // bus data out
- input blank, // blanking input
- output [7:0] red, // red componenent video out
- output [7:0] green, // green component video out
- output [7:0] blue, // blue component video out
- input ecs, // enables ECS chipset features
- input a1k, // control EHB chipset feature
- output reg hires // hires
- );
- //register names and adresses
- parameter DIWSTRT = 9'h08E;
- parameter DIWSTOP = 9'h090;
- parameter DIWHIGH = 9'h1E4;
- parameter BPLCON0 = 9'h100;
- parameter BPLCON2 = 9'h104;
- parameter BPLCON3 = 9'h106;
- parameter BPLCON4 = 9'h10C;
- parameter DENISEID = 9'h07C;
- parameter BPL1DAT = 9'h110;
- //local signals
- reg [8:0] hpos; // horizontal beamcounter
- reg shres; // super high resolution select
- reg homod; // HAM mode select
- reg dblpf; // double playfield select
- reg [3:0] bpu; // bitplane enable
- reg [3:0] l_bpu; // latched bitplane enable
- reg enaecs; // enable ECS features like border blank (bplcon0.0)
- reg [15:0] bplcon2; // bplcon2 (playfield video priority) register
- reg [15:0] bplcon3; // bplcon3 register (border blank) (palette bank for writes), low word enable
- reg [15:0] bplcon4; // Palette offset - upper 8 bits xored with bitplane data.
- wire brdrblnk; // border blank enable
- reg [8:0] hdiwstrt; // horizontal display window start position
- reg [8:0] hdiwstop; // horizontal display window stop position
- wire [8:1] bpldata_out; // bitplane serial data out from shifters
- wire [8:1] bpldata; // raw bitplane serial video data
- wire [3:0] sprdata; // sprite serial video data
- wire [7:0] plfdata; // playfield serial video data
- wire [2:1] nplayfield; // playfield 1,2 valid data signals
- wire [7:0] nsprite; // sprite 0-7 valid data signals
- wire sprsel; // sprite select
- reg [7:0] clut_data; // colour table colour select in
- wire [23:0] clut_rgb; // colour table rgb data out
- wire [23:0] ham_rgb; // hold and modify mode RGB video data
- wire [23:0] out_rgb; // final multiplexer rgb output data
- reg window; // window enable signal
- wire [15:0] deniseid_out; // deniseid data_out
- wire [15:0] col_out; // colision detection data_out
- reg display_ena; // in OCS sprites are visible between first write to BPL1DAT and end of scanline
- //--------------------------------------------------------------------------------------
- // data out mulitplexer
- assign data_out = col_out | deniseid_out;
- //--------------------------------------------------------------------------------------
- // Denise horizontal counter counting range: $01-$E3 CCKs (2-455 lores pixels)
- always @(posedge clk)
- if (strhor)
- hpos <= 9'd2;
- else
- hpos <= hpos + 9'd1;
- //--------------------------------------------------------------------------------------
- // sprite display enable signal - sprites are visible after the first write to the BPL1DAT register in a scanline
- always @(posedge clk)
- if (reset || hpos[8:0]==8)
- display_ena <= 0;
- else if (reg_address_in[8:1]==BPL1DAT[8:1])
- display_ena <= 1;
- // bpu is updated when bpl1dat register is written
- always @(posedge clk)
- if (reg_address_in[8:1]==BPL1DAT[8:1])
- l_bpu <= bpu;
- // BPLCON0 register
- always @(posedge clk)
- if (reset)
- begin
- hires <= 1'b0;
- shres <= 1'b0;
- homod <= 1'b0;
- dblpf <= 1'b0;
- bpu <= 4'b0000;
- enaecs <= 1'b0;
- end
- else if (reg_address_in[8:1]==BPLCON0[8:1])
- begin
- hires <= data_in[15];
- shres <= data_in[6];
- homod <= data_in[11];
- dblpf <= data_in[10];
- bpu <= {data_in[4],data_in[14:12]};
- enaecs <= data_in[0];
- end
- // BPLCON2 register
- always @(posedge clk)
- if (reset)
- bplcon2 <= 16'h00_00;
- else if (reg_address_in[8:1]==BPLCON2[8:1])
- bplcon2[15:0] <= data_in[15:0];
- // BPLCON3 register
- // LOCT - bit 9
- // BANK - 15:13
- always @(posedge clk)
- if (reset)
- bplcon3 <= 16'b0000_1100_0000_0000;
- else if (reg_address_in[8:1]==BPLCON3[8:1])
- bplcon3[15:0] <= data_in[15:0];
- assign brdrblnk = bplcon3[5];
- // BPLCON4 register - bitplane and sprite palette offsets (xored)
- always @(posedge clk)
- if (reset)
- bplcon4 <= 16'b0000_0000_0001_0001;
- else if (reg_address_in[8:1]==BPLCON4[8:1])
- bplcon4[15:0] <= data_in[15:0];
- // DIWSTART and DIWSTOP registers (vertical and horizontal limits of display window)
- // HDIWSTRT
- always @(posedge clk)
- if (reg_address_in[8:1]==DIWSTRT[8:1])
- hdiwstrt[7:0] <= data_in[7:0];
- always @(posedge clk)
- if (reg_address_in[8:1]==DIWSTRT[8:1])
- hdiwstrt[8] <= 1'b0; // diwstop H9 = 0
- else if (reg_address_in[8:1]==DIWHIGH[8:1] && ecs)
- hdiwstrt[8] <= data_in[5];
- // HDIWSTOP
- always @(posedge clk)
- if (reg_address_in[8:1]==DIWSTOP[8:1])
- hdiwstop[7:0] <= data_in[7:0];
- always @(posedge clk)
- if (reg_address_in[8:1]==DIWSTOP[8:1])
- hdiwstop[8] <= 1'b1; // diwstop H8 = 1
- else if (reg_address_in[8:1]==DIWHIGH[8:1] && ecs)
- hdiwstop[8] <= data_in[13];
- // Denise ID.
- // NOTE: Low bits are 0xFF for OCS, 0xFC for ECS, and 0xF8 for AGA.
- // Apparently, the older LISA chip also had the LSB set, so would be 0xF9? Best to stick with 0xF8 for AGA though. OzOnE
- //
- //assign deniseid_out = reg_address_in[8:1]==DENISEID[8:1] ? ecs ? 16'hFF_FC : 16'hFF_FF : 16'h00_00;
- assign deniseid_out = reg_address_in[8:1]==DENISEID[8:1] ? ecs ? 16'hFF_F8 : 16'hFF_FF : 16'h00_00; // Force Denise ID to AGA when ECS enabled! OzOnE
- //--------------------------------------------------------------------------------------
- // generate window enable signal
- // true when beamcounter satisfies horizontal diwstrt/diwstop limits
- always @(posedge clk)
- if (hpos[8:0]==hdiwstrt[8:0])
- window <= 1;
- else if (hpos[8:0]==hdiwstop[8:0])
- window <= 0;
- reg window_ena;
- always @(posedge clk)
- window_ena <= window;
- //--------------------------------------------------------------------------------------
- // instantiate bitplane module
- bitplanes bplm0
- (
- .clk(clk),
- .clk28m(clk28m),
- .c1(c1),
- .c3(c3),
- .reg_address_in(reg_address_in),
- .data_in(data_in),
- .hires(hires),
- .shres(shres & ecs),
- .hpos(hpos),
- .bpldata(bpldata_out)
- );
- assign bpldata[1] = l_bpu > 0 ? bpldata_out[1] : 1'b0;
- assign bpldata[2] = l_bpu > 1 ? bpldata_out[2] : 1'b0;
- assign bpldata[3] = l_bpu > 2 ? bpldata_out[3] : 1'b0;
- assign bpldata[4] = l_bpu > 3 ? bpldata_out[4] : 1'b0;
- assign bpldata[5] = l_bpu > 4 ? bpldata_out[5] : 1'b0;
- assign bpldata[6] = l_bpu > 5 ? bpldata_out[6] : 1'b0;
- assign bpldata[7] = l_bpu > 6 ? bpldata_out[7] : 1'b0;
- assign bpldata[8] = l_bpu > 7 ? bpldata_out[8] : 1'b0;
- // instantiate playfield module
- playfields plfm0
- (
- .bpldata(bpldata),
- .dblpf(dblpf),
- .bplcon2(bplcon2[6:0]),
- .nplayfield(nplayfield),
- .plfdata(plfdata)
- );
- // instantiate sprite module
- sprites sprm0
- (
- .clk(clk),
- .reset(reset),
- .ecs(1'b0),
- .reg_address_in(reg_address_in),
- .hpos(hpos),
- .data_in(data_in),
- .sprena(display_ena),
- .nsprite(nsprite),
- .sprdata(sprdata)
- );
- // instantiate video priority logic module
- sprpriority spm0
- (
- .bplcon2(bplcon2[5:0]),
- .nplayfield(nplayfield),
- .nsprite(nsprite),
- .sprsel(sprsel)
- );
- // instantiate colour look up table
- colortable clut0
- (
- .clk(clk),
- .clk28m(clk28m),
- .bank(bplcon3[15:13]),
- .reg_address_in(reg_address_in),
- .data_in(data_in[11:0]),
- .loct(bplcon3[9]), // (LOCT bit.)
- // .select(clut_data ^ bplcon4[15:8]), // Apply palette offset. (added extra two bits for bitplane 7+8. AGA stuff. OzOnE.)
- .select(clut_data),
- .a1k(a1k),
- .rgb(clut_rgb) // RGB data is delayed by one clk28m clock cycle
- );
- // instantiate HAM (hold and modify) module
- hamgenerator ham0
- (
- .clk(clk),
- .clk28m(clk28m),
- .bank(bplcon3[15:13]),
- .reg_address_in(reg_address_in),
- .data_in(data_in[11:0]),
- .bpldata(bpldata),
- .ham8( (l_bpu > 7) && homod), // BPU=8 when all 8 bitplanes are enabled, plus check the HOMOD bit! (AGA HAM8 extensions. OzOnE.)
- .loct(bplcon3[9]), // (LOCT bit.)
- .ham_rgb(ham_rgb)
- );
- // instantiate collision detection module
- collision col0
- (
- .clk(clk),
- .reset(reset),
- .reg_address_in(reg_address_in),
- .data_in(data_in),
- .data_out(col_out),
- .dblpf(dblpf),
- .bpldata(bpldata),
- .nsprite(nsprite)
- );
- //--------------------------------------------------------------------------------------
- //
- always @(sprsel or window_ena or sprdata or plfdata)
- begin
- if (!window_ena) // we are outside of the visible window region, display border colour
- clut_data = 8'b00000000;
- else if (sprsel) // select sprites
- clut_data = {4'b0001,sprdata[3:0]}; // Not sure what this 1 bit does yet? OzOnE
- else // select playfield
- clut_data = plfdata;
- end
- reg window_del;
- reg sprsel_del;
- always @(posedge clk28m)
- begin
- window_del <= window_ena;
- sprsel_del <= sprsel;
- end
- // ham_rgb / clut_rgb multiplexer
- assign out_rgb = (homod && window_del && !sprsel_del) ? ham_rgb : clut_rgb; //if no HAM mode, always select normal (table selected) rgb data
- //
- //ham_rgb is now 24-bit, with the lowest 4-bits of each colour set to zero in HAM6 mode. OzOnE
- //--------------------------------------------------------------------------------------
- wire t_blank;
- assign t_blank = blank | ecs & enaecs & brdrblnk & (~window_del | ~display_ena);
- // RGB video output
- assign {red,green,blue} = t_blank ? 24'h000000 : out_rgb; // out_rgb is 24-bit now (AGA. OzOnE.)
- endmodule
- //--------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------
- // this is the 32-colour 12-bit colour table (now 256-colour, 24-bit! AMR / OzONE)
- // because this module also supports EHB (extra half brite) mode,
- // it actually has a 6bit colour select input
- // the 6th bit selects EHB colour while the lower 5 bit select the actual colour register
- module colortable
- (
- input wire clk, // bus clock / lores pixel clock
- input wire clk28m, // 35ns pixel clock
- input wire [2:0] bank, // Write bank from bplcon3
- input wire [8:1] reg_address_in, // register address inputs
- input wire [11:0] data_in, // bus data in
- input wire loct, // data should be written to the 4 LSBs of each gun... (LOCT bit input.)
- input wire [7:0] select, // colour select input
- input wire a1k, // EHB control
- // output reg [11:0] rgb // RGB output
- output wire [23:0] rgb // RGB output
- );
- // register names and adresses
- parameter COLORBASE = 9'h180; // colour table base address
- // local signals
- //reg [11:0] colortable [31:0]; // colour table
- //wire [11:0] selcolor; // selected colour register output
- ColourtableDPBlockram ctbram // Colourtable for High-order colour bits (normal OCS/ECS).
- (
- .wraddress({bank,reg_address_in[5:1]}),
- .rdaddress(select),
- .rdclock(clk28m),
- .wrclock(clk),
- .data(data_in),
- .wren((loct==0) && reg_address_in[8:6]==COLORBASE[8:6]), // If the LOCT bit is CLEARED, both the High-order and Low-order colortable entries will get written to.
- .q({rgb[23:20],rgb[15:12],rgb[7:4]})
- );
- ColourtableDPBlockram ctbram_lo // Colourtable for Low-order colour bits (AGA extension).
- (
- .wraddress({bank,reg_address_in[5:1]}),
- .rdaddress(select),
- .rdclock(clk28m),
- .wrclock(clk),
- .data(data_in),
- .wren((reg_address_in[8:6]==COLORBASE[8:6])), // Writes to the normal High-order colortable bits (above) write to the Low-order bits as well if LOCT is cleared.
- .q({rgb[19:16],rgb[11:8],rgb[3:0]}) // So, you have to clear the LOCT bit first, write the High bits, set LOCT, write the Low bits. ;) OzOnE.
- );
- // writing of colour table from bus (implemented using dual port distributed ram)
- //always @(posedge clk)
- // if (reg_address_in[8:6]==COLORBASE[8:6])
- // colortable[reg_address_in[5:1]] <= data_in[11:0];
- // reading of colour table
- //assign selcolor = colortable[select[4:0]];
- // extra half brite mode shifter
- //always @(posedge clk28m)
- // if (select[5] && !a1k) // half bright, shift every component 1 position to the right
- // rgb <= {1'b0,selcolor[11:9],1'b0,selcolor[7:5],1'b0,selcolor[3:1]};
- // else // normal colour select
- // if (reg_address_in[8:1]=={COLORBASE[8:6],select[4:0]}) // read-during-write...
- // rgb <= data_in[11:0];
- // else
- // rgb <= selcolor;
- endmodule
- //--------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------
- // sprite priority logic module
- // this module checks the playfields and sprites video status and
- // determines if playfield or sprite data must be sent to the video output
- // sprite/playfield priority is configurable through the bplcon2 bits
- module sprpriority
- (
- input wire [5:0] bplcon2, // playfields vs sprites priority setting
- input wire [2:1] nplayfield, // playfields video status
- input wire [7:0] nsprite, // sprites video status
- output reg sprsel // sprites select signal output
- );
- // local signals
- reg [2:0] sprcode; // sprite code
- wire [3:0] sprgroup; // grouped sprites
- wire pf1front; // playfield 1 is on front of sprites
- wire pf2front; // playfield 2 is on front of sprites
- // group sprites together
- assign sprgroup[0] = (nsprite[1:0]==2'd0) ? 1'b0 : 1'b1;
- assign sprgroup[1] = (nsprite[3:2]==2'd0) ? 1'b0 : 1'b1;
- assign sprgroup[2] = (nsprite[5:4]==2'd0) ? 1'b0 : 1'b1;
- assign sprgroup[3] = (nsprite[7:6]==2'd0) ? 1'b0 : 1'b1;
- // sprites priority encoder
- always @(sprgroup)
- if (sprgroup[0])
- sprcode = 3'd1;
- else if (sprgroup[1])
- sprcode = 3'd2;
- else if (sprgroup[2])
- sprcode = 3'd3;
- else if (sprgroup[3])
- sprcode = 3'd4;
- else
- sprcode = 3'd7;
- // check if playfields are in front of sprites
- assign pf1front = sprcode[2:0]>bplcon2[2:0] ? 1'b1 : 1'b0;
- assign pf2front = sprcode[2:0]>bplcon2[5:3] ? 1'b1 : 1'b0;
- // generate final playfield/sprite select signal
- always @(sprcode or pf1front or pf2front or nplayfield)
- begin
- if (sprcode[2:0]==3'd7) // if no valid sprite data, always select playfields
- sprsel = 1'b0;
- else if (pf1front && nplayfield[1]) // else if pf1 in front and valid data, select playfields
- sprsel = 1'b0;
- else if (pf2front && nplayfield[2]) // else if pf2 in front and valid data, select playfields
- sprsel = 1'b0;
- else // else select sprites
- sprsel = 1'b1;
- end
- endmodule
- //--------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------
- // This module handles the hold and modify mode (HAM).
- // The module has its own colour palette bank, this is to let
- // the sprites run simultanously with a HAM playfield.
- //
- module hamgenerator
- (
- input wire clk, // bus clock
- input wire clk28m, // 35ns pixel clock
- input wire [8:1] reg_address_in, // register address inputs
- input wire [11:0] data_in, // bus data in
- input wire [7:0] bpldata, // bitplane data input
- input wire ham8, // Enable HAM8 mode. (enabled when BPU[3] and HOMOD bits are set. OzOnE.)
- input wire [2:0] bank, // Bank bits. (bank[0] allows access to second group of color table entries in HAM8 mode.)
- // Extra bank bits brought in for future use. OzOnE
- input wire loct, // LOCT bit.
- output reg [23:0] ham_rgb // RGB output (24-bit packed, RRRRRRRRGGGGGGGGBBBBBBBB.)
- );
- //register names and adresses
- parameter COLORBASE = 9'h180; // colour table base address
- //local signals
- reg [11:0] colortable_high [63:0]; // colour table. (Extended from 16 to 64 entries. AGA stuff. OzOnE.)
- // Note: HAM6 mode only accesses palette entries 0 to 15!
- reg [11:0] colortable_low [63:0]; // colour table. (Lower 12-bits, for AGA. OzOnE.)
- wire [23:0] selcolor; // selected colour output from colour table
- //--------------------------------------------------------------------------------------
- //writing of HAM colour table from bus (implemented using dual port distributed ram)
- //
- // (LOCT bit Low, OCS/ECS) (LOCT bit High, AGA only)
- // || ||
- // Only 16 entries for OCS/ECS! 64 Entries for AGA!
- // [Colour table - HIGH bits] [Colour tablet, LOW bits]
- //
- // 1 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 2 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 3 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // .
- // .
- // 13 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 14 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 15 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- //
- // NOTE: HAM6 only uses palette entries 0 to 15.
- //
- //
- // NOTE2: HAM8 can use palette entries 0 to 63.
- //
- // 16 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 17 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 18 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // .
- // .
- // 29 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 30 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 31 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- //
- // 2nd Bank. (Bank0 bit High, AGA only)...
- //
- // 32 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 33 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 34 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // .
- // .
- // 61 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 62 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- // 63 [11,10,9,8,7,6,5,4,3,2,1,0] [11,10,9,8,7,6,5,4,3,2,1,0]
- //
- //
- // COLORxx 180-1BE W COLOR table xx
- // There are thirty-two (32) of these registers
- // (xx=00~31) and together with the banking bits they
- // address the 256 locations in the Color Palette.
- // There are actually 2 sets of color registers,
- // selection of which is controlled by the LOCT
- // register bit. When LOCT=0, the 4 MSB of
- // RED,GREEEN, and BLUE video data are selected along
- // with the ZD bit for Genlocks. The low-order set of
- // registers is also selected simultaneously, so that
- // the 4 bit values are automatically extended to 8
- // bits. This provides compatibility with old
- // software. If the full range of palette values are
- // desired, then LOCT can be set high and independent
- // values for the 4 LSB of RED,GREEN, and BLUE can be
- // written. The low-order color registers do not
- // contain a transparency(T) bit. The Table below
- // shows the color register bit usage.
- //
- // (Our data bus is only 12-bits atm, so data bits 15:12 don't exist on Minimig yet. OzOnE.)
- //
- // BIT * 15,14,13,12, 11,10,09,08, 07,06,05,04, 03,02,01,00
- // LOCT=0 T X X X R7 R6 R5 R4 G7 G6 G5 G4 B7 B6 B5 B4 (colortable_high, LOCT=0 !)
- // LOCT=1 X X X X R3 R2 R1 R0 G3 G2 G1 GO B3 B2 B1 HO (colortable_low, LOCT=1 !)
- //
- // T = TRANSPARENCY R = RED G = GREEN B = BLUE X = UNUSED
- //
- //
- wire [6:1] ct_addr = (ham8==1'b1) ? {bank[0],reg_address_in[5:1]} : {2'b00,reg_address_in[4:1]};
- always @(posedge clk)
- // if (reg_address_in[8:6]==COLORBASE[8:6]) begin // True for Reg Addr 0x180 up to 0x1BE.
- // // (colour table entries 0 to 31.) OzOnE.
- // if (reg_address_in[8:5]==COLORBASE[8:5]) begin // True for Reg Addr 0x180 up to 0x19E.
- // // (colour table entries 0 to 15.) OzOnE.
- if (ham8==1'b1 && reg_address_in[8:6]==COLORBASE[8:6]) begin // HAM8 mode, and Reg Addr between 0x180 and 0x1BE...
- // (color table entries 0 to 31) OzOnE.
- if (loct==1'b0) begin
- colortable_high[ct_addr] <= data_in[11:0]; // In HAM8 mode, writes with LOCT set LOW go to both the
- colortable_low[ct_addr] <= data_in[11:0]; // upper and lower 12-bits of the colour table....
- end
- else begin
- colortable_low[ct_addr] <= data_in[11:0]; // ...Writes with LOCT set HIGH go to the LOWER 12-bits of the colour table only.
- end
- end
- else if (ham8==1'b0 && reg_address_in[8:5]==COLORBASE[8:5]) begin // HAM6 mode, and Reg Addr between 0x180 and 0x19E...
- // (color table entries 0 to 15). OzOnE.
- colortable_high[ct_addr] <= data_in[11:0]; // HAM6 has no bank bit(s), and it only accesses entries 0 to 15 of the color table.
- end // ...(and only writes to the Upper 12-bits of each color table entry. I think?)
- // end
- //reading of colour table
- //
- // In HAM8 mode, the two extra bitplane bits are then used to access colour table entries 0 to 63.
- // The upper and lower 12-bit colour tables are also combined for output.
- //
- assign selcolor = (ham8==1'b1) ? { colortable_high[bpldata[7:2]], colortable_low[bpldata[7:2]] } : // HAM8 - extra 2 bitplane bits (6 total) can access all 64 palette entries.
- { colortable_high[{2'b00,bpldata[3:0]}], colortable_high[{2'b00,bpldata[3:0]}] }; // HAM6 (duplicated the 12-bit output to both halves). OzOnE.
- // HAM6 only access the first 16 color table entries, so padding the top two bits of the address.
- //--------------------------------------------------------------------------------------
- // HAM selcolor...
- //
- // Color Table HIGH (HAM6 and HAM8) Color Table LOW (HAM8 only)
- //
- // [11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] [11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
- // [R7,R6,R5,R4,G7,G6,G5,G4,B7,B6,B5,B4] [R3,R2,R1,R0,G3,G2,G1,G0,B3,B2,B1,B0]
- //
- //
- //HAM instruction decoder/processor
- always @(posedge clk28m)
- begin
- if (ham8==1'b1) begin // HAM8 mode enabled....
- case (bpldata[1:0]) // Note: HAM8 uses the two LOW bits of the bitplane data as the control bits!
- // NOTE: Take care when unpacking the correct bits from the color table output! OzOnE...
- 2'b00://Load (set) RGB output wite color table. R=[23:20]+[11:8]. G=[19:16]+[7:4]. B=[15:12]+[3:0].
- ham_rgb <= {selcolor[23:20],selcolor[11:8], selcolor[19:16],selcolor[7:4], selcolor[15:12],selcolor[3:0]};
- 2'b01://HOLD red and green, MODIFY Blue
- ham_rgb <= {ham_rgb[23:8] ,bpldata[7:2],ham_rgb[1:0]};
- 2'b10://HOLD green and blue, MODIFY Red
- ham_rgb <= {bpldata[7:2],ham_rgb[17:16], ham_rgb[15:0]};
- 2'b11://HOLD red and blue, MODIFY Green
- ham_rgb <= {ham_rgb[23:16] ,bpldata[7:2],ham_rgb[9:8], ,ham_rgb[7:0]};
- endcase
- end
- else begin // HAM6 mode enabled... (D Paint V definitely using HAM6 for the "Elke_Mund.HAM" file). OzOnE
- case (bpldata[5:4]) // Note: HAM6 uses the two HIGH bits of the bitplane data as the control bits!
- 2'b00://Load (set) RGB output with color from table
- ham_rgb <= {selcolor[23:20],4'b0000, selcolor[19:16],4'b0000, selcolor[15:12],4'b0000};
- 2'b01://HOLD red and green, MODIFY Blue
- ham_rgb <= {ham_rgb[23:20],4'b0000, ham_rgb[19:16],4'b0000, bpldata[3:0],4'b0000}; // Lower 4 bits of each colour padded with zeros. OzOnE
- 2'b10://HOLD green and blue, MODIFY Red
- ham_rgb <= {bpldata[3:0],4'b0000, ham_rgb[19:16],4'b0000, ham_rgb[15:12],4'b0000};
- 2'b11://HOLD red and blue, MODIFY Green
- ham_rgb <= {ham_rgb[23:20],4'b0000, bpldata[3:0],4'b0000, ham_rgb[15:12],4'b0000};
- endcase
- end
- end
- endmodule
- //--------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------
- //this is the collision detection module
- module collision
- (
- input wire clk, //bus clock / lores pixel clock
- input wire reset, //reset
- input wire [8:1] reg_address_in, //register address inputs
- input wire [15:0] data_in, //bus data in
- output wire [15:0] data_out, //bus data out
- input wire dblpf, //dual playfield signal, required to support undocumented feature
- input wire [7:0] bpldata, //bitplane serial video data in
- input wire [7:0] nsprite
- );
- //register names and adresses
- parameter CLXCON = 9'h098;
- parameter CLXCON2 = 9'h10E;
- parameter CLXDAT = 9'h00E;
- //local signals
- reg [15:0] clxcon; //collision detection control register
- reg [15:0] clxcon2; //collision detection control 2 register -AGA extensions. OzOnE.
- reg [14:0] clxdat; //collision detection data register
- wire [3:0] sprmatch; //sprite group matches clxcon settings
- wire oddmatch; //odd bitplane data matches clxcon settings
- wire evenmatch; //even bitplane data matches clxcon settings
- //--------------------------------------------------------------------------------------
- //CLXCON register
- always @(posedge clk)
- if (reset) //reset to safe value
- clxcon <= 16'h0fff;
- else if (reg_address_in[8:1]==CLXCON[8:1])
- clxcon <= data_in;
- //CLXCON2 register (AGA extensions for bitplane 7 and 8. OzOnE).
- always @(posedge clk)
- if (reset) //reset to safe value
- clxcon2 <= 16'h00c3;
- else if (reg_address_in[8:1]==CLXCON2[8:1])
- clxcon2 <= data_in;
- //--------------------------------------------------------------------------------------
- //generate bitplane match signal
- wire [7:0] bm;
- assign bm = (bpldata[7:0] ^ ~{clxcon2[1:0],clxcon[5:0]} ) | (~{clxcon2[7:6],clxcon[11:6]}); // JB: playfield collision detection fix
- // (Extra bits for AGA added by OzOnE.)
- // this is the implementation of an undocumented function in the real Denise chip, developed by Yaqube.
- // trigger was the game Rotor. mentioned in WinUAE sources to be the only known game needing this feature.
- // it also fixes the Spaceport instantly helicopter crash at takeoff
- // and Archon-1 'sticky effect' of player sprite at the battlefield.
- // the OCS mystery is cleaning up :)
- assign oddmatch = bm[6] & bm[4] & bm[2] & bm[0] & (dblpf | evenmatch);
- assign evenmatch = bm[7] & bm[5] & bm[3] & bm[1];
- //generate sprite group match signal
- assign sprmatch[0] = nsprite[0] | (nsprite[1] & clxcon[12]);
- assign sprmatch[1] = nsprite[2] | (nsprite[3] & clxcon[13]);
- assign sprmatch[2] = nsprite[4] | (nsprite[5] & clxcon[14]);
- assign sprmatch[3] = nsprite[6] | (nsprite[7] & clxcon[15]);
- //--------------------------------------------------------------------------------------
- //detect collisions
- wire [14:0] cl;
- reg clxdat_read_del;
- assign cl[0] = evenmatch & oddmatch; //odd to even bitplanes
- assign cl[1] = oddmatch & sprmatch[0]; //odd bitplanes to sprite 0(or 1)
- assign cl[2] = oddmatch & sprmatch[1]; //odd bitplanes to sprite 2(or 3)
- assign cl[3] = oddmatch & sprmatch[2]; //odd bitplanes to sprite 4(or 5)
- assign cl[4] = oddmatch & sprmatch[3]; //odd bitplanes to sprite 6(or 7)
- assign cl[5] = evenmatch & sprmatch[0]; //even bitplanes to sprite 0(or 1)
- assign cl[6] = evenmatch & sprmatch[1]; //even bitplanes to sprite 2(or 3)
- assign cl[7] = evenmatch & sprmatch[2]; //even bitplanes to sprite 4(or 5)
- assign cl[8] = evenmatch & sprmatch[3]; //even bitplanes to sprite 6(or 7)
- assign cl[9] = sprmatch[0] & sprmatch[1]; //sprite 0(or 1) to sprite 2(or 3)
- assign cl[10] = sprmatch[0] & sprmatch[2]; //sprite 0(or 1) to sprite 4(or 5)
- assign cl[11] = sprmatch[0] & sprmatch[3]; //sprite 0(or 1) to sprite 6(or 7)
- assign cl[12] = sprmatch[1] & sprmatch[2]; //sprite 2(or 3) to sprite 4(or 5)
- assign cl[13] = sprmatch[1] & sprmatch[3]; //sprite 2(or 3) to sprite 6(or 7)
- assign cl[14] = sprmatch[2] & sprmatch[3]; //sprite 4(or 5) to sprite 6(or 7)
- wire clxdat_read = (reg_address_in[8:1]==CLXDAT[8:1]);// clxdat read
- always @(posedge clk)
- clxdat_read_del <= clxdat_read;
- //register detected collisions
- always @(posedge clk)
- // if (reg_address_in[8:1]==CLXDAT[8:1]) //if clxdat is read, clxdat is cleared to all zero's
- if (!clxdat_read & clxdat_read_del) //if clxdat is read, clxdat is cleared to all zero's after read
- clxdat <= 0;
- else //else register collisions
- clxdat <= clxdat[14:0] | cl[14:0];
- //--------------------------------------------------------------------------------------
- //reading of clxdat register
- assign data_out = reg_address_in[8:1]==CLXDAT[8:1] ? {1'b1,clxdat[14:0]} : 16'd0;
- endmodule
Advertisement
RAW Paste Data
Copied
Advertisement