差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
屏幕保护系统设计 [2018/11/01 10:34]
anran [设计框图]
屏幕保护系统设计 [2021/08/18 09:04] (当前版本)
gongyusu
行 1: 行 1:
-=====屏幕保护系统设计===== +## 屏幕保护系统设计 
------ +### 实验任务
-====实验任务====+
  
   * 任务:基于 STEP-MAX10M08核心板 和 STEP BaseBoard V3.0底板 完成屏幕保护系统设计并观察调试结果   * 任务:基于 STEP-MAX10M08核心板 和 STEP BaseBoard V3.0底板 完成屏幕保护系统设计并观察调试结果
行 7: 行 6:
   * 解析:将小脚丫Logo取模得到128x128像素的图片数据,通过FPGA编程驱动VGA液晶显示器,实现现经典屏幕保护的界面效果。   * 解析:将小脚丫Logo取模得到128x128像素的图片数据,通过FPGA编程驱动VGA液晶显示器,实现现经典屏幕保护的界面效果。
  
-====实验目的====+### 实验目的
  
 在图片显示系统实验中我们学习过图片取模的方法,根据取模数据创建ram模块,本实验我们要学习VGA接口液晶显示器的驱动原理及方法,结合图片ram数据,最终实现屏幕保护系统的总体设计。VGA接口显示有固定的模式,本实验800x600@60Hz模式需要40MHz的时钟主频,可以按照简易电压表实验中的方法例化PLL的IP核实现。 在图片显示系统实验中我们学习过图片取模的方法,根据取模数据创建ram模块,本实验我们要学习VGA接口液晶显示器的驱动原理及方法,结合图片ram数据,最终实现屏幕保护系统的总体设计。VGA接口显示有固定的模式,本实验800x600@60Hz模式需要40MHz的时钟主频,可以按照简易电压表实验中的方法例化PLL的IP核实现。
行 14: 行 13:
   * 完成屏幕保护系统设计实现   * 完成屏幕保护系统设计实现
  
-====设计框图====+### 设计框图
  
 根据前面的实验解析我们可以得知,该设计总体可以拆分成如下功能模块实现, 根据前面的实验解析我们可以得知,该设计总体可以拆分成如下功能模块实现,
行 23: 行 22:
 {{:​13-Top-Down层次设计.png?​500|Top-Down层次设计}} {{:​13-模块结构设计.png?​500|模块结构设计}} {{:​13-Top-Down层次设计.png?​500|Top-Down层次设计}} {{:​13-模块结构设计.png?​500|模块结构设计}}
  
-====实验原理==== +### 实验原理
-===VGA接口介绍=== +
-===VGA模块硬件连接=== +
-===VGA模块驱动设计=== +
-===系统总体实现===+
  
 +#### VGA接口介绍
  
