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

📄 freedev_bt656.v

📁 verilog代码读写SDRAM 不带仿真
💻 V
字号:
//---------------------------------------------------------------
//模块名称:freedev_bt656 
//功能说明:BT656视频采集处理模块
//	    1、通过slave port设置模块工作参数和模式
//          2、视频采集部分以输入视频时钟采集数据并缓存到视频FIFO
//          3、avalone master部分读视频FIFO数据,存放到内存
//日    期:20070630
//备    注:
//          1、Avalone总线Slave设备
//          2、Avalon总线Master设备 burst传输
//	    3、视频采集
//
//公司:杭州自由电子科技
//电话:0571-85084089
//网址:www.freefpga.com
//邮件:tech@freefpga.com
//----------------------------------------------------------------

module freedev_bt656(
	clk,
	rst_n,
	
	//从端口
	s_irq,
	s_chipselect_n,
	s_read_n,
	s_write_n,
	s_address,
	s_readdata,
	s_writedata,
	
	//主端口
	m_waitrequest,
	m_address,
	m_read,
	m_readdata,
	m_write,
	m_writedata,
	m_byteenable,
	m_burstcount,
	m_readdatavalid,
	
	//视频信号
	v_clk,
	v_data
	);
	
	input clk;		// clk
	input rst_n;		// reset
	
	//slave 接口信号
	output s_irq;		// interrupt request
	input  s_chipselect_n;	// chip select
	input  s_read_n;	// read signal
	input  s_write_n;	// write signal
	input  [3:0]s_address;	// address
	output [31:0]s_readdata;	// out data
	input  [31:0]s_writedata;	// in  data
		
	//master 接口信号
	input m_waitrequest;		// 等待
	output [31:0]m_address;		// master 地址
	output m_read;			// 读信号
	input [31:0]m_readdata;		// 读数据
	output m_write;			// 写信号
	output [31:0]m_writedata;	// 写数据
	output [3:0]m_byteenable;	// 字节选择
	output [7:0]m_burstcount;	// 突发传输数
	input  m_readdatavalid;		// 突发传输读数据有效
	
	//视频信号
	input v_clk;			// 视频数据时钟
	input [7:0]v_data;		// 8bit YCbCr视频数据
		
/////////////////////////////avalone slave部分//////////////////////////////////////

	// 寄存器定义
	reg [31:0] mode;	// 模式寄存器         0x00
	reg [31:0] command;     // 命令寄存器         0x01
	reg [31:0] status;	// 状态寄存器         0x02
	reg [31:0] irq_mask;	// 中断屏蔽寄存器     0x03
	reg [31:0] video_buff; 	// 视频存储地址       0x04
	
	reg [31:0] test_reg1;	// 测试调试寄存器     0x05
	
	reg rirq,wirq;	  
	reg [31:0] s_readdata;		// out data
	
	// 模块软件复位
	wire s_rst = command[0];
	wire capture_enable = command[1];	// 数据采集控制位
	wire write_enable   = command[2];	// 数据存储控制位

	// 总线写信号
	wire write_req = ~s_chipselect_n & ~s_write_n;

	// 总线读信号
	wire read_req = ~s_chipselect_n & ~s_read_n;

	// 写寄存器
	always @(posedge clk or negedge rst_n)
	if (!rst_n )
	begin
		mode        <= #1 32'h00000000;		//模式寄存器清0
		command     <= #1 32'h00000000;		//命令寄存器清0
		irq_mask    <= #1 32'hffffffff;		//默认屏蔽中断
		video_buff  <= #1 32'hffff0000;		//默认视频存储地址		
	end
	else
	begin
	    if ( write_req )
		begin
		      case ( s_address ) 
				4'b0000 : mode        <= #1 s_writedata;	// 写模式寄存器
				4'b0001 : command     <= #1 s_writedata;	// 写命令
				4'b0010 : status      <= #1 s_writedata;	// 状态
				4'b0011 : irq_mask    <= #1 s_writedata;	// 写中断屏蔽寄存器
				4'b0100 : video_buff  <= #1 s_writedata; 	// 视频存储地址
				4'b0101 : test_reg1   <= #1 s_writedata;	// 测试调试寄存器
				default: ;
		      endcase
		end 
	end
		
	always @(posedge clk)
	begin
	if( read_req )
	  case (s_address) 
		4'b0000: s_readdata <= #1 mode;
		4'b0001: s_readdata <= #1 command;		
		4'b0010: s_readdata <= #1 status;		
		4'b0011: s_readdata <= #1 irq_mask;		
		4'b0100: s_readdata <= #1 video_buff;
		4'b0101: s_readdata <= #1 fifo_writedata;
		4'b0110: s_readdata <= #1 {{30{1'b0}},wrfull,wrempty};
		4'b0111: s_readdata <= #1 {{26{1'b0}},current_state};	// 状态机当前状态;
		4'b1000: s_readdata <= #1 {{23{1'b0}},wrusedw};		
		4'b1001: s_readdata <= #1 {{23{1'b0}},rdusedw};
		4'b1010: s_readdata <= #1 count_8010;
		4'b1011: s_readdata <= #1 count_ycbcr;
		4'b1100: s_readdata <= #1 count_total; 
		4'b1101: s_readdata <= #1 line_total;  
		4'b1110: s_readdata <= #1 odd_line;    
		4'b1111: s_readdata <= #1 even_line;
	  endcase
	end

