目录
一、实验目的
二、设计要求
三、实验代码
1.design source文件代码
2.仿真文件代码
3.代码原理分析
四、实验结果及分析
1、引脚锁定
2、仿真波形及分析
3、下载测试结果及分析
五、实验心得
1.解决实验中遇见的问题及解决
2.实验完成的心得
(1)熟悉交通灯控制器的工作原理;
(2)掌握状态机的设计;
(3)掌握用Verilog语言实现较复杂时序电路的设计过程。
实现一个由一条主干道和一条乡间公路形成的十字路口的交通灯控制器功能:
(1)有MR(主红)、MY(主黄)、MG(主绿)、CR(乡红)、CY(乡黄)、CG(乡绿)六盏交通灯需要控制;
(2)交通灯由绿转红前有4秒亮黄灯的间隔时间,由红转绿没有间隔时间;
(3)乡间公路右侧各埋有一个串连传感器,当有车辆准备通过乡间公路时,发出请求信号S=1,其余时间S=0;
(4)平时系统停留在主干道通行(MGCR)状态,一旦S信号有效,经主道黄灯4秒(MYCR)状态后转入乡间公路通行(MRCG)状态,但要保证主干60s后才能转换;
(5)一旦S信号消失,系统脱离MRCG状态,即经乡道黄灯4秒(MRCY)状态进入MGCR状态,即使S信号一直有效,MRCG状态也不得长于20秒钟。
`timescale 1ns / 1ps
module traffic(clk,Traffic_Light,s,sout,rst,count_display);//,cnt,state,clk1
input clk,s,rst;//clk时钟信号输入,s来车信号(开关),rst复位信号输入(按钮)
output[10:0] count_display;//数码管输出
output[5:0] Traffic_Light;//5-3主 2-0乡 (led*6)
output sout;//sout来车信号显示(led)
//定义交通灯的各种状态
parameter[5:0] MGCR=6'b001100,MYCR=6'b010100,MRCG=6'b100001,MRCY=6'b100010;
reg[5:0] state;
reg[15:0] cnt;
reg[5:0] Traffic_Light;
reg clk1,sout;
//进行状态初始化
initial
begin
cnt<=59; //60s倒计时
state<=MGCR;
Traffic_Light<=MGCR;
end
//分频:
reg[26:0] clk_cnt;
reg [2:0] sel=3'b0;
always @(posedge clk)
begin
clk_cnt=clk_cnt+1;
if(clk_cnt==100000000)
begin
clk_cnt=0;
clk1=1'b1;
end
else
clk1=1'b0;
if(clk_cnt%100000==0)
begin
sel=sel+1;
if(sel==3)
sel=0;
end
end
display SG_display(
.clk (clk),
.rst (rst),
.counter (cnt),
.count_display (count_display),
.sel(sel)
);
always @(s)
begin
if(s==1) sout=1;
else sout=0;
end
//状态转移
always @(posedge clk1 or negedge rst)
if(!rst)begin state<=MGCR;cnt<=16'd59;end
else begin
case (state)
MGCR:if (cnt==0)
begin
if(s==1)begin Traffic_Light<=MYCR; cnt<=3;
state<=MYCR; end
//如果s信号为0,则回到初始状态,开始60s倒计时
else cnt<=59;
end
//开始60s倒计时
else cnt<=cnt-1;
//主红乡黄状态后,仍然s=1,则开始20s倒计时状态
MYCR:if (cnt==0)begin Traffic_Light<=MRCG; cnt<=19;state<=MRCG;end
else cnt<=cnt-1;
//经过乡道黄灯4s后,进入MGCR状态
MRCG:if (cnt==0||s==0) begin Traffic_Light<=MRCY; cnt<=3;state<=MRCY;end
else cnt<=cnt-1;
//4s倒计时结束后,进入主绿乡红状态,数码管60s倒计时
MRCY:if (cnt==0) begin Traffic_Light<=MGCR; cnt<=59;state<=MGCR;end
else cnt<=cnt-1;
default: state<=MGCR;
endcase
end
endmodule
`timescale 1ns / 1ps
module traffic_tb();
reg clk,rst,s;
wire sout;
wire[5:0] Traffic_Light;
wire[5:0] state;
wire[15:0] cnt;
//开始仿真
traffic sim_traffic(
.clk(clk);
.rst(rst),
.s(s),
.sout(sout),
.Traffic_Light(Traffic_Light[5:0]),
.state(state[5:0]),
.cnt(cnt[15:0])
);
//初始化
initial begin
clk = 0;
rst = 1;
s = 0;
#3250
s = 1;
#1000
s = 1;
end
always #10 clk = ~clk;
endmodule
在本实验中,最最重要的就是对状态机的设计,在此设计了 4 个状态。当在 s0 即 MGCR 时,执行语句如下:如果计时器为 0,则开始判断信号 S,如果信号有效,即乡间公路有车,则跳转到 s1,即 MYCR 状态,进行四秒黄灯倒计时,如果信号无效,则仍处于 MGCR 状态,重新从 60 秒开始倒计时。
当在 s1 即 MYCR 时,执行语句如下:如果计时器为 0,则进入 s2,即 MRCG状态,计时器从 20 秒开始倒计时。当在 s2 即 MRCG 时,执行语句如下:如果乡间公路信号 S 持续为 1,且 20
秒倒计时结束,计时器为 0 时,状态转换为 s3,即 MRCY 状态,进行四秒黄灯倒计时,但一旦 S 信号为 0,则立即跳出状态 s2,进入 s3 MRCY 状态。当在 s3 即 MRCY 时,执行语句如下:四秒黄灯倒计时结束后,重新回到状态 MGCR,开始 60 秒倒计时,并等待下一个状态转换。
如约束文件所示
set_property -dict { PACKAGE_PIN W5 IOSTANDARD LVCMOS33 } [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
## Switches
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports {s}]
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports {rst}]
## LEDs
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports {Traffic_Light[0]}]
set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports {Traffic_Light[1]}]
set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports {Traffic_Light[2]}]
set_property -dict { PACKAGE_PIN V19 IOSTANDARD LVCMOS33 } [get_ports {Traffic_Light[3]}]
set_property -dict { PACKAGE_PIN W18 IOSTANDARD LVCMOS33 } [get_ports {Traffic_Light[4]}]
set_property -dict { PACKAGE_PIN U15 IOSTANDARD LVCMOS33 } [get_ports {Traffic_Light[5]}]
set_property -dict { PACKAGE_PIN L1 IOSTANDARD LVCMOS33 } [get_ports {sout}]
##7 Segment Display
set_property -dict { PACKAGE_PIN W7 IOSTANDARD LVCMOS33 } [get_ports {count_display[6]}]
set_property -dict { PACKAGE_PIN W6 IOSTANDARD LVCMOS33 } [get_ports {count_display[5]}]
set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS33 } [get_ports {count_display[4]}]
set_property -dict { PACKAGE_PIN V8 IOSTANDARD LVCMOS33 } [get_ports {count_display[3]}]
set_property -dict { PACKAGE_PIN U5 IOSTANDARD LVCMOS33 } [get_ports {count_display[2]}]
set_property -dict { PACKAGE_PIN V5 IOSTANDARD LVCMOS33 } [get_ports {count_display[1]}]
set_property -dict { PACKAGE_PIN U7 IOSTANDARD LVCMOS33 } [get_ports {count_display[0]}]
首先画出状态分析图如下所示
交通灯设计对应波形及分析
首先对一些关键信号的含义
clk:时钟信号
rst:使能端
sout:即要求中的s信号
cnt:显示倒计时计数
Traffic_light:交通灯的状态
(1)在使能端有效时,从起始状态主绿乡红开始,进行60s倒计时
(2)当60s减1计数完成后,如果s信号为1(代表乡干道有车要求通过)时,变为主黄乡绿状态,数码管4s倒计时;4s倒计时后,进入主红乡绿状态,如果s信号一直为1,则数码管开始20s倒计时
观察波形很明显可以观察到60s倒计时的结束到4s倒计时的转变,在4s倒计时结束后,由于s信号依旧为1,于是进入20s倒计时状态。
(3)当20s倒计时完成后也会入主红乡黄状态。主红乡黄,数码管开始4s倒计时,计数完成后进入主绿乡红状态
(4)计数完成后进入主绿乡红状态,数码管60s倒计时,重复上述状态。
在实验室用bassy3开发板下载测试。
(1)复位时,起始状态是主绿乡红,数码管从60开始倒计时。如图1所示
(2)要求:当60s减1计数完成后,如果s信号为1(代表乡干道有车要求通过)时,变为主黄乡绿状态,数码管4s倒计时;如果s信号为0(代表乡干道没有车要求通过)时, 则回到起始状态,主绿乡红重新60s倒计时。
此时开发板s信号为1,数码管处于4s倒计时阶段,如图2所示
图3 图4
(3)分析:4s倒计时后,进入主红乡绿状态,如果此时s信号为0,则立即转入主红乡黄状态;如果s信号一直为1,则数码管开始20s倒计时,计数期间一旦出现s信号为0,则立即转入主红乡黄状态,即使s信号一直为1,当20s倒计时完成后也会入主红乡黄状态。由于此时s信号依旧为1,数码管进入20s倒计时,如图3所示
(4)分析:主红乡黄,数码管开始4s倒计时,计数完成后进入主绿乡红状态,数码管60s倒计时,重复上述状态。而此时s信号为1,重新进行60s倒计时状态,如图5所示。
实验中发现对各盏交通灯状态的判断是单独的,程序过于繁冗。
解决方法:可以将各盏交通灯的状态判断与状态机的状态联系起来,这里也参考了网上的方法,给状态机的每个状态设定一个六位参数,一个位数对应一盏交通灯的状态,1亮0灭。这样,只需要针对状态机的状态就可以判断出所有交通灯的明灭情况。
交通灯的设计实验是一项非常有意义的实践项目,通过这个实验可以更好地理解状态机的应用,并且在实际场景中体现出状态机的作用。
在这个实验中,我深刻地认识到了状态机对于交通灯控制的重要性,同时也学习到了如何使用Verilog HDL编程语言来设计状态机。
在完成这个实验的过程中,我遇到了一些问题和挑战,但最终还是成功地完成了整个实验。以下是我在实验过程中所得到的心得和体会:
本次实验是在实验三的基础上,进一步对状态机进行运用理解,完成更复杂的实验设计要求。初看到本实验要求时,觉得很繁多麻烦,但其实细细思考,运用状态机还是很容易实现的,状态机的存在确实给很多设计带来了极大的便利。当然,在程序的设计中还是遇到了许多问题,比如刚开始没有用足位的 BCD码进行倒计时的设计,导致数码管程序出现了问题,还有就是在每个状态后面都单独对交通灯的状态进行了判断,显得冗杂多余等等。只是完成一项功能的实现不难,重要的还是如何用更简洁灵活的语言去实现它,所以对实验方案程序的优化设计是十分必要的,事实上在很多领域中,如何进行更好的优化都是困扰技术人员的一大难题。在本实验中要实现的功能与前几次相比稍多,但完成后的成就感也更大,每完成一个实验,都能感受到自己在逐步进步,逐渐熟练。
2023-04-20