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

📄 lwbsaa7113.v

📁 人民邮电出版社出版的《FPGA硬件接口设计实践》一书的代码
💻 V
字号:
/////////////////////////////////////////////////////////////////////
////                                                             ////
////             LWB rev 1.2 -- SAA7113 Control Logic            ////
////                                                             ////
////                                                             ////
////                 Author: Liu Tao                             ////
////          liutao94@tsinghua.org.cn                           ////
////                                                             ////
////                                                             ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
////                                                             ////
////               Copyright (C) 2003 Liu Tao                    ////
////               liutao94@tsinghua.org.cn                      ////
////                                                             ////
////                                                             ////
/////////////////////////////////////////////////////////////////////

`include "timescale.v"

module LWBSAA7113 (reset,clk,llck,vpo,rst,capture,error,SRAM_CE_,SRAM_OE_,SRAM_WE_,la,ld);

	//=================================================================================
	//input
	//=================================================================================

	    /*___________________________________________________ */
		//reset
		input reset;//
	    /*___________________________________________________ */
		//from saa7113
		input clk;//50MHz clock
		input llck;//SAA7113 video clock (27 MHz)
		input [7:0] vpo;//data from SAA7113
		input [1:0] rst;//real-time video status
		input capture;//flag for grab video data


	//=================================================================================
	//output
	//=================================================================================
	    /*___________________________________________________ */
		//to sram
		output error;//state indicator,to LED
		output SRAM_CE_;
		output SRAM_OE_;
		output SRAM_WE_;
		output [18:0] la;//address bus to sram
		output [7:0] ld;//data bus to sram
		
	//=================================================================================
	//reg
	//=================================================================================

	    /*___________________________________________________ */
		//video in state machine declaration
		reg [3:0] presState;//
		reg [3:0] nextState;//
		reg [3:0] returnState;
		reg [3:0] nextReturnState;

	//=================================================================================
	//parameters
	//=================================================================================

	    /*___________________________________________________ */
		//state declaration
		parameter 	stIdle = 4'b0000;//IDLE STATE,START UP OF A STATE MACHINE,RESET
		parameter	stWaitForEscape = 4'b0001;//CHECK FOR "FF",START OF TIMING REFERENCE CODE
		parameter	stCheckEscape1 = 4'b0010;//CHECK FOR "00",SECOND
		parameter	stCheckEscape2 = 4'b0011;//CHECK FOR "00",THIRD
		parameter	stCheckForNewPage = 4'b0100;//CHECK FOR "01",It is in vertical blanking stage,
		parameter	stCheckForFirstLine = 4'b0101;//CHECK FOR "000",for SAV in valid row
		parameter	stChromaBlue = 4'b0110;//write Cb to sram,here not in use
		parameter	stLumaBlue = 4'b0111;//write Lb to sram
		parameter	stChromaRed = 4'b1000;//write Cr to sram,not in use
		parameter	stLumaRed = 4'b1001;//write Lr to sram,
		parameter	stCheckForEndLine = 4'b1010;//CHECK for end of line
		parameter	stCheckForNewLine = 4'b1011;//CHECK for new line
		parameter	stError = 4'b1100;//ERROR state
	

	//=================================================================================
	//wires
	//=================================================================================

	    /*___________________________________________________ */
		//vpo data from saa7113
		reg [7:0] vpoLatch;//synchronise data on the vpo bus to LLCK
		reg [7:0] luminanceB;
		reg [7:0] luminanceR;
		reg [7:0] chrominanceB;//not use now
		reg [7:0] chrominanceR;//not use now
		reg [7:0] nextLuminanceB;
		reg [7:0] nextLuminanceR;
		reg [7:0] nextChrominanceB;//not use now
		reg [7:0] nextChrominanceR;//not use now

		reg [8:0] grab_cntr_hori;//counter for horizon 720
		reg [8:0] grab_cntr_vert;//counter for vertical 286
		reg clr_grab_cntr;//clear both grab counters
		reg inc_grab_hori;//increment horizontal counter for each 2 pixels
		reg inc_grab_vert;//increment vertical counter and clear horizontal counter
		reg field;//0 for 1st field,1 for 2nd field
		reg nextField;//remember next field

		reg grab;//write current data
		reg nextGrab;

		wire [18:0] grab_addr;
		reg [18:0] write_addr;
		reg [7:0] writeData;
		reg write;
		reg lastwrite;
		reg dowrite;
//		reg capture;//
		reg error;


	//=================================================================================
	//hookup sram interface
	//=================================================================================
	    /*___________________________________________________ */
		//address
		LWBSRAM L_SRAM (
			.clk(clk),
			.reset(reset),
			.doWrite(dowrite),
			.writeAddr(write_addr),
			.writeData(writeData),
			.SRAM_CE_(SRAM_CE_),
			.SRAM_OE_(SRAM_OE_),
			.SRAM_WE_(SRAM_WE_),
			.SRAM_ADDR(la),
			.SRAM_DATA(ld)		
		);



	//=================================================================================
	//Assigning
	//=================================================================================
	    /*___________________________________________________ */
		//address
		assign grab_addr = {grab_cntr_vert,field,grab_cntr_hori};


		//colour calculations:  these have not been fully tested and may need to be edited	
		//These convert the YUV data to RGB
		//	red = ("00" & luminanceB & x"00") + (("01" & x"24") * chrominanceR) - ("00" & x"7D00");
		//	blue <= ("00" & luminanceB & x"00") + (("10" & x"07") * chrominanceB) - ("00" & x"EE80");
		//	green <= ("00" & luminanceB & x"00") + ("00" & x"9200") - (("00" & x"65") * chrominanceB) - (("00" & x"95") * chrominanceR);

	




	//=================================================================================
	//State Machine
	//=================================================================================


	    /*___________________________________________________ */
		//write data to sram

		


	    /*___________________________________________________ */
		//write data to sram
		always @(posedge llck or negedge reset)
			if (!reset)
				begin
					presState <= stIdle;
					grab <= 1'b0;		
					returnState <= stIdle;
					field <= 1'b0;
					grab_cntr_hori <= 1'b0;
					grab_cntr_vert <= 1'b0;

				end
			else 
				begin
					vpoLatch <= vpo;//synchronize asynchronous data
					presState <= nextState;// go to next state
					grab <= nextGrab;//delay so colour can be calculated

					returnState <= nextReturnState;
					field <= nextField;
					chrominanceR <= nextChrominanceR;
					chrominanceB <= nextChrominanceB;
					luminanceR <= nextLuminanceR;			
					luminanceB <= nextLuminanceB;	
					
					if (nextGrab)
						write_addr <= grab_addr;//give write address plenty of setup time

					if (grab)  //note that this is executed 1 cycle after nextGrab is seen to go high.
						begin
//							writeData <= '0' & colour;		-- high colour (15 bit) full colour.  360 double pixels wide.
							writeData <= luminanceR;
							write <= 1'b1;
						end
					else 
						write <= 1'b0;

					// operate on the grab counters for vertical and horizontal movement
					if (clr_grab_cntr)
						begin
							grab_cntr_hori <= 1'b0;
							grab_cntr_vert <= 1'b0;
						end
					else 
						if (inc_grab_hori == 1)
							grab_cntr_hori <= grab_cntr_hori + 1;

						if (inc_grab_vert == 1)
							begin
								grab_cntr_vert <= grab_cntr_vert + 1;
								grab_cntr_hori <= 1'b0; // clear horizontal counter with each new line
							end
				end

	    /*___________________________________________________ */
		//grab data from vpo bus
		always @(presState or vpoLatch or returnState or field or luminanceB or luminanceR or chrominanceB or chrominanceR or capture)
			begin
				//default signal values
				clr_grab_cntr <= 1'b0;
				inc_grab_hori <= 1'b0;
				inc_grab_vert <= 1'b0;

				nextGrab <= 1'b0;
	
				nextReturnState <= returnState;
				nextField <= field;
				nextLuminanceB <= luminanceB;
				nextLuminanceR <= luminanceR;
				nextChrominanceB <= chrominanceB;
				nextChrominanceR <= chrominanceR;	
	
				error <= 1'b0;

				//state machine
				case (presState)
					stIdle://
						if (capture == 1'b1)
							begin
								nextState <= stWaitForEscape;	// Look for an escape sequence
								nextReturnState <= stCheckForNewPage;// Check for start of field 0
							end
						else
							nextState <= stIdle;

					stWaitForEscape://Look for the first character in the sequence, keep looking until found
						if (vpoLatch == 8'hFF)
							nextState <= stCheckEscape1;
						else
							nextState <= stWaitForEscape;

					stCheckEscape1://Second character in the escape sequence is 0
						if (vpoLatch == 8'h00)
							nextState <= stCheckEscape2;
						else
							nextState <= stError;

					stCheckEscape2://Third charcter in the escape sequence is 0.  Go to returnState to check SAV/EAV code
						if (vpoLatch == 8'h00)
							nextState <= returnState;
						else
							nextState <= stError;

					stCheckForNewPage://Wait for an SAV or EAV in field 0 while in the vertical blanking stage
						if (vpoLatch[6:5] == 2'b01) //If it is then wait until the first line of active video
							begin
								nextState <= stWaitForEscape;
								nextReturnState <= stCheckForFirstLine;
								clr_grab_cntr <= 1'b1;//initialise counter
							end
						else  //Look for another SAV/EAV until we find the type we want.
							begin
								nextState <= stWaitForEscape;
								nextReturnState <= stCheckForNewPage;
							end

					stCheckForFirstLine://Wait for an SAV in field 0 while in the active video region
						if (vpoLatch[6:4] == 3'b000)  //start recording data
							begin
								nextState <= stChromaBlue;
								nextField <= 1'b0;//initialise field
							end
						else  //Look for another SAV/EAV until we find the type we want.
							begin
								nextState <= stWaitForEscape;
								nextReturnState <= stCheckForFirstLine;
							end
	
					stChromaBlue://This may be the start of another pair of pixels or the end of data
						if (vpoLatch == 8'hFF) //If the byte is FF then it is the start of the EAV.
							begin
								nextState <= stCheckEscape1;//Go to second state of subroutine
								nextReturnState <= stCheckForEndLine;//Check if this is the last line of the field
							end
						else if (vpoLatch == 8'h00)
							nextState <= stError;			
						else //latch data into register and continue
							begin
								nextState <= stLumaBlue;
								nextChrominanceB <= vpoLatch;
							end

					stLumaBlue://As long as valid data is present continue latching data
						if ((vpoLatch !== 8'hFF) && (vpoLatch !== 8'h00))
							begin
								nextState <= stChromaRed;
								nextLuminanceB <= vpoLatch;
							end
						else
							nextState <= stError;
							
					stChromaRed://As long as valid data is present continue latching data
						if ((vpoLatch !== 8'hFF) && (vpoLatch !== 8'h00))
							begin
								nextState <= stLumaRed;
								nextChrominanceR <= vpoLatch;
							end
						else
							nextState <= stError;

					stLumaRed://As long as valid data is present continue latching data and setup to write current data
						if ((vpoLatch !== 8'hFF) && (vpoLatch !== 8'h00))
							begin
								nextState <= stChromaBlue;
								nextLuminanceR <= vpoLatch;
								nextGrab <= 1'b1;//Set up a write after a delay (see clocked process)
								inc_grab_hori <= 1'b1;//Increment horizontal counter every two pixels
							end
						else
							nextState <= stError;

					stCheckForEndLine://possible conditions here are the end of field 0, end of field 1,or an EAV code indicating a new line in the active region.					
						if (vpoLatch[6:4] == 3'b111) //end of field 1
							nextState <= stIdle;
						else if (vpoLatch[6:4] == 3'b011) //end of field 0
							begin
								clr_grab_cntr <= 1'b1;//reset counter for field 1
								nextState <= stWaitForEscape;
								nextReturnState <= stCheckForNewLine;//start capture at first new line
							end
						else if (vpoLatch[5:4] == 2'b01) //end of line
							begin
								inc_grab_vert <= 1'b1;	// go to next line
								nextState <= stWaitForEscape;
								nextReturnState <= stCheckForNewLine;//capture next line from start
							end
						else // EAV expected but SAV received
							nextState <= stError;

					stCheckForNewLine://Wait until an SAV in the active video range arrives
						if (vpoLatch[5:4] == 2'b00)
							begin
								nextState <= stChromaBlue;// capture next line
								nextField <= vpoLatch[6];
							end
						else	// Wait for another code
							begin
								nextState <= stWaitForEscape;
								nextReturnState <= stCheckForNewLine;
							end

					stError://Wait until another capture is requested before continuing
						if (capture == 1'b1)
							begin
								nextState <= stWaitForEscape;
								nextReturnState <= stCheckForNewPage;
							end
						else
							begin
								nextState <= stError;
								error <= 1'b1;//indicate error on error LED
							end

					default:
						nextState <= stError;

				endcase
			end



	    /*___________________________________________________ */
		//synchronizes writes to the 50MHz clock
		always @(negedge reset or posedge clk)
			if(!reset)
				begin
					dowrite <= 1'b0;
					lastwrite <= 1'b0;
				end
			else
				begin
					lastwrite <= write;
					if (!write && lastwrite)
						dowrite <= 1'b1;
					else
						dowrite <= 1'b0;

				end



endmodule

⌨️ 快捷键说明

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