奉贤集团公司网站建设,小工具文本wordpress,桂林象鼻山的由来,怎么建网站做淘宝客文章目录 前言一、VGA接口定义与传输原理1、VGA接口定义2、传输原理3、不同分辨率对应不同参数 二、Verilog编程1、VGA显示彩色条纹2、VGA显示字符3、输出一幅彩色图像4、Quartus操作1、添加PLL核2、添加ROM核 三、全部代码四、总结五、参考资料 前言
VGA的全称是Video Graphi… 文章目录 前言一、VGA接口定义与传输原理1、VGA接口定义2、传输原理3、不同分辨率对应不同参数 二、Verilog编程1、VGA显示彩色条纹2、VGA显示字符3、输出一幅彩色图像4、Quartus操作1、添加PLL核2、添加ROM核 三、全部代码四、总结五、参考资料 前言
VGA的全称是Video Graphics Array,即视频图形阵列是一个使用模拟信号进行视频传输的标准。早期的 CRT显示器由于设计制造上的原因只能接收模拟信号输入因此计算机内部的显卡负责进行数模转换,而 VGA接口就是显卡上输出模拟信号的接口。如今液晶显示器虽然可以直接接收数字信号但是为了兼容显卡上 的VGA接口也大都支持VGA标准。
环境 1、Quartus 18.1 2、EP4CE115F29C7 3、vscode 一、VGA接口定义与传输原理
1、VGA接口定义 2、传输原理 从上面两幅图中我们可以看到VGA传输过程中的行同步时序和场同步时序非常类似一行或一场(又称一帧)数据都分为四个部分:低电平同步脉冲、显示后沿、有效数据段以及显示前沿。 行同步信号HSYNC在一个行扫描周期中完成一行图像的显示其中在a段维持一段时间的低电平用于 数据同 步其余时间拉高;在有效数据期间(c段) 红绿蓝三原色数据通道上输出一-行图像信号,其余时间数据无 效。与之类似场同步信号在在一个场扫描周期中完成一 帧图像的显示 不同的是行扫描周期的基本单位是像素点时钟即完成一个像素点显示所需要的时间;而场扫描周期的基本单位是完成一-行图像 显示所需要的时间。 3、不同分辨率对应不同参数 二、Verilog编程 1屏幕上显示彩色条纹 2显示自定义的汉字字符姓名-学号 3输出一幅彩色图像 4) 将行、场同步信号中故意分别加入一定 ms延时用delay命令观察会出现什么现象。 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 16h0;endelse if ( valid_area ) beginrgb rgb_data;endelse beginrgb 16b0;end
end
assign rgb_r rgb[ 15:11 ];
assign rgb_g rgb[ 10:5 ];
assign rgb_b rgb[ 4:0 ];endmodule // vga_dirve
效果
2、VGA显示字符
取字模 打开字模选项选择格式 注意这里的学号和名字分开取 注意这里的汉字取的是16x16的点阵数字取的是32x16的点阵。 代码
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 16d63488;
localparam orange 16d64384;
localparam yellow 16d65472;
localparam green 16d1024;
localparam blue 16d31;
localparam indigo 16d18448;
localparam purple 16d32784;
localparam white 16d65503;
localparam black 16d0;
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 ) 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 ] 256h0000010000000000000000000000000000000000000000000000000000000000;char_line[ 1 ] 256h1ff0210020000000000000000000000000000000000000000000000000000000;char_line[ 2 ] 256h101011dc17fc0000000000000000000000000000000000000000000000000000;char_line[ 3 ] 256h101011141040000018003c003c00180018007e001800180018003c003c000400;char_line[ 4 ] 256h1ff0811480400000240042004200240024004200240024002400420042000c00;char_line[ 5 ] 256h0000411440400000400042004200420042000400420040004200420042000c00;char_line[ 6 ] 256h000047d448400000400002004200420042000400420040004200420042001400;char_line[ 7 ] 256h3ff81014084000005c000400020042004200080042005c004200020002002400;char_line[ 8 ] 256h0100111410407e00620018000400420042000800420062004200040004002400;char_line[ 9 ] 256h0100211410400000420004000800420042001000420042004200080008004400;char_line[ 10 ] 256hfffee588e0400000420002001000420042001000420042004200100010007f00;char_line[ 11 ] 256h0280254820400000420042002000420042001000420042004200200020000400;char_line[ 12 ] 256h0440294820400000220042004200240024001000240022002400420042000400;char_line[ 13 ] 256h082021142ffe00001c003c007e0018001800100018001c0018007e007e001f00;char_line[ 14 ] 256h3018251420000000000000000000000000000000000000000000000000000000;char_line[ 15 ] 256hc006022200000000000000000000000000000000000000000000000000000000;end
end//实例化ROM
rom rom_inst (
.address ( rom_address ),
.clock ( vga_clk ),
.q ( rom_data )
);
endmodule // data_drive效果
3、输出一幅彩色图像 使用软件将图片进行转换 生成的hex文件 这里没能成功显示 4、Quartus操作 先是新建工程引入.V文件即可下面是添加两个IP核的操作一个用于时钟分频一个用于存储图片。 分别使用640×480 60HZ和800×600 72HZ,对应时钟分别为25M和50M,需要使用PLL进行分频 时钟频率 行帧长 × 列帧长 * 刷新率,640 ×480 60HZ对应时钟频率 800 ×525 × 60 25.2M。 1、添加PLL核 选择基础时钟 取消勾选输出使能 设置时钟clk0默认50M即可c1设为25M. 勾选下面的选项最后点击finish即可添加pll核
2、添加ROM核
搜索RO核 把宽度设为16位然后根据图片的大小填写160x15424640,根据自己的图片来填写。 取消下面的勾选 引入前面生成的hex文件 勾选下面选项然后点击finish:
三、全部代码
data_drive文件
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 16d63488;
localparam orange 16d64384;
localparam yellow 16d65472;
localparam green 16d1024;
localparam blue 16d31;
localparam indigo 16d18448;
localparam purple 16d32784;
localparam white 16d65503;
localparam black 16d0;
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 ) 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 ] 256h0000010000000000000000000000000000000000000000000000000000000000;char_line[ 1 ] 256h1ff0210020000000000000000000000000000000000000000000000000000000;char_line[ 2 ] 256h101011dc17fc0000000000000000000000000000000000000000000000000000;char_line[ 3 ] 256h101011141040000018003c003c00180018007e001800180018003c003c000400;char_line[ 4 ] 256h1ff0811480400000240042004200240024004200240024002400420042000c00;char_line[ 5 ] 256h0000411440400000400042004200420042000400420040004200420042000c00;char_line[ 6 ] 256h000047d448400000400002004200420042000400420040004200420042001400;char_line[ 7 ] 256h3ff81014084000005c000400020042004200080042005c004200020002002400;char_line[ 8 ] 256h0100111410407e00620018000400420042000800420062004200040004002400;char_line[ 9 ] 256h0100211410400000420004000800420042001000420042004200080008004400;char_line[ 10 ] 256hfffee588e0400000420002001000420042001000420042004200100010007f00;char_line[ 11 ] 256h0280254820400000420042002000420042001000420042004200200020000400;char_line[ 12 ] 256h0440294820400000220042004200240024001000240022002400420042000400;char_line[ 13 ] 256h082021142ffe00001c003c007e0018001800100018001c0018007e007e001f00;char_line[ 14 ] 256h3018251420000000000000000000000000000000000000000000000000000000;char_line[ 15 ] 256hc006022200000000000000000000000000000000000000000000000000000000;end
end//实例化ROM
rom rom_inst (
.address ( rom_address ),
.clock ( vga_clk ),
.q ( rom_data )
);
endmodule // data_drivekey_debounce文件
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 20d1_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
endendmodulevga_dirve文件
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 16h0;endelse if ( valid_area ) beginrgb rgb_data;endelse beginrgb 16b0;end
end
assign rgb_r rgb[ 15:11 ];
assign rgb_g rgb[ 10:5 ];
assign rgb_b rgb[ 4:0 ];endmodule // vga_dirvevga_top顶层文件
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 4b0000;endelse if ( cnt 50_000_000 -1 )beginled ~led;endelse beginled led;end
end
endmodule // vga_top四、总结
了解了VGA显示的原理其实就是为每个坐标分配一个RGB三通道的值就是每个像素场信号扫描得很快就能连成一幅图像。掌握了两种IP核的使用就是图片没能成功显示。
五、参考资料
https://blog.csdn.net/qq_45659777/article/details/124834294 https://blog.csdn.net/qq_47281915/article/details/125134764