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

📄 audio.v

📁 Verilog, c and asm source codes of the Minimig system, a fpga implementation of the Amiga computer.
💻 V
📖 第 1 页 / 共 2 页
字号:
endmodule//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------//This module handles a single amiga audio channel. attached modes are not supportedmodule audiochannel(clk,reset,tick,aen,den,regaddress,data,volume,sample,intreq,intpen,dmareq,dmas);input 	clk;					//bus clock	input 	reset;		    		//resetinput	tick;				//audio clock enableinput	aen;					//address enableinput	den;					//dma enableinput	[3:1]regaddress;		//register address inputinput 	[15:0]data; 			//bus data inputoutput	[6:0]volume;			//channel volume outputoutput	[7:0]sample;			//channel sample outputoutput	intreq;				//interrupt requestinput	intpen;				//interrupt pending inputoutput	dmareq;				//dma requestoutput	dmas;				//dma special (restart)//register names and addressesparameter	AUDLEN=4'h4;parameter	AUDPER=4'h6;parameter	AUDVOL=4'h8;parameter	AUDDAT=4'ha;//local signalsreg		dmareq;				//see abovereg		dmas;				//see abovereg		intreq;				//see abovereg		[15:0]audlen;			//audio length registerreg		[15:0]audper;			//audio period registerreg		[6:0]audvol;			//audio volume registerreg		[15:0]auddat;			//audio data registerreg		[15:0]percount;		//audio period counterreg		[15:0]lencount;		//audio length counterreg		[15:0]datbuf;			//audio data bufferreg		[2:0]audiostate;		//audio current statereg		[2:0]audionext;	   	//audio next statereg		intreq2;				//used to time interruptsreg		datld;				//load audio buffer from auddatreg		datsh;				//shift datbuf 8 bits to the left, shift in zero'sreg		lendec;				//decrement length counterreg		lenload;				//load length counterreg		perload;				//load period counterreg		intrst;				//intreq2 latch resetreg		dma;					//request dmawire		lenfin;				//length counter is 1wire		perzero;				//period counter is zerowire		datwrite;				//data register is written//-------------------------------------------------------------------------------------- //length register bus writealways @(posedge clk)	if(reset)		audlen[15:0]<=0;		else if(aen && (regaddress[3:1]==AUDLEN[3:1]))		audlen[15:0]<=data[15:0];//period register bus writealways @(posedge clk)	if(reset)		audper[15:0]<=0;		else if(aen && (regaddress[3:1]==AUDPER[3:1]))		audper[15:0]<=data[15:0];//volume register bus writealways @(posedge clk)	if(reset)		audvol[6:0]<=0;		else if(aen && (regaddress[3:1]==AUDVOL[3:1]))		audvol[6:0]<=data[6:0];//data register strobeassign datwrite=(aen && (regaddress[3:1]==AUDDAT[3:1]))?1:0;//data register bus writealways @(posedge clk)	if(reset)		auddat[15:0]<=0;		else if(datwrite)		auddat[15:0]<=data[15:0];	//--------------------------------------------------------------------------------------//period counter always @(posedge clk)	if(perload || perzero)//load period counter from audio period register		percount[15:0]<=audper[15:0];	else if(tick)//period counter count down		percount[15:0]<=percount[15:0]-1;assign perzero=(percount[15:0]==0)?1:0;//length counter always @(posedge clk)	if(lenload)//load length counter from audio length register		lencount[15:0]<=audlen[15:0];	else if(lendec)//length counter count down		lencount[15:0]<=lencount[15:0]-1;assign lenfin=(lencount[15:0]==1)?1:0;//--------------------------------------------------------------------------------------//audio bufferalways @(posedge clk)	if(reset)		datbuf[15:0]<=0;	else if(datld)		datbuf[15:0]<=auddat[15:0];	else if(datsh)		datbuf[15:0]<={datbuf[7:0],8'h00};	//sample outputassign sample[7:0]=datbuf[15:8];//volume outputassign volume[6:0]=audvol[6:0];//--------------------------------------------------------------------------------------//dma request logic//dma is requested by main state machine//dma is cleared when auddat is written//if length counter is being reloaded, dma restart is requestedalways @(posedge clk)begin	if(reset || datwrite)	begin		dmareq<=0;		dmas<=0;	end	else if(dma)	begin		dmareq<=1;		dmas<=lenload;	endend//intreq2 latch//this signal is used to properly request interrupts in dma mode//if data from dma restart request has come in --> intreq2 is truealways @(posedge clk)	if(reset||intrst)		intreq2<=0;	else if(dmas && den && datwrite)//(dmas=1 if restart request is pending)		intreq2<=1;//audio statesparameter AUDIDLE=0;parameter AUDGET=1;parameter AUDSTATE1=2;parameter AUDSTATE2=3;parameter AUDSTATE3=4;//audio channel state machinealways @(posedge clk)begin	if(reset)		audiostate<=AUDIDLE;	else		audiostate<=audionext;endalways @(audiostate or den or datwrite or lenfin or intreq2 or perzero or intpen)begin	case(audiostate)				//audio state machine idle state (state 000)		//mute output		//reload period counter		//start dma driven audio immediately if dma enabled		//start interrupt driven audio immediately when auddat is written		AUDIDLE:		begin			datld=0;			datsh=1;//this mutes sample output after max 2 clocks			intrst=0;			lendec=0;			lenload=1;//**dma restart enable**			perload=0;			intreq=0;			dma=den;			if(datwrite)//start interrupt driven audio				audionext=AUDSTATE1;			else if(den)//start dma driven audio				audionext=AUDGET;			else				audionext=AUDIDLE;			end		//wait for first word of dma driven audio to arrive (state 101)		//reset intreq2 latch		//when it arrives, reload period counter, request interrupt and go to next state		//if dma is disabled, return to idle state		AUDGET:		begin			datld=0;			datsh=0;			intrst=1;			lendec=0;			lenload=0;			perload=1;			intreq=datwrite;			dma=0;			if(!den)				audionext=AUDIDLE;							else if(datwrite)				audionext=AUDSTATE1;			else				audionext=AUDGET;			end		//state transition handling (transition 101->010 and 011->010)		//load data from auddat to sample buffer		//reset intreq2 latch		//decrement length counter if len>1 		//reload length counter if len=1		//request interrupt if dma disabled (interrupt driven mode)		//request interrupt if intreq2 occurred(dma driven mode)		//request new data by dma if dma enabled		AUDSTATE1:		begin			datld=1;			datsh=0;			intrst=1;			lendec=~lenfin;			lenload=lenfin;//**dma restart enable**			perload=0;			intreq=~den|intreq2;			dma=den;			audionext=AUDSTATE2;			end		//first sample of word state (state 010)		//load second sample when period counter expires		//go to next state when period counter expires		AUDSTATE2:		begin			datld=0;			datsh=perzero;			intrst=0;			lendec=0;			lenload=0;			perload=0;			intreq=0;			dma=0;			if(perzero)//next state				audionext=AUDSTATE3;			else//stay here				audionext=AUDSTATE2;			end		//second sample of word state (state 011)		//go to idle state when period counter expires and not (enabled or intterupt not pending)		//else go to next state if period counter expires 		AUDSTATE3:		begin			datld=0;			datsh=0;			intrst=0;			lendec=0;			lenload=0;			perload=0;			intreq=0;			dma=0;			if(perzero && !(den || !intpen))//see HRM state diagram				audionext=AUDIDLE;							else if(perzero)				audionext=AUDSTATE1;			else				audionext=AUDSTATE3;			end		//we should never come here (state 100,110,111)		default:		begin			datld=1'bx;			datsh=1'bx;			intrst=1'bx;			lendec=1'bx;			lenload=1'bx;			perload=1'bx;			intreq=1'bx;			dma=1'bx;			audionext=AUDIDLE;			end	endcaseend//--------------------------------------------------------------------------------------endmodule

⌨️ 快捷键说明

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