# VGA协议实践

news2024/7/6 18:38:20

VGA协议实践


文章目录

  • VGA协议实践
    • 1.VGA介绍
    • 2. ALTPLL
    • 3. 字模与图像生成
    • 4. ROM
    • 5. 代码
      • 5.1 vga驱动模块
      • 5.2 显示数据生成模块
      • 5.3 按键消抖模块
      • 5.4 顶层模块
      • 5.5 TCL绑定引脚代码
    • 6. 效果
    • 7.总结
    • 8.参考文章


1.VGA介绍

VGA:Video Graphics Array视频图形阵列是IBM于1987年提出的一个使用模拟信号的电脑显示标准。VGA接口即电脑采用VGA标准输出数据的专用接口。VGA接口共有15针,分成3排,每排5个孔,显卡上应用最为广泛的接口类型,绝大多数显卡都带有此种接口。它传输红、绿、蓝模拟信号以及同步信号(水平和垂直信号)。

VGA接口是一种D型接口,上面共有15针孔,分成三排,每排五个。 其中,除了2根NC(Not Connect)信号、3根显示数据总线和5个GND信号,比较重要的是3根RGB彩色分量信号和2根扫描同步信号HSYNC和VSYNC针。VGA接口中彩色分量采用RS343电平标准。RS343电平标准的峰值电压为1V。VGA接口是显卡上应用最为广泛的接口类型,多数的显卡都带有此种接口。有些不带VGA接口而带有DVI(Digital Visual Interface数字视频接口)接口的显卡,也可以通过一个简单的转接头将DVI接口转成VGA接口,通常没有VGA接口的显卡会附赠这样的转接头。

大多数计算机与外部显示设备之间都是通过模拟VGA接口连接,计算机内部以数字方式生成的显示图像信息,被显卡中的数字/模拟转换器转变为R、G、B三原色信号和行、场同步信号,信号通过电缆传输到显示设备中。对于模拟显示设备,如模拟CRT显示器,信号被直接送到相应的处理电路,驱动控制显像管生成图像。而对于LCD、DLP等数字显示设备,显示设备中需配置相应的A/D(模拟/数字)转换器,将模拟信号转变为数字信号。在经过D/A和A/D两次转换后,不可避免地造成了一些图像细节的损失。VGA接口应用于CRT显示器无可厚非,但用于连接液晶之类的显示设备,则转换过程的图像损失会使显示效果略微下降。
而且可以从接口处来判断显卡是独显还是集成显卡,VGA接口竖置的说明是集成显卡,VGA接口横置说明是独立显卡(一般的台式主机都可以用此方法来查看)。

管脚定义:

管脚定义
1红基色
2绿基色
3蓝基色
4地址码 ID Bit
5自测试
6红地
7绿地
8蓝地
9保留(各家定义不同)
10数字码
11地址码
12地址码
13行同步
14场同步
15地址码(各家定义不同)

VGA显示原理:

VGA通过引脚的模拟电压(0V-0.714V)显示红绿蓝三种颜色,不同的电压值对应不同的颜色。
VGA驱动显示器用的是扫描的方式,一般是逐行扫描。
逐行扫描是扫描从屏幕左上角一点开始,从左像右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,CRT对电子束进行消隐,每行结束时,用行同步信号进行同步;
当扫描完所有的行,形成一帧后,用场同步信号进行场同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。

在这里插入图片描述
FPGA芯片驱动VGA显示,需要先产生模拟信号,这就要借助数模转换器D/A,利用D/A产生模拟信号,输出至VGA的RED、GREEN、BLUE基色数据线。另一种方法是利用电阻网络分流模拟D/A实现的。

VGA通信协议:

VS:帧时序
帧时序的四个部分别是:同步脉冲(Sync o)、显示后沿(Back porch p)、显示时序段(Display interval q)和显示前沿(Front porchr)。其中同步脉冲(Sync o)、显示后沿(Back porch p)和显示前沿(Front porch r)是消隐区,RGB信号无效,屏幕不显示数据。显示时序段(Display interval q)是有效数据区。

HS:行时序
行时序的四个部分分别是:同步脉冲(Sync a)、显示后沿(Back porch b)、显示时序(Display interval c)和显示前沿(Front porchd)。其中同步脉冲(Sync a)、显示后沿(Back porch b)和显示前沿(Front porch d)是消隐区,RGB信号无效,屏幕不显示数据。显示时序段(Display interval c)是有效数据区。

