⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 agnus.v

📁 Verilog, c and asm source codes of the Minimig system, a fpga implementation of the Amiga computer.
💻 V
📖 第 1 页 / 共 3 页
字号:
	if(bplen && (verbeam[8:0]>={1'b0,vdiwstrt[15:8]}) && (verbeam[8:0]<{~vdiwstop[15],vdiwstop[15:8]}))		bplenable=1;	else		bplenable=0;		bpldma_engine bpd1(	.clk(clk),	.reset(reset),	.enable(bplenable),	.horbeam(horbeam),	.dma(dma_bpl),	.interlace(interlace),	.regaddressin(regaddress),	.regaddressout(regaddress_bpl),	.datain(datain),	.addressout(address_bpl)	);//--------------------------------------------------------------------------------------//instantiate sprite dma enginesprdma_engine spr1(	.clk(clk),	.clk28m(clk28m),	.reqdma(req_spr),	.ackdma(ack_spr),	.hpos(horbeam),	.vpos(verbeam),	.vbl(vbl),	.vblend(vblend),	.regaddressin(regaddress),	.regaddressout(regaddress_spr),	.datain(datain),	.addressout(address_spr)	);//--------------------------------------------------------------------------------------//instantiate coppercopper cp1(	.clk(clk),	.reset(reset),	.reqdma(req_cop),	.ackdma(ack_cop),	.sof(sof),	.eol(sol),	.bbusy(bbusy),	.vpos(verbeam[7:0]),	.datain(datain),	.regaddressin(regaddress),	.regaddressout(regaddress_cop),	.addressout(address_cop)	);//--------------------------------------------------------------------------------------//instantiate blitterblitter bl1(	.clk(clk),	.reset(reset),	.reqdma(req_blt),	.ackdma(ack_blt),	.bzero(bzero),	.bbusy(bbusy),	.bblck(bblck),	.horbeam(horbeam[0]^horbeam[1]),//HACK, avoid dma contention a bit	.wr(wr_blt),	.datain(datain),	.dataout(data_blt),	.regaddressin(regaddress),	.addressout(address_blt)	);//generate blitter finished intterupt (int3)reg bbusyd;always @(posedge clk)	bbusyd<=bbusy;assign int3=(~bbusy)&bbusyd;//--------------------------------------------------------------------------------------//instantiate beam countersbeamcounter	bc1(		.clk(clk),	.reset(reset),	.interlace(interlace),	.ntsc(ntsc),	.datain(datain),	.dataout(data_bmc),	.regaddressin(regaddress),	.hpos(horbeam),	.vpos(verbeam),	._hsync(_hsync),	._vsync(_vsync),	.blank(blank),	.vbl(vbl),	.vblend(vblend),	.eol(sol),	.eof(sof));//horizontal strobe for Deniseassign strhor = horbeam==15 ? 1 : 0;//--------------------------------------------------------------------------------------endmodule//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------//bit plane dma enginemodule bpldma_engine(	input 	clk,		    			//bus clock	input	reset,						//reset	input	enable,						//enable dma input	input	[8:0]horbeam,				//horizontal beam counter	output	reg dma,					//true if bitplane dma engine uses it's cycle	output	reg interlace,				//interlace mode is selected through bplcon0	input 	[8:1]regaddressin,		//register address inputs	output 	reg [8:1]regaddressout,	//register address outputs	input	[15:0]datain,				//bus data in	output	[20:1]addressout			//chip address out);//register names and adresses		parameter BPLPTBASE=9'h0e0;	//bitplane pointers base addressparameter DDFSTRT=9'h092;		parameter DDFSTOP=9'h094;parameter BPL1MOD=9'h108;parameter BPL2MOD=9'h10a;parameter BPLCON0=9'h100;parameter BPLCON1=9'h102;		//JB: needed for better ddfstrt/ddfstop handling//local signalsreg		[8:2]ddfstrt;			//display data fetch start //JB: added bit #2reg 	[8:2]ddfstop; 		//display data fetch stop //JB: added bit #2reg		[15:1]bpl1mod;		//modulo for odd bitplanesreg		[15:1]bpl2mod;		//modulo for even bitplanesreg		[15:12]bplcon0;		//bitplane control (HIRES and BPU bits)reg		[7:0]bplcon1;	 		//JB:reg 	hires;				 	//JB:reg		shres;				 	//JB:reg		[20:1]newpt;			//new pointer				reg 	[20:16]bplpth[7:0];	//upper 5 bits bitplane pointersreg 	[15:1]bplptl[7:0];	//lower 16 bits bitplane pointersreg		[2:0]plane;			//plane pointer selectwire	mod;					//end of data fetch, add modulo	//JB: changed reg to wire//--------------------------------------------------------------------------------------//register bank address multiplexerwire [2:0]select;assign select=(dma)?plane:regaddressin[4:2];//high word pointer register bank (implemented using distributed ram)wire [20:16]bplpth_in;assign bplpth_in=(dma)?newpt[20:16]:datain[4:0];always @(posedge clk)	if(dma || ((regaddressin[8:5]==BPLPTBASE[8:5]) && !regaddressin[1]))//if bitplane dma cycle or bus write		bplpth[select]<=bplpth_in;assign addressout[20:16]=bplpth[plane];//low word pointer register bank (implemented using distributed ram)wire [15:1]bplptl_in;assign bplptl_in=(dma)?newpt[15:1]:datain[15:1];always @(posedge clk)	if(dma || ((regaddressin[8:5]==BPLPTBASE[8:5]) && regaddressin[1]))//if bitplane dma cycle or bus write		bplptl[select]<=bplptl_in;assign addressout[15:1]=bplptl[plane];//--------------------------------------------------------------------------------------//write ddfstrt and ddfstop registersalways @(posedge clk)	if(regaddressin[8:1]==DDFSTRT[8:1])		if (datain[7:1] < 7'b0001_100)			ddfstrt[8:2] <= 7'b0001_100;		else			ddfstrt[8:2]<=datain[7:1];			//JB: added LSB		always @(posedge clk)	if(regaddressin[8:1]==DDFSTOP[8:1])		if (datain[7:1] > 7'b1101_100)			ddfstop[8:2] <= 7'b1101_100;		else			ddfstop[8:2] <= datain[7:1];		//JB: added LSB//write modulo registersalways @(posedge clk)	if(regaddressin[8:1]==BPL1MOD[8:1])		bpl1mod[15:1]<=datain[15:1];always @(posedge clk)	if(regaddressin[8:1]==BPL2MOD[8:1])		bpl2mod[15:1]<=datain[15:1];//write parts of bplcon0 register that are relevant to bitplane dma + interlace and ersyalways @(posedge clk)	if(reset)	begin		bplcon0[15:12]<=4'b0000;		interlace<=0;		hires <= 0;	//JB:		shres <= 0;	//JB:	end	else if(regaddressin[8:1]==BPLCON0[8:1])	begin		bplcon0[15:12]<=datain[15:12];		interlace<=datain[2];		hires <= datain[15];	//JB:		shres <= datain[6];	//JB:	end//JB: needed for better ddf handling//write part of bplcon1 registeralways @(posedge clk)	if (regaddressin[8:1] == BPLCON1[8:1])		bplcon1[7:0] <= datain[7:0];//--------------------------------------------------------------------------------------// (JB) More on mystical magic investigation after some experiments with my real A4k:// H3/H2 bits in DDFSTRT and DDFSTOP registers are important in all resolutions.// LORES:// if H3 or H2 of DDFSTRT is set the display is delayed by one full dma fetch cycle (8 colour clocks [cck])// it means that the display stop position is also shifted by 16 lowres pixels eventhough DDFSTOP hasn't changed// if H3:H2 of DDFSTOP is greater than H3:H2 of DDFSTRT the display is stopped after an extra dma cycle//   (extra 16 pixels fetched in lowres, 32 in hires and 64 in super hires)// if the DDFSTOP is close enough to the HTOTAL value in some cases the dma engine doesn't see a display stop// and total display corruption happens, i.e://  DDFSTOP=$D4 and DDFSTRT[3:2]=%01,//  DDFSTOP=$D6 and (DDFSTRT[3:2]=%01 or DDFSTRT[3:2]=%10),//  DDFSTOP>=$D8 and DDFSTRT[3:2]!=%00 //  if DDFSTOP > $D8 and DDFSTRT[3:2]=%00 the display stops at $D8 (hardware stop)// in lores dma cycles always begin and end on 8 colour clock (cck) cycle boundary// HIRES:// dma cycles can start and stop on 4 cck boundary and always last 8 ccks// if H2 of DDFSTART is set the display starts on next 4 cck boundary// (the display is a multiple of 32 hires pixels)// SUPER HIRES:// dma cycles can start and stop on 2 cck boundary and always last 8 ccks// (the display is a multiple of 64 super hires pixels)// in all resolutions the dma engine fetch cycle lasts 8 colour clocks// it can start at a multiple of: 8 cck's in lowres, 4 cck's in hires and 2 cck's in super hires// hint: SHRES bit in BPLCON0 takes precedence over HIRES bit// all tests were performed with FMODE=0// more magic: ddfstrt is delayed by one fetch cycle only if ddfstrt[3:2]>bplcon1[3:2] (tested only under UAE)wire	[8:2]ddf_start;reg 	[3:2]ddfstrt_latched;reg 	[3:2]ddf_start_latched;reg		[3:2]bplcon1_latched;wire	[8:2]ddf_stop;wire	[8:2]ddf_stop_delay;reg		ddf_enable;wire	[8:2]ddf_mask;assign ddf_mask = shres ? 7'b000_0000 : hires ? 7'b000_0001 : 7'b000_0011;//this should be rewritten someday to use more efficient codeassign ddf_start = ddfstrt-7'd1-bplcon1[3:2] | ddf_mask;assign ddf_stop_delay = ddfstop[3:2] > ddfstrt_latched[3:2] ? 7'd4 : 7'd0;assign ddf_stop = ({ddfstop[8:4],ddfstrt_latched[3:2]}-7'd1-bplcon1_latched[3:2] | ddf_mask) + ddf_stop_delay; //display dma last cyclereg	  ddf_last_fetch;// changing ddfstrt register value when display has already started doesn't affect the stop condition// so we have to store the initial value of ddfstrt to determine stop condition (only two bits do matter)always @(posedge clk)	if (reset)	begin		ddfstrt_latched <= 2'b00;		ddf_start_latched <= 2'b00;		bplcon1_latched <= 2'b00;	end	else if ({ddf_start,2'b11} == horbeam[8:0])	begin		ddfstrt_latched[3:2] <= ddfstrt[3:2];		ddf_start_latched[3:2] <= ddf_start[3:2];		bplcon1_latched <= bplcon1[3:2];	endalways @(posedge clk)	if (reset)		ddf_last_fetch <= 0;	else if ({ddf_stop,2'b11} == horbeam[8:0])		ddf_last_fetch <= ddf_enable;	else if ({ddf_start_latched[3:2],2'b11} == horbeam[3:0])		ddf_last_fetch <= 0;	always @(posedge clk)	if (reset)		ddf_enable <= 0;	else if ({ddf_start,2'b11} == horbeam[8:0])		ddf_enable <= 1;	else if (ddf_last_fetch && {ddf_start_latched[3:2],2'b11} == horbeam[3:0])		ddf_enable <= 0;assign mod = (ddf_last_fetch) & (hires ? horbeam[3]^ddfstrt_latched[3] : shres ? (&(horbeam[3:2]^ddfstrt_latched[3:2])): 1'b1);assign ddfenable = ddf_enable;always @(shres or hires or horbeam)	if (shres)		plane = {2'b00,~horbeam[1]};	else if (hires)		plane = {1'b0,~horbeam[1],~horbeam[2]};	else		plane = {~horbeam[1],~horbeam[2],~horbeam[3]};//generate dma signal//for a dma to happen plane must be less than BPU (bplcon0), dma must be enabled//(enable) and datafetch compares must be true (ddfenable)//because invalid slots are coded as plane=7, the compare with BPU is//automatically falsealways @(plane or bplcon0[14:12] or horbeam[0] or enable or ddfenable)begin	if(ddfenable && enable && horbeam[0])//if dma enabled and within ddf limits and dma slot	begin		if(plane[2:0]<bplcon0[14:12])//if valid plane			dma=1;		else			dma=0;	end	else		dma=0;end//--------------------------------------------------------------------------------------//dma pointer arithmetic unitalways @(addressout or bpl1mod or bpl2mod or plane[0] or mod)	if(mod)	begin		if(plane[0])//even plane	modulo			newpt[20:1]=addressout[20:1]+{bpl2mod[15],bpl2mod[15],bpl2mod[15],bpl2mod[15],bpl2mod[15],bpl2mod[15:1]}+1;		else//odd plane modulo			newpt[20:1]=addressout[20:1]+{bpl1mod[15],bpl1mod[15],bpl1mod[15],bpl1mod[15],bpl1mod[15],bpl1mod[15:1]}+1;	end	else		newpt[20:1]=addressout[20:1]+1;//Denise bitplane shift registers address lookup tablealways @(plane)begin	case(plane)		3'b000:	regaddressout[8:1]=8'h88;		3'b001:	regaddressout[8:1]=8'h89;		3'b010:	regaddressout[8:1]=8'h8a;		3'b011:	regaddressout[8:1]=8'h8b;		3'b100:	regaddressout[8:1]=8'h8c;		3'b101:	regaddressout[8:1]=8'h8d;		default:	regaddressout[8:1]=8'hff;	endcaseend//--------------------------------------------------------------------------------------endmodule//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------/*JB: some conclusions of sprite engine investigation, it seems to be as follows:- during vblank sprite dma is disabled by hardware, no automatic fetches occur but copper or cpucan write to any sprite register, and all SPRxPTR pointers should be refreshed- during the last line of vblank (PAL: $19, NTSC: $14) if sprite dma is enabledit fetches SPRxPOS/SPRxCTL registers according to current SPRxPTR pointers	This is the only chance for DMA to fetch new values of SPRxPOS/SPRxCTL. If DMA isn't enabledduring this line new values won't be placed into SPRxPOS/SPRxCTL registers.	Enabling DMA after this line can have two results depending on current value of SPRxPOS/SPRxCTL.- if VSTOP value is matched first with VERBEAM, data from memory is fetched and placed into SPRxPOS/SPRxCTL- or if VSTART value is matched with VERBEAM, data from memory is fetched and placed into SPRxDATA/SPRxDATB   and the situation repeats with every new line until VSTOP condition is met.The VSTOP condition takes precedence.	If you set VSTART to value lower or the same (remember that VSTOP takes precedence) as the current VERBEAMthis condition will never be met and sprite engine will wait till VSTOP matches VERBEAM. If it happens then itfetches another two words into SPRxPOS/SPRxCTL. And again if new VSTART is lower or the same as VERBEAMit will fetch another new SPRxPOS/SPRxCTL when VSTOP is met (or will wait till next vbl).

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -