基于FPGA的VGA协议实现

文章目录

  • 一、VGA介绍
    • 1.1 VGA原理
    • 1.2VGA电路
  • 二、配置
  • 三、实现
    • 3.1 字符显示
    • 3.2图片显示
  • 四、代码
    • 4.1.vga驱动模块
    • 4.2数据模块
    • 4.3按键消抖模块
    • 4.4顶层模块
    • 4.5TCL引脚绑定
  • 参考

一、VGA介绍

1.1 VGA原理

VGA接口
在这里插入图片描述
最主要的几根线:
在这里插入图片描述
VGA其实就是相当于一块芯片,跟单片机驱动IC一样,满足一定的时序,便能驱动起来。VGA的扫描其实很简单,大致轨迹如下所示:
在这里插入图片描述
每扫描完一行,从新开始下一行;每扫完一场,重新开始下一场。
以下是行扫描,场扫描HS,VS时序图
在这里插入图片描述
VS时序如下所示:
在这里插入图片描述
可见时序的循环,可被划分为a,b,c,d4个时期。这四个时期定义如下:

A~B:场消隐期 即同步,相当于还原扫描坐标吧

B~C:场消隐后肩 相当于准备开始扫描吧

C~D:场显示期 扫描中,数据有效区域

D~E:场消隐前肩 完成扫描,相当于准备同步

HS时序深入分析
在这里插入图片描述
可见时序的循环,可被划分为a,b,c,d4个时期。这四个时期定义如下:

A~B:行消隐期 即同步,相当于还原扫描坐标吧

B~C:行消隐后肩 相当于准备开始扫描吧

C~D:行显示期 扫描中,数据有效区域

D~E:行消隐前肩 完成扫描,相当于准备同步

综上描述,我们只要知道每个时期的时间,便可以表示出VGA的时序。而FPGA的工作是由固定频率的时钟触发的,因此某固定时间可以用n次触发来表示。因此我们很容易就想到了FPGA常用的计数方法:比如说行扫描,我们计数0~H_total-1。用另一个进程将其划分为4个时期,安标注分配。其实这相当于状态机。

1.2VGA电路

VGA接口:R,G,B三通道,直接赋给数字信号,RGB,最多产生8种色彩。这是最基本的。电路如下所示:
在这里插入图片描述

二、配置

打开Quartus,选择IP核
在这里插入图片描述
命名之后,将基础时钟改为50M
在这里插入图片描述
点击next后,取消该勾选
在这里插入图片描述
默认next,直到该界面,c0默认输出50M即可,c1分频到25M,如需其他时钟频率可以自己进行设置在这里插入图片描述
勾选,finish
在这里插入图片描述

三、实现

3.1 字符显示

字模软件
百度网盘:
https://pan.baidu.com/s/1542q14FRzCawo8WNp8J-Kg
提取码: jdzg
在子模提取工具里面输入需要显示的字符并设置字符大小为64*64
在这里插入图片描述
然后点击文件-另存为,把图片保存为BMP图片,再点击文件-打开,把保存的BMP图片打开得到整体的字符。
在这里插入图片描述
参数设置
在这里插入图片描述
保存为.txt格式
在这里插入图片描述
在这里插入图片描述
将得到的字模替换。

3.2图片显示

想要显示的图片,但是图片的大小超过了芯片的内存,无法把图片保存进去,故采用一张100*100的图片进行显示。
在这里插入图片描述
使用工具把图片转为HEX文件

工具链接: https://pan.baidu.com/s/1o8ii9ei密码:62uv
在这里插入图片描述
图片数据太多需要使用ROM来存储数据
打开quartus,找到ROM
在这里插入图片描述
取消勾选下列选项
在这里插入图片描述
刚才生成的,hex
在这里插入图片描述
finish
在这里插入图片描述

四、代码

4.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时钟 25Moutput			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 ) beginif ( !rst_n ) begincnt_h <= 0;endelse if ( flag_enable_cnt_h ) beginif ( flag_clear_cnt_h ) begincnt_h <= 0;endelse begincnt_h <= cnt_h + 1;endendelse begincnt_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 ) beginif ( !rst_n ) beginh_sync <= 0;endelse if ( cnt_h == H_SYNC - 1 ) begin // 同步周期时为1h_sync <= 1;endelse if ( flag_clear_cnt_h ) begin // 其余为0h_sync <= 0;endelse beginh_sync <= h_sync;end
end// 场计数
always @( posedge vga_clk or negedge rst_n ) beginif ( !rst_n ) begincnt_v <= 0;endelse if ( flag_enable_cnt_v ) beginif ( flag_clear_cnt_v ) begincnt_v <= 0;endelse if ( flag_add_cnt_v ) begincnt_v <= cnt_v + 1;endelse begincnt_v <= cnt_v;endendelse begincnt_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 ) beginif ( !rst_n ) beginv_sync <= 0;endelse if ( cnt_v == V_SYNC - 1 ) beginv_sync <= 1;endelse if ( flag_clear_cnt_v ) beginv_sync <= 0;endelse beginv_sync <= v_sync;end
end// 对应有效区域行地址 1-640
always @( posedge vga_clk or negedge rst_n ) beginif ( !rst_n ) beginaddr_h <= 0;endelse if ( valid_area ) beginaddr_h <= cnt_h - H_SYNC - H_BLACK + 1;endelse beginaddr_h <= 0;end
end
// 对应有效区域列地址 1-480
always @( posedge vga_clk or negedge rst_n ) beginif ( !rst_n ) beginaddr_v <= 0;endelse if ( valid_area ) beginaddr_v <= cnt_v -V_SYNC - V_BLACK + 1;endelse beginaddr_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 ) beginif ( !rst_n ) beginrgb <= 16'h0;endelse if ( valid_area ) beginrgb <= rgb_data;endelse beginrgb <= 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

4.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[ 89: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 ) beginif ( !rst_n ) beginstates_current <= states_1;endelse beginstates_current <= states_next;end
end//状态判断
always @( posedge vga_clk or negedge rst_n ) beginif ( !rst_n ) beginstates_next <= states_1;endelse if ( key[ 0 ] ) beginstates_next <= states_1;endelse if ( key[ 1 ] ) beginstates_next <= states_2;endelse if ( key[ 2 ] ) beginstates_next <= states_3;endelse beginstates_next <= states_next;end
end//状态输出
always @( * ) begincase ( states_current )states_1 : beginif ( addr_h == 0 ) beginrgb_data = black;endelse if ( addr_h >0 && addr_h <81 ) beginrgb_data = red;endelse if ( addr_h >80 && addr_h <161 ) beginrgb_data = orange;endelse if ( addr_h >160 && addr_h <241 ) beginrgb_data = yellow;endelse if ( addr_h >240 && addr_h <321 ) beginrgb_data = green;endelse if ( addr_h >320 && addr_h <401 ) beginrgb_data = blue;endelse if ( addr_h >400 && addr_h <481 ) beginrgb_data = indigo;endelse if ( addr_h >480 && addr_h <561 ) beginrgb_data = purple;endelse if ( addr_h >560 && addr_h <641 ) beginrgb_data = white;endelse beginrgb_data = black;endendstates_2 : beginif ( flag_enable_out1 ) beginrgb_data = char_line[ addr_v-208 ][ 532 - addr_h ]? white:black;endelse beginrgb_data = black;endendstates_3 : beginif ( flag_enable_out2 ) beginrgb_data = rom_data;endelse beginrgb_data = black;endenddefault: begincase ( 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;endcaseendendcase
endassign 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 ) beginif ( !rst_n ) beginrom_address <= 0;endelse if ( flag_clear_rom_address ) begin //计数满清零rom_address <= 0;endelse if ( flag_enable_out2 ) begin  //在有效区域内+1rom_address <= rom_address + 1;endelse 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 ) beginif ( !rst_n ) beginchar_line[0]=  384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;char_line[1]=  384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;char_line[2]=  384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;char_line[3]=  384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;char_line[4]=  384'h000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000;char_line[5]=  384'h0000000000000000000000000000000000000000000000000000000000000000000000000E0000000000000400000000;char_line[6]=  384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;char_line[7]=  384'h00000000000004000F8000000100000E0000080000000000000000000000000000000000000000000000000000000000;char_line[8]=  384'h00000000000000000000000000000000000000000000000003000E000F8000000180001F0C001C000000000000000000;char_line[9]=  384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003FFFF00;char_line[10]= 384'h0F00000001FFFFFF0FFFFF00000000000000000000000000000000000000000000000000000000000000000000000000;char_line[11]= 384'h0000000000000000000000000000000003FFFF001F00000001FFFFFF8FFFFF0000000000000000000000000000000000;char_line[12]= 384'h00000000000000000000000000000000000000000000000000000000000000000000000003C01E001E00000001E00F00;char_line[13]= 384'h0F001C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;char_line[14]= 384'h000000000000000003C01C001E00000001E00F000F001C00000000000000000000000000000000000000000000000000;char_line[15]= 384'h0000000000000000000000000000000000000000000000000000000003C03C003C00030001E00F000F001C0000000000;char_line[16]= 384'h0001FC00000FE000000FF000000040000007E00003FFFFF00007E0000001FC000007E00000000E00000FE00000004000;char_line[17]= 384'h03C038003C00078001E00F000F001C00000000000007FF00007FF800003FFE000000C000001FF80007FFFFF0001FF800;char_line[18]= 384'h0007FF00001FF80000000E00007FF8000000C00003C039FFFFFFFFC001E00F000F001C0000000000001E078000E07C00;char_line[19]= 384'h00F81F000001C000003C1E0007FFFFF0003C1E00001E0780003C1E0000001E0000E07C000001C00003C070FFFFFFFFE0;char_line[20]= 384'h01E00F000F001C0000000000003803C001801E0001E007800007C00000700F0007FFFFE000700F00003803C000700F00;char_line[21]= 384'h00003E0001801E000007C00003C070407800000001E00F080F001C0000000000007003E003000F0003C003C001FFC000;char_line[22]= 384'h00E0070007C000C000E00700007003E000E0070000003E0003000F0001FFC00003C060007000000001E30F1C0F001C00;char_line[23]= 384'h0000000000E003E003000780078001E001FFC00001E00380070000C001E0038000E003E001E0038000007E0003000780;char_line[24]= 384'h01FFC00003C0E000F000000001E3FFFE0F001C000000000001C003E007000780070001E00007C00003C003C006000180;char_line[25]= 384'h03C003C001C003E003C003C00000FE00070007800007C00003C0E000E000000001E3FFFE0F001C0000000000038003E0;char_line[26]= 384'h070007C0070000F00003C00003C001C00600018003C001C0038003E003C001C00000DE00070007C00003C00003C0C001;char_line[27]= 384'hE000000001E3C01C0F001C0000000000038001C0078003C00F0000F00003C000078001E00C000300078001E0038001C0;char_line[28]= 384'h078001E000019E00078003C00003C00003C0C001C0E0000001E3C01C0F001C000000000007000000078003C00F8000F0;char_line[29]= 384'h0003C000078000E00C000300078000E007000000078000E000039E00078003C00003C00003C18003C0F8000001E3C01C;char_line[30]= 384'h0FFFFC000000000007000000078003C00F8000F00003C000070000E00C000600070000E007000000070000E000031E00;char_line[31]= 384'h078003C00003C00003C1800380F8000001E3C01C0FFFFC000000000007000000030003C00FC000F00003C0000F0000F0;char_line[32]= 384'h000006000F0000F0070000000F0000F000071E00030003C00003C00003C1000380F0000001E3C01C0F001C0000000000;char_line[33]= 384'h0F000000000003C00FC000F00003C0000F0000F000000C000F0000F00F0000000F0000F000061E00000003C00003C000;char_line[34]= 384'h03C3000780F0000001E3C01C0F001C00000000000F000000000003C00FC000F00003C0000F0000F000001C000F0000F0;char_line[35]= 384'h0F0000000F0000F0000C1E00000003C00003C00003C1000700F0000001E3C01C0F001800000000000E00000000000780;char_line[36]= 384'h078001E00003C0000F000070000018000F0000700E0000000F000070001C1E00000007800003C00003C0800F00F00000;char_line[37]= 384'h01E3C01C0F000000000000000E00000000000780000001E00003C0001E000078000038001E0000780E0000001E000078;char_line[38]= 384'h00181E00000007800003C00003C0C00E00F0000001E3FFFC0F000000000000000E03F80000000F00000001E00003C000;char_line[39]= 384'h1E000078000038001E0000780E03F8001E00007800301E0000000F000003C00003C0601E00F0010001E3FFFC0F000000;char_line[40]= 384'h000000001E0FFF0000000E00000003C00003C0001E000078000030001E0000781E0FFF001E00007800701E0000000E00;char_line[41]= 384'h0003C00003C0301C00F0030001E3CF1C0F000000000000001E3FFF8000003C00000003C00003C0001E00007800007000;char_line[42]= 384'h1E0000781E3FFF801E00007800601E0000003C000003C00003C0383C00F0078001E38F180F0001803FFFFFFC1E7C0FC0;char_line[43]= 384'h0000F800000007800003C0001E000078000070001E0000781E7C0FC01E00007800C01E000000F8000003C00003C01C7F;char_line[44]= 384'hFFFFFFC001E20F000F0001803FFFFFFC1EF003E0000FE00000000F000003C0001E0000780000E0001E0000781EF003E0;char_line[45]= 384'h1E00007801C01E00000FE0000003C00003C01CFFFFFFFFE001E00F000F000180000000001EE001E0000FF80000000E00;char_line[46]= 384'h0003C0001E0000780000E0001E0000781EE001E01E00007801801E00000FF8000003C00003C01E7800F0000001E00F00;char_line[47]= 384'h0F000180000000001FC001F000007C0000001C000003C0001E0000780001E0001E0000781FC001F01E00007803001E00;char_line[48]= 384'h00007C000003C00003C00E3000F0000001E00F000F000180000000001F8000F000000F00000038000003C0001E000078;char_line[49]= 384'h0001C0001E0000781F8000F01E00007803001E0000000F000003C00003C00E0000F0000001E00F000F00018000000000;char_line[50]= 384'h1F0000F000000780000070000003C0001E0000780003C0001E0000781F0000F01E00007806001E00000007800003C000;char_line[51]= 384'h03C00E0000F0000001E00F000F000180000000001F000078000003C00000E0000003C0001E0000780003C0001E000078;char_line[52]= 384'h1F0000781E0000780E001E00000003C00003C00003C00F0080F0000001E00F000F0001C0000000001E000078000001C0;char_line[53]= 384'h0001C0000003C0001E000078000380001E0000781E0000781E0000780C001E00000001C00003C00003C00F01E0F00000;char_line[54]= 384'h01E00F030F8003E0000000001E000078000001E0000380000003C0001E000078000780001E0000781E0000781E000078;char_line[55]= 384'h18001E00000001E00003C00003C00F01F0F1000001E00F0787FFFFE0000000001E000078000000E0000700000003C000;char_line[56]= 384'h1E000078000780001E0000781E0000781E00007838001E00000000E00003C00003C00E03F8F0C00003FFFFFFC7FFFFE0;char_line[57]= 384'h000000001E000078000000F0000E00000003C0000F000070000780000F0000701E0000780F0000703FFFFFFC000000F0;char_line[58]= 384'h0003C00003E01E03E0F0600001FFFFFFE1FFFF80000000001E000078000000F0001C00000003C0000F0000F0000F8000;char_line[59]= 384'h0F0000F01E0000780F0000F03FFFFFFC000000F00003C00003DFFE07C0F0380000C0000000000000000000000E000078;char_line[60]= 384'h000000F0003800000003C0000F0000F0000F80000F0000F00E0000780F0000F000001E00000000F00003C00003C7FC07;char_line[61]= 384'h80F01C000000000000000000000000000F000078038000F0007000000003C0000F0000F0000F80000F0000F00F000078;char_line[62]= 384'h0F0000F000001E00038000F00003C00003C3F80F00F00E000000000000000000000000000F00007807C000F000E00030;char_line[63]= 384'h0003C000070000E0000F8000070000E00F000078070000E000001E0007C000F00003C00003C1F01E00F00F8000000000;char_line[64]= 384'h00000000000000000F0000700FC000F001C000300003C000078001E0000F8000078001E00F000070078001E000001E00;char_line[65]= 384'h0FC000F00003C00003C0C01E00F007C0000000002000C00000000000070000F00FC000F0038000300003C000078001E0;char_line[66]= 384'h001F8000078001E0070000F0078001E000001E000FC000F00003C00003C0003C00F003C000180C003000700000000000;char_line[67]= 384'h078000F00FC001E0078000300003C00003C001C0001F800003C001C0078000F003C001C000001E000FC001E00003C000;char_line[68]= 384'h03C0007800F003E0001806001C0038000000000003C000E00F8001E0070000600003C00003C003C0001F800003C003C0;char_line[69]= 384'h03C000E003C003C000001E000F8001E00003C00003C000F000F001E0001807000E003C000000000003C001E0078003C0;char_line[70]= 384'h0E0000E00003C00001E00380001F800001E0038003C001E001E0038000001E00078003C00003C00003C000E000F001F0;char_line[71]= 384'h003803800F001E000000000001E001C0078003801C0001E00003C00000E00700001F800000E0070001E001C000E00700;char_line[72]= 384'h00001E00078003800003C00003C001C000F000F0003803C007801F000000000000F0038003C007001FFFFFE00007E000;char_line[73]= 384'h00700F00001F800000700F0000F0038000700F0000001E0003C007000007E00003C0038000F000E0007803E007800F00;char_line[74]= 384'h00000000007C0F0001F01E001FFFFFE0000FF000003C1E00001F8000003C1E00007C0F00003C1E0000003F0001F01E00;char_line[75]= 384'h000FF00003C0070000F0006000F001E007C00F8000000000003FFE00007FFC001FFFFFE001FFFF80001FF800001F8000;char_line[76]= 384'h001FF800003FFE00001FF800000FFFF8007FFC0001FFFF8003C00C0000F0000000F001E003C00F80000000000007F000;char_line[77]= 384'h001FE0001FFFFFE001FFFF800007E000000F00000007E0000007F0000007E000000FFFF8001FE00001FFFF8003C01801;char_line[78]= 384'hF0F0000001F001E003C00780000000000000000000000000000000000000000000000000000000000000000000000000;char_line[79]= 384'h0000000000000000000000000000000003C020007FF0000007E001E00380078000000000000000000000000000000000;char_line[80]= 384'h00000000000000000000000000000000000000000000000000000000000000000000000003C000001FE0000007E000C0;char_line[81]= 384'h030007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;char_line[82]= 384'h000000000000000003C0000007E000000380008000000200000000000000000000000000000000000000000000000000;char_line[83]= 384'h0000000000000000000000000000000000000000000000000000000003C0000003C00000000000000000000000000000;char_line[84]= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;char_line[85]= 384'h038000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000;char_line[86]= 384'h000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000;char_line[87]= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;char_line[88]= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;char_line[89]= 384'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;end
end//实例化ROM
rom	rom_inst (
.address ( rom_address ),
.clock ( vga_clk ),
.q ( rom_data )
);
endmodule // data_drive

