差别

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

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
vga显示模块 [2017/07/03 16:38]
anran [硬件说明]
vga显示模块 [2017/09/06 11:08] (当前版本)
anran [硬件说明]
行 7: 行 7:
 ------- -------
 VGA(video graphics array)即视频图形阵列,是IBM在1987年随PS/​2一起推出的使用模拟信号的一种视频传输标准。VGA接口分公口和母口,如下图: VGA(video graphics array)即视频图形阵列,是IBM在1987年随PS/​2一起推出的使用模拟信号的一种视频传输标准。VGA接口分公口和母口,如下图:
-//+\\
 {{ :​vga接口.jpg?​400 |}} {{ :​vga接口.jpg?​400 |}}
-//+\\
 VGA接口引脚定义如下: VGA接口引脚定义如下:
-//+\\
 {{ :​vga接口定义.jpg?​800 |}} {{ :​vga接口定义.jpg?​800 |}}
-//+\\ 
 +一个标准的VGA接口应该有以下端口: 
 +\\ 
 +  * 红绿蓝三色信号(R\G\B) 
 +  * 行场同步信号(HS\VS) 
 +  * 以及很多的地屏蔽; 
 +三色信号都是模拟信号,行场同步信号都是数字信号; 
 +\\
 对于VGA的接口模拟电压,为0~0.714V,0代表无色,0.714代表满色,FPGA输出3.3V,所以还必须要经过DAC的转换。现今有两种比较成熟的方法:电阻分压方式和DAC转换方式。 对于VGA的接口模拟电压,为0~0.714V,0代表无色,0.714代表满色,FPGA输出3.3V,所以还必须要经过DAC的转换。现今有两种比较成熟的方法:电阻分压方式和DAC转换方式。
-// 
-我们的底板上就是采用的电阻分压的方式 
-// 
-// 
-// 
-// 
-// 
-// 
-// 
-// 
-// 
-// 
- 
- 
-PCF8591是集成了4路ADC和1路DAC的芯片,使用I2C总线通信。 
 \\ \\
-I2C总线是由Philips公司开发一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线的器件之间传送信息。主器件于启动总线传送数据,并产生时钟以开放传送器件,此时任何被寻址器件均被认为是从器件。如果主机要发送数据给从器件则主机首先寻址从件,然后主动发送数据至从器件,最后由主机终止数据传送;如果主机要接收从器件数据首先由主器件寻址从器件,然后主机接收从器件发送数据最后由主机终止接收过程这里不做过多的讲解,硬件连接如下: +我们底板就是采用的电阻分压方式因VGA显示端有75欧下拉电阻为了得到0.714V电压我们给RGB信号线上串入270欧的电阻3.3V*75/​(270+75)=0.717V。如下
-{{ :​i2c总线框架.jpg?​800 |}}+
 \\ \\
-本设计的硬件连接如下 +{{ :vga口电路.png?800 |}}
-{{ :pcf8591硬件连接.jpg?1000 |}}+
 \\ \\
-本设计中FPGA作为I2C主设备,PCF8591作为I2C从设备,从设备地址固定地址和可编程地址组成我们外设底板已将可编程地址A0、A1、A2接地,所以7位地址为7'​h48最低位的读写控制所以给PCF8591写数据的寻址地址为8'​h90对PCF8591读数据时的寻址地址为8'​h91。如 +VGA驱动显示器用的是扫描的方式逐行扫描the HS (Horizontal Synchronization)逐行扫描是扫描屏幕左上角一点开始,左向右逐点扫描每扫描完一行,电子束回到屏幕左边下一行的起始位置在这期间CRT(阴极射线显像管)对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完有行之后形成一帧用场同步信号进行同步,并使扫描回到屏幕左进行场消隐开始一帧。VGA一直在扫描,每一场的扫描包括了若干行扫描,依次循环;
-{{ :​pcf8591_i2c地址.jpg?​800 |}}+
 \\ \\
-PCF8591集成了很多功能,当需要不同的功能要对PCF8591做相应的配置,配置数据存储在名为CONTROL BYTE的寄存器中,图展示了寄存器中部分bit的功能,详细请参考PCF8591的datasheet,本设计中我们只使用通道1的ADC功能,配置数据为8'​h01。 +VGA显示序如 
-{{ :pcf8591_控制字.jpg?800 |}}+{{ :vga时序.png?800 |}}
 \\ \\
