名称:交通灯图像VGA显示DE1-SoC开发板红绿灯(代码在文末下载)
软件:Quartus II
语言:VHDL
代码功能:
本设计使用VHDL语言设计VGA显示的交通灯,VGA显示屏上显示主干道和支干道,道路用白色线条描绘,每个道路中间用黄色线条隔开分为左右两个车道。每条主干道和支干道都对应有3个红绿灯,分别为红色、黄色、绿色。红黄绿三色交通灯指挥车辆的通行,红灯停,绿灯行,黄灯为绿灯到红灯的过渡。其中左转和直行都按红绿灯的指示通行,右转的话不需要看红绿灯,在任何时刻均可右转。
本代码已在DE1-SoC开发板验证,其他开发板可以修改管脚适配,开发板如下:
实际上板验证效果如下:
FPGA代码Verilog/VHDL代码资源下载:www.hdlcode.com
部分代码展示:
LIBRARY?ieee; ???USE?ieee.std_logic_1164.all; ENTITY?vga_controller_top?IS ???PORT?(?????? ??????clk_50M???:?IN?STD_LOGIC; ??????rst???????:?IN?STD_LOGIC; ??????hsync?????:?OUT?STD_LOGIC; ??????vsync?????:?OUT?STD_LOGIC; key_1?????:?IN?STD_LOGIC; key_2?????:?IN?STD_LOGIC; key_3?????:?IN?STD_LOGIC; key_4?????:?IN?STD_LOGIC; key_5?????:?IN?STD_LOGIC; key_6?????:?IN?STD_LOGIC; key_7?????:?IN?STD_LOGIC; key_8?????:?IN?STD_LOGIC; VGA_CLK???????:?OUT?STD_LOGIC; VGA_BLANK_N???:?OUT?STD_LOGIC; ??????main_green_add?????:?IN?STD_LOGIC;--主路绿灯加 ??????main_green_sub?????:?IN?STD_LOGIC;--主路绿灯减 ??????branch_green_add???:?IN?STD_LOGIC;--支路绿灯加 ??????branch_green_sub???:?IN?STD_LOGIC;--支路绿灯减 ??????HEX0??:?OUT?STD_LOGIC_VECTOR(6?DOWNTO?0);--数码管段选 HEX1??:?OUT?STD_LOGIC_VECTOR(6?DOWNTO?0);--数码管段选 HEX2??:?OUT?STD_LOGIC_VECTOR(6?DOWNTO?0);--数码管段选 HEX3??:?OUT?STD_LOGIC_VECTOR(6?DOWNTO?0);--数码管段选 ??????rgb???????:?OUT?STD_LOGIC_VECTOR(11?DOWNTO?0) ???); END?vga_controller_top; ARCHITECTURE?behave?OF?vga_controller_top?IS --???COMPONENT?clk_PLL?IS --??????PORT?( --?????????refclk???????:?IN?STD_LOGIC; --?????????rst?????:?IN?STD_LOGIC; --?????????outclk_0???:?OUT?STD_LOGIC --??????); --???END?COMPONENT; --交通灯控制 COMPONENT?Traffic_Light_Control?IS ???PORT?( ??????clk?????:?IN?STD_LOGIC;--50Mhz reset?:?IN?STD_LOGIC;--复位 main_key?:?IN?STD_LOGIC; ??????branch_key?:?IN?STD_LOGIC; ??????main_green_add?????:?IN?STD_LOGIC;--主路绿灯加 ??????main_green_sub?????:?IN?STD_LOGIC;--主路绿灯减 ??????branch_green_add???:?IN?STD_LOGIC;--支路绿灯加 ??????branch_green_sub???:?IN?STD_LOGIC;--支路绿灯减 ??????R1??????:?OUT?STD_LOGIC;--高电平亮,主路红灯 ??????G1??????:?OUT?STD_LOGIC;--高电平亮,主路绿灯 ??????Y1??????:?OUT?STD_LOGIC;--高电平亮,主路黄灯 ??????R2??????:?OUT?STD_LOGIC;--高电平亮,支路红灯 ??????G2??????:?OUT?STD_LOGIC;--高电平亮,支路绿灯 ??????Y2??????:?OUT?STD_LOGIC;--高电平亮,支路黄灯 ??????HEX0??:?OUT?STD_LOGIC_VECTOR(6?DOWNTO?0);--数码管段选 HEX1??:?OUT?STD_LOGIC_VECTOR(6?DOWNTO?0);--数码管段选 HEX2??:?OUT?STD_LOGIC_VECTOR(6?DOWNTO?0);--数码管段选 HEX3??:?OUT?STD_LOGIC_VECTOR(6?DOWNTO?0)--数码管段选 ???); END?COMPONENT; ???COMPONENT?aiso_rst?IS ??????PORT?( ?????????clk???????:?IN?STD_LOGIC; ?????????reset?????:?IN?STD_LOGIC; ?????????reset_s???:?OUT?STD_LOGIC ??????); ???END?COMPONENT; ??? ???COMPONENT?vga_sync?IS ??????PORT?( ?????????clk???????:?IN?STD_LOGIC; ?????????rst???????:?IN?STD_LOGIC; VGA_CLK???????:?OUT?STD_LOGIC; VGA_BLANK_N???:?OUT?STD_LOGIC; ?????????hsync?????:?OUT?STD_LOGIC; ?????????vsync?????:?OUT?STD_LOGIC; ?????????pixel_x???:?OUT?STD_LOGIC_VECTOR(9?DOWNTO?0); ?????????pixel_y???:?OUT?STD_LOGIC_VECTOR(9?DOWNTO?0); ?????????video_on??:?OUT?STD_LOGIC ??????); ???END?COMPONENT; ??? ???COMPONENT?debounce?IS ??????PORT?( ?????????clk???????:?IN?STD_LOGIC; ?????????reset?????:?IN?STD_LOGIC; ?????????sw????????:?IN?STD_LOGIC; ?????????db????????:?OUT?STD_LOGIC ??????); ???END?COMPONENT; ??? ???COMPONENT?graphic_generator?IS ??????PORT?( ?????????clk???????:?IN?STD_LOGIC; ?????????rst???????:?IN?STD_LOGIC; ??????R1??????:?IN?STD_LOGIC;--高电平亮,主路红灯 ??????G1??????:?IN?STD_LOGIC;--高电平亮,主路绿灯 ??????Y1??????:?IN?STD_LOGIC;--高电平亮,主路黄灯 ??????R2??????:?IN?STD_LOGIC;--高电平亮,支路红灯 ??????G2??????:?IN?STD_LOGIC;--高电平亮,支路绿灯 ??????Y2??????:?IN?STD_LOGIC;--高电平亮,支路黄灯 ?????????pixel_x???:?IN?STD_LOGIC_VECTOR(9?DOWNTO?0); ?????????pixel_y???:?IN?STD_LOGIC_VECTOR(9?DOWNTO?0); ?????????video_on??:?IN?STD_LOGIC; ?????????rgb???????:?OUT?STD_LOGIC_VECTOR(11?DOWNTO?0) ??????); ???END?COMPONENT; COMPONENT?display?is ??PORT( ?score:IN?STD_LOGIC_VECTOR(3?DOWNTO?0); ???????HEX:out?STD_LOGIC_VECTOR(6?DOWNTO?0) ?); end?COMPONENT; ??? SIGNAL?clk?????????:?STD_LOGIC:='0'; ???SIGNAL?video_on????:?STD_LOGIC; ???SIGNAL?rst_s???????:?STD_LOGIC; ???SIGNAL?pixel_x?????:?STD_LOGIC_VECTOR(9?DOWNTO?0); ???SIGNAL?pixel_y?????:?STD_LOGIC_VECTOR(9?DOWNTO?0); ???--?Declare?intermediate?signals?for?referenced?outputs ???SIGNAL?hsync_buf?:?STD_LOGIC; ???SIGNAL?vsync_buf?:?STD_LOGIC; ???SIGNAL?rgb_buf???:?STD_LOGIC_VECTOR(11?DOWNTO?0); ???SIGNAL???R1??????:??STD_LOGIC;--高电平亮,主路红灯 ???SIGNAL???G1??????:??STD_LOGIC;--高电平亮,主路绿灯 ???SIGNAL???Y1??????:??STD_LOGIC;--高电平亮,主路黄灯 ???SIGNAL???R2??????:??STD_LOGIC;--高电平亮,支路红灯 ???SIGNAL???G2??????:??STD_LOGIC;--高电平亮,支路绿灯 ???SIGNAL???Y2??????:??STD_LOGIC;--高电平亮,支路黄灯 ???SIGNAL?main_key?:?STD_LOGIC; ???SIGNAL?branch_key?:?STD_LOGIC; BEGIN ???--?Drive?referenced?outputs ???hsync?<=?hsync_buf; ???vsync?<=?vsync_buf; ???rgb?<=?rgb_buf; main_key<=key_1?or?key_2?or?key_3?or?key_4; branch_key<=key_5?or?key_6?or?key_7?or?key_8; ??? --???u_clk_PLL:?clk_PLL --??????PORT?MAP??( --?????????refclk??=>?clk_50M, --?????????rst?????=>?rst_s, --?????????outclk_0?=>?clk --??????);? clk?<=?clk_50M; --交通灯控制 U_Traffic_Light_Control:?Traffic_Light_Control ???PORT?MAP( ??????clk????=>?clk,--50Mhz reset?=>?rst_s,--复位 main_key=>main_key, branch_key=>branch_key, ??????main_green_add?????=>?main_green_add,--主路绿灯加 ??????main_green_sub?????=>?main_green_sub,--主路绿灯减 ??????branch_green_add???=>?branch_green_add,--支路绿灯加 ??????branch_green_sub???=>?branch_green_sub,--支路绿灯减 ??????R1??????=>?R1,--高电平亮,主路红灯 ??????G1??????=>?G1,--高电平亮,主路绿灯 ??????Y1??????=>?Y1,--高电平亮,主路黄灯 ??????R2??????=>?R2,--高电平亮,支路红灯 ??????G2??????=>?G2,--高电平亮,支路绿灯 ??????Y2??????=>?Y2,--高电平亮,支路黄灯 ??????HEX0???=>?HEX0,-- ??????HEX1???=>?HEX1,-- HEX2???=>?HEX2,-- HEX3???=>?HEX3 ???); ??? ???u0?:?aiso_rst ??????PORT?MAP?( ?????????clk??????=>?clk, ?????????reset????=>?rst, ?????????reset_s??=>?rst_s ??????); ? ??? ???u1?:?vga_sync ??????PORT?MAP?( ?????????clk???????=>?clk, ?????????rst???????=>?rst_s, VGA_CLK???=>?VGA_CLK, VGA_BLANK_N?=>?VGA_BLANK_N, ?????????hsync?????=>?hsync_buf, ?????????vsync?????=>?vsync_buf, ?????????pixel_x???=>?pixel_x, ?????????pixel_y???=>?pixel_y, ?????????video_on??=>?video_on ??????); ??? ??? ???u4?:?graphic_generator ??????PORT?MAP?( ?????????clk???????=>?clk, ?????????rst???????=>?rst_s, ?????????pixel_x???=>?pixel_x, ?????????pixel_y???=>?pixel_y, ??????R1??????=>?R1,--高电平亮,主路红灯 ??????G1??????=>?G1,--高电平亮,主路绿灯 ??????Y1??????=>?Y1,--高电平亮,主路黄灯 ??????R2??????=>?R2,--高电平亮,支路红灯 ??????G2??????=>?G2,--高电平亮,支路绿灯 ??????Y2??????=>?Y2,--高电平亮,支路黄灯 ?????????video_on??=>?video_on, ?????????rgb???????=>?rgb_buf ??????); END?behave;
1.?导言
本设计使用VHDL语言设计VGA显示的交通灯,VGA显示屏上显示主干道和支干道,道路用白色线条描绘,每个道路中间用黄色线条隔开分为左右两个车道。每条主干道和支干道都对应有3个红绿灯,分别为红色、黄色、绿色。红黄绿三色交通灯指挥车辆的通行,红灯停,绿灯行,黄灯为绿灯到红灯的过渡。其中左转和直行都按红绿灯的指示通行,右转的话不需要看红绿灯,在任何时刻均可右转。
2.?背景
2.1 VGA显示原理
显示器扫描方式分为逐行扫描和隔行扫描:逐行扫描是扫描从屏幕左上角一点开始,从左向右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,CRT对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有的行,形成一帧,用场同步信号进行场同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。隔行扫描是指电子束扫描时每隔一行扫一行,完成一屏后再返回来扫描剩下的行,隔行扫描的显示器闪烁的厉害,会让使用者的眼睛疲劳。
完成一行扫描的时间称为水平扫描时间,其倒数称为行频率;完成一帧(整屏)扫描的时间称为垂直扫描时间,其倒数称为场频率,即刷新一屏的频率,常见的有60Hz,75Hz等等。标准的VGA显示的场频60Hz,行频31.5KHz。
行场消隐信号:是针对老式显像管的成像扫描电路而言的。电子枪所发出的电子束从屏幕的左上角开始向右扫描,一行扫完需将电子束从右边移回到左边以便扫描第二行。在移动期间就必须有一个信号加到电路上,使得电子束不能发出。不然这个回扫线会破坏屏幕图像的。这个阻止回扫线产生的信号就叫作消隐信号,场信号的消隐也是一个道理。
显示带宽指的显示器可以处理的频率范围。如果是60Hz刷新频率的VGA,其带宽达640x480x60=18.4MHz,70Hz的刷新频率1024x768分辨率的SVGA,其带宽达1024x768x70=55.1MHz。

