學習ZYNQ之FPGA14(RGB_LCD彩條實驗)

本次實驗需要編寫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驅動模塊:

 

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屏進行驅動,程序中要有對應的前沿、後沿、顯示區域、行同步、等信息,還有就是一些信號名的定義,這裏需要對行和楨的顯示區域進行統計,並根據不同區域劃分(在先熟程序中體現)顯示不同的顏色。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章