学习ZYNQ之FPGA14(RGB_LCD彩条实验)

学习ZYNQ之FPGA14(RGB_LCD彩条实验)_第1张图片

本次实验需要编写4个模块,分别为ID读取模块,时钟分频模块,LCD显示模块和LCD驱动模块。

ID读取模块:

实验中每次复位后,ID的读取只有一次 。

module rd_id(
    input              clk,
    input              rst_n,
    
    input       [23:0] lcd_rgb,
    output reg  [15:0] lcd_id 
);

reg    rd_flag;

always @ (posedge clk or negedge rst_n) begin
    if(!rst_n)
        rd_flag <= 1'b0;
    else if(rd_flag == 1'b0) begin
            rd_flag <= 1'b1;
            case({lcd_rgb[7],lcd_rgb[15],lcd_rgb[23]})
                3'b000 : lcd_id <= 16'h4342;
                3'b001  : lcd_id <= 16'h7084;
				3'b010  : lcd_id <= 16'h7016;
				3'b100  : lcd_id <= 16'h4384;
				3'b101  : lcd_id <= 16'h1018;
				default : lcd_id <= 16'd0;
            endcase    
    end
end
endmodule

时钟分频模块

module clk_div(
    input          clk,
    input          rst_n,

    input  [15:0]  lcd_id,
    output   reg   lcd_pclk
);

reg    clk_25m;
reg    clk_12_5m;
reg    div_4_cnt;

always @ (posedge clk or negedge rst_n) begin
    if(!rst_n)
        clk_25m <= 1'b0;
    else
        clk_25m <= ~clk_25m;
end  

always @ (posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        clk_12_5m <= 1'b0;
        div_4_cnt <= 1'b0;
    end
    else begin
        div_4_cnt <= div_4_cnt + 1'b1;
        if(div_4_cnt == 1'b1)
            clk_12_5m <= ~ clk_12_5m;    
    end
end
always @ (*) begin
    case(lcd_id)
    	16'h4342 :  lcd_pclk = clk_12_5m;
		16'h7084 :  lcd_pclk = clk_25m;
		16'h7016 :  lcd_pclk = clk; 
		16'h4384 :  lcd_pclk = clk_12_5m;
		16'h1018 :  lcd_pclk = clk;
		default  :  lcd_pclk = 1'b0;
    endcase
end




endmodule

lcd驱动模块:

学习ZYNQ之FPGA14(RGB_LCD彩条实验)_第2张图片

 

module lcd_driver(
    input               lcd_pclk,
    input               rst_n,

    input       [15:0]  lcd_id,
    input       [23:0]  pixel_data,
    output 		[11:0]	pixel_xpos,
	output 		[11:0]	pixel_ypos,
	output reg  [11:0]  h_disp,
	output reg  [11:0]	v_disp,
	
	output 				lcd_de,
	output				lcd_hs,
	output				lcd_vs,
	output				lcd_bl,
	output				lcd_clk,
	output	[23:0]		lcd_rgb	
);
//4342   
parameter	H_SYNC_4342 = 12'd41;
parameter	H_BACK_4342 = 12'd2;
parameter	H_DISP_4342 = 12'd480;
parameter	H_FRONT_4342 = 12'd2;
parameter	H_TOTAL_4342 = 12'd525;

parameter	V_SYNC_4342 = 12'd10;
parameter	V_BACK_4342 = 12'd2;
parameter	V_DISP_4342 = 12'd272;
parameter	V_FRONT_4342 = 12'd2;
parameter	V_TOTAL_4342 = 12'd286;

//7084
parameter	H_SYNC_7084 = 12'd128;
parameter	H_BACK_7084 = 12'd88;
parameter	H_DISP_7084 = 12'd800;
parameter	H_FRONT_7084 = 12'd40;
parameter	H_TOTAL_7084 = 12'd1056;

parameter	V_SYNC_7084 = 12'd2;
parameter	V_BACK_7084 = 12'd33;
parameter	V_DISP_7084 = 12'd480;
parameter	V_FRONT_7084 = 12'd10;
parameter	V_TOTAL_7084 = 12'd525;

//7016
parameter	H_SYNC_7016 = 12'd20;
parameter	H_BACK_7016 = 12'd140;
parameter	H_DISP_7016 = 12'd1024;
parameter	H_FRONT_7016 = 12'd160;
parameter	H_TOTAL_7016 = 12'd1344;

parameter	V_SYNC_7016 = 12'd3;
parameter	V_BACK_7016 = 12'd20;
parameter	V_DISP_7016 = 12'd600;
parameter	V_FRONT_7016 = 12'd12;
parameter	V_TOTAL_7016 = 12'd635;

//4384
parameter	H_SYNC_4384 = 12'd41;
parameter	H_BACK_4384 = 12'd2;
parameter	H_DISP_4384 = 12'd480;
parameter	H_FRONT_4384 = 12'd2;
parameter	H_TOTAL_4384 = 12'd525;

parameter	V_SYNC_4384 = 12'd10;
parameter	V_BACK_4384 = 12'd2;
parameter	V_DISP_4384 = 12'd272;
parameter	V_FRONT_4384 = 12'd2;
parameter	V_TOTAL_4384 = 12'd286;

//1018
parameter	H_SYNC_1018 = 12'd10;
parameter	H_BACK_1018 = 12'd80;
parameter	H_DISP_1018 = 12'd1280;
parameter	H_FRONT_1018 = 12'd70;
parameter	H_TOTAL_1018 = 12'd1440;

parameter	V_SYNC_1018 = 12'd3;
parameter	V_BACK_1018 = 12'd10;
parameter	V_DISP_1018 = 12'd800;
parameter	V_FRONT_1018 = 12'd10;
parameter	V_TOTAL_1018 = 12'd823;

reg [11:0] h_sync;
reg [11:0] h_back;
reg [11:0] h_total;
reg [11:0] v_sync;
reg [11:0] v_back;
reg [11:0] v_total;

reg [11:0] h_cnt;
reg [11:0] v_cnt;


wire 	   data_req;
wire 	   lcd_en;

assign lcd_bl = 1'b1;
assign lcd_vs = 1'b1;
assign lcd_hs = 1'b1;
assign lcd_clk = lcd_pclk;
assign lcd_de = lce_en;

assign lce_en = (h_cnt >= h_sync + h_back) && (h_cnt <= h_sync + h_back + h_disp)
				&& (v_cnt >= v_sync + v_back) && (v_cnt <= v_sync + v_back + v_disp)
				? 1'b1 : 1'b0;

assign data_req = (h_cnt >= h_sync + h_back - 1'b1) && (h_cnt <= h_sync + h_back + h_disp                         
                  -1'b1)
   				&& (v_cnt >= v_sync + v_back) && (v_cnt <= v_sync + v_back + v_disp)
				? 1'b1 : 1'b0;
assign pixel_xpos = data_req ? (h_cnt - (h_sync + h_back - 1'b1)) : 12'd0;
assign pixel_ypos = data_req ? (v_cnt - (v_sync + v_back - 1'b1)) : 12'd0;
assign lcd_rgb = lcd_en ? pixel_data : 24'd0;

always @ (*) begin
	case(lcd_id)
		16'h4342 : begin
		h_sync	= H_SYNC_4342;
		h_back	= H_BACK_4342;
		h_total	= H_TOTAL_4342;
		v_sync	= V_SYNC_4342;
		v_back	= V_BACK_4342;
		v_total	= V_TOTAL_4342;		
		end 
		16'h7084 : begin
            h_sync  = H_SYNC_7084; 
            h_back  = H_BACK_7084; 
            h_disp  = H_DISP_7084; 
            h_total = H_TOTAL_7084;
            v_sync  = V_SYNC_7084; 
            v_back  = V_BACK_7084; 
            v_disp  = V_DISP_7084; 
            v_total = V_TOTAL_7084;        
        end
        16'h7016 : begin
            h_sync  = H_SYNC_7016; 
            h_back  = H_BACK_7016; 
            h_disp  = H_DISP_7016; 
            h_total = H_TOTAL_7016;
            v_sync  = V_SYNC_7016; 
            v_back  = V_BACK_7016; 
            v_disp  = V_DISP_7016; 
            v_total = V_TOTAL_7016;            
        end
        16'h4384 : begin
            h_sync  = H_SYNC_4384; 
            h_back  = H_BACK_4384; 
            h_disp  = H_DISP_4384; 
            h_total = H_TOTAL_4384;
            v_sync  = V_SYNC_4384; 
            v_back  = V_BACK_4384; 
            v_disp  = V_DISP_4384; 
            v_total = V_TOTAL_4384;             
        end        
        16'h1018 : begin
            h_sync  = H_SYNC_1018; 
            h_back  = H_BACK_1018; 
            h_disp  = H_DISP_1018; 
            h_total = H_TOTAL_1018;
            v_sync  = V_SYNC_1018; 
            v_back  = V_BACK_1018; 
            v_disp  = V_DISP_1018; 
            v_total = V_TOTAL_1018;        
        end
        default : begin
            h_sync  = H_SYNC_4342; 
            h_back  = H_BACK_4342; 
            h_disp  = H_DISP_4342; 
            h_total = H_TOTAL_4342;
            v_sync  = V_SYNC_4342; 
            v_back  = V_BACK_4342; 
            v_disp  = V_DISP_4342; 
            v_total = V_TOTAL_4342;          
        end
    endcase
end

always @ (posedge lcd_pclk or negedge rst_n) begin
	if(!rst_n)
		h_cnt <= 12'd0;
	else begin
		if(h_cnt == h_total - 1'b1)
			h_cnt <= 12'd0;
		else
			h_cnt <= h_cnt + 1'b1;
	end
end

always @ (posedge lcd_pclk or negedge rst_n) begin
	if(!rst_n)
		v_cnt <= 12'd0;
	else begin
		if(h_cnt == h_total - 1'b1)	begin
			if(v_cnt == v_total - 1'b1)
				v_cnt <= 12'd0;
			else
				v_cnt <= v_cnt + 1'b1;
		end
	end
end



endmodule

lcd显示模块:

module lcd_display(
    input                   lcd_pclk,
    input                   rst_n,
    
	input 			[11:0]	pixel_xpos,
	input 			[11:0]	pixel_ypos,
	input 			[11:0]  h_disp,
	input 			[11:0]	v_disp,
	output  reg     [23:0]  pixel_data
);
parameter WHITE = 24'hffffff;
parameter BLACK = 24'h000000;
parameter RED   = 24'hff0000;
parameter GREEN = 24'h00ff00;
parameter BLUE  = 24'h0000ff;

always @ (posedge lcd_pclk or negedge rst_n) begin
	if(!rst_n)
		pixel_data <= BLACK;
	else begin
		if(pixel_xpos >= 12'd0 && pixel_xpos <= h_disp/5*1)
			pixel_data <= WHITE;
		else if(pixel_xpos >= h_disp/5*1 && pixel_xpos <= h_disp/5*2)
				pixel_data <= BLACK;
			 else if(pixel_xpos >= h_disp/5*2 && pixel_xpos <= h_disp/5*3)
			 		 pixel_data <= RED;
			 	   else if(pixel_xpos >= h_disp/5*3 && pixel_xpos <= h_disp/5*4)
			  			 	pixel_data <= GREEN;
			  			else
			  				pixel_data <= BLUE;
   end		  
end    



endmodule

用头文件将四个模块的端口连接起来,再添加约束文件。

首先根据系统时钟和复位信号,在刚开始时,只读取一次id,在读取了屏幕id之后,根据id赋予对应的时钟(这里有二分频和四分分频的程序,可以推出其他频率信号的程序),赋予时钟之后,需要对lcd屏进行驱动,程序中要有对应的前沿、后沿、显示区域、行同步、等信息,还有就是一些信号名的定义,这里需要对行和桢的显示区域进行统计,并根据不同区域划分(在先熟程序中体现)显示不同的颜色。

 

 

你可能感兴趣的:(FPGA)