VGA时序解析:
在这里插入图片描述

2. ALTPLL

使用640×480 60HZ,对应时钟为25M,需要使用PLL进行分频 时钟频率 = 行帧长 × 列帧长 * 刷新率,640 ×480 60HZ对应时钟频率= 800 ×525 × 60 = 25.2M
在这里插入图片描述
基础时钟选择50M
在这里插入图片描述

取消勾选输出使能
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
c0默认输出50M即可
在这里插入图片描述
c1分频到25M,如需其他时钟频率可以自己进行设置
在这里插入图片描述
勾选如下选项后finish
在这里插入图片描述

3. 字模与图像生成

在子模提取工具里面输入需要显示的字符并设置字符大小为64*64
在这里插入图片描述
然后点击文件-另存为,把图片保存为BMP图片
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

点击文件-打开,把保存的BMP图片打开得到整体的字符,点击选项按如下参数设置在这里插入图片描述
最后点击生成字符并保存字符为文本文件,文件如下
在这里插入图片描述
把得到的字符在verilog里面使用即可
在这里插入图片描述

使用BMP2Mif工具把图片转为HEX文件
在这里插入图片描述

4. ROM

图片数据太多需要使用ROM来存储数据
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5. 代码

基于EP4CEF17C8型号芯片

5.1 vga驱动模块

module vga_dirve (input			wire						clk,            //系统时钟
                  input			wire						rst_n,          //复位
                  input			wire		[ 15:0 ]		rgb_data,       //16位RGB对应值
                  output			wire							vga_clk,    //vga时钟 25M
                  output			reg							h_sync,     //行同步信号
                  output			reg							v_sync,     //场同步信号
                  output			reg		[ 11:0 ]				addr_h, //行地址
                  output			reg		[ 11:0 ]				addr_v,  //列地址
                  output			wire		[ 4:0 ]				rgb_r,  //红基色
                  output			wire		[ 5:0 ]				rgb_g,  //绿基色
                  output			wire		[ 4:0 ]				rgb_b  //蓝基色
);

// 640 * 480 60HZ
localparam	 H_FRONT = 16; // 行同步前沿信号周期长
localparam	 H_SYNC  = 96; // 行同步信号周期长
localparam	 H_BLACK = 48; // 行同步后沿信号周期长
localparam	 H_ACT   = 640; // 行显示周期长
localparam	 V_FRONT = 11; // 场同步前沿信号周期长
localparam	 V_SYNC  = 2; // 场同步信号周期长
localparam	 V_BLACK = 31; // 场同步后沿信号周期长
localparam	 V_ACT   = 480; // 场显示周期长

// 800 * 600 72HZ
// localparam	 H_FRONT = 40; // 行同步前沿信号周期长
// localparam	 H_SYNC  = 120; // 行同步信号周期长
// localparam	 H_BLACK = 88; // 行同步后沿信号周期长
// localparam	 H_ACT   = 800; // 行显示周期长
// localparam	 V_FRONT = 37; // 场同步前沿信号周期长
// localparam	 V_SYNC  = 6; // 场同步信号周期长
// localparam	 V_BLACK = 23; // 场同步后沿信号周期长
// localparam	 V_ACT   = 600; // 场显示周期长


localparam	H_TOTAL = H_FRONT + H_SYNC + H_BLACK + H_ACT; // 行周期
localparam	V_TOTAL = V_FRONT + V_SYNC + V_BLACK + V_ACT; // 列周期

reg			[ 11:0 ]			cnt_h			; // 行计数器
reg			[ 11:0 ]			cnt_v			; // 场计数器
reg			[ 15:0 ]			rgb			; // 对应显示颜色值

// 对应计数器开始、结束、计数信号
wire							flag_enable_cnt_h			;
wire							flag_clear_cnt_h			;
wire							flag_enable_cnt_v			;
wire							flag_clear_cnt_v			;
wire							flag_add_cnt_v  			;
wire							valid_area      			;


// 25M时钟 行周期*场周期*刷新率 = 800 * 525* 60
wire							clk_25			;
// 50M时钟 1040 * 666 * 72
wire							clk_50			;
//PLL
pll	pll_inst (
	.areset ( ~rst_n ),
	.inclk0 ( clk ),
	.c0 ( clk_50 ), //50M
	.c1 ( clk_25 ), //25M
	);
//根据不同分配率选择不同频率时钟
assign vga_clk = clk_25;


