VGA、TFT顯示模塊——verilog實現

来源:https://www.cnblogs.com/Lclone/archive/2023/02/07/17099393.html
-Advertisement-
Play Games

這次設計一個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 三基色,合成一個彩色像素,掃描從屏幕的左上方開始,從左到右,從上到下進行掃描,每掃完一行,電子束都回到屏幕的下一行左邊的起始位置。
image
在這期間,CRT 對電子束進行消隱。每行結束時,用行同步信號進行行同步;掃描完所有行,用場同步信號進行場同步,並使掃描回到屏幕的左上方。同時進行場消隱,預備下一場的掃描。
隨著顯示技術的發展,出現了液晶顯示器,液晶顯示器的成像原理與 CRT 不同,液晶顯示器是通過對液晶像素點單元施加電壓與否,來實現液晶單元的透明程度,並添加三色濾光片、分別使 R、G、B 這 3 中光線透過濾光片,最後通過 3 個像素點合成一個彩色像素點,從而實現彩色顯示。由於液晶技術晚於 CRT 顯示技術誕生,為了能夠相容傳統的顯示介面,液晶顯示器通過內部電路實現了對 VGA 介面的完全相容。因此,在使用顯示器時,只要該顯示器帶有標準的 VGA 介面,就不用去關註其成像原理,直接用標準的 VGA 時序即可驅動。
RGB 介面的 TFT 屏,掃描方式與 VGA 完全一致。不同之處只是在於,VGA 顯示器是接收模擬信號,而 TFT 屏則省略了這一過程,直接接受數字信號。例如,在驅動 VGA 時首先產生對應像素的顏色數字信號編碼,再使用數模轉換電路(例如 ADV7123)將數字轉換為模擬信號,然後通過 VGA 線纜將模擬信號傳輸到 VGA 顯示器上進行顯示。而 TFT 屏則直接省略了數模轉換這一過程,直接將接收到的數字信號進行顯示。因此在控制器設計端,並沒有任何區別,因此本章學習結束可以只適當修改時序參數便可驅動學習套件中的 VGA 介面。
如圖所示為該屏介面的行掃描時序圖。
image
以 5 寸 TFT 屏(解析度 800*480)為例,對行掃描時序要求如下(單位:輸出一個像素的時間間隔,即像素時鐘)。
image
如圖所示為屏幕場掃描的時序圖。
image
5 寸 TFT 屏中對場掃描時序要求如下(單位:輸出一行 Line 的時間間隔)。
image
整個 TFT 屏的圖像掃描示意圖如下。
image
(以上介紹摘抄自小梅哥的教材文檔,侵權刪)

總之就是在行和場同步信號都是可視區域的時間時輸出圖像型號即可。

一、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、模擬分析

image
可見行時序符合參數設計。
image
image
可見場時序也符合參數設計。
image
數據行地址從0計到799共800次
image
數據列地址從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、上板實驗現象

image
可見TFT屏能夠正常顯示8個色塊,實驗成功,驗證模塊可用。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • R2M分散式鎖原理可以理解為一條內容或者圖片+文字+鏈接的載體,常見的案例有鎖說明和分散式鎖選擇、r2m分散式鎖選擇、r2m分散式鎖原理,加鎖核心流程。 ...
  • 問題場景:當用戶量增大的時候,系統內的消息推送(比如 系統內簡訊推送,微信,釘釘,極光個推推送)將是我們常見業務場景。當系統中的用戶量逐漸增大時候,群發用戶消息的推送也將成為系統中致命的性能瓶頸。 消息推送緩衝隊列模型 意義: 構建大批量消息推送隊列,來解決大批量數據通過拉長時間隊列模式來換取性能提 ...
  • 一、認證組件 簡介: 登錄認證的限制 認證組件是drf框架給我們提供的認證介面,它能夠在請求進入視圖函數/類前進驗證(例如:認證用戶是否登錄),對不符合認證的請求進行攔截並返回校驗失敗的信息 (1)、登錄介面 # 認證是基於登錄的介面上面操作的 所以前戲編寫一個簡單的登錄介面 models.py c ...
  • 視圖和視圖解析器 1.基本介紹 在SpringMVC中的目標方法,最終返回的都是一個視圖(有各種視圖) 註意,這裡的視圖是一個類對象,不是一個頁面!! 返回的視圖都會由一個視圖解析器來處理(視圖解析器有很多種) 2.自定義視圖 2.1為什麼需要自定義視圖 在預設情況下,我們都是返回預設的視圖,然後返 ...
  • 這篇文章主要描述分散式技術中的選舉演算法,分散式選舉是為選出一個主節點,由它來協調和管理其他節點,保證集群有序運行和節點間數據的一致性。涉及到的選舉演算法包括Bully演算法、Raft演算法和ZAB演算法。 ...
  • 最近在寫一本Xilinx的FPGA方面的書,現將HLS部分內容在這裡分享給大家,希望大家喜歡,也歡迎批評指正。[原創www.cnblogs.com/helesheng] 在可編程邏輯器件被用於電子系統設計的前期,由於所含的邏輯資源較少,絕大部分情況下,它們被用於實現數據的傳輸和介面電路。工程師們習慣 ...
  • 1 簡介 AOP,即面向切麵編程是很常用的技術,特別是在Java Web開發中。而最流行的AOP框架分別是Spring AOP和AspectJ。 2 Spring AOP vs AspectJ Spring AOP是基於Spring IoC實現的,它解決大部分常見的需求,但它並不是一個完整的AOP解 ...
  • 原文地址:https://bysocket.com/openai-chatgpt-error-1020/ 最近打開 chat.openai.com/chat 地址,如下圖會提示錯誤碼:Access denied Error code 1020。這裡通過學習和排查,總結了 3 種方法區解決這個問題。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...