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

📄 0923freedev_vga.v

📁 verilog代码读写SDRAM 不带仿真
💻 V
字号:
//---------------------------------------------------------------
//模块名称:freedev_vga
//功能说明:VGA显示模块
//	    1、通过slave port设置模块工作参数
//          2、avalon master bust方式读内存显示缓冲区
//         
//日    期:20070917
//备    注:
//          1、Avalone总线Slave设备
//          2、Avalon总线Master设备 burst传输
//          数字图象处理板EP2C35F672C6支持以下分辨率(后为象素频率) 
//	    3、1024*768*60 65M
//	    4、800*600*60  40M
//	    5、640*480*60  25M
//
//公司:杭州自由电子科技
//电话:0571-85084089
//网址:www.freefpga.com
//邮件:tech@freefpga.com
//----------------------------------------------------------------

//1024 X 768 X 60
`define	HOR_PIXELS		1344
`define	HBLANK_START		1024
`define	HSYNC_START		1048
`define	HSYNC_TIME		136

`define	VER_LINES		806
`define	VBLANK_START		768
`define	VSYNC_START		771
`define	VSYNC_TIME		6
`define LINE_SIZE		4096

/*
// 800 X 600 X 60
`define	HOR_PIXELS		1056
`define	HBLANK_START		800
`define	HSYNC_START		840
`define	HSYNC_TIME		128

`define	VER_LINES		628
`define	VBLANK_START		600
`define	VSYNC_START		601
`define	VSYNC_TIME		6
`define LINE_SIZE		3200
*/

/*
// 640 X 480 X 60
`define	HOR_PIXELS		800
`define	HBLANK_START		640
`define	HSYNC_START		659
`define	HSYNC_TIME		96

`define	VER_LINES		525
`define	VBLANK_START		480
`define	VSYNC_START		493
`define	VSYNC_TIME		2
`define LINE_SIZE		2560
*/

module freedev_vga(
	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,
	
	//VGA输信号
	pclk,	
	r , 
	g , 
	b ,
	 
	hsync , 
	vsync , 
	blank,
	sync,
	psave
	);    
	      
	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 reg [31:0]m_address;		// master 地址
	output reg m_read;			// 读信号
	input [31:0]m_readdata;		// 读数据
	output reg m_write;			// 写信号
	output [31:0]m_writedata;	// 写数据
	output reg [3:0]m_byteenable;	// 字节选择
	output reg [7:0]m_burstcount;	// 突发传输数
	input  m_readdatavalid;		// 突发传输读数据有效
	
	//VGA输信号
	input pclk;			// 输入象素时钟	
	output [7:0]r ; 		// 输出红
	output [7:0]g ; 		// 输出绿
	output [7:0]b ;			// 输出蓝
	 
	output hsync ;			// 输出行同步
	output vsync ;			// 输出场同步
	output blank;			// 输出消隐
	output sync;			
	output psave;
	
	//VGA输信号寄存器
	reg [7:0]r ; 			// 输出红
	reg [7:0]g ; 			// 输出绿
	reg [7:0]b ;			// 输出蓝
	 
	reg hsync ;			// 输出行同步
	reg vsync ;			// 输出场同步

	assign blank = 1'b1;
	assign sync  = 1'b1;	
        assign psave = 1'b1;
		
/////////////////////////////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 rirq,wirq;	  
	reg [31:0] s_readdata;		// out data
	
	// 模块软件复位
	wire s_rst = command[0];
	wire vga_enable = command[1];	// VGA显示控制位
	wire mem_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; 	// 显示缓存地址
				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 {{22{1'b0}},wrusedw};		// fifo 读使用字节    
		4'b0110: s_readdata <= #1 {{22{1'b0}},rdusedw};		// fifo 写使用字节
		4'b0111: s_readdata <= #1 {{30{1'b0}},rdempty,rdfull}; 
		4'b1000: s_readdata <= #1 {{30{1'b0}},wrempty,wrfull};   
		4'b1001: s_readdata <= #1 fifo_line_use;     
		4'b1010: s_readdata <= #1 fifo_line_show;
		4'b1011: s_readdata <= #1 fifo_line_show_end; 
		4'b1100: s_readdata <= #1 count639;   
		4'b1101: s_readdata <= #1 readdata; 
		4'b1110: s_readdata <= #1 32'h00000000;
		4'b1111: s_readdata <= #1 32'h00000000;
	  endcase
	end