/////////////////////Avalon Master//////////////////////////////////
// 读视频FIFO数据,每次一行432个DWORD存放到内存 突发传输

	reg [31:0]m_address;	// master 地址
	reg m_read;		// 读信号
	reg m_write;		// 写信号
	//reg [31:0]m_writedata;	// 写数据
	reg [3:0]m_byteenable;	// 字节选择
	reg [7:0]m_burstcount;	// 突发传输次数
	
	reg [5:0] next_state,current_state;	

	reg [31:0] readdata;		// 读数据	
	reg [31:0] transfer_count;	// 传输计数
	reg [31:0] remain_count;	// 剩余传输
	reg [7:0]  burstcount; 		// 突发传输次数
	reg [31:0]  count;		// 一次突发传输内计数
	reg [31:0]  v_line;		// 行计数
	wire [31:0] c_line=test_reg1;		// 存储行数
	
	parameter [5:0] 
		IDLE   		= 6'b000001,	// 空闲		0x01
		R_START0 	= 6'b000010,	// 读地址准备0 	0x02
		R_START1 	= 6'b000100,	// 等待wait无效 0x04
		R_DATA		= 6'b001000,	// 读数据0	0x08
		W_START 	= 6'b010000,	// 写地址准备	0x10
		W_DATA 		= 6'B100000;	// 写数据	0x20

	// Avalon Master bust memory write control
	always @(posedge clk or negedge rst_n)
	if(!rst_n)
	begin
		current_state <= #1 IDLE;
		
		m_address 	<= #1 32'hzzzzzzzz;
		m_read    	<= #1 1'b0;
		m_write   	<= #1 1'b0;
		//m_writedata 	<= #1 32'hxxxxxxxx;
		m_byteenable	<= #1 4'h0;
		m_burstcount	<= #1 8'h00;
		transfer_count 	<= #1 32'h00000000;
		v_line		<= #1 32'd0;

	end
	else
	begin
		case(current_state)
			IDLE:	begin
					m_address 	<= #1 32'hzzzzzzzz;
					m_read    	<= #1 1'b0;
					m_write   	<= #1 1'b0;
					m_byteenable	<= #1 4'h0;
															
					if( (rdusedw >= 9'd432) && write_enable == 1'b1 )// 一行数据 并且写内存控制位等于1
					begin
						burstcount <= #1 128;		// 突发传输次数128
						remain_count <= #1 432 ;	// 剩余传输数 
					 	current_state <= #1 W_START;
					 						 	
					 	if( v_line < 624)
					 		v_line <= v_line+1;
					 	else					 		
					 		v_line <= 0;
					 	
					 	if(v_line == 0)
					 		transfer_count <= #1 32'h00000000;
					 end
					else 		current_state <= #1 IDLE;
					
				end 
			W_START:	begin
											
					m_address 	<= #1 video_buff + (transfer_count*4);
					m_write   	<= #1 1'b1;
					m_byteenable	<= #1 4'hf;
					m_burstcount	<= #1 burstcount; 
					count		<= #1 32'h00000000;
					remain_count	<= #1 remain_count - {{24{1'b0}},burstcount};//剩余传输数
					
					current_state <= #1 W_DATA;
				end
			W_DATA:	begin					
					if ( m_waitrequest == 1'b1 )
					begin
						current_state <= #1 W_DATA;
					end
					else begin						
						count <= count +1;
						if(count == (burstcount-1))	// 本次突发写传输完成
						begin
							m_write <= #1 1'b0;
							
							transfer_count	<= #1 transfer_count+ burstcount;
							
							if( remain_count == 32'h00000000) 
							begin
								current_state <= IDLE;
							end
							else begin
								burstcount 	<= #1 (remain_count < 128) ? {remain_count[6:0]}:128; // 下一次突发传输次数
								
								current_state  	<= #1 W_START;	// 再一次启动读和写
							end
						end
						else
							current_state <= #1 W_DATA;	// 突发传输未完成,继续
					end
				end  
			default:	current_state <= #1 IDLE;
			
			endcase
	end
	
/////////////////////////// bt656视频数据参数检测部分 ///////////////////////////////////////////
// 视频参数检测,应用程序通过Avalon slave接口读取相关参数
	wire [31:0]count_8010;
	wire [31:0]count_ycbcr;
	wire [31:0]count_total;
	wire [31:0]line_total;
	wire [31:0]odd_line;
	wire [31:0]even_line;

	bt656_detection the_bt656_detection(	
	.v_clk(v_clk),
	.v_data(v_data),
	
	.count_8010(count_8010),
	.count_ycbcr(count_ycbcr),
	.count_total(count_total),
	.line_total(line_total),
	.odd_line(odd_line),
	.even_line(even_line)
	);

/////////////////////////// bt656视频数据采集部分 ///////////////////////////////////////////////
// 视频数据采集,每4字节做一次FIFO存储

	reg	[7:0]RR1,RR2,RR3;
	
	always @(posedge v_clk)
	begin
		RR1 <= #1 v_data;
		RR2 <= #1 RR1;
		RR3 <= #1 RR2;
	end
	
	// EAV SAV CODE检测
	wire av_flag = (( RR3 == 8'hff) && ( RR2 == 8'h00 ) && ( RR1 == 8'h00)) ? 1 : 0;
	
	// FIFO写数据生成
	wire [31:0]dwdata={RR3,RR2,RR1,v_data};
	
	// 奇场数据行开始
	wire [1:0]odd_even={fvh[2],v_data[6]};
	// SAV and EAV 
	reg [2:0] fvh;
	
	wire f_flag = v_data[6];	// field flag
	wire v_flag = v_data[5];	// blanking flag
	wire h_flag = v_data[4];	// h=0 at SAV , h=1 at EAV
	
	// 相关起始标志
	reg capture_start;	// 数据采集起始
	reg capture_stop;	// 数据采集终止
	reg h_start;		// 行起始信号 检测到EAV开始到p_count到1727结束
	reg v_start;		// 帧起始信号 检测到偶场到奇场切换开始 到 h_start到624行结束
	
	reg [10:0]p_count;	// 27M时钟计数	MAX 1728字节(432DWORD)
	reg [9:0]h_count;	// 行计数	MAX 625行
	
	reg line0_flag;		// 测试行0标志
	
	wire [1:0]mod4 = {p_count[1:0]};	
	
	// 写FIFO请求
	reg wreq;
	
	always @(posedge v_clk)
	if(capture_enable == 1'b1)	// 采集控制位==1
	begin	
		if( av_flag == 1'b1 && h_flag == 1'b1 )  // 行EAV
		begin
			fvh 	     <= v_data[6:4];
			
			if ( odd_even == 2'b10  )	// 帧起始行
			begin
				// 遇到帧开始,数据采集开始
				capture_start <= #1 1'b1;
				
				// 行计数清0						
				h_count <= #1 0;
				
				// 置第0行标志为1
				line0_flag <= #1 1'b1;
				
				// 第一个帧起始 capture_start还是0,所以需要此处特定置wreq 将EAV写入队列
				if( capture_start == 1'b0)
				begin
					wreq <= #1 1'b1;
					fifo_writedata <= #1 dwdata;
				end
			end else if(capture_start)	// 非帧起始行
			begin
				//capture_stop <= 1'b1;
				
				// 置第0行标志为0
				line0_flag <= 1'b0;
				
				// 行计数增加1	
				h_count <= h_count + 1;
			end
			
			// EAV数据写入队列
			if( capture_start == 1'b1)
			begin
				wreq <= #1 1'b1;
				fifo_writedata <= #1 dwdata;
			end
						
			p_count <= #1 4;		// 重置行内字节计数
		end 
		else		
		if( capture_start == 1'b1 ) //开始采集
		begin
			p_count <= p_count + 1;
			if( mod4 == 2'b11)
			begin
				wreq <= #1 1'b1;
				fifo_writedata <= #1 dwdata;
			end 
		end
		
		if(wreq == 1'b1) 	// wreq 只持续1 v_clk
			wreq <= #1 1'b0;
	end else 
	begin
		capture_start <= #1 1'b0;
		capture_stop  <= #1 1'b0;
	end
	
//////////////////////////// 视频缓冲FIFO ///////////////////////////////////////////////////////
	
	wire fifo_wrreq =  wreq ;	//FIFO写请求 受命令控制位capture_enable控制
	wire fifo_rdreq =  (current_state == W_DATA) & (m_waitrequest == 1'b0);	//FIFO 读请求
		
	wire [8:0] rdusedw,wrusedw;
	reg[31:0] fifo_writedata;
	wire rdempty,rdfull;
	wire wrempty,wrfull;
		
	//缓存FIFO
	bt656_fifo in_fifo(
	.aclr(s_rst),			// 异步清除
	
	.rdclk(clk),			// 读时钟
	.rdreq(fifo_rdreq),		// 读请求
	.q(m_writedata),		// 读数据
	.rdfull(rdfull),		// 读满标志
	.rdempty(rdempty),		// 读空标志
	.rdusedw(rdusedw),		// 读使用计数
	
	.wrclk(v_clk),			// 写时钟
	.wrreq(fifo_wrreq),		// 写请求
	.data(fifo_writedata),		// 写数据
	.wrfull(wrfull),		// 写满标志
	.wrempty(wrempty),		// 写空标志
	.wrusedw(wrusedw)		// 写使用计数
	);
		                
endmodule

⌨️ 快捷键说明

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