概述
有限状态机交通灯的实现
- 一、 实验目的
- 二、 实验内容
- 1. 实验流程
- 2. Verilog代码分析
- (1) Design source(.v文件):
- clkdivtransport.v:
- transport.v:
- (2) Constraints source(.xdc文件)
- (3) Elaborated design:
- 三、 实验结论
- 四、 思考与讨论
- (一) 问题与提升
- (二) 实验感想:
一、 实验目的
设计一个交通灯控制器,要求实现功能:
- 交通灯位于四个方向(东南西北)
- 南北和东西向在同一时间亮相同的灯
- 灯变化的次序为:绿-黄-红,循环
- 南北和东西向灯不同时为绿灯或黄灯
- 灯的持续时间:绿9s,黄-3s,红-9s
用verilog语言描述有限状态机的功能,熟悉有限状态机原理,了解用计数器控制时间等方法。
二、 实验内容
1. 实验流程
① 分析实验目的,在实验中南北东西的交通灯一共有四种状态,因为南北,东西在同一时刻分别具有相同的状态,故南北灯,东西灯可以分别由3个灯——红,黄,绿灯表示状态。
② 以led[2:0]依次表示南北灯的绿灯,黄灯,红灯,以led[5:3]依次表示东西灯的绿灯、黄灯、红灯。状态表如下:
③ 根据状态表,利用计数器完成verilog代码并上板实验。
2. Verilog代码分析
(1) Design source(.v文件):
clkdivtransport.v:
module clkdivtransport(
input CLK100MHZ,
input reset,
output [5:0]LED,
output clk1HZ
);
reg [100:0]count1;
always@(posedge CLK100MHZ)
begin
if(count1==100000000)count1<=0;
else count1<=count1+1;
end
assign clk1HZ=(count1<50000000?0:1); //分频得到1hz的时钟信号
transport x1(.CP(clk1HZ),.reset(reset),.led(LED));
endmodule
transport.v:
module transport(
input CP,
input reset,
output reg [5:0]led
);
wire t1,t2,t3,t4;
reg ST,LT;
reg [5:0]count;
assign t1=led[3]&led[2];
assign t2=led[3]&led[1];
assign t3=led[5]&led[0];
assign t4=led[4]&led[0];
always@(posedge CP)
begin
if(!reset)begin ST=0;LT=0;count=0;led=6'b001100;end//清零
if(count==9)begin LT<=1;count<=0;end//长短时间
else if(count==3)begin ST<=1;count=count+1;end
else begin count<=count+1;ST<=0;LT<=0;end
if(t1<)led=6'b001010;
else if(t2&ST)led=6'b100001;
else if(t3<)led=6'b010001;
else if(t4&ST)led=6'b001100;
else led<=led;
end
endmodule
.v分析:
clkdivtransport.v:
① Input时钟信号CLK100MHZ,清零信号reset,output交通灯状态[5:0]LED,output一个1hz的时钟信号clk1HZ 。
② 定义一个reg变量作为计数信号,通过计数器将100MHZ的时钟信号分频为 1HZ的时钟信号。
③ 调用transport模块,输入1HZ的时钟信号
transport.v:
① Input时钟吸纳后CP,清零信号reset,output交通灯状态[5:0]led。
② 定义四个wire类型变量t1,t2,t3,t4,用assign语句赋值表示当前状态。
③ 定义短时钟ST表示已经过一个3s,长时钟信号LT表示已经过一个9s。
④ 定义6位count向量作为计数信号。
⑤ 在时钟上升沿执行always语句,清零操作具有第一优先级,当清零信号为0时,短时钟信号和长时钟信号都置数为0,交通灯状态返回初始状态:001100,即南北亮绿灯,东西亮红灯。
⑥ 没有进行清零操作时,若count为9,长时钟信号赋值为1,count赋值为0;否则,若count为3,短时钟信号赋值为1,count加一;否则count加一且ST,LT归零
⑦ 若处于第一状态且长时钟信号为1,则从第一状态转换到第二状态;若处于第二状态且短时钟信号为1,则从第二状态转换到第三状态;若处于第三状态且长时钟信号为1,则从第三状态转换到第四状态;若处于第四状态且短时钟信号为1,则从第四状态转换到第三状态。其他时刻led灯状态保持上一时刻状态。
(2) Constraints source(.xdc文件)
## Clock signal
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { CLK100MHZ }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {CLK100MHZ}];
##switches
set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { reset }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
## LEDs
set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { LED[0] }]; #IO_L18P_T2_A24_15 Sch=led[0]
set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { LED[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1]
set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { LED[2] }]; #IO_L17N_T2_A25_15 Sch=led[2]
set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { LED[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { LED[4]}]; #IO_L7P_T1_D09_14 Sch=led[4]
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { LED[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5]
set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { clk1HZ }]; #IO_L17P_T2_A14_D30_14 Sch=led[6]
.xdc分析
① 每个引脚两行语句:第一行代表引脚在实验板上的位置;第二行代表输入输出标准电平3.3V
② 引脚锁定文件使用到的引脚名称与design source中所使用到变量名称相对应
(3) Elaborated design:
三、 实验结论
本次实验中,通过理解题意,作出有限状态机的状态表,再通过状态表实现有限状态机,最终完成了每隔9s或3s代表南北、东西交通灯的led灯进行对称跳变的上板实验。同时通过计数器对时钟信号进行分频,我了解到偶数分频和奇数分频的写法,增加了一些经验。对于9s,3s等不同时间标志的设置,我对计数器在电路中的多种应用有了更加深刻的印象。
四、 思考与讨论
(一) 问题与提升
① 本次实验中,我采用了直接根据本状态(t1,t2,t3,t4是否为1,他们的赋值为每个状态为1的位数的与)和长短时间标志判断下一状态。
② 实际可以根据状态表写出每个led位数的布尔表达式,再根据时钟信号进行赋值操作。
③ 此外,我尝试了另一种完成该实验的方式,其电路图如下:
top.v:
module transtop(
input reset,//清零信号
input CLK100MHZ,//实验板时钟信号
output [5:0]led
//输出交通灯状态
//led[5:3]分别表示南北方向的绿、黄、红灯状态
//led[2:0]分别表示东西方向的绿、黄、红灯状态
);
wire CLK;
clkdivtransport div1(.mclk(CLK100MHZ),.clk12(CLK));
wire [1:0] EN;
//使能信号EN,多路选择器的控制信号,4种排列决定交通灯的4种状态
twobitcounter c1(.CP(CLK),.reset(reset),.EN(EN));
//调用2位计数器,EN在时钟信号控制下发生0-3-0循环
transportlight t1(.EN(EN),.led(led));
//EN选择交通灯状态
endmodule
clkdivtransport.v:
module clkdivtransport(
input mclk,
output clk12//hz=1/12
);
reg count1,count2;
wire clk1HZ;
always@(posedge mclk)
begin
if(count1==100000000)count2<=0;
else count1<=count1+1;
end
assign clk1HZ=count1<50000000?0:1; //先分频得到1hz的时钟信号
always@(posedge clk1HZ)
begin
if(count2==12)count2<=0;
else count2<=count2+1;
end
assign clk12=count2<9?0:1;
endmodule
twobitcounter.v:
module twobitcounter(
input CP,
input reset,//清零
output reg [1:0]EN//控制交通灯状态的信号
);
wire [1:0]D;
wire load;
assign load=~(EN[1]&EN[0]);//当EN=2’b11时,load=0,在下一时钟周期中EN载入数据D00
assign D=2'b00;
always@(posedge CP or negedge CP or negedge reset)
begin
if(!reset&&!CP)
EN<=0;
else if(!load)
EN<=D;
else
EN<=EN+1;
end
//若在CP上升沿执行always,此时从已经持续9s的低电平转向持续3s的高电平
//若在CP下降沿执行always,此时从已经持续3s的高电平转向持续9s的低电平
//当EN=2'b11时,load=0,11保持3s后CP下降沿进入always,EN载入D=2'b00的值,形成循环
/*当拨动开关reset=0且CP处在低电平时,可以进行清零操作EN=2'b00,
这是因为一个周期内高电平和低电平时间不等,
异步清零操作下:
if(!reset):若在CP高电平清零,0~3s期间若再将reset拨回1,则接下来的CP下降沿执行EN+1,01状态将保持9s,这与交通灯要求不一致;
if(!reset&&!CP) 若在CP低电平清零,则若遇到上升沿,即使reset信号保持为0,EN仍执行+1操作,下一次下降沿继续清零
同步清零操作下:
if(!reset):若在CP上升沿清零,00保持3s遇到下降沿,期间若拨reset为1,则下降沿后01保持9s,不符要求
if(!reset&&!CP)若CP下降沿清零,00保持9s遇到上升沿,即使reset信号保持为0,EN仍执行+1操作,下一次下降沿继续清零
解决意见:
虽然if(!reset&&!CP)条件下,异步清零操作可能会有0~3s延时,同步0~12s延时,
但为了避免对应交通灯状态持续时长的混乱,
仍采用此条件,同时为了避免该条件清零操作下出现的01状态,当清零成功时,即状态转变为N-S:Green,E-W:Red时,
应迅速将reset拨回1*/
Endmodule
tranportlight.v:
module transportlight(
output reg[5:0]led,
input [1:0]EN
);
always@(*)
begin
case(EN)
2'b00:led<=6'b100_001;//N-S:Green,E-W:Red,保持9s
2'b01:led<=6'b010_001;//N-S:Yellow,E-W:Red,保持3s
2'b10:led<=6'b001_100;//N-S:Red,E-W:Green,保持9s
2'b11:led<=6'b001_010;//N-S:Red,E-W:Yellow,保持3s
endcase
end
endmodule
transportlight.xdc:
##Clock signal
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { CLK100MHZ }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {CLK100MHZ}];
##Switches
set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { reset }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
## LEDs
set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; #IO_L18P_T2_A24_15 Sch=led[0]
set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1]
set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_L17N_T2_A25_15 Sch=led[2]
set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { led[4] }]; #IO_L7P_T1_D09_14 Sch=led[4]
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { led[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5]
(二) 实验感想:
本次实验中,我访问了许多网站,请教了老师和同学,对有限状态机以及其他逻辑部件的原理和应用都有了更加深入的理解。
最后
以上就是天真咖啡豆为你收集整理的数字逻辑——有限状态机交通灯一、 实验目的二、 实验内容三、 实验结论四、 思考与讨论的全部内容,希望文章能够帮你解决数字逻辑——有限状态机交通灯一、 实验目的二、 实验内容三、 实验结论四、 思考与讨论所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复