当前位置:   article > 正文

基于FPGA的VGA显示彩条、字符、图片_vga显示字符

vga显示字符

一.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显示器,信号被直接送到相应的处理电路,驱动控制显像管生成图像。

二.时序图

在这里插入图片描述

三.实现过程

1.时钟分频设置

先在Quartus中创建一个工程文件,然后根据下图确定使用的时钟分频。

在这里插入图片描述
分别使用640×480 60HZ和800×600 72HZ,对应时钟分别为25M和50M,需要使用PLL进行分频 时钟频率 = 行帧长 × 列帧长 * 刷新率,640 ×480 60HZ对应时钟频率= 800 ×525 × 60 = 25.2M
ip核里面找到ALTPLL
在这里插入图片描述
基础时钟选择50M,设置如图
在这里插入图片描述
取消勾选输出使能,设置如图

在这里插入图片描述
c0默认输出50M即可,c1分频到25M,设置如图
在这里插入图片描述
勾选如下选项后finish
在这里插入图片描述

2.字符显示

字符工具:参考下载链接
在子模提取工具里面输入需要显示的字符并设置字符大小为64*64
在这里插入图片描述
然后点击文件-另存为,把图片保存为BMP图片
在这里插入图片描述
再点击文件-打开,把保存的BMP图片打开得到整体的字符

在这里插入图片描述
再点击选项按如下参数设置
在这里插入图片描述
最后点击生成字符并保存字符为txt文件
在这里插入图片描述最后得到字符如下
在这里插入图片描述

3.图片显示

由于一张640×480的24位的图片的大小超过了芯片的内存,无法把图片保存进去,故采用一张128*78的图片进行显示。
原图:
在这里插入图片描述
使用工具把图片转为HEX文件
在这里插入图片描述

转换完成得到data1.hex,内容如图
在这里插入图片描述
图片数据太多需要使用ROM来存储数据
打开quartus,找到ROM
在这里插入图片描述
设置位宽度为16位,大小为图片大小128×78 = 9984
在这里插入图片描述
取消勾选下列选项
在这里插入图片描述
找到刚才生成的data1.hex文件
在这里插入图片描述
勾选以下选项后直接finsh即可
在这里插入图片描述

4.彩条显示

根据当前行地址判断需要显示的颜色即可。

四.代码

基于EP4CEF17C8型号芯片

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


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188

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;

