• verilog实现VGA显示方块屏幕保护


    verilog实现VGA显示方块屏幕保护


    输入和输出

    • 时钟信号 clk
    • 复位信号 reset
    • rgb三颜色输出 [2:0] r,g, [1:0] b
    • 行信号输出 hs
    • 列信号输出 vs

    参数设定

    设定边界,决定改变方向与否

    parameter UP_BOUND = 31;
    parameter DOWN_BOUND = 510;
    parameter LEFT_BOUND = 144;
    parameter RIGHT_BOUND = 783;
    

    状态机决定下一次扫描输出的颜色

    parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
    reg [2:0] state, nextstate;
    reg [2:0] nextr, nextg;
    reg [1:0] nextb;
    

    程序处理

    行信号和列信号的处理

    行信号和列信号决定着当前像素是否显示出来。该程序选择的是在25Hz下640 * 480的分辨率显示。具体想改变分辨率的,可以在参考网上的资料。VGA的显示是逐行扫描像素点,除了可见区域,还有不可见区域的像素点,因此可以通过边界控制是否输出。

    	wire myclk;
    	reg [1:0] count;
    	reg [9:0] hcount, vcount;
    	
    	assign myclk = count[1];
    	always@(posedge clk)
    	begin
    		if(reset)
    			count <= 0;
    		else
    			count <= count + 1'b1;
    	end
    	
    	assign hs = (hcount < 96) ? 1'b0 : 1'b1;
    	always@(posedge myclk or posedge reset)
    	begin
    		if(reset)
    			hcount <= 0;
    		else if(hcount == 799)
    			hcount <= 0;
    		else
    			hcount <= hcount + 1'b1;
    	end
    	
    	assign vs = (vcount < 2) ? 1'b0 : 1'b1;
    	always@(posedge myclk or posedge reset)
    	begin
    		if(reset)
    			vcount <= 0;
    		else if(hcount == 799) 
    		begin
    			if(vcount == 520)
    				vcount <= 0;
    			else
    				vcount <= vcount + 1'b1;
    		end
    		else
    			vcount <= vcount;
    	end
    

    颜色持续变换形成彩色轮变

    彩色变化,通过状态机实现。每一列像素点对应一个颜色,但是方块区域才通过彩色输出,否则输出黑色,形成了彩色轮转。

    	always@(posedge myclk or posedge reset)
    	begin
    		if(reset) 
    		begin
    			r <= 0;
    			g <= 0;
    			b <= 0;
    		end
    		else begin
    			if((vcount >= up_pos) 
    			&& (vcount <= down_pos)
    			&& (hcount >= left_pos) 
    			&& (hcount<=right_pos)) 
    			begin
    				r <= nextr; 
    				g <= nextg; 
    				b <= nextb;
    			end
    			else 
    			begin
    				r <= 3'b000;
    				g <= 3'b000;
    				b <= 2'b00;
    			end
    		end
    	end
    	
    	always@(posedge myclk or posedge reset)
    	begin
    		if(reset)
    			state <= S0;
    		else
    			state <= nextstate;
    	end
    	
    	always@(*)
    	begin
    		case(state)
    			S0:		nextstate <= S1;
    			S1:		nextstate <= S2;
    			S2:		nextstate <= S3;
    			S3:		nextstate <= S0;
    			default:	nextstate <= S0;
    		endcase
    	end
    	
    	always@(*)
    	begin
    		case(state)
    			S0:		begin nextr <= 3'b111; nextg <= 3'b000; nextb <= 2'b00; end
    			S1:		begin nextr <= 3'b000; nextg <= 3'b111; nextb <= 2'b00; end
    			S2:		begin nextr <= 3'b000; nextg <= 3'b000; nextb <= 2'b11; end
    			S3:		begin nextr <= 3'b111; nextg <= 3'b111; nextb <= 2'b00; end
    			default:	begin nextr <= 3'b111; nextg <= 3'b000; nextb <= 2'b11; end
    		endcase
    	end
    

    信号处理

    但列信号由输出变成非输出时触发。在这个情况下,应该处理下一帧的方向和速度。详见代码。

    	always@(negedge vs or posedge reset)
    	begin
    		if(reset)
    		begin
    			h_speed <= 1;
    			v_speed <= 0;
    		end
    		else 
    		begin
    			if(up_pos == UP_BOUND)
    				v_speed <= 1;
    			else if(down_pos == DOWN_BOUND)
    				v_speed <= 0;
    			else
    				v_speed <= v_speed;
    			
    			if (left_pos == LEFT_BOUND)
    				h_speed <= 1;
    			else if (right_pos == RIGHT_BOUND)
    				h_speed <= 0;
    			else
    				h_speed <= h_speed;
    		end
    	end
    	
    	always@(posedge vs or posedge reset)
    	begin
    		if(reset) 
    		begin
    			up_pos <= 391;
    			down_pos <= 510;
    			left_pos <= 384;
    			right_pos <= 543;
    		end
    		else
    		begin
    			if(v_speed) 
    			begin
    				up_pos <= up_pos + 1'b1;
    				down_pos <= down_pos + 1'b1;
    			end
    			else 
    			begin
    				up_pos <= up_pos - 1'b1;
    				down_pos <= down_pos - 1'b1;
    			end
    			
    			if(h_speed)
    			begin
    				left_pos <= left_pos + 1'b1;
    				right_pos <= right_pos + 1'b1;
    			end
    			else 
    			begin
    				left_pos <= left_pos - 1'b1;
    				right_pos <= right_pos - 1'b1;
    			end
    		end
    	end
    

    完整代码

    //main.v
    `timescale 1ns / 1ps
    
    module VGA(
        input clk,
        input reset,
        output reg [2:0] r,
        output reg [2:0] g,
        output reg [1:0] b,
        output hs,
        output vs
        );
    
    	parameter UP_BOUND = 31;
    	parameter DOWN_BOUND = 510;
    	parameter LEFT_BOUND = 144;
    	parameter RIGHT_BOUND = 783;
    	
    	parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
    	reg [2:0] state, nextstate;
    	reg [2:0] nextr, nextg;
    	reg [1:0] nextb;
    	
    	reg h_speed, v_speed;
    	reg [9:0] up_pos, down_pos, left_pos, right_pos;
    
    	wire myclk;
    	reg [1:0] count;
    	reg [9:0] hcount, vcount;
    	
    	assign myclk = count[1];
    	always@(posedge clk)
    	begin
    		if(reset)
    			count <= 0;
    		else
    			count <= count + 1'b1;
    	end
    	
    	assign hs = (hcount < 96) ? 1'b0 : 1'b1;
    	always@(posedge myclk or posedge reset)
    	begin
    		if(reset)
    			hcount <= 0;
    		else if(hcount == 799)
    			hcount <= 0;
    		else
    			hcount <= hcount + 1'b1;
    	end
    	
    	assign vs = (vcount < 2) ? 1'b0 : 1'b1;
    	always@(posedge myclk or posedge reset)
    	begin
    		if(reset)
    			vcount <= 0;
    		else if(hcount == 799) 
    		begin
    			if(vcount == 520)
    				vcount <= 0;
    			else
    				vcount <= vcount + 1'b1;
    		end
    		else
    			vcount <= vcount;
    	end
    	
    	always@(posedge myclk or posedge reset)
    	begin
    		if(reset) 
    		begin
    			r <= 0;
    			g <= 0;
    			b <= 0;
    		end
    		else begin
    			if((vcount >= up_pos) 
    			&& (vcount <= down_pos)
    			&& (hcount >= left_pos) 
    			&& (hcount<=right_pos)) 
    			begin
    				r <= nextr; 
    				g <= nextg; 
    				b <= nextb;
    			end
    			else 
    			begin
    				r <= 3'b000;
    				g <= 3'b000;
    				b <= 2'b00;
    			end
    		end
    	end
    	
    	always@(posedge myclk or posedge reset)
    	begin
    		if(reset)
    			state <= S0;
    		else
    			state <= nextstate;
    	end
    	
    	always@(*)
    	begin
    		case(state)
    			S0:		nextstate <= S1;
    			S1:		nextstate <= S2;
    			S2:		nextstate <= S3;
    			S3:		nextstate <= S0;
    			default:	nextstate <= S0;
    		endcase
    	end
    	
    	always@(*)
    	begin
    		case(state)
    			S0:		begin nextr <= 3'b111; nextg <= 3'b000; nextb <= 2'b00; end
    			S1:		begin nextr <= 3'b000; nextg <= 3'b111; nextb <= 2'b00; end
    			S2:		begin nextr <= 3'b000; nextg <= 3'b000; nextb <= 2'b11; end
    			S3:		begin nextr <= 3'b111; nextg <= 3'b111; nextb <= 2'b00; end
    			default:	begin nextr <= 3'b111; nextg <= 3'b000; nextb <= 2'b11; end
    		endcase
    	end
    	
    	always@(negedge vs or posedge reset)
    	begin
    		if(reset)
    		begin
    			h_speed <= 1;
    			v_speed <= 0;
    		end
    		else 
    		begin
    			if(up_pos == UP_BOUND)
    				v_speed <= 1;
    			else if(down_pos == DOWN_BOUND)
    				v_speed <= 0;
    			else
    				v_speed <= v_speed;
    			
    			if (left_pos == LEFT_BOUND)
    				h_speed <= 1;
    			else if (right_pos == RIGHT_BOUND)
    				h_speed <= 0;
    			else
    				h_speed <= h_speed;
    		end
    	end
    	
    	always@(posedge vs or posedge reset)
    	begin
    		if(reset) 
    		begin
    			up_pos <= 391;
    			down_pos <= 510;
    			left_pos <= 384;
    			right_pos <= 543;
    		end
    		else
    		begin
    			if(v_speed) 
    			begin
    				up_pos <= up_pos + 1'b1;
    				down_pos <= down_pos + 1'b1;
    			end
    			else 
    			begin
    				up_pos <= up_pos - 1'b1;
    				down_pos <= down_pos - 1'b1;
    			end
    			
    			if(h_speed)
    			begin
    				left_pos <= left_pos + 1'b1;
    				right_pos <= right_pos + 1'b1;
    			end
    			else 
    			begin
    				left_pos <= left_pos - 1'b1;
    				right_pos <= right_pos - 1'b1;
    			end
    		end
    	end
    
    endmodule
    
  • 相关阅读:
    git 提交解决冲突(转载)
    impala系列: 时间函数
    impala系列: 字符串函数
    Impala系列: Impala常用的功能函数
    impala系列:impala特有的操作符
    impala系列: 同步Hive元数据和收集统计信息
    ETL脚本的版本管理方法和 SourceTree 使用
    几本不错的数据仓库和Hadoop书籍
    Kudu系列-基础
    sql parser
  • 原文地址:https://www.cnblogs.com/wsine/p/4292687.html
Copyright © 2020-2023  润新知