-本设计中我们需要两次通信, +VGA显示区域和消隐区域: 
-  * 第一次为配置数据,具体为:开始--写寻址--读响应--写配置数据--读响应--结束 +{{ :vga显示区域.png?800 |}}
-  * 第二次为读ADC数据,具体为:开始--读寻址--读响应--[读ADC数据--写响应--]循环读 +
-第二次的时序如下图: +
-{{ :pcf8591_adc时序.jpg?1000 |}}+
 \\ \\
-通过上面介绍大家应该对如何驱动PCF8591进行ADC采样有了整体的概念,还有一些细节就是I2C通信的时序明细,如下图 +常见VGA显示模式: 
-{{ :pcf8591_时序控制.jpg?​800 |}} +{{ :常见的vga显示模式.png?800 |}}
-{{ :​pcf8591_时序控制2.jpg?800 |}}+
  
 ====Verilog代码==== ====Verilog代码====
行 59: 行 44:
 // >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​ // >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​
 // -------------------------------------------------------------------- // --------------------------------------------------------------------
-// Module: ​ADC_I2C+// Module: ​Param_define
 //  // 
 // Author: Step // Author: Step
 //  // 
-// Description: ​ADC_I2C+// Description: ​Param_define
 //  // 
 // Web: www.stepfpga.com // Web: www.stepfpga.com
行 73: 行 58:
 // V1.1     ​|2016/​10/​30 ​  ​|Initial ver // V1.1     ​|2016/​10/​30 ​  ​|Initial ver
 // -------------------------------------------------------------------- // --------------------------------------------------------------------
