赞
踩
实现功能:十字路口A和B两个方向用红灯20秒、黄灯5秒、绿灯9秒的方式变化,数码管同时倒计时显示通行或禁止通行时间。
所需模块:
1.数码管动态扫描子模块
2.数码管显示子模块
3.1秒时钟产生子模块
4.9s-5s-20s-20s顺序计时子模块
5.20s-20s-9s-5s顺序计时子模块
6.mealy四状态机子模块
7.顶层运用模块
应用原理及方法:
状态机:MOORE状态机、MEALY状态机
仿真:
1.将各个功能模块化,分别测试各个模块的功能是否正确。
2.仿真初值设置,采用rst按键复位产生初值。
代码:
顶层模块:
- module main(clk,dig,rst,seg,ledA,ledB);
- input clk;
- output ledA,ledB;
- input rst;
- output dig;
- output seg;
- wire [3:0]dig;
- wire [7:0]seg;
- wire [2:0]ledA,ledB;
- wire clk_1Hz;//1Hz
- wire clkA,clkB;//15s
- wire clk_scan;//动态扫描频率
- wire [3:0]cntA_1,cntA_2;
- wire [3:0]cntB_1,cntB_2;
-
- CLK_1S CLK1S(.clk_100MHz(clk),.clk_1Hz(clk_1Hz));//产生1Hz时钟
- CLK_A A1(.clk_1Hz(clk_1Hz),.clk_out(clkA),.cnt_1(cntA_1),.cnt_2(cntA_2));//产生周期为15秒时钟
- CLK_B B1(.clk_1Hz(clk_1Hz),.clk_out(clkB),.cnt_1(cntB_1),.cnt_2(cntB_2));
- CLK_SCAN S1(.clk_100MHz(clk),.clk_scan(clk_scan));//产生3KHz扫描时钟
- DIG_SEG D1(.clk_sel(clk_scan),.dig(dig),.seg(seg),.seg1(cntB_2),.seg2(cntB_1),.seg3(cntA_2),.seg4(cntA_1));//数码管显示
- STATEA L1(.clk_in(clkA),.rst(rst),.currentstate(ledA));
- STATEB L2(.clk_in(clkB),.rst(rst),.currentstate(ledB));
- endmodule
1秒时钟产生子模块:
BASYS 3的时钟为100MHz,100M个周期,即是一秒。T=1S时,0.5S反转一次。所以这里用到一个cnt,计数50M满,1s输出信号跳变,cnt==28'b10111110101111000010000000,50 000 000。
- //时钟分频模块:将Basys3上的100MHz时钟clk分频到1Hz输出,作为15秒倒计时计数时钟clk_1hz ;
- module CLK_1S(clk_100MHz,clk_1Hz);
- input clk_100MHz;//100M时钟输入
- output reg clk_1Hz;//输出1s
- reg [27:0] cnt;
-
- always @(posedge clk_100MHz)
- begin
- if(cnt==28'b0010_1111_1010_1111_0000_1000_0000)//100MHz/1Hz
- begin
- cnt <=0;//清零
- clk_1Hz <= ~clk_1Hz;
- end
-
- else
- cnt <= cnt + 1;
- end
- endmodule
9s-5s-20s-20s顺序计时子模块:
- module CLK_A(clk_1Hz,clk_out,cnt_1,cnt_2);
- input clk_1Hz;//1s
- output reg clk_out;//15s
- output cnt_1,cnt_2;//两位记数 0-9
- reg [4:0]cnt;//0-15
- wire [3:0]cnt_1;//十位
- wire [3:0]cnt_2;//个位
- reg [1:0]sig;
-
- assign cnt_1 =cnt/'b1010; //十位除10
- assign cnt_2 =cnt%'b1010;//各位余10
-
-
-
-
- always @(posedge clk_1Hz)//产生两位数
- begin
- if(cnt==5'b00000||cnt==5'b11111)begin // cnt0-14 不需要到达1
- case(sig)
- 2'b00:begin
- cnt<=5'b01001; //9
- sig<=sig+'b1;
- clk_out<=1;
- end
- 2'b01:begin
- cnt<=5'b00101; //5
- sig<=sig+'b1;
- clk_out<=1;
- end
- 2'b10:begin
- cnt<=5'b10100; //20
- sig<=sig+'b1;
- clk_out<=1;
- end
- 2'b11:begin
- cnt<=5'b10100; //20
- sig<=sig+'b1;
- clk_out<=1;
- end
- endcase
- end
-
- else begin
- cnt <= cnt -'b1;
- clk_out<=0;
- end
- end
- endmodule
20s-20s-9s-5s顺序计时子模块:
- module CLK_B(clk_1Hz,clk_out,cnt_1,cnt_2);
- input clk_1Hz;//1s
- output reg clk_out;//15s
- output cnt_1,cnt_2;//两位记数 0-9
- reg [4:0]cnt;//0-15
- wire [3:0]cnt_1;//十位
- wire [3:0]cnt_2;//个位
- reg [1:0]sig;
-
- assign cnt_1 =cnt/'b1010; //十位除10
- assign cnt_2 =cnt%'b1010;//各位余10
-
-
-
- always @(posedge clk_1Hz)//产生两位数
- begin
- if(cnt==5'b00000||cnt==5'b11111)begin // cnt0-14 不需要到达1
- case(sig)
- 2'b00:begin
- cnt<=5'b10100; //20
- sig<=sig+'b1;
- clk_out<=1;
-
- end
- 2'b01:begin
- cnt<=5'b10100; //20
- sig<=sig+'b1;
- clk_out<=1;
- end
- 2'b10:begin
- cnt<=5'b01001; //9
- sig<=sig+'b1;
- clk_out<=1;
- end
- 2'b11:begin
- cnt<=5'b00101; //5
- sig<=sig+'b1;
- clk_out<=1;
- end
- endcase
- end
-
- else begin
- cnt <= cnt -'b1;
- clk_out<=0;
- end
- end
- endmodule
数码管动态扫描子模块:
- //100MHz分频到2.5KHz~4KHz输出,作为数码管动态显示的扫描频率clk-scan,3Khz动态扫描
- module CLK_SCAN(clk_100MHz,clk_scan);
- input clk_100MHz;
- output reg clk_scan;
- reg [15:0] cnt;
-
- always @(posedge clk_100MHz)
- begin
- cnt <= cnt + 1;
- if(cnt==16'b1000_0010_0011_0101)//100MHz/33333Hz
- begin
- cnt <=0;//清零
- clk_scan <= ~clk_scan;
- end
- end
- endmodule
数码管显示子模块:
- odule DIG_SEG(clk_sel,seg1,seg2,seg3,seg4,dig,seg);
- input clk_sel;
- input [3:0]seg1,seg2,seg3,seg4;
- output dig,seg;
- reg [3:0]dig;
- reg [7:0]seg;
- reg [1:0]selcnt;
-
-
- //parameter seg_0=8'b11000000;
- //parameter seg_1=8'b11111001;
- //parameter seg_2=8'b10100100;
- //parameter seg_3=8'b10110000;
- //parameter seg_4=8'b10011001;
- //parameter seg_5=8'b10010010;
- //parameter seg_6=8'b10000010;
- //parameter seg_7=8'b11111000;
- //parameter seg_8=8'b10000000;
- //parameter seg_9=8'b10010000;
-
-
- always @(posedge clk_sel)//位选标志位
- begin
- selcnt <= selcnt + 1;//标志位+1,11记满后加一回到00
- end
-
- always @(selcnt) //位选信号控制
- begin
- case (selcnt)
- 2'b00: begin dig <= 4'b0111;end //1号数码管显示ain对应的段码
- 2'b01: begin dig <= 4'b1011;end
- 2'b10: begin dig <= 4'b1101;end
- 2'b11: begin dig <= 4'b1110;end
- endcase
- end
-
- always @(selcnt or seg1 or seg2 or seg3 or seg4) //位选信号控制
- begin
- if (selcnt==2'b00)
- begin
- case(seg1)
- 4'b0000:seg <= 8'b11000000;
- 4'b0001:seg <= 8'b11111001;
- 4'b0010:seg <= 8'b10100100;
- 4'b0011:seg <= 8'b10110000;
-
- 4'b0100:seg <= 8'b10011001;
- 4'b0101:seg <= 8'b10010010;
- 4'b0110:seg <= 8'b10000010;
- 4'b0111:seg <= 8'b11111000;
-
- 4'b1000:seg <= 8'b10000000;
- 4'b1001:seg <= 8'b10010000;
- default: seg<=8'b11000000;
- endcase
- end
-
- if (selcnt==2'b01)
- begin
- case(seg2)
- 4'b0000:seg <= 8'b11000000;
- 4'b0001:seg <= 8'b11111001;
- 4'b0010:seg <= 8'b10100100;
- 4'b0011:seg <= 8'b10110000;
-
- 4'b0100:seg <= 8'b10011001;
- 4'b0101:seg <= 8'b10010010;
- 4'b0110:seg <= 8'b10000010;
- 4'b0111:seg <= 8'b11111000;
-
- 4'b1000:seg <= 8'b10000000;
- 4'b1001:seg <= 8'b10010000;
- default: seg<=8'b11000000;
- endcase
- end
-
- if (selcnt==2'b10)
- begin
- case(seg3)
- 4'b0000:seg <= 8'b11000000;
- 4'b0001:seg <= 8'b11111001;
- 4'b0010:seg <= 8'b10100100;
- 4'b0011:seg <= 8'b10110000;
-
- 4'b0100:seg <= 8'b10011001;
- 4'b0101:seg <= 8'b10010010;
- 4'b0110:seg <= 8'b10000010;
- 4'b0111:seg <= 8'b11111000;
-
- 4'b1000:seg <= 8'b10000000;
- 4'b1001:seg <= 8'b10010000;
- default: seg<=8'b11000000;
- endcase
- end
-
- if (selcnt==2'b11)
- begin
- case(seg4)
- 4'b0000:seg <= 8'b11000000;
- 4'b0001:seg <= 8'b11111001;
- 4'b0010:seg <= 8'b10100100;
- 4'b0011:seg <= 8'b10110000;
-
- 4'b0100:seg <= 8'b10011001;
- 4'b0101:seg <= 8'b10010010;
- 4'b0110:seg <= 8'b10000010;
- 4'b0111:seg <= 8'b11111000;
-
- 4'b1000:seg <= 8'b10000000;
- 4'b1001:seg <= 8'b10010000;
- default: seg<=8'b11000000;
- endcase
- end
-
- end
-
- endmodule
A路状态机:利用sig标志位控制红灯亮两次,sig=0,为红灯时,状态不跳转,红灯显示一次,sig加1。sig=1,为红灯时,状态下一次翻转。
- module STATEA(clk_in,rst,currentstate);
- input clk_in;
- input rst;
- output reg [2:0]currentstate;
- reg [2:0]nextstate;
- reg sig;
- parameter S0=3'b001;
- parameter S1=3'b010;
- parameter S2=3'b100;
- always @(posedge clk_in or posedge rst)
- begin
- if(rst)
- currentstate<=S0;
- else begin
- currentstate<=nextstate;
- if(currentstate==S2)
- sig<=sig+1;
- end
- end
- always @(currentstate or sig)
- begin
- case(currentstate)
- S0:nextstate=S1;
- S1:nextstate=S2;
- S2:begin
- if(sig)
- nextstate=S0;
- else
- nextstate=S2;
- end
- default: nextstate=S1;
- endcase
- end
- endmodule
B路状态机:
- module STATEB(clk_in,rst,currentstate);
- input clk_in;
- input rst;
- output reg [2:0]currentstate;
- reg [2:0]nextstate;
- reg sig;
- parameter S0=3'b001;
- parameter S1=3'b010;
- parameter S2=3'b100;
- always @(posedge clk_in or posedge rst)
- begin
- if(rst)
- currentstate<=S2;
- else begin
- currentstate<=nextstate;
- if(currentstate==S2)
- sig<=sig+1;
- end
- end
- always @(currentstate or sig)
- begin
- case(currentstate)
- S0:nextstate=S1;
- S1:nextstate=S2;
- S2:begin
- if(sig)
- nextstate=S0;
- else
- nextstate=S2;
- end
- default: nextstate=S1;
- endcase
- end
- endmodule
工程文件实例:
代码改进,若需要不同时间的红绿灯,只需要重新设置在顺序计时模块中的时间条件即可。
红绿灯系统的目标是优化交通流量,提高交通效率和安全性。单个的红绿灯设计可以帮助我们对状态机的理解。
但是在实际生活中,红绿灯是一个庞大的系统,一条主干道上有很多的红绿灯,需要对实际路况和车流量和道路宽窄设计转换时间,并且需要和多个红绿灯协同运作。这样的设计才能解决实际性问题。
当然,现代的红绿灯系统已经很完善了,缺少的是对路况和人车流量的智能检测和分析。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。