-====实验步====+VGA(Video Graphics Array)是IBM在1987年随PS/​2机一起推出的一种视频传输标准,具有分辨率高、显示速率快、颜色丰富等优点,在彩色显示器领域得到了广泛的应用,VGA接口定义如下: 
 + 
 +{{:​13-VGA接口.png?​500|VGA接口(左侧为公口,右侧为母口)}} 
 + 
 +VGA接口定义如下: 
 + 
 +{{:​13-VGA接口定义.png?​800|VGA接口定义}} 
 + 
 +一个标准的VGA接口硬件连接应该有以下端口: 
 +  * 红绿蓝三色信号(R\G\B) 
 +  * 行场同步信号(HS\VS) 
 + 
 +其中三色信号(R\G\B)都是模拟信号,行场同步信号(HS\VS)都是数字信号。 
 + 
 +对于VGA的接口模拟电压(R\G\B),为0~0.714V范围峰峰值,0代表无色,0.714代表满色,一些非标准的显示器使用的是1Vpp的满色电平。三基色信号源端和终端匹配电阻均为75欧姆,如下图所示: 
 + 
 +{{:​13-VGA三基色匹配电阻示意.png?​500|VGA三基色匹配电阻示意}} 
 + 
 +FPGA为数字逻辑器件,想要得到0~0.714V范围电压主要有两种方法,DAC转换方式和电阻分压方式,我们的扩展板卡上就是采用的电阻分压的方式,因VGA显示器端有75欧的下拉电阻,为了得到0.714V的电压我们给RGB信号线上串入270欧姆的电阻,3.3V*75/​(270+75)=0.717V。如下图所示: 
 + 
 +{{:​13-VGA电阻分压方式示意.png?​600|VGA电阻分压方式示意}} 
 + 
 +当FPGA驱动输出高电平(3.3V)时,模拟分压为0.714V,为满色,当FPGA驱动输出低电平(0V)时,模拟分压为0V,为无色,这样RGB三基色都对应两种状态输出,共有2^3=8种颜色输出。 
 + 
 +VGA 接口时序是对其实现驱动与控制的关键所在,也是难点所在。难不光难在时序的产生,更多的是在于处理速度上的问题。VGA扫描显示其实就是两条线,一个是行扫描,一个是场扫描,在行有效和场有效的时候把数据发送给VGA即可显示了。显示标准就是行分辨率x列分辨率@60hz即一秒屏幕刷新60次,以800×600@60Hz模式为例,即行为800个像素,场为600个像素。 
 + 
 +{{:13-VGA 800×600@60Hz模式示意.png?​600|VGA 800×600@60Hz模式示意}} 
 + 
 +显示器扫描一般采用逐行扫描的方式实现:逐行扫描是扫描从屏幕左上角一点开始,从左像右逐点扫描,每扫描完一行,​电子束回到屏幕的左边下一行的起始位置,在这期间,CRT对电子束进行消隐,行与行之间的返回过程称为水平消隐,也称行消隐(HBlank),每行结束时,用行同步信号进行同步;当扫描完所有的行,形成一帧,扫描点扫描完一帧后,要从图像的右下角返回到图像的左上角,开始新一帧的扫描,这一时间间隔,叫做垂直消隐,也称场消隐(VBlank),用场同步信号进行场同步。 
 + 
 +{{:​13-VGA行场消隐示意.png?​600|VGA行场消隐示意}} 
 + 
 +{{:​13-VGA扫描时序图.png?​800|VGA扫描时序图}} 
 + 
 +VGA显示常用模式列举如下: 
 + 
 +{{:​13-VGA显示模式.png?​600|VGA显示模式}} 
 + 
 +#### VGA模块硬件连接 
 + 
 +以下是STEP BaseBoard V3.0底板上的VGA模块电路,其电路图如下: 
 + 
 +{{:​13-VGA模块电路.png?​600|VGA模块电路}} 
 + 
 +底板上的VGA显示电路与1.8寸串行彩色液晶屏电路复用部分FPGA管脚,两者不能同时使用,当使用VGA接口模块电路时,FPGA直接驱动VGA接口完成VGA液晶显示器控制即可。VGA硬件采用电阻分压方式连接,每个基色智能显示无色或满色,所以显示效果最多有2^3=8种颜色显示(包含黑色)。 
 + 
 +#### VGA模块驱动设计 
 + 
 +端口列表中三基色控制管脚定义为vga[2:​0],高位到低位依次接红绿蓝,那么8中颜色对应的数据如下: 
 + 
 +<code verilog>​ 
 +output reg [2:0] vga;    // vga,​MSB~LSB ​{R,G,B} 
 +localparam ​ RED = 3'​b100,​ GREEN = 3'​b010,​ BLUE = 3'​b001;​ 
 +localparam ​ YELLOW = 3'​b110,​ CYAN = 3'​b011,​ PURPLE = 3'​b101;​ 
 +localparam ​ WHITE = 3'​b111,​ BLACK = 3'​b000;​ 
 +</​code>​ 
 + 
 +实验使用800x600@60Hz的VGA显示模式,首先将该VGA显示模式下的参数定义,在40MHz的主频下,参数如下: 
 + 
 +<WRAP group> 
 +<WRAP half column>​ 
 +|水平方向 | 
 +|同脉冲 Thp |后廊 Thb |有效线数 Thd |前廊 Thf | 
 +|128 |88 |800 |40 | 
 +</​WRAP>​ 
 +|垂直方向 | 
 +|同步脉冲 Thp |后廊 Thb |有效线数 Thd |前廊 Thf | 
 +|4 |23 |600 |1 | 
 +<WRAP half column>​ 
 +</​WRAP>​ 
 +</​WRAP>​ 
 + 
 +将参数定义,更改VGA显示模式时,只需要更改下面参数,参数定义如下: 
 + 
 +<code verilog>​ 
 +//-- Horizonal timing information 
 +`define HSYNC_A ​  ​16'​d128 ​  // 128 
 +`define HSYNC_B ​  ​16'​d216 ​  // 128 + 88 
 +`define HSYNC_C ​  ​16'​d1016 ​ // 128 + 88 + 800 
 +`define HSYNC_D ​  ​16'​d1056 ​ // 128 + 88 + 800 + 40 
 +//-- Vertical ​ timing information 
 +`define VSYNC_O ​  ​16'​d4 ​    // 4  
 +`define VSYNC_P ​  ​16'​d27 ​   // 4 + 23 
 +`define VSYNC_Q ​  ​16'​d627 ​  // 4 + 23 + 600 
 +`define VSYNC_R ​  ​16'​d628 ​  // 4 + 23 + 600 + 1 
 +</​code>​ 
 + 
 +根据VGA扫描的时序,在40MHz主频时钟下,每一行需要1056个主频时钟周期的时间,而每一帧需要628行扫描时间,我们定义两个计数器,分别对主频时钟和行扫描进行计数,程序实现如下: 
 + 
 +<code verilog>​ 
 +reg [15:0] x_cnt,​y_cnt;​ 
 +always @ (posedge clk or negedge rst_n) ​ // Count for HSYNC 
 +    if(!rst_n) x_cnt <16'​d1;​ 
 +    else if(x_cnt ​== `HSYNC_D) x_cnt <16'​d1;​ 
 +else x_cnt <= x_cnt + 1'​b1;​ 
 + 
 +always @ (posedge clk or negedge rst_n) // Count for VSYNC 
 +    if(!rst_n) y_cnt <= 16'​d1;​ 
 +    else if(x_cnt == `HSYNC_D) begin 
 +        if(y_cnt == `VSYNC_R) y_cnt <= 16'​d1;​ 
 +        else y_cnt <= y_cnt + 1'​b1;​ 
 +    end else y_cnt <= y_cnt; 
 +</​code>​ 
 + 
 +当行计数器x_cnt计数到1056且场计数器y_cnt计数到628时,就是VGA扫描一帧的时间,行计数和场计数开始的时候为同步信号,行场同步信号端口输出,根据时序要求程序实现如下: 
 + 
 +<code verilog>​ 
 +output ​ reg         ​sync_v; ​    // sync_v 
 +output ​ reg         ​sync_h; ​    // sync_h 
 + 
 +always @ (posedge clk or negedge rst_n) // HSYNC signal 
 +    if(!rst_n) sync_h <= 1'​b1;​ 
 +    else if(x_cnt <= `HSYNC_A) sync_h <= 1'​b0;​ 
 +    else sync_h <= 1'b1;  
 + 
 +always @ (posedge clk or negedge rst_n) // VSYNC signal 
 +    if(!rst_n) sync_v <= 1'​b1;​ 
 +    else if(y_cnt <= `VSYNC_O) sync_v <= 1'​b0;​ 
 +    else sync_v <= 1'​b1;​ 
 +</​code>​ 
 + 
 +行同步和场同步的信号有了,接下来就是三基色数据的控制了,如果整个扫描过程中三基色端口一直输出红色数据,那么我们就可以看到整个显示器显示红色,整个扫描过程分为消隐区和显示区,只有在显示区的数据才能显示出来,落在消隐区的颜色数据没有任何意义,显示区就是当行场计数器都在对应有效线数的区间。即是说,如果我们让三基色端口只在行计数器x_cnt计数在216~1056之间且场计数器y_cnt计数在27~627之间时输出红色数据,依然可以看到整个显示器显示红色。 
 + 
 +{{:​13-图片坐标轨迹区间.png?​600|图片坐标轨迹区间}} 
 + 
 +屏幕保护实验需要小脚丫Logo图片显示并反弹移动,图片显示在液晶显示器上我们需要知道图片所在显示区的坐标,图片宽度和高度已知,我们以图片左上角的像素点作为基点,就可以知道图片ram数据中每个数据对应的坐标,假设我们知道了图片基点的坐标为(x_set,y_set)。图片的显示程序实现如下: 
 + 
 +注:这里讲的坐标是是以行计数器x_cnt和场计数器y_cnt为基准的。 
 + 
 +<code verilog>​ 
 +`define P_WIDTH 8'​d128 ​ // 图片像素的水平宽度 
 +`define P_DEPTH 8'​d128 ​ // 图片像素的垂直高度 
 +always @ (posedge clk or negedge rst_n) // rom address 
 +    if(!rst_n) rom_addr <= 1'​b0;​ 
 +    else if((x_cnt>​=x_set)&​(x_cnt<​(x_set+`P_WIDTH))&​(y_cnt>​=y_set)&​(y_cnt<​(y_set+`P_DEPTH))) 
 +        rom_addr <= y_cnt - y_set; 
 +else rom_addr <= rom_addr; 
 + 
 +always @ (posedge clk or negedge rst_n) // rom data display 
 +    if(!rst_n) vga <= BLACK; 
 +    else if((x_cnt>​=x_set)&​(x_cnt<​(x_set+`P_WIDTH))&​(y_cnt>​=y_set)&​(y_cnt<​(y_set+`P_DEPTH))) 
 +        if(rom_data[x_cnt - x_set]) vga <= color; 
 +        else vga <= BLACK; 
 +    else vga <= BLACK; 
 +</​code>​ 
 + 
 +图片可能显示在屏幕的任何位置,那么基点(x_set,y_set)的移动轨迹范围为上图中红色虚线框区域,只要控制基点移动和反弹就可以实现图片的移动和反弹,这里需要考虑两个参数:移动速度和反弹方向。 
 + 
 +**<wrap hi>​移动速度</​wrap>​** 
 + 
 +移动速度就是基点(x_set,y_set)变化的速度,我们设置一个计数器延迟来控制基点的变化速度,cnt的计数周期为2^19 * 1000ms / 12000000 = 44ms,基点坐标每秒移动次数为1s / 44ms = 23次,计数程序实现如下: 
 + 
 +<code verilog>​ 
 +reg         ​[18:​0] ​ cnt; 
 +always @ (posedge clk or negedge rst_n) ​ // delay count 
 +    if(!rst_n) cnt <= 1'​b0;​ 
 +    else cnt <= cnt + 1'​b1;​ 
 +</​code>​ 
 + 
 +**<wrap hi>​反弹方向</​wrap>​** 
 + 
 +屏幕保护图片碰到显示器边沿会反弹,反弹效果同镜面反射一样,与边沿平行方向不变,垂直方向反向,所以行方向和场方向的反弹控制是相互独立的,实现方法相同,这里我们以行(水平)方向的控制为例,程序实现如下: 
 + 
 +<code verilog>​ 
 +always @ (posedge clk or negedge rst_n) //​水平方向反弹标志 
 +    if(!rst_n) x_flag <= 1'​b1;​ 
 +    else if(x_set == `HSYNC_B) x_flag <= 1'b1;  
 +    else if(x_set == (`HSYNC_C - `P_WIDTH)) x_flag <= 1'​b0;​ 
 +    else x_flag <= x_flag; 
 +     
 +always @ (posedge clk or negedge rst_n) //​根据水平方向反弹标志移动基点 
 +    if(!rst_n) x_set <= `HSYNC_B; 
 +    else if(!cnt) ​ //​控制基点行坐标x_set的变化速度 
 +        if(x_flag) x_set <= x_set + 1'b1; //​根据水平方向反弹标志移动基点  
 +        else x_set <= x_set - 1'​b1;​ 
 +    else x_set <= x_set; 
 +</​code>​ 
 + 
 +#### 系统总体实现 
 + 
 +例化pll IP核得到40MHz时钟信号,提供给VGA驱动模块做时钟信号,例化配置方法在简易电压表实验中有讲解,这里不再重复。 
 + 
 +屏幕保护图片数据的ram模块,提供小脚丫Logo图片数据,图片显示系统实验中也有相关内容,调整一下图像分辨率的宽度和高度就可以直接使用。 
 + 
 +综合后的设计框图如下: 
 + 
 +{{:​13-RTL设计框图.png?​800|RTL设计框图}} 
 + 
 +### 实验步骤
   - 双击打开Quartus Prime工具软件;   - 双击打开Quartus Prime工具软件;
   - 新建工程:File → New Project Wizard(工程命名,工程目录选择,设备型号选择,EDA工具选择);   - 新建工程:File → New Project Wizard(工程命名,工程目录选择,设备型号选择,EDA工具选择);
行 41: 行 225:
  
  
-====实验现象====+### 实验现象 
 + 
 +将程序加载到FPGA中,使用VGA线连接液晶显示器和FPGA底板,观察显示现象。小脚丫Logo图片在显示屏上移动,到达边沿后反弹,每次反弹都会颜色改变,共有6中颜色。 
 +