**这是本文档旧的修订版!**

简易交通灯

本节将向您介绍Verilog语法之中的精髓内容——状态机,并且将利用状态机实现十字路口的交通灯。


====硬件说明与实现项目框图====

上图为十字路口交通示意图分之路与主路,要求如下: * 交通灯主路上绿灯持续15s的时间,黄灯3s的时间,红灯10s的时间; * 交通灯支路上绿灯持续7s的时间, 黄灯持续3秒的时间,红灯18秒的时间; 根据上述要求,状态机设计框架分析如下: * S1:主路绿灯点亮,支路红灯点亮,持续15s的时间; * S2:主路黄灯点亮,支路红灯点亮,持续3s的时间; * S3:主路红灯点亮,支路绿灯点亮,持续10s的时间; * S4:主路红灯点亮,支路黄灯点亮,持续3s的时间; } ====Verilog代码==== —— 首先是时钟分频部分: <code verilog> Copyright©2016, STEP FPGA All rights reserved File name : divide.v Module name : divide Author : STEP Email : info@stepfpga.com Data : 2016/08/01 Version : V1.0 Description :
Modification history —————————————————————————- Version
Description

DEFINE MODULE PORT module divide ( INPUT clk , rstn , OUTPUT clkout ); DEFINE PARAMETER parameter WIDTH = 3; parameter N = 5; DEFINE INPUT * input clk,rst_n;
DEFINE OUTPUT output clkout; OUTPUT ATTRIBUTE REGS reg [WIDTH-1:0] cntp,cntn; reg clkp,clkn; assign clkout = (N==1)?clk:(N[0])?(clkp&clkn):clkp; Sequential logic style always @ (posedge clk) begin if(!rstn) cntp⇐0; else if (cntp==(N-1)) cntp⇐0; else cntp⇐cntp+1; end always @ (negedge clk) begin if(!rstn) cntn⇐0; else if (cntn==(N-1)) cntn⇐0; else cntn⇐cntn+1; end always @ (posedge clk) begin if(!rstn) clkp⇐0; else if (cntp<(N»1))
clk
p⇐0; else clk_p⇐1; end always @ (negedge clk) begin if(!rstn) clkn⇐0; else if (cntn<(N»1))
clk
n⇐0; else clk_n⇐1; end endmodule
</code>
接下来就是利用三段式状态机实现的交通灯部分: <code verilog>
»»»»»»»»»»»»> COPYRIGHT NOTICE ««««««««««««< File name : traffic.v Module name : traffic Author : STEP Description : Web : www.stepfpga.com ——————————————————————– Code Revision History : ——————————————————————– Version: |Mod. Date: |Changes Made: V1.0 |2017/03/02 |Initial ver ——————————————————————– Module Function:简易交通灯 module traffic ( clk , 时钟 rst
n , 复位 out 三色led代表交通灯 ); input clk,rstn;
output reg[5:0] out; parameter S1 = 4'b00, 状态机状态编码 S2 = 4'b01, S3 = 4'b10, S4 = 4'b11; parameter times1 = 4'd15, 计时参数 times2 = 4'd3, times3 = 4'd10, times4 = 4'd3; 交通灯的控制 parameter leds1 = 6'b101011, LED2 绿色 LED1 红色 leds2 = 6'b110011, LED2 蓝色 LED1 红色 leds3 = 6'b011101, LED2 红色 LED1 绿色 leds4 = 6'b011110; LED2 红色 LED1 蓝色 reg [3:0] timecont; reg [1:0] curstate,nextstate; 现态、次态 wire clk1h; 1Hz时钟 产生1秒的时钟周期 divide #(.WIDTH(32),.N(12000000)) CLK1H ( .clk(clk), .rstn(rstn), .clkout(clk1h)); 第一段 同步逻辑 描述次态到现态的转移 always @ (posedge clk1h or negedge rstn) begin if(!rstn) curstate ⇐ S1; else curstate ⇐ nextstate; end 第二段 组合逻辑描述状态转移的判断 always @ (curstate or rstn or timecont) begin if(!rstn) begin nextstate = S1; end else begin case(curstate) S1:begin if(timecont==1) nextstate = S2; else nextstate = S1; end S2:begin if(timecont==1) nextstate = S3; else nextstate = S2; end S3:begin if(timecont==1) nextstate = S4; else nextstate = S3; end S4:begin if(timecont==1) nextstate = S1; else nextstate = S4; end default: nextstate = S1; endcase end end 第三段 同步逻辑 描述次态的输出动作 always @ (posedge clk1h or negedge rstn) begin if(!rstn==1) begin out ⇐ leds1; timecont ⇐ times1; end else begin case(nextstate) S1:begin out ⇐ leds1; if(timecont == 1) timecont ⇐ times1; else timecont ⇐ timecont - 1; end S2:begin out ⇐ leds2; if(timecont == 1) timecont ⇐ times2; else timecont ⇐ timecont - 1; end S3:begin out ⇐ leds3; if(timecont == 1) timecont ⇐ times3; else timecont ⇐ timecont - 1; end S4:begin out ⇐ leds4; if(timecont == 1) timecont ⇐ times4; else timecont ⇐ timecont - 1; end default:begin out ⇐ led_s1; end endcase end end endmodule </code>

====引脚分配==== ——- 小脚丫上正好有4路按键和4路开关,可以用来作为输入信号分别控制数码管的输出。按照下面表格定义输入输出信号
^信号 ^引脚 ^信号 ^引脚 ^
|clk |C1 |rst |L14 ^ |out[0] |P2 |out[1] |N2 ^ |out[2] |M2 |out[3] |P4 ^ |out[4] |N3 |out[5] |M3 ^

配置好以后编译下载程序。您也可以试试修改程序,观察修改代码对于FPGA内部电路所造成的影响。
====小结==== —— 状态机是一类很重要的时序逻辑电路,是许多数字系统的核心部件,掌握状态机的使用是利用FPGA与CPLD进行开发的一项必会技能,本小节的交通灯程序即是利用三段式状态机描述方法实现的,希望读者能够快速掌握这项技能。