-module ​ADC_I2C+`timescale 1ns / 1ns 
 + 
 +//​VGA显示器驱动只需要5个信号即可(行同步、场同步、红色、绿色、蓝色信号) 
 +//​红绿蓝三色信号为模拟信号,输入电压范围为0.0V~0.7V 
 +//​VGA时序中行同步和场同步都分为四个阶段(同步脉冲、后廊、有效线数、前廊) 
 +//​VGA显示有很多模式,每种模式都是有固定的时钟和时序参数,需要根据要求控制 
 + 
 +`ifdef VGA_800X600_60Hz //​不同VGA显示模式相应的参数 
 +//​--------------------------------------------------------------------------- 
 +//-- 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 //​场同步脉冲+后廊+有效线数+前廊 
 +//​--------------------------------------------------------------------------- 
 +`endif 
 + 
 +`ifdef VGA_640X480_85Hz //​不同VGA显示模式相应的参数 
 +//​--------------------------------------------------------------------------- 
 +//-- Horizonal timing information 
 +`define HSYNC_A ​  ​16'​d48 //​ 48 
 +`define HSYNC_B ​  ​16'​d160 //​ 48 + 112 
 +`define HSYNC_C ​  ​16'​d800 //​ 48 + 112 + 640 
 +`define HSYNC_D ​  ​16'​d832 //​ 48 + 112 + 640 + 32 //​行同步脉冲+后廊+有效线数+前廊 
 +//-- Vertical ​ timing information 
 +`define VSYNC_O ​  ​16'​d3 //​ 3  
 +`define VSYNC_P ​  ​16'​d28 //​ 3 + 25 
 +`define VSYNC_Q ​  ​16'​d508 //​ 3 + 25 + 480 
 +`define VSYNC_R ​  ​16'​d509 //​ 3 + 25 + 480 + 1 //​场同步脉冲+后廊+有效线数+前廊 
 +//​--------------------------------------------------------------------------- 
 +`endif 
 +</​code>​ 
 + 
 +<code verilog>​ 
 +// -------------------------------------------------------------------- 
 +// >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​ 
 +// -------------------------------------------------------------------- 
 +// Module: Vga_Module 
 +//  
 +// Author: Step 
 +//  
 +// Description:​ Vga_Module 
 +//  
 +// Web: www.stepfpga.com 
 +// 
 +// -------------------------------------------------------------------- 
 +// Code Revision History : 
 +// -------------------------------------------------------------------- 
 +// Version: |Mod. Date:   ​|Changes Made: 
 +// V1.1     ​|2016/​10/​30 ​  ​|Initial ver 
 +// -------------------------------------------------------------------- 
 +`define VGA_800X600_60Hz //​定义使用的VGA显示模式 
 + 
 +`ifdef VGA_800X600_60Hz //​根据VGA显示模式的定义调用相应的参数 
 +`include "​Param_define.v"​ //​调用Param_define.v文件中的全局定义 
 +`endif  
 + 
 +module ​Vga_Module
 ( (
- input clk_in, //​系统时钟 +input  clk_in, //40MHz系统时钟 
- input rst_n_in,​ //​系统复位,低有效 +input  rst_n_in, //​系统复位,低有效 
- output scl_out, //​I2C总线SCL +output ​ reg sync_v, //VGA场同步sync_v 
- inout sda_out, //I2C总线SDA +output ​ reg sync_h, //VGA行同步sync_h 
- output reg adc_done, //ADC采样完成标志 +output ​ reg [2:0] vga_data //VGA数据MSB~LSB = {R,G,B}
- output reg [7:0] adc_data //ADC采样数据+
 ); );
-  
- parameter CNT_NUM = 15;​ 
-  
- localparam IDLE = 3'​d0;​ 
- localparam MAIN = 3'​d1;​ 
- localparam START = 3'​d2;​ 
- localparam WRITE = 3'​d3;​ 
- localparam READ = 3'​d4;​ 
- localparam STOP = 3'​d5;​ 
-  
- //​根据PCF8591的datasheet,I2C的频率最高为100KHz, 
- //​我们准备使用4个节拍完成1bit数据的传输,所以需要400KHz的时钟触发完成该设计 
- //​使用计数器分频产生400KHz时钟信号clk_400khz 
- reg clk_400khz;​ 
- reg [9:​0] cnt_400khz;​ 
- always@(posedge clk_in or negedge rst_n_in) begin 
- if(!rst_n_in) begin 
- cnt_400khz <= 10'd0; 
- clk_400khz <= 1'b0; 
- end else if(cnt_400khz >= CNT_NUM-1) begin 
- cnt_400khz <= 10'd0; 
- clk_400khz <= ~clk_400khz;​ 
- end else begin 
- cnt_400khz <= cnt_400khz + 1'b1; 
- end 
- end 
-  
- reg [7:​0] adc_data_r;​ 
- reg scl_out_r;​ 
- reg sda_out_r;​ 
- reg [2:​0] cnt;​ 
- reg [3:​0] cnt_main;​ 
- reg [7:​0] data_wr;​ 
- reg [2:​0] cnt_start;​ 
- reg [2:​0] cnt_write;​ 
- reg [4:​0] cnt_read;​ 
- reg [2:​0] cnt_stop;​ 
- reg [2:0] state; 
  
- always@(posedge clk_400khz or negedge rst_n_in) begin +reg  [15:0] x_cnt
- if(!rst_n_in) begin //​如果按键复位,将相关数据初始化 +reg  [15:0 y_cnt
- scl_out_r <= 1'​d1;​ +reg  vga_valid;
- sda_out_r <= 1'​d1;​ +
- cnt <= 1'​b0;​ +
- cnt_main <= 4'​d0;​ +
- cnt_start <= 3'​d0;​ +
- cnt_write <= 3'​d0;​ +
- cnt_read <= 5'​d0;​ +
- cnt_stop <= 1'​d0;​ +
- adc_done <= 1'​b0;​ +
- adc_data <= 1'​b0;​ +
- state <= IDLE; +
- end else begin +
- case(state) +
- IDLE:begin //​软件自复位,主要用于程序跑飞后的处理 +
- scl_out_r <= 1'​d1;​ +
- sda_out_r <= 1'​d1;​ +
- cnt <= 1'​b0;​ +
- cnt_main <= 4'​d0;​ +
- cnt_start <= 3'​d0;​ +
- cnt_write <= 3'​d0;​ +
- cnt_read <= 5'​d0;​ +
- cnt_stop <= 1'​d0;​ +
- adc_done <= 1'​b0;​ +
- state <= MAIN; +
- end +
- MAIN:​begin +
- if(cnt_main >= 4'd6) cnt_main <= 4'​d6; ​ //​对MAIN中的子状态执行控制cnt_main +
- else cnt_main <= cnt_main + 1'​b1;​ +
- case(cnt_main) +
- 4'​d0:​ begin state <= START; end //​I2C通信时序中的START +
- 4'​d1:​ begin data_wr <= 8'h90; state <= WRITE; end //​A0,​A1,​A2都接了GND,写地址为8'​h90 +
- 4'​d2:​ begin data_wr <= 8'h00; state <= WRITE; end //​control byte为8'​h00,采用4通道ADC中的通道0 +
- 4'​d3:​ begin state <= STOPend //​I2C通信时序中的START +
- 4'​d4:​ begin state <= START; end //​I2C通信时序中的STOP +
- 4'​d5:​ begin data_wr <= 8'h91; state <= WRITE; end //A0 A1 A2都接了GND,读地址为8'​h91 +
- 4'​d6:​ begin state <= READ; adc_done <= 1'b0; end //​读取ADC的采样数据 +
- 4'​d7:​ begin state <= STOP; adc_done <= 1'b1; end //​I2C通信时序中的STOP,读取完成标志 +
- 4'​d8:​ begin state <= MAIN; end //​预留状态,不执行 +
- default:​ state <= IDLE;​ //​如果程序失控,进入IDLE自复位状态 +
- endcase +
- end +
- START:​begin //​I2C通信时序中的起始START +
- if(cnt_start >= 3'd5) cnt_start <= 1'​b0;​ //​对START中的子状态执行控制cnt_start +
- else cnt_start <= cnt_start + 1'​b1;​ +
- case(cnt_start) +
- 3'​d0:​ begin sda_out_r <= 1'b1; scl_out_r <= 1'b1; end //​将SCL和SDA拉高,保持4.7us以上 +
- 3'​d1:​ begin sda_out_r <= 1'b1; scl_out_r <= 1'b1; end //​clk_400khz每个周期2.5us,需要两个周期 +
- 3'​d2:​ begin sda_out_r <= 1'b0; end //​SDA拉低到SCL拉低,保持4.0us以上 +
- 3'​d3:​ begin sda_out_r <= 1'b0; end //​clk_400khz每个周期2.5us,需要两个周期 +
- 3'​d4:​ begin scl_out_r <= 1'b0; end //​SCL拉低,保持4.7us以上 +
- 3'​d5:​ begin scl_out_r <= 1'b0; state <= MAIN; end //​clk_400khz每个周期2.5us,需要两个周期,返回MAIN +
- default:​ state <= IDLE;​ //​如果程序失控,进入IDLE自复位状态 +
- endcase +
- end +
- WRITE:​begin //​I2C通信时序中的写操作WRITE和相应判断操作ACK +
- if(cnt <= 3'd6) begin //​共需要发送8bit的数据,这里控制循环的次数 +
- if(cnt_write >= 3'd3) begin cnt_write <= 1'b0; cnt <= cnt + 1'b1; end +
- else begin cnt_write <= cnt_write + 1'b1; cnt <= cnt; end +
- end else begin +
- if(cnt_write >= 3'd7) begin cnt_write <= 1'b0; cnt <= 1'b0; end //​两个变量都恢复初值 +
- else begin cnt_write <= cnt_write + 1'b1; cnt <= cnt; end +
- end +
- case(cnt_write) +
- //​按照I2C的时序传输数据 +
- 3'​d0:​ begin scl_out_r <= 1'b0; sda_out_r <= data_wr[7-cnt]; end //​SCL拉低,并控制SDA输出对应的位 +
- 3'​d1: begin scl_out_r <= 1'b1; end //​SCL拉高,保持4.0us以上 +
- 3'​d2:​ begin scl_out_r <= 1'b1; end //​clk_400khz每个周期2.5us,需要两个周期 +
- 3'​d3:​ begin scl_out_r <= 1'b0; end //​SCL拉低,准备发送下1bit的数据 +
- //​获取从设备的响应信号并判断 +
- 3'​d4:​ begin sda_out_r <= 1'bz; end //​释放SDA线,准备接收从设备的响应信号 +
- 3'​d5:​ begin scl_out_r <= 1'b1; end //​SCL拉高,保持4.0us以上 +
- 3'​d6:​ begin if(sda_out) state <= IDLE; else state <= state; end //​获取从设备的响应信号并判断 +
- 3'​d7:​ begin scl_out_r <= 1'b0; state <= MAIN; end //​SCL拉低,返回MAIN状态 +
- default:​ state <= IDLE;​ //​如果程序失控,进入IDLE自复位状态 +
- endcase +
- end +
- READ:​begin //​I2C通信时序中的读操作READ和返回ACK的操作 +
- if(cnt <= 3'd6) begin //​共需要接收8bit的数据,这里控制循环的次数 +
- if(cnt_read >= 3'd3) begin cnt_read <= 1'b0; cnt <= cnt + 1'b1; end +
- else begin cnt_read <= cnt_read + 1'b1; cnt <= cnt; end +
- end else begin +
- if(cnt_read >= 3'd7) begin cnt_read <= 1'b0; cnt <= 1'b0; end //​两个变量都恢复初值 +
- else begin cnt_read <= cnt_read + 1'b1; cnt <= cnt; end +
- end +
- case(cnt_read) +
- //​按照I2C的时序接收数据 +
- 3'​d0:​ begin scl_out_r <= 1'b0; sda_out_r <= 1'bz; end //​SCL拉低,释放SDA线,准备接收从设备数据 +
- 3'​d1:​ begin scl_out_r <= 1'b1; end //​SCL拉高,保持4.0us以上 +
- 3'​d2:​ begin adc_data_r[7-cnt<= sda_outend //​读取从设备返回的数据 +
- 3'​d3:​ begin scl_out_r <= 1'b0; end //​SCL拉低,准备接收下1bit的数据 +
- //​向从设备发送响应信号 +
- 3'​d4:​ begin sda_out_r <= 1'b0; adc_done <= 1'b1; adc_data <= adc_data_r; end //​发送响应信号,将前面接收的数据锁存 +
- 3'​d5:​ begin scl_out_r <= 1'b1; end //​SCL拉高,保持4.0us以上 +
- 3'​d6:​ begin scl_out_r <= 1'b1; adc_done <= 1'b0; end //​SCL拉高,保持4.0us以上 +
- 3'​d7:​ begin scl_out_r <= 1'b0; state <= MAIN; end //​SCL拉低,返回MAIN状态 +
- default:​ state <= IDLE;​ //​如果程序失控,进入IDLE自复位状态 +
- endcase +
- end +
- STOP:​begin //​I2C通信时序中的结束STOP +
- if(cnt_stop >= 3'd5) cnt_stop <= 1'b0; //​对STOP中的子状态执行控制cnt_stop +
- else cnt_stop <= cnt_stop + 1'​b1;​ +
- case(cnt_stop) +
- 3'​d0:​ begin sda_out_r <= 1'b0; end //​SDA拉低,准备STOP +
- 3'​d1:​ begin sda_out_r <= 1'b0; end //​SDA拉低,准备STOP +
- 3'​d2:​ begin scl_out_r <= 1'b1; end //​SCL提前SDA拉高4.0us +
- 3'​d3:​ begin scl_out_r <= 1'b1; end //​SCL提前SDA拉高4.0us +
- 3'​d4:​ begin sda_out_r <= 1'b1; end //​SDA拉高 +
- 3'​d5:​ begin sda_out_r <= 1'b1; state <= MAIN; end //​完成STOP操作,返回MAIN状态 +
- default:​ state <= IDLE;​ //​如果程序失控,进入IDLE自复位状态 +
- endcase +
- end +
- default:;​ +
- endcase +
- end +
- end+
   
- assign scl_out ​scl_out_r; //对SCL端口赋值 +//​对时钟计数标识VGA一次行扫描需要的时间 
- assign sda_out ​sda_out_r; //对SDA端口赋值+always @ (posedge clk_in or negedge rst_n_in) 
 + if(!rst_n_in) x_cnt <16'd0; //复位时初始值 
 + else if(x_cnt >`HSYNC_D) x_cnt <= 16'd0; //一次行扫描需要1056个时钟(128+88+800+40) 
 + else x_cnt <= x_cnt + 1'b1;
  