VGA时序图
VESA中定义行时序和场时序都需要同步脉冲(Sync a)、显示后沿(Back porch b)、显示时序段(Display interval c)和显示前沿(Front porch d)四部分。VGA工业标准显示模式要求:行同步,场同步都为负极性,即同步脉冲要求是负脉冲。
由VGA的行时序可知:每一行都有一个负极性行同步脉冲(Sync a),是数据行的结束标志,同时也是下一行的开始标志。在同步脉冲之后为显示后沿(Back porch b),在显示时序段(Display interval c)显示器为亮的过程,RGB数据驱动一行上的每一个像素点,从而显示一行。在一行的最后为显示前沿(Front porch d)。在显示时间段(Display interval c)之外没有图像投射到屏幕是插入消隐信号。同步脉冲(Sync a)、显示后沿(Back porch b)和显示前沿(Front porch d)都是在行消隐间隔内(Horizontal Blanking Interval),当消隐有效时,RGB信号无效,屏幕不显示数据。
VGA的场时序与行时序基本一样,每一帧的负极性脉冲(Sync a)是一帧的结束标志,同时也是下一帧的开始标志。而显示数据是一帧的所有行数据。
2.2 交通灯原理
道路交通信号灯是用于给互相冲突的交通流分配有效的通行权,以提高道路交通安全和道路容量的一类交通灯。当今,红绿灯安装在各个道口上,已经成为疏导交通车辆最常见和最有效的手段,这一技术已经有相当长的发展历史了。
1858年,在英国伦敦主要街头安装了以燃煤气为光源的红,蓝两色的机械扳手式信号灯,用以指挥马车通行。这是世界上最早的交通信号灯。1868年,英国机械工程师纳伊特在伦敦威斯敏斯特区的议会大厦前的广场上,安装了世界上最早的煤气红绿灯。它由红绿两以旋转式方形玻璃提灯组成,红色表示“停止”,绿色表示“注意”。1869年1月2日,煤气灯爆炸,使警察受伤,遂被取消。
电气启动的红绿灯出现在美国,这种红绿灯由红绿黄三色圆形的投光器组成,1914年始安装于纽约市5号大街的一座高塔上。红灯亮表示“停止”,绿灯亮表示“通行”。
1918年,又出现了带控制的红绿灯和红外线红绿灯。带控制的红绿灯,一种是把压力探测器安在地下,车辆一接近红灯便变为绿灯;另一种是用扩音器来启动红绿灯,司机遇红灯时按一下嗽叭,就使红灯变为绿灯。红外线红绿灯当行人踏上对压力敏感的路面时,它就能察觉到有人要过马路。红外光束能把信号灯的红灯延长一段时间,推迟汽车放行,以免发生交通事故。
又经过前人的设计和改造,交通信号灯终于普及整个城市的十字路口。
交通信号灯的出现,使交通得以有效管制,对于疏导交通流量、提高道路通行能力,减少交通事故有明显效果,更改变了交警轮流指挥和疏散交通拥挤的现状,实现了人,车,路三者的同步协调。现阶段,许多设计工作者又设计出许多智能化,自动化,数字化等更先进的交通灯控制方案,这更方便于维护管理,给人们提供了更加便利的交通环境。
目前,城市规模还在不断的扩大,人们对交通信号灯的控制也越来越高,我们需要更高层次的去了解交通信号灯,结合城市十字路口交通的需要,不断地去创新,才能达到发展的需求,所以研究交通信号灯的极为重要。
3.?工作章节
本设计主要分为两大部分,一部分是VGA显示的控制,另一部分是交通灯的控制。系统的整体框图如下所示。

