這次設計一個VGA、TFT顯示模塊,其特點如下: 行同步信號、場同步信號、數據有效信號的延遲數可調。(應用時方便與存儲模塊數據對齊) 解析度可以通過調整參數來改變。 數據格式為RGR565,可簡單修改位寬來修改成其他數據格式。 TFT的介面時序和VGA的時序相似,但是TFT介面比VGA多了數據有效信 ...
這次設計一個VGA、TFT顯示模塊,其特點如下:
- 行同步信號、場同步信號、數據有效信號的延遲數可調。(應用時方便與存儲模塊數據對齊)
- 解析度可以通過調整參數來改變。
- 數據格式為RGR565,可簡單修改位寬來修改成其他數據格式。
TFT的介面時序和VGA的時序相似,但是TFT介面比VGA多了數據有效信號和背光信號。
所以該模塊可以用在TFT上,也可以用在VGA顯示上。
VGA時序
RGB 介面的 TFT 屏掃描方式和 VGA (Video Graphics Array)標準類似,使用行列掃描的方式。在介紹 TFT 屏掃描原理之前,先來介紹下 VGA 顯示器的掃描原理。
在 VGA 標準興起的時候,常見的彩色顯示器一般由 CRT(陰極射線管)構成,色彩是由 RGB 三基色組成。顯示是用逐行掃描的方式解決。陰極射線槍發出的電子束打在塗有熒光粉的熒光屏上,產生 RGB 三基色,合成一個彩色像素,掃描從屏幕的左上方開始,從左到右,從上到下進行掃描,每掃完一行,電子束都回到屏幕的下一行左邊的起始位置。
在這期間,CRT 對電子束進行消隱。每行結束時,用行同步信號進行行同步;掃描完所有行,用場同步信號進行場同步,並使掃描回到屏幕的左上方。同時進行場消隱,預備下一場的掃描。
隨著顯示技術的發展,出現了液晶顯示器,液晶顯示器的成像原理與 CRT 不同,液晶顯示器是通過對液晶像素點單元施加電壓與否,來實現液晶單元的透明程度,並添加三色濾光片、分別使 R、G、B 這 3 中光線透過濾光片,最後通過 3 個像素點合成一個彩色像素點,從而實現彩色顯示。由於液晶技術晚於 CRT 顯示技術誕生,為了能夠相容傳統的顯示介面,液晶顯示器通過內部電路實現了對 VGA 介面的完全相容。因此,在使用顯示器時,只要該顯示器帶有標準的 VGA 介面,就不用去關註其成像原理,直接用標準的 VGA 時序即可驅動。
RGB 介面的 TFT 屏,掃描方式與 VGA 完全一致。不同之處只是在於,VGA 顯示器是接收模擬信號,而 TFT 屏則省略了這一過程,直接接受數字信號。例如,在驅動 VGA 時首先產生對應像素的顏色數字信號編碼,再使用數模轉換電路(例如 ADV7123)將數字轉換為模擬信號,然後通過 VGA 線纜將模擬信號傳輸到 VGA 顯示器上進行顯示。而 TFT 屏則直接省略了數模轉換這一過程,直接將接收到的數字信號進行顯示。因此在控制器設計端,並沒有任何區別,因此本章學習結束可以只適當修改時序參數便可驅動學習套件中的 VGA 介面。
如圖所示為該屏介面的行掃描時序圖。
以 5 寸 TFT 屏(解析度 800*480)為例,對行掃描時序要求如下(單位:輸出一個像素的時間間隔,即像素時鐘)。
如圖所示為屏幕場掃描的時序圖。
5 寸 TFT 屏中對場掃描時序要求如下(單位:輸出一行 Line 的時間間隔)。
整個 TFT 屏的圖像掃描示意圖如下。
(以上介紹摘抄自小梅哥的教材文檔,侵權刪)
總之就是在行和場同步信號都是可視區域的時間時輸出圖像型號即可。
一、VGA顯示模塊
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: GDUT
// Engineer: Lclone
//
// Create Date: 2023/02/07 13:58:13
// Design Name: VGA_Display
// Module Name: VGA_Display
// Project Name: VGA_Display
// Target Devices:
// Tool Versions:
// Description:
// 行同步信號、場同步信號、數據有效信號的延遲數可調。(應用時方便與存儲模塊數據對齊)
// 解析度可以通過調整參數來改變。
// 數據格式為RGR565,可簡單修改位寬來修改成其他數據格式。
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module VGA_Display
# ( parameter HS_DELAY = 0, //信號延遲參數
parameter VS_DELAY = 0,
parameter DE_DELAY = 0 )
(
//-----------內部介面------------
input Clk, //時鐘信號
input Rst_n, //複位信號
output Data_Req, //數據請求信號
input [15:0] RGB_Data, //圖像數據輸入
output reg [11:0] H_addr, //數據行地址
output reg [11:0] V_addr, //數據列地址
//-----------外部介面------------
output Disp_Pclk, //像素時鐘
output [ 4:0] Disp_Red, //數據紅色
output [ 5:0] Disp_Green, //數據綠色
output [ 4:0] Disp_Blue, //數據藍色
output HS, //行同步信號
output VS, //場同步信號
output DE, //數據有效信號
output BL //背光信號(可以通過PWM來調節亮度,這裡直接輸出1)
);
localparam H_PULSE_BEGIN = 0;
localparam H_PULSE_END = 128;
localparam H_DATA_BEGIN = 128 + 88 + 0;
localparam H_DATA_END = 128 + 88 + 0 + 800;
localparam H_END = 128 + 88 + 0 + 800 + 40 + 0;
localparam V_PULSE_BEGIN = 0;
localparam V_PULSE_END = 2;
localparam V_DATA_BEGIN = 2 + 25 + 8;
localparam V_DATA_END = 2 + 25 + 8 + 480;
localparam V_END = 2 + 25 + 8 + 480 + 8 + 2;
reg [11:0] H_cnt; //行計數
reg [11:0] V_cnt; //場計數
reg HS_act; //行 有效信號
reg VS_act; //場 有效信號
reg DE_act; //數據有效 有效信號
reg [3:0] HS_reg; //行同步信號延遲寄存器
reg [3:0] VS_reg; //場同步信號延遲寄存器
reg [3:0] DE_reg; //數據有效信號延遲寄存器
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
H_cnt <= 0;
else if(H_cnt == H_END - 1)
H_cnt <= 0;
else
H_cnt <= H_cnt + 1'b1;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
V_cnt <= 0;
else if(V_cnt == V_END - 1 & H_cnt == H_END - 1)
V_cnt <= 0;
else if(H_cnt == H_END - 1)
V_cnt <= V_cnt + 1'b1;
else
V_cnt <= V_cnt;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
H_addr <= 0;
else if(H_cnt == H_DATA_END - 1)
H_addr <= 0;
else if(H_cnt >= H_DATA_BEGIN & DE_act == 1)
H_addr <= H_addr + 1'b1;
else
H_addr <= 0;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
V_addr <= 0;
else if(V_cnt >= V_DATA_END - 1 & H_cnt == H_DATA_END - 1)
V_addr <= 0;
else if(V_cnt >= V_DATA_BEGIN & H_cnt == H_DATA_END - 1)
V_addr <= V_addr + 1'b1;
else
V_addr <= V_addr;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
HS_act <= 1;
else if(H_cnt == H_PULSE_BEGIN )
HS_act <= 0;
else if(H_cnt == H_PULSE_END - 1)
HS_act <= 1;
else if(H_cnt == H_END - 1)
HS_act <= 0;
else
HS_act <= HS_act;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
VS_act <= 1;
else if(V_cnt == V_PULSE_BEGIN)
VS_act <= 0;
else if(V_cnt == V_PULSE_END)
VS_act <= 1;
else if(V_cnt == V_END)
VS_act <= 0;
else
VS_act <= VS_act;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
DE_act <= 0;
else if(H_cnt >= H_DATA_BEGIN - 1 & H_cnt <= H_DATA_END - 1 - 1 &
V_cnt >= V_DATA_BEGIN & V_cnt <= V_DATA_END - 1) // 這裡H_DATA_END減兩個1是通過模擬得出的結果。
DE_act <= 1;
else
DE_act <= 0;
end
always @(posedge Clk) begin
HS_reg[0] <= HS_act;
HS_reg[3:1] <= HS_reg[2:0];
VS_reg[0] <= VS_act;
VS_reg[3:1] <= VS_reg[2:0];
DE_reg[0] <= DE_act;
DE_reg[3:1] <= DE_reg[2:0];
end
assign HS = (HS_DELAY == 0)? HS_act : HS_reg[HS_DELAY - 1];
assign VS = (VS_DELAY == 0)? VS_act : VS_reg[VS_DELAY - 1];
assign DE = (DE_DELAY == 0)? DE_act : DE_reg[DE_DELAY - 1];
assign Disp_Pclk = Clk;
assign Disp_Red = (DE == 1)? RGB_Data[4:0] : 0 ;
assign Disp_Green = (DE == 1)? RGB_Data[10:5] : 0 ;
assign Disp_Blue = (DE == 1)? RGB_Data[15:11] : 0 ;
assign Data_Req = DE_act;
assign BL = 1'b1;
endmodule
二、模擬
1、模擬激勵
`timescale 1ns / 1ps
module VGA_Display_tb();
reg clk_50m;
initial clk_50m <= 0;
always #10 clk_50m <= ~clk_50m;
reg rst_n;
initial begin
rst_n <= 0;
#200
rst_n <= 1;
end
wire Data_Req;
wire [11:0] H_addr;
wire [11:0] V_addr;
reg [15:0] RGB_Data;
wire [15:0] output_data;
wire Disp_Pclk;
wire HS;
wire VS;
wire DE;
wire BL;
always @(posedge clk_50m or negedge rst_n) begin
if(rst_n == 0)
RGB_Data <= 0;
else if(Data_Req)
RGB_Data <= RGB_Data + 1'b1;
else
RGB_Data <= RGB_Data;
end
VGA_Display
# ( .HS_DELAY (1),
.VS_DELAY (1),
.DE_DELAY (1))
VGA_Display_inst
(
//-----------內部介面------------
.Clk (clk_50m),
.Rst_n (rst_n),
.Data_Req (Data_Req),
.RGB_Data (RGB_Data),
.H_addr (H_addr),
.V_addr (V_addr),
//-----------外部介面------------
.Disp_Pclk (Disp_Pclk),
.Disp_Red (output_data[4:0]),
.Disp_Green (output_data[10:5]),
.Disp_Blue (output_data[15:11]),
.HS (HS),
.VS (VS),
.DE (DE),
.BL (BL)
);
endmodule
2、模擬分析
可見行時序符合參數設計。
可見場時序也符合參數設計。
數據行地址從0計到799共800次
數據列地址從0記到479共480次
結論:模擬驗證初步通過
三、上板驗證
1、上板驗證代碼
此段代碼中例化了一個時鐘管理單元,輸入為50M的時鐘,輸出為33M的時鐘。
本模塊設計預期為顯示8個色塊。
module VGA_TFT(
//內部信號
input CLK,
input Rst_n,
//外部信號
output Disp_HS,
output Disp_VS,
output [4:0] Disp_Red,
output [5:0] Disp_Green,
output [4:0] Disp_Blue,
output Disp_DE,
output Disp_PCLK,
output Disp_BL
);
reg [15:0] RGB_Data_in;
wire DataReq;
wire[11:0] H_Addr;
wire[11:0] V_Addr;
parameter
BLACK = 16'h0000, //黑色
BLUE = 16'h001F, //藍色
RED = 16'hF800, //紅色
PURPPLE = 16'hF81F, //紫色
GREEN = 16'h07E0, //綠色
CYAN = 16'h07FF, //青色
YELLOW = 16'hFFE0, //黃色
WHITE = 16'hFFFF; //白色
parameter
C0_R0 = BLACK, //第0行0列像素塊
C1_R0 = BLUE, //第0行1列像素塊
C0_R1 = RED, //第1行0列像素塊
C1_R1 = PURPPLE, //第1行1列像素塊
C0_R2 = GREEN, //第2行0列像素塊
C1_R2 = CYAN, //第2行1列像素塊
C0_R3 = YELLOW, //第3行0列像素塊
C1_R3 = WHITE; //第3行1列像素塊
wire C0_ACT = H_Addr >= 0 && H_Addr < 401;
wire C1_ACT = H_Addr >= 401 && H_Addr <= 800;
wire R0_ACT = V_Addr >= 0 && V_Addr < 119;
wire R1_ACT = V_Addr >= 120 && V_Addr < 239;
wire R2_ACT = V_Addr >= 240 && V_Addr < 359;
wire R3_ACT = V_Addr >= 360 && V_Addr < 479;
wire C0_R0_ACT = C0_ACT & R0_ACT & DataReq;
wire C0_R1_ACT = C0_ACT & R1_ACT & DataReq;
wire C0_R2_ACT = C0_ACT & R2_ACT & DataReq;
wire C0_R3_ACT = C0_ACT & R3_ACT & DataReq;
wire C1_R0_ACT = C1_ACT & R0_ACT & DataReq;
wire C1_R1_ACT = C1_ACT & R1_ACT & DataReq;
wire C1_R2_ACT = C1_ACT & R2_ACT & DataReq;
wire C1_R3_ACT = C1_ACT & R3_ACT & DataReq;
always @(*)
case({C0_R0_ACT,C0_R1_ACT,C0_R2_ACT,C0_R3_ACT,
C1_R0_ACT,C1_R1_ACT,C1_R2_ACT,C1_R3_ACT})
8'b0000_0001:RGB_Data_in = C1_R3;
8'b0000_0010:RGB_Data_in = C1_R2;
8'b0000_0100:RGB_Data_in = C1_R1;
8'b0000_1000:RGB_Data_in = C1_R0;
8'b0001_0000:RGB_Data_in = C0_R3;
8'b0010_0000:RGB_Data_in = C0_R2;
8'b0100_0000:RGB_Data_in = C0_R1;
8'b1000_0000:RGB_Data_in = C0_R0;
default: RGB_Data_in <= 0;
endcase
assign Disp_BL = 1'b1;
wire CLK_33M;
clk_wiz_0 clk_wiz_0_inst
(
// Clock out ports
.clk_out1(CLK_33M), // output clk_out1
// Status and control signals
.reset(~Rst_n), // input reset
.locked(), // output locked
// Clock in ports
.clk_in1(CLK)); // input clk_in1
VGA_Display
# ( .HS_DELAY (1),
.VS_DELAY (1),
.DE_DELAY (1))
VGA_Display_inst
(
//-----------內部介面------------
.Clk (CLK_33M),
.Rst_n (Rst_n),
.Data_Req (DataReq),
.RGB_Data (RGB_Data_in),
.H_addr (H_Addr),
.V_addr (V_Addr),
//-----------外部介面------------
.Disp_Pclk (Disp_PCLK),
.Disp_Red (Disp_Red),
.Disp_Green (Disp_Green),
.Disp_Blue (Disp_Blue),
.HS (Disp_HS),
.VS (Disp_VS),
.DE (Disp_DE),
.BL ()
);
endmodule
2、上板實驗現象
可見TFT屏能夠正常顯示8個色塊,實驗成功,驗證模塊可用。