4.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_000reg key_reg;//key上一次的值always @(posedge clk or negedge rst_n) beginif(!rst_n) beginkey_reg <= 1;delay_cnt <= 0;endelse beginkey_reg <= key;//当key为1 key 为0 表示按下抖动,开始计时if(key_reg  != key  ) begin delay_cnt <= MAX_NUM ;endelse beginif(delay_cnt > 0)delay_cnt <= delay_cnt -1;elsedelay_cnt <= 0;endend
end//当计时完成,获取key的值
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginflag <= 0;key_value <= 1;endelse begin// 计时完成 处于稳定状态,进行赋值if(delay_cnt == 1) beginflag <= 1;key_value <= key;endelse beginflag <= 0;key_value <= key_value;endend
endendmodule

4.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 ) beginif ( !rst_n ) begincnt <= 0;endelse if ( cnt == 50_000_000 - 1 ) begincnt <= 0;endelse begincnt <= cnt + 1;end
end
always @( posedge clk or negedge rst_n ) beginif ( !rst_n ) beginled <= 4'b0000;endelse if ( cnt == 50_000_000 -1 )beginled <= ~led;endelse beginled <= led;end
end
endmodule // vga_top

4.5TCL引脚绑定

package require ::quartus::projectset_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_syncset_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]