上图中,aiso_rst、vga_sync、vga_sync这三个模块实现VGA显示的控制,Traffic_Light_Control模块实现交通灯的控制。其中Traffic_Light_Control模块内部又分为RGY、SMG、display、CLOCK、time_ctrl等模块,具体内部框图如下所示:

3.1?VGA显示控制部分
aiso_rst模块
该模块实现复位的同步控制,将系统外部的异步复位信号转换为同步复位信号,外部输入信号为开发板上的按键,低电平有效。将该信号通过两级触发器进行同步,然后再通过一个非门实现低电平复位到高电平复位的转换。内部电路如下图所示:

vga_sync模块
该模块实现VGA时序的控制,用于产生VGA的CLK信号,BLANK信号,hsync信号和vsync信号,模块框图如下图所示。

本设计使用25MHz的时钟,屏幕分辨率为640x480,刷新频率60Hz,每场对应525个行周期(525=10+2+480+33),其中480为显示行。每场有场同步信号,该脉冲宽度为2个行周期的负脉冲,每显示行包括800点时钟,其中640点为有效显示区,每一行有一个行同步信号,该脉冲宽度为96个点时钟。由此可知:行频为525*59.94=31469Hz,需要的时钟频率:525*800*59.94约25MHz。25MHz的时钟通过50MHz的系统时钟分频得到,hsync信号和vsync信号通过计数器计数控制,其中hcount计数到最大799,vcount计数最大到524,再通过对计数器计数区域的选择控制输出hsync信号和vsync信号。下图为本模块实现的VGA时序图,