//初始化显示文字
always@( posedge vga_clk or negedge rst_n ) begin
    if ( !rst_n ) begin
        char_line[0 ]  = 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
        char_line[1 ]  = 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
        char_line[2 ]  = 384'h000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000;
        char_line[3 ]  = 384'h000000000000000000000007000000000000000000000000000040000000000000000001000000000000000000040000;
        char_line[4 ]  = 384'h00000000000001000000000F8000000000000000000004000000600001C0000000000001C000000000006000000F0000;
        char_line[5 ]  = 384'h00000000000003800000000FC000000000C0000000000E000000F80001F0000000000001F000000000007FFFFFFF8000;
        char_line[6 ]  = 384'h00000000000007C00000001FC000000000FFFFFFFFFFFF000000FC0001F8000000000001F800000000007FFFFFFF8000;
        char_line[7 ]  = 384'h0FFFFFFFFFFFFFE00000001F0000000000FFFFFFFFFFFF800000F80001F0000000000001E000000000007800000F0000;
        char_line[8 ]  = 384'h07FFFFFFFFFFFFF00000003F8000000000F0000000000F000000F00003E0000000000001E000000000007800000F0000;
        char_line[9 ]  = 384'h02000000F00000000000003EC000000000F0000300000F000000E00003E0000000000001E000000000007800000F0000;
        char_line[10 ] = 384'h00000001F00000000000007C6000000000F00003C0000F000000E00003C0000000000001E000000000007800000F0000;
        char_line[11 ] = 384'h00000001E0000000000000786000000000F00003F0000F000001C00003C0000000000001E000000000007800000F0000;
        char_line[12 ] = 384'h00000003E0000000000000F83000000000F00003E0000F00000180000780000000000001E000000000007800000F0000;
        char_line[13 ] = 384'h00000003C0000000000001F01800000000F00003C0000F00000180000700000000000001E000000000007800000F0000;
        char_line[14 ] = 384'h00000007C0000000000001E01C00000000F00003C0000F00000100200F00030000000001E000000000007FFFFFFF0000;
        char_line[15 ] = 384'h0000000780000000000003C00F00000000F00003C0000F0000C300700E00078000000001E000000000007FFFFFFF0000;
        char_line[16 ] = 384'h0000000F80000000000007800780000000F00003C0000F0000FFFFF80FFFFFC000000001E000000000007800000F0000;
        char_line[17 ] = 384'h0000000F8000000000000F8003C0000000F00003C0000F0000FFFFFC1FFFFFE000000001E000000000007800000F0000;
        char_line[18 ] = 384'h0000001F0000000000000F0001E0000000F00003C0040F0000E000F81C0007C000000001E000000000007800000F0000;
        char_line[19 ] = 384'h0000001F0000000000001E0000F8000000F00003C00E0F0000E000F03C00078000001001E000000000007800000F0000;
        char_line[20 ] = 384'h0000003FC000000000003C00007C000000F00003C01F0F0000E000F03800078000001801E040000000007800000F0000;
        char_line[21 ] = 384'h0000003FF000000000007800003F000000F3FFFFFFFF8F0000E000F07000078000003E01E060000000007800000F0000;
        char_line[22 ] = 384'h0000007FE00000000000F000001FC00000F1FFFFFFFFCF0000E000F07000078000003F01E030000000007800000F0000;
        char_line[23 ] = 384'h0000007BC00000000001E000004FF00000F0800FC0000F0000E000F0E000078000007E01E01C000000007FFFFFFF0000;
        char_line[24 ] = 384'h000000F3C0C000000003C00000E3FE0000F0001FC0000F0000E000F0C000078000007C01E00E000000007FFFFFFF0000;
        char_line[25 ] = 384'h000001F3C06000000007000001F1FFF000F0001FC0000F0000E000F18000078000007C01E007000000007A00000F0000;
        char_line[26 ] = 384'h000001E3C0380000000EFFFFFFF87FF800F0003FC0000F0000E000F3000007800000F801E007800000007B00000E0000;
        char_line[27 ] = 384'h000003C3C01C0000001C7FFFFFFC3FC000F0003FC0000F0000E000F3000007800000F001E003C000000047C000080000;
        char_line[28 ] = 384'h00000783C00E00000038200000000F8000F0003BC0000F0000E000F6180007800001F001E001E00000000FE000000000;
        char_line[29 ] = 384'h00000F83C007800000E000000000030000F0007BE0000F0000E000FC0C0007800001E001E000F00000000F8000000000;
        char_line[30 ] = 384'h00001F03C003C00001C000000000000000F00073F8000F0000E000F00E0007800003C001E000F80000001F0000000400;
        char_line[31 ] = 384'h00001E03C001F000030000000000000000F000F3DE000F0000E000F0070007800003C001E0007C0000001E0000000E00;
        char_line[32 ] = 384'h00003C03C000F8000C0000000000000000F001E3C7800F0000E000F00780070000078001E0003E0000003FFFFFFFFF00;
        char_line[33 ] = 384'h00007803C0007C00300000000000000000F001C3C3E00F0000FFFFF003C0070000070001E0003F0000007FFFFFFFFF80;
        char_line[34 ] = 384'h0000F003C0003E000000000000000C0000F003C3C1F80F0000FFFFF003C00700000F0001E0001F800000F80F00F01F00;
        char_line[35 ] = 384'h0001E003C0003F000000000000001E0000F00383C0FC0F0000E000F001E00700000E0001E0001FC00000F01F01E01E00;
        char_line[36 ] = 384'h0003C003C0001F800000000000003F0000F00703C07E0F0000E000F001E00700001C0001E0000FC00001E01E01E01E00;
        char_line[37 ] = 384'h00078003C0000FC003FFFFFFFFFFFF8000F00F03C03E0F0000E000F001E0070000380001E0000FC00003C03C01E01E00;
        char_line[38 ] = 384'h000F0003C00007C001FFFFFFFFFFFFC000F00E03C01F0F0000E000F001E0070000380001E00007E00007803C03C01C00;
        char_line[39 ] = 384'h001E0003C00007E000C000380000000000F01C03C01F0F0000E000F001E00F0000700001E00007E0000E007803C01C00;
        char_line[40 ] = 384'h00380003C00003E00000007E0000000000F03803C00F0F0000E000F000C00F0000E00001E00003E0001C00F007803C00;
        char_line[41 ] = 384'h00700003C00001E00000007F0000000000F07003C0070F0000E000F000800F0000C00001E00003E0003800F007803C00;
        char_line[42 ] = 384'h00E00003C00001E0000000FC0000000000F0E003C0060F0000E000F000000F0001800001E00001C000E001E00F003C00;
        char_line[43 ] = 384'h01800003C00000C0000000F80000000000F0C003C0020F0000E000F000000F0003000001E00001C0018003C00F003C00;
        char_line[44 ] = 384'h07000003C0000000000001F00000000000F18003C0000F0000E000F000000F0006000001E0000180000007801E003800;
        char_line[45 ] = 384'h0C000003C0000000000003E00400000000F20003C0000F0000E000F000000F000C000001E000000000000F003E003800;
        char_line[46 ] = 384'h08000003C0000000000003C00600000000FC0003C0000F0000E000F000000F0000000001E000000000001E003C007800;
        char_line[47 ] = 384'h00000003C0000000000007800380000000F00003C0000F0000E000F000000F0000000001E00000000000780078007800;
        char_line[48 ] = 384'h00000003C000000000000F0001E0000000F00003C0000F0000E000F000000F0000000001E00000000000F000F8007800;
        char_line[49 ] = 384'h00000003C000000000001E0000F0000000F00003C0000F0000E000F000000F0000000001E00000000003C001F0007800;
        char_line[50 ] = 384'h00000003C000000000001C00007C000000F00003C0000F0000E000F000000F0000000001E0000000000F0003E000F000;
        char_line[51 ] = 384'h00000003C000000000003800003E000000F00003C0000F0000E000F000000F0000000001E0000000003C0007C000F000;
        char_line[52 ] = 384'h00000003C000000000007000001F000000F0000300000F0000FFFFF000001E0000000001E000000000E0000F8000F000;
        char_line[53 ] = 384'h00000003C00000000000E000000FC00000F0000000000F0000FFFFF000001E0000000803C00000000000003E0001E000;
        char_line[54 ] = 384'h00000003C00000000001C0000007E00000F0000000000F0000E000F001F03E0000000FFFC00000000000007C0701E000;
        char_line[55 ] = 384'h00000003C0000000000780000FFFE00000FFFFFFFFFFFF0000E000F0007FFE00000003FFC0000000000001F001FFE000;
        char_line[56 ] = 384'h00000003C0000000001FFFFFFFFFF00000FFFFFFFFFFFF0000E000F0000FFC00000000FFC0000000000007C000FFC000;
        char_line[57 ] = 384'h00000003C0000000000FFFFFF801F00000F0000000000F0000E000E00007FC000000003F8000000000001F00003F8000;
        char_line[58 ] = 384'h00000003C0000000000FFFF00000F00000F0000000000F0000E000C00003F8000000001F0000000000007800001F0000;
        char_line[59 ] = 384'h00000003800000000007F8000000F00000F0000000000C00008000000001E0000000000E000000000001C000001E0000;
        char_line[60 ] = 384'h0000000200000000000700000000600000C0000000000000000000000000800000000008000000000006000000000000;
        char_line[61 ] = 384'h000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000;
        char_line[62 ] = 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
        char_line[63 ] = 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
    end
end

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


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

4.顶层模块

module vga_top (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


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

5.引脚
在这里插入图片描述

五.效果

图像
在这里插入图片描述
彩条
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/798466
推荐阅读
相关标签
  

闽ICP备14008679号