参考

``

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

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

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

相关文章

gcc g++不同版本切换命令

sudo update-alternatives --config g sudo update-alternatives --config gcc ubuntu20.04 切换 gcc/g 版本_ubuntu降低g版本-CSDN博客

YOLOv10尝鲜测试五分钟极简配置

最近清华大学团队又推出YOLOv10&#xff0c;真是好家伙了。 安装&#xff1a; pip install supervision githttps://github.com/THU-MIG/yolov10.git下载权重&#xff1a;https://github.com/THU-MIG/yolov10/releases/download/v1.0/yolov10n.pt 预测&#xff1a; from ult…

Superset,基于浏览器的开源BI工具

BI工具是数据分析的得力武器&#xff0c;目前市场上有很多BI软件&#xff0c;众所周知的有Tableau、PowerBI、Qlikview、帆软等&#xff0c;其中大部分是收费软件或者部分功能收费。这些工具一通百通&#xff0c;用好一个就够了&#xff0c;重要的是分析思维。 我一直用的Tabl…

【HMGD】STM32/GD32 CAN通信

各种通信协议速度分析 协议最高速度(btis/s)I2C400KCAN1MCAN-FD5M48510MSPI36M CAN协议图和通信帧 CubeMX CAN配置说明 CAN通信波特率 APB1频率 / 分频系数 /&#xff08;BS1 BS2 同步通信段&#xff09;* 1000 ​ 42 / 1 / (111) * 1000 ​ 14,000 KHz ​ 1400000…