本模块还输出pixel_x、pixel_y用于指示当前屏幕上的坐标。其中pixel_x=hcount(横坐标),pixel_y=vcount(纵坐标)。video_on信号指示当前区域为有效显示区,范围为640*480,即hcount<640,vcount<480.
graphic_generator模块
该模块控制显示器显示交通灯的图案,包括道路、斑马线、红绿灯等部分。模块框图如下图所示。

该模块接收vga_sync模块输出的pixel_x、pixel_y信息和Traffic_Light_Control模块输出的红绿灯控制信息,其中pixel_x、pixel_y信息用于在显示器绘制道路和红绿灯,Traffic_Light_Control模块输出的红绿灯控制信息用于控制对应的红绿灯什么时候亮灭。对应的图案如下图所示,其中左下角为坐标原点,X轴最大值为640,Y轴坐标最大值为480。

图中上下方向的车道为主路,左右方向的车道为支路,下面以图中用红色框标识的主路道路线为例,说明如何绘制该线条,该段代码对应如下:
road1_on <= '1' when ((pixel_x >= 220) AND (pixel_x <= 223) AND (pixel_y >= 0) AND (pixel_y <= 143)) else '0';--定义线条的位置
road1_rgb <= "111111111111";--显示白色
将该段线条命名为road1_on,其范围为X坐标的(220~223),即从X轴的220到223,共占4个横坐标像素;Y坐标为(0~143),即从Y轴的0到143,共占144个纵坐标像素。该段线条根据XY轴的范围定义即对应图中的位置。road1_rgb表示该段线条的颜色,111111111111表示红色、绿色、蓝色三色的混合,混合色为白色。至此该段线条的位置和颜色均通过代码进行了规定,其他图案的设计以此类推。
3.2?交通灯控制部分
交通灯控制部分用于实现红、黄、绿三种信号灯的控制及对应数码管的显示,其中主路和支路的绿灯时间可以通过板子外部的按键增加或者减小。内部具体包含RGY、SMG、display、CLOCK、time_ctrl等模块。
RGY模块
该模块根据输入的主路、支路时间,实现红、黄、绿三种信号灯的控制,使用状态机进行控制。模块框图如下图所示:

