【红色飓风Nano二代测评】VGA驱动
0赞经过这两天的摸索,以及做了以上几个测评,现在对Xilinx的开发流程基本了解了,现在就将我在QuartusII上面的一个VGA显示的工程移植过来,进一步的加深印象。
我在接触Xilinx开发的时候确实碰到了好多纠结的问题,归纳起来就是对这个东西的不熟悉。不过不要紧,闻道有先后,术业有专攻,学习是个快乐的过程。希望在今后的日子里和大家共同进步。
首先我们来看看什么是VGA时序,VGA显示接口的时序主要是需要考虑行同步信号(HSYNC),场同步信号(VSYNC),以及三个基本颜色信号(RGB)。VGA显示采用逐行扫描方式。扫描是从屏幕的左上方开始,从左到右,从上到下。每扫完一行,电子束回到左边下一行的开始位置,期间对电子束进行行消隐。并在每行结束时,用行同步信号对行进行同步,扫描完所有行后,再用场同步信号对场进行同步,并使电子束回到屏幕的左上方,同时对场进行消隐,并预备下一次扫描。该方法的关键是对时序的控制。至于VGA的时序图百度谷歌上面大把的,大家可以去了解下。
这个只是一个VGA驱动测试的模块,如果后续需要丰富功能,该模块可以发出一个读取FIFO信号,然后将RGB颜色线信号从FIFO中读出,FIFO这边再连接到DDR3上面,这样就可以将DDR3中的图片啊什么的显示出来了。显示器其实就是一个能够将ram中数据通过不同颜色显示出来的器件。昨天刚在网上买了一本怎么构建嵌入式系统的书,网上的资料讲的很杂,而且DDR3的IP核配置我这边还有点问题,等书一到,学习了这方面的知识我就试试更加复杂的功能,后续有时间的话再加上个摄像头玩玩。
module VGA ( input clk, //50MHz input rst_n, output hsync,//场同步扫描 output vsync,//行同步扫描 output ENAB, output OCLK, output RORL, output UORD, output[5:0] vga_r, output[5:0] vga_g, output[5:0] vga_b //显示颜色数据信号 ); reg clk_25M; always @ (posedge clk or negedge rst_n) begin if(!rst_n) begin clk_25M <= 1'b0; end else begin clk_25M <= !clk_25M; end end assign OCLK = clk_25M; assign RORL = 1'b1; assign UORD = 1'b0; //----------------------------------------- reg[9:0] x_cnt; //行坐标 reg[9:0] y_cnt; //列坐标 always @ (posedge clk_25M or negedge rst_n) if(!rst_n) x_cnt <= 10'd0; else if(x_cnt == 10'd799) x_cnt <= 10'd0; else x_cnt <= x_cnt + 1'b1; always @ (posedge clk_25M or negedge rst_n) if(!rst_n) y_cnt <= 10'd0; else if(y_cnt == 10'd525) y_cnt <= 10'd0; else if(x_cnt == 10'd799) y_cnt <= y_cnt + 1'b1; //-------------------------------------------- //场同步 行同步 reg hsync_r,vsync_r; always @ (posedge clk_25M or negedge rst_n) //场同步 if(!rst_n) hsync_r <= 1'b1; else if(x_cnt == 10'd0) hsync_r <= 1'b0; else if(x_cnt == 10'd96) hsync_r <= 1'b1; always @ (posedge clk_25M or negedge rst_n) //行同步 if(!rst_n) vsync_r <= 1'b1; else if(y_cnt == 10'd0) vsync_r <= 1'b0; else if(y_cnt == 10'd2) vsync_r <= 1'b1; assign hsync = hsync_r; assign vsync = vsync_r; //-------------------------------------------- //有效标志位的产生 reg valid_yr; always @ (posedge clk_25M or negedge rst_n) if(!rst_n) valid_yr <= 1'b0; else if(y_cnt == 10'd34) valid_yr <= 1'b1; else if(y_cnt == 10'd514) valid_yr <= 1'b0; //VGA有效显示区标志位 reg valid_r; always @ (posedge clk_25M or negedge rst_n) if(!rst_n) valid_r <= 1'b0; else if((x_cnt == 10'd45) && valid_yr) valid_r <= 1'b1; else if((x_cnt == 10'd685) && valid_yr)valid_r <= 1'b0; assign ENAB = valid_r; /*always @ (posedge clk_25M or negedge rst_n) if(!rst_n) VGA_FRAME_O <= 1'b0; else if((y_cnt < 10'd34)) VGA_FRAME_O <= 1'b1; else VGA_FRAME_O <= 1'b0;*/ reg[17:0] color; always @ (posedge clk_25M or negedge rst_n) begin if(!rst_n) begin color <= 18'd0; end else if((y_cnt >= 10'd34) && (y_cnt < 10'd194)) begin color <= 18'b111111_000000_000000; end else if((y_cnt >= 10'd194) && (y_cnt < 10'd354)) begin color <= 18'b000000_111111_000000; end else if((y_cnt >= 10'd354) && (y_cnt < 10'd514)) begin color <= 18'b000000_000000_111111; end end assign vga_r = color[17:12]; assign vga_g = color[11: 6]; assign vga_b = color[ 5: 0]; endmodule
这个软件写起来相对简单,主要是我这个并行的VGA屏连线比较麻烦,RGB六位颜色线,加上时钟、时能、行列扫描等。为了区分这些线还专门在线上贴了小标签。
效果如下图1所示
图1 VGA显示效果图
图2 VGA仿真图1