///////////////////// VGA 时序 //////////////////////////////////
	reg[10:0]	pixcel_count;		// 行计数寄存器
	reg[9:0]	line_count;		// 场计数寄存器
	
	reg hblank;	// 行消隐
	reg vblank;	// 场笑隐
	reg d_pclk;
	wire [1:0]pclk_state={d_pclk,pclk};
	
	// clk时钟同步处理pclk
	
	always @(posedge clk)
	begin
		d_pclk <= pclk;
	end
	
	// 象素计数
	always @(posedge clk  or negedge rst_n)
	if(~rst_n)
			pixcel_count <= 0;
	else if( pclk_state == 2'b01)
			pixcel_count <= (pixcel_count == `HOR_PIXELS - 1) ? 0 : pixcel_count + 1; 
	
	
	// 读显示缓冲控制
	always @(posedge clk  or negedge rst_n)
	if(~rst_n)
			read_start <= 0;
	else begin
		if( (pclk_state == 2'b01) && ((line_count >0 && line_count < `VBLANK_START)||line_count==0) && (pixcel_count == `HSYNC_START))
			read_start <= 1'b1;
		
		if(read_start)
			read_start <= 1'b0;
	end
	
	
	// 行消隐
	always @(posedge clk  or negedge rst_n) 
	if(~rst_n)
		hblank <= 0;
	else if( pclk_state == 2'b01)	// pclk上升沿
		begin
			if(pixcel_count > `HBLANK_START - 1 && pixcel_count < `HOR_PIXELS - 1)
				hblank <= 1;
			else
				hblank <= 0;
		end
	 
	// 行同步
	always @(posedge clk or negedge rst_n) 
	if(~rst_n)
		hsync <= 1;
	else if( pclk_state == 2'b01)	// pclk上升沿
		begin 
		if(pixcel_count >= `HSYNC_START - 1 && pixcel_count < `HSYNC_START + `HSYNC_TIME - 1)
			hsync <= 1;
		else
			hsync <= 0;
		end 
	
	reg [31:0]line_addr;	// 行显示内存地址
	
	//行计数
	always @(posedge clk or negedge rst_n)
	if(~rst_n)
		line_count <= 0;
	else if( pclk_state == 2'b01)	// pclk上升沿
	begin
		if(pixcel_count == `HOR_PIXELS - 1)
			line_count <= (line_count == `VER_LINES - 1) ? 0 : line_count + 1;
		
		if(pixcel_count == 0)
		begin
			if (line_count == 0 )
				line_addr <= video_buff ;
			else
				line_addr <= line_addr + `LINE_SIZE;
		end
	end


	// 场消隐
	always @(posedge clk or negedge rst_n)
	if(~rst_n)
		vblank <= 0;
	else if( pclk_state == 2'b01)	// pclk上升沿
	begin
		if(pixcel_count == `HOR_PIXELS - 1)
		begin
			if(line_count > `VBLANK_START - 1 && line_count < `VER_LINES - 1 )
				vblank <= 1;
			else
				vblank <= 0;
		end
	end


	// 场同步
	always @(posedge clk or negedge rst_n)
	if(~rst_n)
		vsync <= 1;
	else if( pclk_state == 2'b01)	// pclk上升沿
	begin
		if(pixcel_count == `HOR_PIXELS - 1)
		begin
			if(line_count >= `VSYNC_START - 1 && line_count < `VSYNC_START + `VSYNC_TIME - 1 )
				vsync <= 1;
			else
				vsync <= 0;
		end
	end
	
	reg rdreq;
	reg [31:0]rgb;
	reg [31:0]fifo_line_show;
	reg [31:0]fifo_line_show_end;
	reg [31:0]read_fifo_count;
	reg [31:0]count639;

	// r,g,b 输出
	always @(posedge pclk or negedge rst_n )
	if(~rst_n)
	begin
		r <= 8'hFF;
		g <= 8'hFF;
		b <= 8'hFF;
		rdreq <= 1'b0;
	end else
	begin	
		if((pixcel_count >= 0 && pixcel_count <`HBLANK_START) || pixcel_count == (`HOR_PIXELS-1))	// 0~639需要FIFO数据
		begin
			rdreq <= 1'b1;
			if(rdempty )
			begin
				r <= 8'h00;
				g <= 8'h00;
				b <= 8'h00;
			end else begin
				r <= fifo_readdata[23:16];
				g <= fifo_readdata[15:8];
				b <= fifo_readdata[7:0];
			end
		end
		else begin
			rdreq <= 1'b0;
			r <= 8'h00;
			g <= 8'h00;
			b <= 8'h00;
		end  
	end
		
////////////////////////行数据读取控制///////////////////////////////////////////////////////////
	parameter [3:0] 
		IDLE   		= 6'b0001,	// 空闲		0x01
		R_START0 	= 6'b0010,	// 读地址准备0 	0x02
		R_START1 	= 6'b0100,	// 等待wait无效 0x04
		R_DATA		= 6'b1000;	// 读数据0	0x08	
	
	reg [31:0] readdata;		// 读数据寄存器	
	reg [3:0]  current_state;	// 当前状态
	reg [31:0] transfer_count;	// 传输计数
	reg [31:0] remain_count;	// 剩余传输
	reg [7:0]  burstcount; 		// 突发传输次数
	reg [31:0]  count;		// 一次突发传输内计数
	reg [31:0] fifo_line_use;
	
	reg read_start;			// 读显示数据开始
	reg only_one;
	
	// Avalon Master读控制状态机
	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_byteenable	<= #1 4'h0;
		m_burstcount	<= #1 8'h00;
		transfer_count 	<= #1 32'h00000000;
	end
	else  if(mem_enable == 1'b1)
	begin		
		case(current_state)
			IDLE:	begin
					m_address 	<= #1 32'hzzzzzzzz;
					m_read    	<= #1 1'b0;
					m_byteenable	<= #1 4'h0;
					transfer_count	<= #1 32'h00000000;
										
					if(  read_start )
					begin
						fifo_line_use <= {{22{1'b0}},wrusedw};		// fifo 读使用字节
						current_state <= #1 R_START0;
						burstcount    <= #1 128; 		// 突发传输次数
						remain_count  <= #1 `HBLANK_START;	// 剩余传输数等于待传输数
					end
					else
						current_state <= #1 IDLE;
					
				end 
			R_START0:	begin	// 提交address、read、byteenable、burstcount
					
					if( transfer_count == `HBLANK_START) 
						current_state <= #1 IDLE;
					else begin
						m_address 	<= #1 line_addr+ (transfer_count*4);
						m_read    	<= #1 1'b1;
						m_byteenable	<= #1 4'hf;
						m_burstcount	<= #1 burstcount;
						remain_count	<= #1 remain_count - {{24{1'b0}},burstcount};//剩余传输数
						count		<= #1 32'h00000000;
						current_state <= #1 R_DATA;  
					end
				end
			R_START1:	begin
					if( m_waitrequest == 1'b1) current_state <= #1 R_START1;
					else begin
						m_read		<= #1 1'b0;
						
						current_state <= #1 R_DATA;
					end
				end
			R_DATA:	begin
					if( m_readdatavalid == 1'b0 ) 		// 数据无效等待 
						current_state <= #1 R_DATA;
					else begin
						readdata <= m_readdata; // m_readdata数据进FIFO	
						
						count <= count + 1;		
						if( count == (burstcount-1 ))		//本次突发读传输完成
						begin
							m_read		<= #1 1'b0;
							m_byteenable	<= #1 4'h0;
							
							if( remain_count == 32'h00000000) 
							begin
								current_state <= IDLE;
							end
							else begin
								transfer_count	<= #1 transfer_count+ burstcount;
								burstcount 	<= #1 (remain_count < 128) ? {remain_count[6:0]}:128; // 下一次突发传输次数
								
								current_state  	<= #1 R_START0;	// 再一次启动读和写
							end
						end
						else 
							current_state <= #1 R_DATA;	//突发传输未完成,继续
					end
				end
			default:	current_state <= #1 IDLE;
			
			endcase
	end else 
		only_one <= 1'b0;
        
	
//////////////////////////// 视频缓冲FIFO ///////////////////////////////////////////////////////
	
	//wire fifo_wrreq = (current_state == R_DATA) & m_readdatavalid;	//FIFO 写请求
	wire fifo_wrreq = m_readdatavalid;					//FIFO 写请求
	wire fifo_rdreq =  rdreq;						//FIFO 读请求
		
	wire [9:0] rdusedw,wrusedw;
	wire [31:0] fifo_readdata;
	wire rdempty,rdfull;
	wire wrempty,wrfull;
		
	//缓存FIFO
	vga_fifo line_fifo(
	.aclr(s_rst),			// 异步清除
	
	.rdclk(pclk),			// 读时钟
	.rdreq(fifo_rdreq),		// 读请求
	.q(fifo_readdata),		// 读数据
	.rdfull(rdfull),		// 读满标志
	.rdempty(rdempty),		// 读空标志
	.rdusedw(rdusedw),		// 读使用计数
	
	.wrclk(clk),			// 写时钟
	.wrreq(fifo_wrreq),		// 写请求
	.data(m_readdata),		// 写数据
	.wrfull(wrfull),		// 写满标志
	.wrempty(wrempty),		// 写空标志
	.wrusedw(wrusedw)		// 写使用计数
	);
		                
endmodule

⌨️ 快捷键说明

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