状态机一共分为4个状态,分别用001、010、011、100表示。状态转移顺序为:
001->010->011->100->001
其中001表示主路绿灯状态,010表示主路黄灯黄灯状态,011表示支路绿灯状态,100表示支路黄灯状态。每个状态下通过计数器来控制对应灯的时间,当计数达到设置的时间后,切换到下一个状态。主路绿灯状态和主路黄灯状态下支路为红灯,支路绿灯状态和支路黄灯状态下主路为红灯。将红黄绿三色灯对应的计数值输出到SMG模块。
本模块还有行人按键控制功能,分主路控制信号main_key和支路控制信号branch_key。main_key由主路4个行人斑马线位置的控制按键进行或运算得到,branch_key由支路4个行人斑马线位置的控制按键进行或运算得到,当main_key为1时表示主路有人按下,则状态机状态先转换到主路黄灯状态(010),然后自动进入到主路红灯状态。当branch_key为1时表示支路有人按下,则状态机状态先转换到支路黄灯状态(100),然后自动进入到支路红灯状态。
SMG模块
该模块接收主路和支路红黄绿三种灯的控制信号和对应灯计数计数信号,再将其转换为倒计时。模块框图如下图所示:

由于RGY模块内是按加法计数,因而所得的计数信号为正计数,故需要将正计数转换为倒计数。转换原理为将总时间减去正计时的时间,例如主路绿灯时间为20秒,正计数的顺序为1~20,将20减去正计数即可以得到19~0的倒计数。
Display模块
该模块用于控制数码管显示倒计时,模块输入主路和支路的倒计时信号,再通过数码管显示出来。首先需要将输入的倒计时信号转换为十位和个位,再将十位个位分别通过数码管显示。模块框图如下图所示:

