前言:因为VGA是一种模拟图像传输数据接口,所要将数字信号用DAC转换成模拟量。本文用的一款ADI公司高精度的视频IC,实则一款高带宽的视频DAC。因为VGA时序较为简单,并且网上的VGA驱动基本大同小异。本文也没有什么特别创新之处。
注意点:(a)行扫描计数器和场扫描计数器需要与每个像素点、消隐数目想对应,这样才能得到正确的行列地址坐标。
参考资料:《VESA_VGA时序标准》、《ADV7123a》
源码1:逐行扫描的VGA控制器
1 `timescale 1 ns / 100 ps 2 `define RedWidth 10 3 `define GreenWidth 10 4 `define BlueWidth 10 5 `define VGA640x480x60Hz 6 module vga_pscan_ctrl( 7 sys_clk, 8 sys_rst_n, 9 vga_red_i, 10 vga_green_i, 11 vga_blue_i, 12 column_addr_o, 13 row_addr_o, 14 frame_flag_o, 15 video_valid_o, 16 //vga port 17 vga_red, 18 vga_green, 19 vga_blue, 20 vga_v_sync, 21 vga_h_sync, 22 //special port 23 vga_sync, 24 vga_blank, 25 vga_clk 26 ); 27 //macro 28 `ifdef VGA640x480x60Hz 29 `define ColumnWidth 10 30 `define RowWidth 9 31 `define H_SYNC 96 32 `define H_BACK_PORCH 48 33 `define H_VIDEO 640 34 `define H_FRONT_PORCH 16 35 `define H_TOTAL 800 36 `define H_BIAS 144 //`H_SYNC+`H_BACK_PORCH 37 `define V_SYNC 2 38 `define V_BACK_PORCH 33 39 `define V_VIDEO 480 40 `define V_FRONT_PORCH 10 41 `define V_TOTAL 525 42 `define V_BIAS 35 //V_SYNC+V_BACK_PORCH 43 `endif 44 input sys_clk; 45 input sys_rst_n; 46 input [`RedWidth-1:0] vga_red_i; 47 input [`GreenWidth-1:0] vga_green_i; 48 input [`BlueWidth-1:0] vga_blue_i; 49 output [`ColumnWidth-1:0] column_addr_o; //像素当前列地址 50 output [`RowWidth-1:0] row_addr_o; //像素当前行地址 51 output frame_flag_o; //帧结束 52 output video_valid_o; //数据有效 53 //vga port 54 output [`RedWidth-1:0] vga_red; 55 output [`GreenWidth-1:0] vga_green; 56 output [`BlueWidth-1:0] vga_blue; 57 output vga_v_sync; 58 output vga_h_sync; 59 //special port 60 output vga_blank; 61 output vga_sync; 62 output vga_clk; 63 //pix clk divider 64 reg pix_clk=1; 65 always @ (posedge sys_clk) begin 66 pix_clk <= ~pix_clk; 67 end 68 69 //horizion counter 70 reg [`ColumnWidth-1:0] h_cnt = 0; 71 always @ (posedge sys_clk) begin 72 if(sys_rst_n == 1'b0) h_cnt <= 0; 73 else if((pix_clk == 1'b1)&&(h_cnt < `H_TOTAL-1)) h_cnt <= h_cnt + 1'd1; 74 else if((pix_clk == 1'b1)&&(h_cnt == `H_TOTAL-1)) h_cnt <= 0; 75 else h_cnt <= h_cnt; 76 end 77 78 //vertical counter 79 reg [`RedWidth-1:0] v_cnt = 0; 80 always @ (posedge sys_clk) begin 81 if(1'b0 == sys_rst_n) v_cnt <= 0; 82 else if((pix_clk)&&(h_cnt == `H_TOTAL-1)&&(v_cnt < `V_TOTAL-1)) v_cnt <= v_cnt + 1'd1; 83 else if((pix_clk)&&(h_cnt == `H_TOTAL-1)&&(v_cnt == `V_TOTAL-1)) v_cnt <= 0; 84 else v_cnt <= v_cnt; 85 end 86 87 //generate the sync 88 assign vga_h_sync = (h_cnt > `H_SYNC-1)?1'b1:1'b0; 89 assign vga_v_sync = (v_cnt > `V_SYNC-1)?1'b1:1'b0; 90 91 //generate data valid 92 wire h_video_valid = ((h_cnt > `H_SYNC+`H_BACK_PORCH-1)&&(h_cnt < `H_TOTAL-`H_FRONT_PORCH))?1'b1:1'b0; 93 wire v_video_valid = ((v_cnt > `V_SYNC+`V_BACK_PORCH-1)&&(v_cnt < `V_TOTAL-`V_FRONT_PORCH))?1'b1:1'b0; 94 assign video_valid_o = (h_video_valid && v_video_valid)?1'b1:1'b0; 95 //generate frame_flag_o 96 assign frame_flag_o = ((v_cnt == `V_TOTAL-1)&&(h_cnt == `H_TOTAL-1))?1'b1:1'b0; 97 98 //generate vga_blank and vga_sync and vga_clk 99 assign vga_clk = pix_clk; 100 assign vga_sync = 1'b0; 101 assign vga_blank = vga_h_sync & vga_v_sync; 102 103 //generate column_addr_o and row_addr_o 104 reg [`ColumnWidth-1:0] column_addr_o=0; 105 reg [`RowWidth-1:0] row_addr_o=0; 106 always @ (posedge sys_clk) begin 107 if(sys_rst_n == 1'b0) begin 108 column_addr_o <= 0; 109 row_addr_o <= 0;end 110 else if(video_valid_o) begin 111 column_addr_o <= h_cnt - `H_BIAS; 112 row_addr_o <= v_cnt - `V_BIAS;end 113 else begin 114 column_addr_o <= column_addr_o; 115 row_addr_o <= row_addr_o;end 116 end 117 //generate RGB 118 assign vga_red = (video_valid_o)?vga_red_i:`RedWidth'd0; 119 assign vga_green = (video_valid_o)?vga_green_i:`GreenWidth'd0; 120 assign vga_blue = (video_valid_o)?vga_blue_i:`BlueWidth'd0; 121 122 endmodule
源码2:简单驱动
1 `timescale 1 ns / 100 ps 2 `define RedWidth 10 3 `define GreenWidth 10 4 `define BlueWidth 10 5 `define Offset1 0 6 `define Offset2 0 7 module vga_driver( 8 sys_clk, 9 sys_rst_n, 10 sys_en, 11 vga_red_o, 12 vga_green_o, 13 vga_blue_o 14 ); 15 input sys_clk; 16 input sys_rst_n; 17 input sys_en; 18 output [`RedWidth-1:0] vga_red_o; 19 output [`GreenWidth-1:0] vga_green_o; 20 output [`BlueWidth-1:0] vga_blue_o; 21 reg [`RedWidth-1:0] vga_red_o=0; 22 reg [`GreenWidth-1:0] vga_green_o=0; 23 reg [`BlueWidth-1:0] vga_blue_o=0; 24 25 //generate red vector 26 always @ (posedge sys_clk) begin 27 if(sys_rst_n == 1'b0) vga_red_o <= 0; 28 else if(sys_en) vga_red_o <= vga_red_o + 1'd1; 29 else vga_red_o <= vga_red_o; 30 end 31 32 //generate green vector 33 always @ (posedge sys_clk) begin 34 if(sys_rst_n == 1'b0) vga_green_o <= `Offset1; 35 else if(sys_en) vga_green_o <= vga_green_o + 1'd1; 36 else vga_green_o <= vga_green_o; 37 end 38 39 //generate blue vector 40 always @ (posedge sys_clk) begin 41 if(sys_rst_n == 1'b0) vga_blue_o <= `Offset2; 42 else if (sys_en) vga_blue_o <= vga_blue_o + 1'd1; 43 else vga_blue_o <= vga_blue_o; 44 end 45 46 endmodule
源码3:VGA相关模块的顶层例化
1 `timescale 1 ns / 100 ps 2 `define RedWidth 10 3 `define GreenWidth 10 4 `define BlueWidth 10 5 `define VGA640x480x60Hz 6 module vga( 7 sys_clk, 8 sys_rst_n, 9 //vga port 10 vga_red, 11 vga_blue, 12 vga_green, 13 vga_h_sync, 14 vga_v_sync, 15 //special port 16 vga_blank, 17 vga_sync, 18 vga_clk 19 ); 20 `ifdef VGA640x480x60Hz 21 `define ColumnWidth 10 22 `define RowWidth 9 23 `endif 24 input sys_clk; 25 input sys_rst_n; 26 //vga port 27 output [`RedWidth-1:0] vga_red; 28 output [`GreenWidth-1:0] vga_green; 29 output [`BlueWidth-1:0] vga_blue; 30 output vga_v_sync; 31 output vga_h_sync; 32 //special io 33 output vga_blank; 34 output vga_sync; 35 output vga_clk; 36 //wires 37 wire [`RedWidth-1:0] vga_red_w; 38 wire [`GreenWidth-1:0] vga_green_w; 39 wire [`BlueWidth-1:0] vga_blue_w; 40 wire [`ColumnWidth-1:0] column_addr_w; 41 wire [`RowWidth-1:0] row_addr_w; 42 wire frame_flag_w; 43 wire video_valid_w; 44 vga_driver inst_vga_driver( 45 .sys_clk(sys_clk), 46 .sys_rst_n(sys_rst_n), 47 .sys_en(video_valid_w), 48 .vga_red_o(vga_red_w), 49 .vga_green_o(vga_green_w), 50 .vga_blue_o(vga_blue_w) 51 ); 52 53 vga_pscan_ctrl inst_vga_pscan_ctrl( 54 .sys_clk(sys_clk), 55 .sys_rst_n(sys_rst_n), 56 .vga_red_i(vga_red_w), 57 .vga_green_i(vga_green_w), 58 .vga_blue_i(vga_blue_w), 59 .column_addr_o(column_addr_w), 60 .row_addr_o(row_addr_w), 61 .frame_flag_o(frame_flag_w), 62 .video_valid_o(video_valid_w), 63 //vga port 64 .vga_red(vga_red), 65 .vga_green(vga_green), 66 .vga_blue(vga_blue), 67 .vga_v_sync(vga_v_sync), 68 .vga_h_sync(vga_h_sync), 69 //special port 70 .vga_sync(vga_sync), 71 .vga_blank(vga_blank), 72 .vga_clk(vga_clk) 73 ); 74 75 endmodule
仿真文件:
1 `timescale 1 ns / 100 ps 2 `define RedWidth 10 3 `define GreenWidth 10 4 `define BlueWidth 10 5 module vga_tsb; 6 reg sys_clk; 7 reg sys_rst_n; 8 initial begin 9 sys_clk=1; 10 sys_rst_n=0; 11 #100 sys_rst_n=1; 12 end 13 always begin 14 #10 sys_clk=~sys_clk; 15 end 16 17 wire [`RedWidth-1:0] vga_red; 18 wire [`GreenWidth-1:0] vga_green; 19 wire [`BlueWidth-1:0] vga_blue; 20 wire vga_h_sync; 21 wire vga_v_sync; 22 vga inst_vga( 23 .sys_clk(sys_clk), 24 .sys_rst_n(sys_rst_n), 25 //vga port 26 .vga_red(vga_red), 27 .vga_blue(vga_blue), 28 .vga_green(vga_green), 29 .vga_h_sync(vga_h_sync), 30 .vga_v_sync(vga_v_sync), 31 .vga_blank(vga_blank), 32 .vga_sync(vga_sync) 33 ); 34 35 36 37 endmodule
仿真脚本文件:
1 vlib work 2 vmap work work 3 4 vlog -work work vga_pscan_ctrl.v 5 vlog -work work vga_driver.v 6 vlog -work work vga.v 7 vlog -work work vga_tsb.v 8 9 vsim -novopt -lib work vga_tsb 10 11 view wave 12 # signals in vga_driver 13 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_driver/vga_red_o 14 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_driver/vga_green_o 15 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_driver/vga_blue_o 16 add wave sim:/vga_tsb/inst_vga/inst_vga_driver/sys_en 17 18 # signals in vga_pscan_ctrl 19 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/vga_red_i 20 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/vga_green_i 21 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/vga_blue_i 22 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/column_addr_o 23 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/row_addr_o 24 add wave sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/frame_flag_o 25 add wave sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/video_valid_o 26 add wave sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/vga_sync 27 add wave sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/vga_blank 28 add wave sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/pix_clk 29 add wave sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/v_video_valid 30 add wave sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/vga_v_sync 31 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/v_cnt 32 add wave sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/vga_h_sync 33 add wave sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/h_video_valid 34 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/h_cnt 35 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/vga_red 36 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/vga_green 37 add wave -radix unsigned sim:/vga_tsb/inst_vga/inst_vga_pscan_ctrl/vga_blue 38 39 run 50ms