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

📄 agnus.v

📁 Verilog, c and asm source codes of the Minimig system, a fpga implementation of the Amiga computer.
💻 V
📖 第 1 页 / 共 3 页
字号:
	To disable further sprite list processing it's enough to set VSTART and VSTOP to values which are outsideof the screen or has been already achieved.	When waiting for VSTART condition any write to SPRxDATA (write to SPRxDATB takes no effect) makes the written valuevisible on the screen but it doesn't start DMA although it's enabled. The same value is displayed in every subsequent line until DMA starts and delivers new data to SPRxDAT or SPRxCTL is written (by DMA, copper or cpu).It seems like only VSTART condition starts DMA transfer.	Any write to SPRxCTL while DMA is active doesn't stop display but new value of VSTOP takes effect. Actually display is reenabled by DMA write to SPRxDATA in next line.	The same applies to SPRxPOS writes when sprite is beeing displayed - only HSTART position changes (if new VSTARTis specified to be met before VSTOP nothing interesting happens).	The DMA engine sees VSTART condition as true even if DMA is dissabled. Enabling DMA after VSTART and before VSTOPstarts sprite display in enabled line (if it's enabled early enough).	Dissabling DMA in the line when new SPRxPOS/SPRxCTL is fetched and enabling it in the next one results in stoppedDMA transfer but the last line of sprite is displayed till the end of the screen.VSTART and VSTOP specified within vbl are not met.vbl stops dma transfer.The first possible line to display a sprite is line $1A (PAL).During vbl SPRxPOS/SPRxCTL are not automatically modified, values written before vbl are still present when vbl ends.algo:	if vbl or VSTOP : disable data dma	else if VSTART: start data dma		if vblend or (VSTOP and not vbl): dma transfer to sprxpos/sprxctl	else if data dma active: transfer to sprxdata/sprcdatbIt doesn't seem to be complicated :)Sprite which has been triggered by write to SPRxDATA is not disabled by vbl.It seems that vstop and vstart conditions are checked every cycle. Dma doesn't fetch new pos/ctl if vstop is not equal to the current line number.Feature:If new vstart is specified to be the same as the line during which it's fetched, display starts in the next linebut is one line shorter.*///sprite dma enginemodule sprdma_engine(	input 	clk,		    			//bus clock	input	clk28m,	output	reg reqdma,				//sprite dma engine requests dma cycle	input	ackdma,						//agnus dma priority logic grants dma cycle	input	[8:0]hpos,				//horizontal beam counter	input	[10:0]vpos,				//vertical beam counter	input	vbl,						//JB: vertical blanking	input	vblend,						//JB: last line of vertical blanking	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 SPRPTBASE=9'h120;		//sprite pointers base addressparameter SPRPOSCTLBASE=9'h140;	//sprite data, position and control register base address//local signalsreg 	[20:16]sprpth[7:0];		//upper 5 bits sprite pointers register bankreg 	[15:1]sprptl[7:0];		//lower 16 bits sprite pointers register bankreg		[15:8]sprpos[7:0];		//sprite vertical start position register bank//JB: implementing ECS extended vertical sprite positionreg		[15:4]sprctl[7:0];		//sprite vertical stop position register bankwire	[9:0]vstart;				//vertical start of selected spritewire	[9:0]vstop;				//vertical stop of selected spritewire	[2:0]sprite;				//sprite select signalwire	[20:1]newptr;				//new sprite pointer valuewire 	enable;						//hpos in sprite region//the following signals change their value during cycle 0 of 4-cycle dma sprite windowreg		sprvstop;					//current line is sprite's vstopreg		sprdmastate;				//sprite dma state (sprite image data cycles)reg		dmastate_mem[7:0];		//dma state for every spritewire	dmastate;					//output from memoryreg		dmastate_in;				//input to memoryreg		[2:0]sprsel;				//memory selection//sprite selection signal (in real amiga sprites are evaluated concurently,//in our solution to save resources they are evaluated sequencially but 8 times faster (28MHz clock)always @(posedge clk28m)	if (sprsel[2]==hpos[0])	//sprsel[2] is synced with hpos[0]		sprsel <= sprsel + 1;//--------------------------------------------------------------------------------------//register bank address multiplexerwire	[2:0]ptsel;			//sprite pointer and state registers selectwire	[2:0]pcsel;			//sprite position and control registers selectassign ptsel = (ackdma) ? sprite : regaddressin[4:2];assign pcsel = (ackdma) ? sprite : regaddressin[5:3];//sprite pointer arithmetic unitassign newptr = addressout[20:1] + 1;//sprite pointer high word register bank (implemented using distributed ram)wire [20:16]sprpth_in;assign sprpth_in = ackdma ? newptr[20:16] : datain[4:0];always @(posedge clk)	if(ackdma || ((regaddressin[8:5]==SPRPTBASE[8:5]) && !regaddressin[1]))//if dma cycle or bus write		sprpth[ptsel] <= sprpth_in;assign addressout[20:16] = sprpth[sprite];//sprite pointer low word register bank (implemented using distributed ram)wire [15:1]sprptl_in;assign sprptl_in = ackdma ? newptr[15:1] : datain[15:1];always @(posedge clk)	if(ackdma || ((regaddressin[8:5]==SPRPTBASE[8:5]) && regaddressin[1]))//if dma cycle or bus write		sprptl[ptsel] <= sprptl_in;assign addressout[15:1] = sprptl[sprite];//sprite vertical start position register bank (implemented using distributed ram)always @(posedge clk)	if((regaddressin[8:6]==SPRPOSCTLBASE[8:6]) && (regaddressin[2:1]==2'b00))//if bus write		sprpos[pcsel] <= datain[15:8];assign vstart[7:0] = sprpos[sprsel];//sprite vertical stop position register bank (implemented using distributed ram)always @(posedge clk)	if((regaddressin[8:6]==SPRPOSCTLBASE[8:6]) && (regaddressin[2:1]==2'b01))//if bus write		sprctl[pcsel] <= {datain[15:8],datain[6],datain[5],datain[2],datain[1]};		assign {vstop[7:0],vstart[9],vstop[9],vstart[8],vstop[8]} = sprctl[sprsel];//sprite dma channel state register bank//update dmastate when hpos is in sprite fetch region//every sprite has allocated 8 system clock cycles with two active dma slots://the first during cycle #3 and the second during cycle #7//first slot transfers data to sprxpos register during vstop or vblend or to sprxdata when dma is active//second slot transfers data to sprxctl register during vstop or vblend or to sprxdatb when dma is active//current dmastate is valid after cycle #1 for given sprite and it's needed during cycle #3 and #7always @(posedge clk28m)	dmastate_mem[sprsel] <= dmastate_in;assign dmastate = dmastate_mem[sprsel];//evaluating sprite image dma data statealways @(vbl or vpos or vstop or vstart or dmastate) 	if (vbl || (vstop[9:0]==vpos[9:0]))		dmastate_in = 0;	else if (vstart[9:0]==vpos[9:0])		dmastate_in = 1;	else		dmastate_in = dmastate;always @(posedge clk28m)	if (sprite==sprsel && hpos[2:1]==2'b00)		sprdmastate <= dmastate;always @(posedge clk28m)	if (sprite==sprsel && hpos[2:1]==2'b00)		sprvstop <= vstop[9:0]==vpos[9:0] ? 1 : 0;//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------//check if we are allowed to allocate dma slots for sprites//dma slots for sprites from cycle 20 till 51assign enable = hpos[8:1]>=8'b0001_0100 && hpos[8:1]<8'b0011_0100 ? 1: 0;		//get sprite number for which we are going to do dmaassign sprite = hpos[5:3] - 3'b101;//generate regdma signalalways @(vpos or vbl or vblend or hpos or enable or sprite or sprvstop or sprdmastate)	if (enable && hpos[1:0]==2'b11)	begin		if (vblend || (sprvstop && ~vbl))		begin			reqdma = 1;			if (~hpos[2])				regaddressout[8:1] = {SPRPOSCTLBASE[8:6],sprite,2'b00};	//SPRxPOS			else				regaddressout[8:1] = {SPRPOSCTLBASE[8:6],sprite,2'b01};	//SPRxCTL		end		else if (sprdmastate)		begin			reqdma = 1;			if (~hpos[2])				regaddressout[8:1] = {SPRPOSCTLBASE[8:6],sprite,2'b10};	//SPRxDATA			else				regaddressout[8:1] = {SPRPOSCTLBASE[8:6],sprite,2'b11};	//SPRxDATB		end
		else		begin			reqdma = 0;			regaddressout[8:1] = 8'hFF;		end	end	else	begin		reqdma = 0;		regaddressout[8:1] = 8'hFF;	end//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------endmodule//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------//disk dma engine//the DMA cycle allocation is not completely according to the HRM,//there are 4 slots allocated for disk dma instead of 3////slots are: (horbeam[8:0] counts) //slot 0x000000011 //slot 0x000000111 //slot 0x000001011 //slot 0x000001111 module dskdma_engine(	input 	clk,		    		//bus clock	output	dma,					//true if disk dma engine uses it's cycle	input	dmal,					//Paula requests dma	input	dmas,					//Paula special dma	input	[8:0]horbeam,			//horizontal beam counter	output	wr,						//write (disk dma writes to memory)	input 	[8:1]regaddressin,	//register address inputs	output 	[8:1]regaddressout,	//register address outputs	input	[15:0]datain,			//bus data in	output	reg [20:1]addressout	//chip address out current disk dma pointer);//register names and adresses		parameter DSKPTH=9'h020;			parameter DSKPTL=9'h022;			parameter DSKDAT=9'h026;			parameter DSKDATR=9'h008;		//local signalswire	[20:1]addressoutnew;	//new disk dma pointer//--------------------------------------------------------------------------------------//dma cycle allocationassign dma=(dmal && (horbeam[8:4]==5'b00000) && (horbeam[1:0]==2'b11))?1:0;//write signalassign wr=~dmas;//--------------------------------------------------------------------------------------//addressout input multiplexer and ALUassign addressoutnew[20:1] = dma ? addressout[20:1]+1 : {datain[4:0],datain[15:1]}; //disk pointer controlalways @(posedge clk)	if(dma || (regaddressin[8:1]==DSKPTH[8:1]))		addressout[20:16]<=addressoutnew[20:16];//high 5 bitsalways @(posedge clk)	if(dma || (regaddressin[8:1]==DSKPTL[8:1]))		addressout[15:1]<=addressoutnew[15:1];//low 15 bits//--------------------------------------------------------------------------------------//register address outputassign regaddressout[8:1] = wr ? DSKDATR[8:1] : DSKDAT[8:1];//--------------------------------------------------------------------------------------endmodule//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------//Audio dma engine//2 cycle types are defined, restart pointer, (go back to beginning of sample) and next pointer//(get next word of sample, dmas indicates restart pointer cycle//////slots are: (horbeam[8:0] counts) //slot 0x000010011 (channel #0)//slot 0x000010111 (channel #1)//slot 0x000011011 (channel #2)//slot 0x000011111 (channel #3)module auddma_engine(clk,dma,dmal,dmas,horbeam,regaddressin,regaddressout,datain,addressout);input 	clk;		    			//bus clockoutput	dma;					//true if audio dma engine uses it's cycleinput	dmal;				//Paula requests dmainput	dmas;				//Paula special dmainput	[8:0]horbeam;			//horizontal beam counterinput 	[8:1]regaddressin;		//register address inputsoutput 	[8:1]regaddressout;		//register address outputsinput	[15:0]datain;			//bus data inoutput	[20:1]addressout;		//chip address out//register names and adresses		parameter AUD0DAT=9'h0aa;			parameter AUD1DAT=9'h0ba;			parameter AUD2DAT=9'h0ca;			parameter AUD3DAT=9'h0da;			parameter AUD0LCH=9'h0a0;			parameter AUD1LCH=9'h0b0;			parameter AUD2LCH=9'h0c0;			parameter AUD3LCH=9'h0d0;			//local signalsreg		[8:1]regaddressout;		//see abovereg		[20:1]aud0lc;			//audio location register channel 0reg		[20:1]aud1lc;			//audio location register channel 1reg		[20:1]aud2lc;			//audio location register channel 2reg		[20:1]aud3lc;			//audio location register channel 3reg		[20:1]audlcout;		//audio location outputreg		[20:1]audpt[3:0];		//audio pointer bankwire		[20:1]audptout;		//audio pointer bank output//--------------------------------------------------------------------------------------//audio location register channel 0always @(posedge clk)	if((regaddressin[8:2]==AUD0LCH[8:2]) && !regaddressin[1])		aud0lc[20:16]<=datain[4:0];	else if((regaddressin[8:2]==AUD0LCH[8:2]) && regaddressin[1])		aud0lc[15:1]<=datain[15:1];//audio location register channel 1always @(posedge clk)	if((regaddressin[8:2]==AUD1LCH[8:2]) && !regaddressin[1])		aud1lc[20:16]<=datain[4:0];	else if((regaddressin[8:2]==AUD1LCH[8:2]) && regaddressin[1])		aud1lc[15:1]<=datain[15:1];//audio location register channel 2always @(posedge clk)	if((regaddressin[8:2]==AUD2LCH[8:2]) && !regaddressin[1])		aud2lc[20:16]<=datain[4:0];	else if((regaddressin[8:2]==AUD2LCH[8:2]) && regaddressin[1])		aud2lc[15:1]<=datain[15:1];//audio location register channel 3always @(posedge clk)	if((regaddressin[8:2]==AUD3LCH[8:2]) && !regaddressin[1])		aud3lc[20:16]<=datain[4:0];	else if((regaddressin[8:2]==AUD3LCH[8:2]) && regaddressin[1])		aud3lc[15:1]<=datain[15:1];//--------------------------------------------------------------------------------------//get audio location pointeralways @(horbeam or aud0lc or aud1lc or aud2lc or aud3lc)	case(horbeam[3:2])		2'b00: audlcout[20:1]=aud0lc[20:1];		2'b01: audlcout[20:1]=aud1lc[20:1];		2'b10: audlcout[20:1]=aud2lc[20:1];		2'b11: audlcout[20:1]=aud3lc[20:1];	endcase//dma cycle allocationassign dma=(dmal && (horbeam[8:4]==5'b00001) && (horbeam[1:0]==2'b11))?1:0;//addressout output multiplexerassign addressout[20:1]=(dmas)?audlcout[20:1]:audptout[20:1]; //audio location register bank (implemented using distributed ram)//and ALUalways @(posedge clk)	if(dma)//dma cycle		audpt[horbeam[3:2]]<=(addressout[20:1]+1);assign audptout[20:1]=audpt[horbeam[3:2]];//register address output multiplexeralways @(horbeam)	case(horbeam[3:2])		2'b00: regaddressout[8:1]=AUD0DAT[8:1];		2'b01: regaddressout[8:1]=AUD1DAT[8:1];		2'b10: regaddressout[8:1]=AUD2DAT[8:1];		2'b11: regaddressout[8:1]=AUD3DAT[8:1];	endcase//--------------------------------------------------------------------------------------endmodule

⌨️ 快捷键说明

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