先将输入的倒计时信号转换为int类型,便于使用乘法和除法运算。将倒计时除以10得到的商即为十位,再用倒计时信号减去十位乘以10得到的差即为个位。倒计时使用开发板的7段数码管显示,每个数码管输入为7位,对应下图中的abcdefg7段,当输入0时对应的段点亮,当输入为1时,对应的段灭。

根据上图可以观察到,若要显示数字0,需要G灭,ABCDEF亮,也就是对应编码为“1000000”,其中从左到右依次对应GFEDCBA。以此类推可以得到0~9的所有编码。
CLOCK模块
分频模块的功能是将系统数字50MHz分频为1Hz,1Hz对应周期为1秒,用分频后的1Hz信号控制秒计时。分频方法使用计数器实现,原理为将50MHz信号计数50000000次就是1秒,将50000000计数分为0~25000000和25000000~50000000两段,计数值在0~25000000时输出低电平,25000000~50000000时输出高电平,得到的信号就是1Hz的信号。模块框图如下图所示

time_ctrl模块
该模块功能为通过外部的时间控制按键控制主路绿灯和支路绿灯的时间。外部按键首先通过按键消抖模块消抖,然后使用消抖后的按键控制绿灯时间。模块框图如下图所示:

消抖模块一方面将按键的机械抖动消除,另一方面将按键信号转换为一个时钟周期的高电平时间。按键包括主路绿灯加键、主路绿灯减键、支路绿灯加键、支路绿灯减键。当加键按下时,绿灯时间加1,当加到99时不再响应按键。当按下减按键时,绿灯时间减1,当减到5时,不再响应按键按下。主路支路都有对应按键,一共4个按键,分别对应主路加减和支路加减。
4.?仿真图
代码设计完成后,编写testbench对代码进行仿真,仿真工具为Modelsim,对应不同模块的仿真图如下:
4.1 VGA时序控制部分仿真图
aiso_rst模块仿真图如下图所示,图中可以看到,输入的reset信号为低电平有效,且输入与时钟clk的上升沿不对齐,经过时钟同步后,输出的reset_s信号与clk信号的时钟上升沿对齐,即将异步的复位信号转换为同步复位信号。

