**这是本文档旧的修订版!**
简易交通灯
本节将向您介绍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))
clkp⇐0;
else
clk_p⇐1;
end
always @ (negedge clk)
begin
if(!rstn)
clkn⇐0;
else if (cntn<(N»1))
clkn⇐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 , 时钟
rstn , 复位
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进行开发的一项必会技能,本小节的交通灯程序即是利用三段式状态机描述方法实现的,希望读者能够快速掌握这项技能。