吉林大学计科21级《软件工程》期末考试真题

文章目录 21级期末考试题一、单选题&#xff08;2分一个&#xff0c;十个题&#xff0c;一共20分&#xff09;二、问答题&#xff08;5分一个&#xff0c;六个题&#xff0c;一共30分&#xff09;三、分析题&#xff08;一个10分&#xff0c;一共2个&#xff0c;共20分&#xf…

【C语言】10.C语言指针(1)

文章目录 1.内存和地址1.1 内存1.2 究竟该如何理解编址 2.指针变量和地址2.1 取地址操作符&#xff08;&&#xff09;2.2 指针变量和解引⽤操作符&#xff08;*&#xff09;2.2.1 指针变量2.2.2 如何拆解指针类型2.2.3 解引⽤操作符 2.3 指针变量的⼤⼩ 3.指针变量类型的意…

汇编:字符串的输出

在16位汇编程序中&#xff0c;可以使用DOS中断21h的功能号09h来打印字符串&#xff1b;下面是一个简单的示例程序&#xff0c;演示了如何在16位汇编程序中打印字符串&#xff1a; assume cs:code,ds:data ​ data segmentszBuffer db 0dh,0ah,HelloWorld$ //定义字符串 data …

Flutter仿照微信实现九宫格头像

一、效果图 2、主要代码 import dart:io; import dart:math;import package:cached_network_image/cached_network_image.dart; import package:flutter/material.dart;class ImageGrid extends StatelessWidget {final List<String> imageUrls; // 假设这是你的图片URL…

关于Iterator 和ListIterator的详解

1.Iterator Iterator的定义如下&#xff1a; public interface Iterator<E> {} Iterator是一个接口&#xff0c;它是集合的迭代器。集合可以通过Iterator去遍历集合中的元素。Iterator提供的API接口如下&#xff1a; forEachRemaining(Consumer<? super E> act…

VS2022通过C++网络库Boost.Asio创建一个简单的同步TCP服务器和客户端

Boost.Asio是一个用于网络和异步编程的C库。它提供了一种跨平台的方式来处理网络编程和异步操作&#xff0c;使开发人员能够创建高性能的网络应用程序&#xff0c;asio几乎支持所有你能够想到的网络协议&#xff0c;比如tcp、udp、ip、http、icmp等&#xff0c;C通过asio库可以…

浅谈网络通信(1)

文章目录 一、认识一些网络基础概念1.1、ip地址1.2、端口号1.3、协议1.4、协议分层1.5、协议分层的2种方式1.5.1、OSI七层模型1.5.2、TCP/IP五层模型[!]1.5.2.1、TCP/IP五层协议各层的含义及功能 二、网络中数据传输的基本流程——封装、分用2.1、封装2.2、分用2.2.1、5元组 三…

python冰雹序列的探索与编程实现

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、冰雹序列的奥秘 二、编程实现冰雹序列 三、测试与验证 四、总结与展望 一、冰雹序列的…

openEuler 22.03 LTS SP3源码编译部署OpenStack-Caracal

openEuler 22.03 LTS SP3源码编译部署OpenStack-Caracal 说明机器详情安装操作系统注意事项基础准备Controller节点 && Compute节点 && Block节点关闭防火墙关闭selinux设置静态IP更新安装前准备Controller节点 && Compute节点 && Block节点设…

第十课,while循环

一&#xff0c;认识循环是什么 循环普遍存在于日常生活中&#xff0c;同样&#xff0c;在程序中&#xff0c;循环功能也是至关重要的基础功能。 当程序需要重复执行某一段代码&#xff0c;利用循环可以轻松完成工作 例如我要你打印100次上课&#xff0c;直接写100次print&…

python调用阿里云通义千问(q-wen-max)API-只能总结pdf文档内容

文章目录 通义千问插件PDF解析插件调用案例通义千问插件 Dashscope插件功能能够使得大模型的生成内容与外部三方应用结合,使得模型生成的内容更加准确和丰富,模型将拥有更好的生成能力。您也可以通过开发自定义插件,来使得模型生成更符合您预期的结果。 使用插件功能,大模…

电子阅览室在管理时需注意什么

关于如今的绝大多数人来说&#xff0c;想必都听说过“电子阅览室”这一概念。它首要运用在校园中&#xff0c;给学生们供给愈加丰厚的常识储藏。它也是一个独立的局域网&#xff0c;在校园网络中作为重要的一个组成部分而存在。但是&#xff0c;一个好的电子阅览室是需求满意运…

CCF20231201——仓库规划

CCF20231201——仓库规划 代码如下&#xff1a; #include<bits/stdc.h> using namespace std; int main() {int n,m,a[1001][11],b[1001]{0};cin>>n>>m;for(int i1;i<n;i){for(int j1;j<m;j)cin>>a[i][j];}for(int i1;i<n;i){bool foundfals…

设计模式在芯片验证中的应用——模板方法

一、模板方法 模板方法(Template Method)设计模式是一种行为设计模式&#xff0c; 它在父类中定义了一个功能的框架&#xff0c; 允许子类在不修改结构的情况下重写功能的特定步骤。也就是模板方法定义了一组有序执行的操作&#xff0c;将一些步骤的实现留给子类&#xff0c;同…

把自己的垃圾代码发布到官方中央仓库

参考博客&#xff1a;将组件发布到maven中央仓库-CSDN博客 感谢这位博主。但是他的步骤有漏缺&#xff0c;相对进行补充 访问管理页面 网址&#xff1a;Maven Central 新注册账号&#xff0c;或者使用github快捷登录&#xff0c;建议使用github快捷登录 添加命名空间 注意&…

【Linux】进程通信实战 —— 进程池项目

送给大家一句话: 没有一颗星&#xff0c;会因为追求梦想而受伤&#xff0c;当你真心渴望某样东西时&#xff0c;整个宇宙都会来帮忙。 – 保罗・戈埃罗 《牧羊少年奇幻之旅》 &#x1f3d5;️&#x1f3d5;️&#x1f3d5;️&#x1f3d5;️&#x1f3d5;️&#x1f3d5;️ &a…