vga_sync模块仿真图如下图所示,图中可以看到25MHz的时钟通过50MHz的系统时钟分频得到,即VGA_CLK频率为系统时钟clk的一半。
hsync信号和vsync信号通过计数器计数控制,其中hcount从0开始计数,计数到最大799,vcount从零开始计数,计数最大到524。

下图为完整的一行数据时序图,图中可以看到,在hcount从0计数到799后,第0行扫描完成,Vcount加1,开始扫描第1行。以此类推一直扫描到第479行。

下图为完整的行扫描时序,可以看到VGA_BLANK_N信号、Video_on信号、hsync信号和vsync信号的时序关系。

下图可以看到VGA_BLANK_N信号在hcount计数到639时变为低电平。

下图可以看到VGA_BLANK_N信号在hcount计数到799时变为高电平。

graphic_generator模块仿真图如下所示,可以看到程序中描述的XY轴范围内的线条对应与图中的_on信号,下图中_on信号为高电平时,表示显示对应的线条。与_on对应的_rgb信号表示该线条的颜色。

4.2 交通灯控制模块部分仿真图
RGY模块仿真图如下图所示,图中默认的主路绿灯时间为30s,主路黄灯时间为5s,支路绿灯为20s,黄灯为5s。R1,G1,Y1对应主路的红灯、绿灯、黄灯信号,高电平表示对应的灯亮。R2,G2,Y2对应支路的红灯、绿灯、黄灯信号,高电平表示对应的灯亮。R1_BCD,G1_BCD,Y1_BCD对应主路的红灯、绿灯、黄灯的正计时时间。R2_BCD,G2_BCD,Y2_BCD对应支路的红灯、绿灯、黄灯的正计时时间。可以看到,主路支路的红绿灯亮灭变化正确,且对应的亮灯时间也正确。


下图为SMG模块的仿真图,该模块接收主路和支路红黄绿三种灯的控制信号和对应灯计数计数信号,再将其转换为倒计时。图中R1,G1,Y1对应主路的红灯、绿灯、黄灯信号。R2,G2,Y2对应支路的红灯、绿灯、黄灯信号。R1_BCD,G1_BCD,Y1_BCD对应主路的红灯、绿灯、黄灯的正计时时间。R2_BCD,G2_BCD,Y2_BCD对应支路的红灯、绿灯、黄灯的正计时时间。最终计算得到的倒计时时间分别为主路倒计时SMG1和支路倒计时SMG2。图中可以看到,倒计时与对应的红绿灯匹配,计时正确。


Display模块仿真图如下图所示,以主路倒计时为29,举例说明,图中主路十位为2,个位为9,根据数码管显示原理,2对应的编码为0100100,9对应的编码为0010000,对应仿真图的HEX3和HEX2,可以看到仿真图的编码正确。

Clock模块通过计时分频得到1Hz信号,分频截图如下所示。可以看到输出的1Hz信号低电平时间和高电平时间分别占一半,即占空比为50%。

time_ctrl模块用于调整交通灯的时间,按键分为主路绿灯加、减按键和支路绿灯加、减按键。下图可以看到,主路绿灯加按下后,主路绿灯时间由30变为31,按下主路绿灯减按键,又从31变为30。同理可以看到支路绿灯在加减按键的控制下,从20变为21,22,又变为21。因此按键控制模块仿真正确。

5. 结论
经过对代码的仿真调试后,对代码进行管脚分配后实际下载到开发板验证,验证经过如下图所示,图中完整的显示了主路、支路的位置,并且在每个路口有对应的红黄绿三色信号灯指示车辆的通行和停止,并且每个路口有供行人通行的斑马线。经过实际测试,交通灯信号变化符合设计要求,每个灯对应的倒计时在数码管显示正确,且可以通过开发板按键控制主路和支路的通行时间。

点击链接获取代码文件:http://www.hdlcode.com/index.php?m=home&c=View&a=index&aid=247
1256