// 行计数
always @( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        cnt_h <= 0;
    end
    else if ( flag_enable_cnt_h ) begin
        if ( flag_clear_cnt_h ) begin
            cnt_h <= 0;
        end
        else begin
            cnt_h <= cnt_h + 1;
        end
    end
    else begin
        cnt_h <= 0;
    end
end
assign flag_enable_cnt_h = 1;
assign flag_clear_cnt_h  = cnt_h == H_TOTAL - 1;

// 行同步信号
always @( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        h_sync <= 0;
    end
    else if ( cnt_h == H_SYNC - 1 ) begin // 同步周期时为1
        h_sync <= 1;
    end
        else if ( flag_clear_cnt_h ) begin // 其余为0
        h_sync <= 0;
        end
    else begin
        h_sync <= h_sync;
    end
end

// 场计数
always @( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        cnt_v <= 0;
    end
    else if ( flag_enable_cnt_v ) begin
        if ( flag_clear_cnt_v ) begin
            cnt_v <= 0;
        end
        else if ( flag_add_cnt_v ) begin
            cnt_v <= cnt_v + 1;
        end
        else begin
            cnt_v <= cnt_v;
        end
    end
    else begin
        cnt_v <= 0;
    end
end
assign flag_enable_cnt_v = flag_enable_cnt_h;
assign flag_clear_cnt_v  = cnt_v == V_TOTAL - 1;
assign flag_add_cnt_v    = flag_clear_cnt_h;

// 场同步信号
always @( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        v_sync <= 0;
    end
    else if ( cnt_v == V_SYNC - 1 ) begin
        v_sync <= 1;
    end
        else if ( flag_clear_cnt_v ) begin
        v_sync <= 0;
        end
    else begin
        v_sync <= v_sync;
    end
end

// 对应有效区域行地址 1-640
always @( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        addr_h <= 0;
    end
    else if ( valid_area ) begin
        addr_h <= cnt_h - H_SYNC - H_BLACK + 1;
    end
    else begin
        addr_h <= 0;
    end
end
// 对应有效区域列地址 1-480
always @( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        addr_v <= 0;
    end
    else if ( valid_area ) begin
        addr_v <= cnt_v -V_SYNC - V_BLACK + 1;
    end
    else begin
        addr_v <= 0;
    end
end
// 有效显示区域
assign valid_area = cnt_h >= H_SYNC + H_BLACK && cnt_h <= H_SYNC + H_BLACK + H_ACT && cnt_v >= V_SYNC + V_BLACK && cnt_v <= V_SYNC + V_BLACK + V_ACT;


// 显示颜色
always @( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        rgb <= 16'h0;
    end
    else if ( valid_area ) begin
        rgb <= rgb_data;
    end
    else begin
        rgb <= 16'b0;
    end
end
assign rgb_r = rgb[ 15:11 ];
assign rgb_g = rgb[ 10:5 ];
assign rgb_b = rgb[ 4:0 ];

endmodule // vga_dirve



5.2 显示数据生成模块

module data_drive (
    input			wire						vga_clk,
    input			wire						rst_n,
    input			wire		[ 11:0 ]		addr_h,
    input			wire		[ 11:0 ]		addr_v,
    input			wire		[ 2:0 ]		    key,
    output			reg		    [ 15:0 ]		rgb_data);

localparam	red    = 16'd63488;
localparam	orange = 16'd64384;
localparam	yellow = 16'd65472;
localparam	green  = 16'd1024;
localparam	blue   = 16'd31;
localparam	indigo = 16'd18448;
localparam	purple = 16'd32784;
localparam	white  = 16'd65503;
localparam	black  = 16'd0;
reg [ 383:0 ] char_line[ 64:0 ];

localparam	states_1 = 1; // 彩条
localparam	states_2 = 2; // 字符
localparam	states_3 = 3; // 图片

parameter	height = 78; // 图片高度
parameter	width  = 128; // 图片宽度
reg			[ 1:0 ]			states_current			; // 当前状态
reg			[ 1:0 ]			states_next			    ; // 下个状态
reg			[ 13:0 ]		rom_address				; // ROM地址
wire		[ 15:0 ]		rom_data				; // 图片数据

wire							flag_enable_out1			; // 文字有效区域
wire							flag_enable_out2			; // 图片有效区域
wire							flag_clear_rom_address		; // 地址清零
wire							flag_begin_h			    ; // 图片显示行
wire							flag_begin_v			    ; // 图片显示列

//状态转移
always @( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        states_current <= states_1;
    end
    else begin
        states_current <= states_next;
    end
end

//状态判断
always @( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        states_next <= states_1;
    end
    else if ( key[ 0 ] ) begin
        states_next <= states_1;
    end
        else if ( key[ 1 ] ) begin
        states_next <= states_2;
        end
        else if ( key[ 2 ] ) begin
        states_next <= states_3;
        end
    else begin
        states_next <= states_next;
    end
end

//状态输出
always @( * ) begin
    case ( states_current )
        states_1 : begin
            if ( addr_h == 0 ) begin
                rgb_data = black;
            end
            else if ( addr_h >0 && addr_h <81 ) begin
                rgb_data = red;
            end
            else if ( addr_h >80 && addr_h <161 ) begin
                rgb_data = orange;
            end
            else if ( addr_h >160 && addr_h <241 ) begin
                rgb_data = yellow;
            end
            else if ( addr_h >240 && addr_h <321 ) begin
                rgb_data = green;
            end
            else if ( addr_h >320 && addr_h <401 ) begin
                rgb_data = blue;
            end
            else if ( addr_h >400 && addr_h <481 ) begin
                rgb_data = indigo;
            end
            else if ( addr_h >480 && addr_h <561 ) begin
                rgb_data = purple;
            end
            else if ( addr_h >560 && addr_h <641 ) begin
                rgb_data = white;
            end
            else begin
                rgb_data = black;
            end
            
        end
        states_2 : begin
            if ( flag_enable_out1 ) begin
                rgb_data = char_line[ addr_v-208 ][ 532 - addr_h ]? white:black;
            end
            else begin
                rgb_data = black;
            end
        end
        states_3 : begin
            if ( flag_enable_out2 ) begin
                rgb_data = rom_data;
            end
            else begin
                rgb_data = black;
            end
            
        end
        default: begin
            case ( addr_h )
                0 : rgb_data      = black;
                1 : rgb_data      = red;
                81 : rgb_data     = orange;
                161: rgb_data     = yellow;
                241: rgb_data     = green;
                321: rgb_data     = blue;
                401: rgb_data     = indigo;
                481: rgb_data     = purple;
                561: rgb_data     = white;
                default: rgb_data = rgb_data;
            endcase
        end
    endcase
end

assign flag_enable_out1 = states_current == states_2 && addr_h > 148 && addr_h < 533 && addr_v > 208  && addr_v < 273 ;
assign flag_begin_h     = addr_h > ( ( 640 - width ) / 2 ) && addr_h < ( ( 640 - width ) / 2 ) + width + 1;
assign flag_begin_v     = addr_v > ( ( 480 - height )/2 ) && addr_v <( ( 480 - height )/2 ) + height + 1;
assign flag_enable_out2 = states_current == states_3 && flag_begin_h && flag_begin_v;

//ROM地址计数器
always @( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        rom_address <= 0;
    end
    else if ( flag_clear_rom_address ) begin //计数满清零
        rom_address <= 0;
    end
    else if ( flag_enable_out2 ) begin  //在有效区域内+1
        rom_address <= rom_address + 1;
    end
    else begin  //无效区域保持
        rom_address <= rom_address;
    end
end
assign flag_clear_rom_address = rom_address == height * width - 1 || states_current != states_3;

//初始化显示文字
always@( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        char_line[ 0 ]      = 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
        char_line[ 1 ]      = 384'h000000000000000000000000000000000000000800000000000200000000000000000010000000000000000E00000000;
        char_line[ 2 ]      = 384'h00038000000000000000001C000000000000000F800000000003E000000000000000001F000000000000000F80000000;
        char_line[ 3 ]      = 384'h0003F0000000400000C0003E000000000000001F000000000003C0000000E0000070003C000000000000001E00000000;
        char_line[ 4 ]      = 384'h0003C01FFFFFF0000078003C000000000000003E000000000003C00FFFFFF800003C0078000006000000003C00000C00;
        char_line[ 5 ]      = 384'h0003C0040003E000001E007800000F000000007C00001E000003C0000007C000001E007FFFFFFF800000007800003F00;
        char_line[ 6 ]      = 384'h0003C000000F8000001E00FFFFFFFFC003FFFFFFFFFFFF800003C000001E0000000E00E00000000001FFFFFFFFFFFFC0;
        char_line[ 7 ]      = 384'h0003C000003C0000000E01E000000000008000F0000000000003C0C000780000000401C000000000000001E000000000;
        char_line[ 8 ]      = 384'h0003C1E000F000000000638000000000000001E0000000000FFFFFF001E000000000438000000000000003C000000000;
        char_line[ 9 ]      = 384'h07FFFFF803C000001800474000004000000003C0000000000003C000078000001C0046600000E0000000078000000000;
        char_line[ 10 ]     = 384'h0003C0000F0000000E008C7FFFFFF00000000F00000000000003C0003E00000007808CFFFFFFF80000000F00C0000000;
        char_line[ 11 ]     = 384'h0003C0007C000000078098F00000E00000001E00F00000000007C000F800000003C1B0F04000E00000001E00F8000000;
        char_line[ 12 ]     = 384'h0007C001F000008003C120F06000E00000003C00F00000000007C003E00001C001C140E03800E00000007800F0000000;
        char_line[ 13 ]     = 384'h0007F007FFFFFFE001C300E01C01E00000007800F0000000000FFC0FFFFFFFF001C300E01E01E0000000F000F0000000;
        char_line[ 14 ]     = 384'h000FDE070781C1E0000201E00F01E0000001E000F0000000000FCF020703C1C0000601E00F01E0000003E000F0006000;
        char_line[ 15 ]     = 384'h001FCF800F03C1C0000601E00601C0000007C000F000F000001FC7C00E0783C0000601E00601C0C0000FFFFFFFFFF800;
        char_line[ 16 ]     = 384'h003FC3C01E0783C0000401C00001C1E0000FFFFFFFFFFC00003BC3C03C0F03C0000DFFFFFFFFFFF000078000F0000000;
        char_line[ 17 ]     = 384'h003BC1C0380F03C0000CFFFFFFFFFFF800030000F00000000073C1C0781E03C0000C43C00001C00000000000F0000000;
        char_line[ 18 ]     = 384'h0073C080701E0380001803C00001C00000000200F000000000E3C000E03C0380001803C06001C00000000380F0000000;
        char_line[ 19 ]     = 384'h00C3C001C03C0380003803803001C000000007C0F060000001C3C003C0780380003803803801C00000000FE0F0300000;
        char_line[ 20 ]     = 384'h0183C00780780380007003803C01C00000000FC0F01C00000303C00F00F00780007007801E01C00000001F00F00F0000;
        char_line[ 21 ]     = 384'h0303C01C01E0078039F007801E01C00000003E00F00780000603C03803C007801FF007001E03C00000007C00F003E000;
        char_line[ 22 ]     = 384'h0403C07003C0078007E007000C03C00000007800F001F0000803C0C00780078001E007000803C1800000F000F000FC00;
        char_line[ 23 ]     = 384'h1803C3800F00078001E00F000003C3C00001E000F0007E001003C6001E00070001E03FFFFFFFFFE00003C000F0003F00;
        char_line[ 24 ]     = 384'h0003C0003C00070001E01FFFFFFFFFF000078000F0001F800003C00078000F0001E00E0000038000000E0000F0000F80;
        char_line[ 25 ]     = 384'h0003C000F0000F0001E0040000038000001C0000F0000FC00003C001C0000F0001E000000003800000380000F00007C0;
        char_line[ 26 ]     = 384'h0003C00380000F0001E000000003800000600000F00003C00003C00F00001E0003E000000007800000C00000F00003C0;
        char_line[ 27 ]     = 384'h0003C01C00401E0003E000003E07800003800000F00001C00003C070007FFE0003E0000007FF800006000381F0000080;
        char_line[ 28 ]     = 384'h0003C0C0000FFC0003E0000001FF0000040001FFE00000000003C1000007FC0001E0000000FF00000000003FE0000000;
        char_line[ 29 ]     = 384'h0003C0000003F80000000000007E00000000001FE00000000003C0000001E00000000000003C000000000007C0000000;
        char_line[ 30 ]     = 384'h000380000001800000000000003000000000000780000000000200000000000000000000000000000000000200000000;
        char_line[ 31 ]     = 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
        

    end
end

//实例化ROM
rom	rom_inst (
.address ( rom_address ),
.clock ( vga_clk ),
.q ( rom_data )
);
endmodule // data_drive


5.3 按键消抖模块

module key_debounce(
	input 	wire	clk,
	input 	wire 	rst_n,
	input 	wire 	key,
	
	output 	reg 	flag,// 0抖动, 1抖动结束
	output 	reg	key_value//key抖动结束后的值
);

parameter MAX_NUM = 20'd1_000_000;

reg [19:0] delay_cnt;//1_000_000

reg key_reg;//key上一次的值

always @(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		key_reg <= 1;
		delay_cnt <= 0;
	end
	
	else begin
		key_reg <= key;
		//当key为1 key 为0 表示按下抖动,开始计时
		if(key_reg  != key  ) begin 
		   delay_cnt <= MAX_NUM ;
		end
		else begin
		    if(delay_cnt > 0)
				delay_cnt <= delay_cnt -1;
			else
				delay_cnt <= 0;
		end
	end
end


//当计时完成,获取key的值
always @(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		flag <= 0;
		key_value <= 1;
	end

	else begin
		
		// 计时完成 处于稳定状态,进行赋值
		if(delay_cnt == 1) begin
			flag <= 1;
			key_value <= key;
		end
		else begin
			flag <= 0;
			key_value <= key_value;
		end
	end
end

endmodule


5.4 顶层模块

module VGA (input			wire						clk,
                input			wire						rst_n,
                input			wire		[ 2:0 ]		    key,
                output			wire						vga_clk,
                output			wire						h_sync,
                output			wire						v_sync,
                output			wire		[ 4:0 ]			rgb_r,
                output			wire		[ 5:0 ]			rgb_g,
                output			wire		[ 4:0 ]			rgb_b,
                output			reg		    [ 3:0 ]			led);

reg			[ 27:0 ]			cnt			        ;
wire		[ 11:0 ]		    addr_h              ;
wire		[ 11:0 ]		    addr_v              ;
wire		[ 15:0 ]			rgb_data			;
wire		[ 2:0 ]			    key_flag			;
wire		[ 2:0 ]			    key_value			;

//vga模块
vga_dirve u_vga_dirve(
.clk      ( clk ),
.rst_n    ( rst_n ),
.rgb_data ( rgb_data ),
.vga_clk  ( vga_clk ),
.h_sync   ( h_sync ),
.v_sync   ( v_sync ),
.rgb_r    ( rgb_r ),
.rgb_g    ( rgb_g ),
.rgb_b    ( rgb_b ),
.addr_h   ( addr_h ),
.addr_v   ( addr_v )
);

//数据模块
data_drive u_data_drive(
.vga_clk ( vga_clk ),
.rst_n   ( rst_n ),
.addr_h  ( addr_h ),
.addr_v  ( addr_v ),
.key     ( {key_value[ 2 ] && key_flag[ 2 ], key_value[ 1 ] && key_flag[ 1 ], key_value[ 0 ] && key_flag[ 0 ] } ),
.rgb_data  ( rgb_data )
);


//按键消抖
key_debounce u_key_debounce0(
.clk   ( vga_clk ),
.rst_n ( rst_n ),
.key   ( key[ 0 ] ),
.flag  ( key_flag[ 0 ] ),
.key_value  ( key_value[ 0 ] )
);

key_debounce u_key_debounce1(
.clk   ( vga_clk ),
.rst_n ( rst_n ),
.key   ( key[ 1 ] ),
.flag  ( key_flag[ 1 ] ),
.key_value  ( key_value[ 1 ] )
);

key_debounce u_key_debounce2(
.clk   ( vga_clk ),
.rst_n ( rst_n ),
.key   ( key[ 2 ] ),
.flag  ( key_flag[ 2 ] ),
.key_value  ( key_value[ 2 ] )
);

// led
always @( posedge clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        cnt <= 0;
    end
    else if ( cnt == 50_000_000 - 1 ) begin
        cnt <= 0;
    end
    else begin
        cnt <= cnt + 1;
    end
end
always @( posedge clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        led <= 4'b0000;
    end
    else if ( cnt == 50_000_000 -1 )begin
        led <= ~led;
    end
    else begin
        led <= led;
    end
end
endmodule // vga_top



5.5 TCL绑定引脚代码

package require ::quartus::project

set_location_assignment PIN_E1 -to clk
set_location_assignment PIN_E15 -to rst_n
set_location_assignment PIN_C16 -to h_sync
set_location_assignment PIN_D15 -to v_sync

set_location_assignment PIN_E16 -to key[0]
set_location_assignment PIN_M16 -to key[1]
set_location_assignment PIN_M15 -to key[2]

set_location_assignment PIN_G15 -to led[0]
set_location_assignment PIN_F16 -to led[1]
set_location_assignment PIN_F15 -to led[2]
set_location_assignment PIN_D16 -to led[3]

set_location_assignment PIN_A14 -to rgb_b[4]
set_location_assignment PIN_B14 -to rgb_b[3]
set_location_assignment PIN_A15 -to rgb_b[2]
set_location_assignment PIN_B16 -to rgb_b[1]
set_location_assignment PIN_C15 -to rgb_b[0]


set_location_assignment PIN_A11 -to rgb_g[5]
set_location_assignment PIN_B11 -to rgb_g[4]
set_location_assignment PIN_A12 -to rgb_g[3]
set_location_assignment PIN_B12 -to rgb_g[2]
set_location_assignment PIN_A13 -to rgb_g[1]
set_location_assignment PIN_B13 -to rgb_g[0]

set_location_assignment PIN_C8 -to rgb_r[4]
set_location_assignment PIN_A9 -to rgb_r[3]
set_location_assignment PIN_B9 -to rgb_r[2]
set_location_assignment PIN_A10 -to rgb_r[1]
set_location_assignment PIN_B10 -to rgb_r[0]


6. 效果

在这里插入图片描述
在这里插入图片描述

7.总结

使用VGA显示,先弄清楚VAG显示原理,将显示屏看为N*M大小的一个坐标系,为每个坐标分配一个RGB三通道的值,也就是每个像素,行场信号扫描的速度很快,就能连成一副完整的图像。图片显示需要用到ROM来存储图片数据,在显示时,从ROM中取出数据赋给相应的RBG通道就能显示了。

8.参考文章

https://blog.csdn.net/qq_47281915/article/details/125134764

https://blog.csdn.net/qq_45659777/article/details/124834294

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/462581.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【react全家桶学习】react中函数组件和类式组件(超详/必看)

函数式组件定义及特点 定义&#xff08;核心就是一个函数&#xff0c;返回虚拟dom&#xff09;&#xff1a; import React from reactexport default function index() {return <div>index</div> }特点&#xff1a; 1、适用于【简单组件】的定义2、是一个函数&a…

macOS与Ubuntu困惑解答

homebrew&#xff08;报管理器&#xff09;、yaml、apt-get、apt是包管理工具&#xff1b; zsh、bash都是解释器&#xff0c;是shell语言的解释器&#xff0c;都是服务于shell语言的&#xff0c;它们之间的区别是&#xff0c;zsh能够很好的兼容bash&#xff0c;zsh更优雅&…

web端导航菜单系列

导航菜单属于导航中最常规的一种导航模式&#xff0c;它有2个显而易见的用途&#xff1a;帮助我们找到想要的任何东西和告诉我们现在身在何处。帮助用户在不同页面之间跳转找到目标功能。 导航作为网站或者平台的骨架&#xff0c;是产品设计中不容忽视的一环。结合自身对于导航…

java第一课

常用dos命令 第一个e&#xff1a;加上回车&#xff0c;直接切换到e盘目录 看e盘文件的文件夹 dir加回车 进入文件夹 cd 文件夹名称加回车 进入文件夹就是 cd加文件夹名称 cd 加一个文件夹的名称就是进入这个文件夹 回退就是cd.. (这样子是单级目录的回退) 进入很多个就是进入…

必备装机软件,软件推荐

https://www.den4b.com/download/renamer/installer?key9d97aa7096681c8342442f75e34f7d5a8b13551ee3283956323516c81b1fe91b 官网https://www.den4b.com/ 从不同的文件夹中选择文件并将它们添加到工作区域。 a、 更改添加文件夹按钮的默认行为(可选步骤) b、添加单独选择的文…

数据库基础篇 《14.视图》

数据库基础篇 《14.视图》 1. 常见的数据库对象 对象描述表(TABLE)表是存储数据的逻辑单元&#xff0c;以行和列的形式存在&#xff0c;列就是字段&#xff0c;行就是记录数据字典就是系统表&#xff0c;存放数据库相关信息的表。系统表的数据通常由数据库系统维护&#xff0…

Ubuntu运行.sh文件

一、运行.sh文件 &#xff08;1&#xff09;使用sh testsh执行 &#xff08;2&#xff09;使用bash testsh 执行 &#xff08;3&#xff09;使用点 执行 &#xff08;4&#xff09;使用source执行./sh 文件开头***的含义&#xff1a; #!/bin/sh     以下的代码由/…

Redis 的 Protected Mode 解读

官方配置文件自带的注释&#xff1a; Protected mode is a layer of security protection, in order to avoid that Redis instances left open on the internet are accessed and exploited.When protected mode is on and if:1) The server is not binding explicitly to a …

服务(第十四篇)lvs的高可用负载均衡

Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案&#xff0c;可以解决静态路由出现的单点故障问题。 在一个LVS服务集群中通常有主服务器&#xff08;MASTER&#xff09;和备份服务器&#xff08;BACKUP&#xff09;两种角色的服务器&#xff0c;但是对外表现为一个虚…

Qt连接MySql数据库(本地和远程数据库均可)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 三种方法方法一 略方法二 使用ODBC设置mysql为数据源库1. 添加ODBC数据源&#xff0c;在控制面板中找到管理工具&#xff0c;其中有ODBC数据源 64位的&#xff0c;打…

美颜sdk与人脸识别技术的结合:为智能化时代注入美感

在当今的智能化时代&#xff0c;人脸识别技术已经成为了很多应用的核心。而在这些应用中&#xff0c;美颜功能也逐渐成为了用户所追求的重要特性之一。因此&#xff0c;美颜sdk的出现和发展&#xff0c;为人脸识别技术注入了更多的美感。 一、定义和作用 美颜sdk可以对人脸进…

Django框架之模板基本使用

本篇文章主要讲解Django 3.0框架配置模板路径&#xff0c;并使用视图和模板结合实现一些小功能。 概述 模板是html页面&#xff0c;可以根据视图中传递过来的数据进行填充。 在project中创建templates目录和应用模板目录 如templates/myapp 配置模板路径 修改settings.py文…

四数相加 II

给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l < n nums1[i] nums2[j] nums3[k] nums4[l] 0 来源&#xff1a;力扣&#xff08;LeetCode&#xff0…

Java 网络IO编程总结 nio netty原理 bio nio aio io多路复用 事件驱动 信号驱动 汇总总结

目录 ​编辑 io 多路复用 NIO 多线程 和 io多路复用区别 &#xff1a; Netty 操作流程 看了众多精简总结 Netty Bio Nio Aio Io多路复用 事件驱动 信号驱动 io 多路复用 I/O 多路复用模型是利用select、poll、epoll可以同时监察多个流的 I/O 事件的能力&#xff…

【备忘录设计模式详解】C/Java/JS/Go/Python/TS不同语言实现

简介 备忘录模式&#xff08;Memento Pattern&#xff09;是一种结构型设计模式。这种模式就是在不破坏封装的条件下&#xff0c;将一个对象的状态捕捉(Capture)住&#xff0c;并放在外部存储起来&#xff0c;从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录…

接口冒烟测试方法

接口冒烟测试方法 今年遇到了几个问题&#xff0c;与接口的功能和性能相关&#xff0c;恰巧最近公司也在组织以冒烟测试为主题的活动&#xff0c;于是乎突发奇想&#xff0c;寻思着能否将接口测试与冒烟测试结合起来&#xff0c;发掘一些新的接口测试思路与方法。 平时对接口…

SpringBoot创建与运行

文章目录 一、SpringBoot是什么&#xff1f;二、SpringBoot项目创建IDEA创建SpringBoot项目网页版创建SpringBoot项目项目目录介绍输出Hello SpringBoot 一、SpringBoot是什么&#xff1f; 如果我们说Spring的诞生是为了简化Java程序开发的&#xff0c;那么SpringBoot的诞生是为…

【三十天精通Vue 3】 第十八天 Vue 3的国际化详解

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: 三十天精通 Vue 3 文章目录 引言一、Vue 3 国际化概述1.1 国际化的概念1.2 国际化的作用1.3 V…

数据结构(数组、链表、栈、队列、树)

文章目录 1.数组1.1数组的特点1.2自定义数组 2.链表2.1链表的特点2.2自定义链表2.2.1自定义单向链表2.2.2自定义双向链表 3.栈3.1栈的特点3.2 Stack使用举例3.3 自定义栈 4. 队列5. 树与二叉树5.1 树的理解5.2 二叉树的基本概念5.3 二叉树的遍历5.4 经典二叉树和红黑树5.5 二叉…

Jmeter基础之---jmeter基础概念

JMeter 介绍&#xff1a; 一个非常优秀的开源的性能测试工具。 优点&#xff1a;你用着用着就会发现它的重多优点&#xff0c;当然不足点也会呈现出来。 从性能工具的原理划分&#xff1a; Jmeter工具和其他性能工具在原理上完全一致&#xff0c;工具包含4个部分&#xff1a…