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

📄 blitter.v

📁 Verilog, c and asm source codes of the Minimig system, a fpga implementation of the Amiga computer.
💻 V
📖 第 1 页 / 共 3 页
字号:
always @(posedge clk)	if(enable && (chs[1:0]==CHD[1:0]))		fcy<=fco;//channel D holding registeralways @(posedge clk)	if(enable && (chs[1:0]==CHD[1:0]))		dhold[15:0]<=fillout[15:0];		//channel D data output gateassign dataout[15:0]=(ackdma && (chs[1:0]==CHD))?dhold[15:0]:16'h0000;assign wr=(chs[1:0]==CHD)?1:0;//channel D blitter zero detectalways @(posedge clk)	if(reset || sbz)		bzero<=1;//reset blitter zero detector	else if(enable && (chs[1:0]==CHD[1:0]) && (dhold[15:0]!=16'h0000))		bzero<=0;//non-zero output of channel D detected//--------------------------------------------------------------------------------------//Blitsize counter and control//This module keeps track of how many lines and words//we have to blit.//The main register bltsize is loaded from the bus and //then decremented during a channel D cycle (chs==CHD)//In line mode, channel D cycle happens twice for every pixel,//hence bltwidth is always 2 in line mode.//This module also generates <fwt> (first word time),//<lwt> (last word time) and <nml> (no more lines to blit)//Note that <nml> is only valid when <fwt> is true. This is to allow//heights of 1024 lines, which are written as 10'b0000000000//by the software. (see amiga hardware reference manual)//<start> is also controlled here (used to start the blitter state machine)//<bbusy1d> and <lwtd> are delayed version for channel D (pipeline delay)reg		[10:0]bltwcount;//start controlalways @(posedge clk)	if(reset)		start <= 0;	else if ( regaddressin[8:1] == BLTSIZE[8:1] || regaddressin[8:1] == BLTSIZH[8:1])//blitter is started by write to BLTSIZE		start <= 1;	else if (bbusy)//state machine has got the message, we can clear start now		start <= 0;//bltwidth register (lower 6 bits of BLTSIZE)always @(posedge clk)	if ( regaddressin[8:1] == BLTSIZE[8:1] )		bltwidth[10:0] <= { 4'b0000, (datain[5:0]==6'b00_0000)?1'b1:1'b0, datain[5:0] };	else if ( regaddressin[8:1] == BLTSIZH[8:1] )		bltwidth[10:0] <= datain[10:0];//bltwidth counter			always @(posedge clk)	if (regaddressin[8:1] == BLTSIZE[8:1] || regaddressin[8:1] == BLTSIZH[8:1])//blitsize written, go to first word time		bltwcount[10:0] <= 11'b000_0000_0001;	else if(enable && (chs[1:0]==CHD[1:0]))//decrement blitsize counter	begin		if (lwt) //if last word time, go to first word time			bltwcount[10:0] <= 11'b000_0000_0001;		else //else go to next word			bltwcount[10:0] <= bltwcount[10:0] + 1'b1;	end//bltheight register (upper 10 bits of BLTSIZE) and counter always @(posedge clk)	if (regaddressin[8:1] == BLTSIZE[8:1]) //blitheight loaded by write to bltsize		bltheight[14:0] <= { 4'b0000, (datain[15:6]==10'b00_0000_0000)?1'b1:1'b0, datain[15:6] };	else if (regaddressin[8:1] == BLTSIZH[8:1]) //blitheight loaded by write to bltsizh		bltheight[14:0]<= bltsizv[14:0];	else if(enable && lwt && (chs[1:0]==CHD[1:0]))//if last word in this line decrement height counter		bltheight[14:0] <= bltheight[14:0] - 1'b1;always @(posedge clk)	if (regaddressin[8:1] == BLTSIZV[8:1]) //blitheight loaded by write to bltsizv		bltsizv[14:0]<= datain[14:0];//generate fwt (first word time) signalassign fwt = (bltwcount[10:0] == 11'b000_0000_0001) ? 1 : 0;//generate lwt (last word time) signalassign lwt = (bltwcount[10:0] == bltwidth[10:0]) ? 1 : 0;//generate lwtd (delayed last word time) signal //and bbusyd1 (delayed bbusy1) signalalways @(posedge clk)	if (regaddressin[8:1]==BLTSIZE[8:1] || regaddressin[8:1]==BLTSIZH[8:1])//reset signals upon BLTSIZE write, just to be sure	begin		lwtd<=1'b0;		bbusyd<=1'b0;	end	else if(enable && (chs[1:0]==CHD[1:0]))	begin		lwtd<=lwt;		bbusyd<=bbusy;	end//generate nml (no more lines) signal (only valid during first word time)assign nml = ((bltheight[14:0] == 15'b000_0000_0000_0000) && fwt) ? 1 : 0;//--------------------------------------------------------------------------------------//instantiate address generatorbltaddress bltad1(	.clk(clk),	.reset(reset),	.enable(enable),	.modb(amb),	.chs(chs),	.alu({ame,ams,ape,apd}),	.signout(signout),	.datain(datain),	.regaddressin(regaddressin),	.addressout(addressout));//--------------------------------------------------------------------------------------//Blitter main controller logic//This code controls the blitter A, B, C and D channelreg	   	[4:0]scn;		//various signals vector used by main state machinereg		[3:0]acn;	    	//address/alu control vector used by main state machine//main statesparameter	BLT_DONE=0;parameter BLT_NB_1=1;parameter BLT_NB_2=2;parameter BLT_NB_3=3;parameter BLT_NB_4=4;parameter BLT_LP_1=5;parameter BLT_LP_2=6;parameter BLT_LB_1=7;parameter BLT_LB_2=8;parameter BLT_LB_3=9;parameter BLT_LB_4=10;				    //Normal/line mode settingsalways @(bltcon1[0] or bltcon0[11:10] or chs)begin	if(bltcon1[0])//line mode	begin		bpa=0;//channel A uses preload		bpb=0;//channel B uses preload		tmb=1;//channel B is in texturing mode		efe=0;//fill mode disabled		ife=0;//fill mode disabled		desc=0;//ascending mode selected		sing=bltcon1[1]&bltcon1[4];//special line mode according to bltcon		if(chs[1:0]==CHA[1:0])//in line mode, channel A is accumulator and modulo's are always added		begin			ams=0;			apd=0;		end		else//for all other channels (C and D) it depends on the octant		begin			if(bltcon1[4])//octant 0,3,4,7			begin				ams=bltcon1[3];//up or down ?				apd=bltcon1[2];//left or right ?			end			else//octant 1,2,5,6			begin				ams=bltcon1[2];//up or down ?				apd=bltcon1[3];//left or right ?			end		end	end	else//normal mode	begin		bpa=bltcon0[11];//if USEA, do not use channel A preload		bpb=bltcon0[10];//if USEB, do not use channel B preload		tmb=0;//channel B is in normal mode		efe=bltcon1[4];//fill mode according to bltcon		ife=bltcon1[3];//fill mode according to bltcon		desc=bltcon1[1];//descending mode according to bltcon		sing=0;//no special line mode		ams=bltcon1[1];//modulo's are subtracted if descending mode		apd=bltcon1[1];//pointers are decremented if descending mode	endend//sign bit handling	and fpl bit handlingalways @(posedge clk)	if(!bbusyd)//if blitter not busy, copy sign from bltcon and preset fpl	begin		sign<=bltcon1[6];		fpl<=1;	end	//update sign flag and fpl bit (if first D cycle has happened and channel A cycle + dma enabled and line mode)	else if(enable && bbusyd && bltcon0[11] && bltcon1[0] && (chs[1:0]==CHA[1:0]))	begin		sign<=signout;		fpl<=~sign;	end//enable signal control //enable controls most of the latches in the blitter//this is a very important signalalways @(horbeam or bbusy or reqdma or ackdma)	if(reqdma && ackdma)//dma requested and granted, do external (dma) cycle		enable=1;	else	if(!reqdma && bbusy && horbeam)//do internal cycle		enable=1;	else//do nothing (blitter not busy)		enable=0;			//bblck control//In order to let this blitter run at the same speed as in a real Amiga, it must block the cpu//in some cases. Apparently (according to winuae sources), cycles that are normally internal//(channel A/D when USEA/USED=0), DO allocate a bus slot when channel A is enabled in blitter nasty mode.//This effectively blocks the cpu from the chip bus. Also, when fill mode is enabled but channel C is not (USEC=0)//we also get some extra idle cycles (cpu is not blocked).//In line mode, blitter never blocks the cpu.//the following logic handles the bblck signalalways @(bltcon0 or bltcon1 or bbusy or bbusyd)begin	if(bbusy&bbusyd)//blitter busy and not first cycle?		//{FILL,LINE,USEA,USEC}		case({bltcon1[3]|bltcon1[4],bltcon1[0],bltcon0[11],bltcon0[9]})			4'b0000: bblck=0;			4'b0001: bblck=0;			4'b0010: bblck=1;			4'b0011: bblck=1;			4'b0100: bblck=0;//LINE MODE			4'b0101: bblck=0;//LINE MODE			4'b0110: bblck=0;//LINE MODE			4'b0111: bblck=0;//LINE MODE			4'b1000: bblck=0;			4'b1001: bblck=0;			4'b1010: bblck=0;			4'b1011: bblck=1;			4'b1100: bblck=0;//LINE MODE			4'b1101: bblck=0;//LINE MODE			4'b1110: bblck=0;//LINE MODE			4'b1111: bblck=0;//LINE MODE		endcase						  		else//blitter not busy		bblck=0;end//state machine outputs//we use a couple of vectors here to keep the statemachine readable//various signals controlassign incash=scn[4];assign decash=scn[3];assign rlb=scn[2];assign sbz=scn[1];assign bbusy=scn[0];//address contolassign reqdma=acn[3]&horbeam;//only request DMA during odd slotsassign amb=acn[2];assign ame=acn[1];assign ape=acn[0];//main state machinealways @(posedge clk)	if(reset)//master reset		bltstate<=BLT_DONE;	else if(enable || (start && !bbusy))//blitter next cycle if (enable) or (start pulse while not yet busy)		bltstate<=bltnext;always @(bltstate or bltcon0 or lwt or lwtd or bbusyd or bltcon1 or sign or nml or plr)begin	case(bltstate)		BLT_DONE://blitter is done			begin				//-----IDRZB				scn=5'b00000;				//-----RBMA				acn=4'b0x00;				chs=CHB;				if(!bltcon1[0])//start normal blit					bltnext=BLT_NB_1;				else//start line blit					bltnext=BLT_LP_1;			end		BLT_LP_1://line blit preparation cycle 1 (load channel B 'old' register with texture)			begin				acn=4'b0x00;				scn=5'b00001;				chs=CHB;				bltnext=BLT_LP_2;	 			end		BLT_LP_2://line blit preparation cycle 2 (load channel B holding register with texture)			begin				acn=4'b0x00;				scn=5'b00001;				chs=CHB;				bltnext=BLT_LB_1;	 			end		BLT_LB_1://line blit cycle 1 (check accumulator, load channel A and update sign)			begin				acn={1'b0,sign,bbusyd,1'b0};//only update accumulator if not first cycle, sign selects modulo A/B					scn=5'b00001;				chs=CHA;				if(nml && bbusyd)//check if blit is done					bltnext=BLT_DONE;				else					bltnext=BLT_LB_2;	 			end		BLT_LB_2://line blit cycle 2 (load channel C)			begin				if(bltcon1[4])					acn={bltcon0[9],1'b0,~sign,plr};				else					acn={bltcon0[9],2'b01,~sign&plr};				scn=5'b00001;				chs=CHC;				bltnext=BLT_LB_3;	 			end		BLT_LB_3://line blit cycle 3 (load channel D and point to next texture bit)			begin				acn=4'b0x00;				scn=5'b00101;				chs=CHD;				bltnext=BLT_LB_4;	 			end		BLT_LB_4://line blit cycle 4 (write channel D and update shifter channel A)			begin				if(bltcon1[4])				begin					acn={bltcon0[9],1'b1,~sign,plr};//modulo C is used for channel D also in line mode					scn={~bltcon1[2],bltcon1[2],3'b001};				end				else				begin					acn={bltcon0[9],2'b11,~sign&plr};					scn={~bltcon1[3]&~sign,bltcon1[3]&~sign,3'b001};				end				chs=CHD;				if(nml)//PANIC! this shouldn't happen but just in case...					bltnext=BLT_DONE;				else					bltnext=BLT_LB_1;	 			end 		BLT_NB_1://normal blit cycle 1			begin				if(nml && bbusyd)//blit is done, handle data still in pipeline				begin					if(bltcon0[8])//DMA						acn={2'b10,lwtd,1'b1};					else//internal						acn=4'b0x00;					//-----IDRZB					scn=5'b00001;						chs=CHD;					bltnext=BLT_DONE;				end				else//else handle channel A				begin					if(bltcon0[11])//DMA						acn={2'b10,lwt,1'b1};					else//internal						acn=4'b0x00;					//-----IDRZB					scn=5'b00001;					chs=CHA;					if(bltcon0[10])						bltnext=BLT_NB_2;					else if(bltcon0[9])						bltnext=BLT_NB_3;					else						bltnext=BLT_NB_4;					end			end		BLT_NB_2://normal blitter operation cycle 2 (always dma, skipped otherwise)			begin				acn={2'b10,lwt,1'b1};				scn=5'b00001;

⌨️ 快捷键说明

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