-endmodule +//​对行扫描计数标识VGA一次场扫描需要的时间 
-</code>+always @ (posedge clk_in or negedge rst_n_in) 
 + if(!rst_n_in) y_cnt <= 16'​d0;​ //​复位时初始值 
 + else if(x_cnt == `HSYNC_D) begin //​每次行扫描时 
 + if(y_cnt ​>= `VSYNC_R) y_cnt <= 16'​d0;​ //​每次场扫描包含628次行扫描 
 + else y_cnt <= y_cnt + 1'​b1;​ 
 + end else y_cnt <= y_cnt;​ //​在每次行扫描过程中场扫描计数器保持不变
  
 +//​按照显示模式的参数产生行同步扫描的脉冲
 +always @ (posedge clk_in or negedge rst_n_in)
 + if(!rst_n_in) sync_h <= 1'b1;
 + else if(x_cnt < `HSYNC_A) sync_h <= 1'b0;
 + else sync_h <= 1'b1;
  
 +//​按照显示模式的参数产生场同步扫描的脉冲
 +always @ (posedge clk_in or negedge rst_n_in)
 + if(!rst_n_in) sync_v <= 1'b1;
 + else if(y_cnt < `VSYNC_O) sync_v <= 1'b0;
 + else sync_v <= 1'b1;
 +
 +//​根据行场同步信号的有效线数确定有效显示区域
 +always @ (posedge clk_in or negedge rst_n_in)
 + if(!rst_n_in) ​
 + vga_valid <= 1'b0;
 + else if((x_cnt > `HSYNC_B) && (x_cnt <​`HSYNC_C) && (y_cnt > `VSYNC_P) && (y_cnt < `VSYNC_Q))
 + vga_valid <= 1'b1; //​有效显示区域中vga_valid标志为1
 + else
 + vga_valid <= 1'b0;
 +
 +//​在VGA有效显示区域不同的段显示不同的颜色
 +always @ (posedge clk_in or negedge rst_n_in)
 +begin
 + if(!rst_n_in) vga_data = 3'​b111;​
 + else if(vga_valid)begin //​在有效显示区域内
 + if((x_cnt > `HSYNC_B) && (x_cnt <= `HSYNC_B + 10'​d100))
 + vga_data = 3'​b100;​ //​红色
 + else if((x_cnt > `HSYNC_B + 10'​d100) && (x_cnt <= `HSYNC_B + 10'​d200))
 + vga_data = 3'​b010;​ //​绿色
 + else if((x_cnt > `HSYNC_B + 10'​d200) && (x_cnt <= `HSYNC_B + 10'​d300))
 + vga_data = 3'​b001;​ //​蓝色
 + else if((x_cnt > `HSYNC_B + 10'​d300) && (x_cnt <= `HSYNC_B + 10'​d400))
 + vga_data = 3'​b110;​ //​黄色
 + else if((x_cnt > `HSYNC_B + 10'​d400) && (x_cnt <= `HSYNC_B + 10'​d500))
 + vga_data = 3'​b101;​ //​紫色
 + else if((x_cnt > `HSYNC_B + 10'​d500) && (x_cnt <= `HSYNC_B + 10'​d600))
 + vga_data = 3'​b011;​ //​青色
 + else if((x_cnt > `HSYNC_B + 10'​d600) && (x_cnt <= `HSYNC_B + 10'​d700))
 + vga_data = 3'​b111;​ //​白色
 + else if((x_cnt > `HSYNC_B + 10'​d700) && (x_cnt <= `HSYNC_B + 10'​d800))
 + vga_data = 3'​b000;​ //​黑色
 + else
 + vga_data = 3'​b111;​ //​白色
 + end else
 + vga_data = 3'​b111;​ //​白色
 +end
 +
 +endmodule
 +</​code>​
 ====小结==== ====小结====
 ------ ------
-本节主要为大家讲解了使用I2C驱动PCF8591的ADC功能的原理及软件设计,需要大家掌握的同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试。+本节主要为大家讲解了VGA显示的原理、时序及软件设计,需要大家掌握的同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试。
 \\ \\
 如果你对Diamond软件的使用不了解,请参考这里:[[lattice_diamond的使用|Diamond的使用]]。 如果你对Diamond软件的使用不了解,请参考这里:[[lattice_diamond的使用|Diamond的使用]]。
行 255: 行 206:
 ------ ------
 \\ \\
-使用[[STEP-MXO2第二代]]的PCF8591的ADC驱动程序: ​ 后续会有下载连接 ​ 待更新+使用[[STEP-MXO2第二代]]的VGA显示驱动程序: ​ 后续会有下载连接 ​ 待更新
 \\ \\
-使用[[STEP-MAX10]]的PCF8591的ADC驱动程序: ​ 后续会有下载连接 ​ 待更新+使用[[STEP-MAX10]]的VGA显示驱动程序: ​ 后续会有下载连接 ​ 待更新
 \\ \\