设计一个十字路口交通控制系统,其东西、南北两个方向除了有红、黄、绿灯指示是否允许通行外,还设有时间显示,以倒计时方式显示每一路允许通行的时间,绿灯、黄灯、红灯的持续时间分别是45、5和50秒。当东西或南北两路中任一道上出现特殊情况,例如有消防车,警车要去执行任务,此时交通控制系统应可由交警手动控制立即进入特殊运行状态,即两条道上的所有车辆皆停止通行,红灯全亮,时钟停止计时,且其数字在闪烁。当特殊运行状态结束后,管理系统恢复原来的状态,继续正常运行。
实现主干道和支干道的红绿灯,并实现时间显示功能;
实现绿灯,黄灯,红灯的持续时间固定的交通控制功能;
顶层设计模块:
module top(ext_clk_25m,ext_rst_n,dtube_cs_n,dtube_data,led
);
//顶层控制模块
input ext_clk_25m; //时钟信号25MHz
input ext_rst_n; //复位信号
output [3:0] dtube_cs_n; //段选数据位
output [6:0] dtube_data;//位选数据位
output [5:0] led;
wire [3:0] TimeL;
wire [3:0] TimeH;
wire [3:0] TimeL1;
wire [3:0] TimeH1;
wire clk;//中间变量
//分频25MHZ变为1HZ
div d1(
.ext_clk_25m(ext_clk_25m),
.ext_rst_n(ext_rst_n),
.mclk(clk)
);
//倒计时计数模块(东西)
counter c1(
.ext_clk_25m(ext_clk_25m),
.mclk(clk),
.ext_rst_n(ext_rst_n),
.TimeH(TimeH),
.TimeL(TimeL),
.led(led[2:0])
);
//数码管显示模块(东西,南北)
seg s1(
.ext_clk_25m(ext_clk_25m),
.ext_rst_n(ext_rst_n),
.TimeH(TimeH),
.TimeL(TimeL),
.TimeH1(TimeH1),
.TimeL1(TimeL1),
.dtube_cs_n(dtube_cs_n),
.dtube_data(dtube_data)
);
//倒计时计数模块(南北)
counter1 c2(
.ext_clk_25m(ext_clk_25m),
.mclk(clk),
.ext_rst_n(ext_rst_n),
.TimeH1(TimeH1),
.TimeL1(TimeL1),
.led(led[5:3])
);
endmodule
数码管显示模块:
module seg(ext_clk_25m,ext_rst_n,TimeH,TimeL,TimeH1,TimeL1,dtube_cs_n,dtube_data
);
input ext_clk_25m; //时钟信号25MHz
input ext_rst_n; //复位信号
input [3:0]TimeH; //两位输入高位 [0]
input [3:0]TimeL; //两位输入低位 [1]
input [3:0]TimeH1; //两位输入高位 [2]
input [3:0]TimeL1; //两位输入低位 [3]
output reg[3:0] dtube_cs_n; //段选数据位
output reg[6:0] dtube_data;//位选数据位
reg[3:0] display_num; //当前显示数据
reg[16:0] div_cnt; //延时计数器计数位
initial div_cnt = 0;//赋初值为0
//延时计数器模块
always@ (posedge ext_clk_25m or negedge ext_rst_n)
begin
if(!ext_rst_n)
div_cnt <= 8'd0;
else if(div_cnt==17'd80000)
div_cnt <= 8'd0;
else
div_cnt <= div_cnt+1'b1;
end
//显示当前的数据模块
always @(posedge ext_clk_25m or negedge ext_rst_n)
begin
if(!ext_rst_n)
display_num <= 4'h0;
else if(div_cnt < 17'd20000)
display_num <= TimeL;
else if((div_cnt>17'd20000)&(div_cnt <17'd40000))
display_num <= TimeH;
else if((div_cnt>17'd40000)&(div_cnt < 17'd60000))
display_num <=TimeL1;
else
display_num <=TimeH1;
end
//段选数据译码模块(共阴数码管)
always @(*)
begin
if(!ext_rst_n)
dtube_data <= 8'h00;
else begin
case(display_num)
4'h0: dtube_data <= 8'h3f;
4'h1: dtube_data <= 8'h06;
4'h2: dtube_data <= 8'h5b;
4'h3: dtube_data <= 8'h4f;
4'h4: dtube_data <= 8'h66;
4'h5: dtube_data <= 8'h6d;
4'h6: dtube_data <= 8'h7d;
4'h7: dtube_data <= 8'h07;
4'h8: dtube_data <= 8'h7f;
4'h9: dtube_data <= 8'h6f;
default:dtube_data <= 8'h00;
endcase
end
end
//位选选译模块
always @(posedge ext_clk_25m or negedge ext_rst_n)
begin
if(!ext_rst_n)
dtube_cs_n <= 4'b1111;
else if(div_cnt <= 17'd20000)
dtube_cs_n <= 4'b1110;
else if((div_cnt>17'd20000)&(div_cnt <=17'd40000))
dtube_cs_n <= 4'b1101;
else if((div_cnt>17'd40000)&(div_cnt <=17'd60000))
dtube_cs_n <= 4'b1011;
else
dtube_cs_n <=4'b0111;
end
endmodule
分频模块:
module div(ext_clk_25m,ext_rst_n,mclk
);
input ext_clk_25m;//输入时钟
input ext_rst_n; //复位端口
output reg mclk;//输出1Hz
reg [23:0] cnt;//存放计数器的值
initial cnt = 0;
parameter TIME=24'd1250_0000;//时钟25MHz
//分频模块
//使得输入时钟为25MHz输出时钟为1Hz
always@(posedge ext_clk_25m or negedge ext_rst_n)
begin
if(!ext_rst_n)
begin
mclk <=1'b0;
cnt <=25'd0;
end
else if(cnt ==TIME-1'b1)
begin
mclk <=~mclk;
cnt <=1'b0;
end
else
cnt <=cnt + 1'b1;
end
endmodule
计数器模块(东西):
module counter(ext_clk_25m,mclk,ext_rst_n,TimeH,TimeL,led
);
input ext_clk_25m;
input mclk;//时钟信号
input ext_rst_n;//复位信号
output reg [3:0]TimeH;//两位数码管显示高位
output reg [3:0]TimeL;//两位数码管显示低位
output reg [2:0] led;
//状态机实现三种状态切换
reg[2:0] state_c,state_n;
reg [7:0] times;
parameter [2:0] IDLE = 3'b001,
S1 = 3'b010,
S2 = 3'b100;
//状态切换模块
always@(posedge ext_clk_25m or negedge ext_rst_n)
begin
if(!ext_rst_n)
state_c <=IDLE;
else
state_c <= state_n;
end
//状态切换
always@(*)
begin
case(state_c)
IDLE:
begin
if({TimeH,TimeL}==8'h00)
state_n=S1;
else
state_n=IDLE;
end
S1:
begin
if({TimeH,TimeL}==8'h00)
state_n=S2;
else
state_n=S1;
end
S2:
begin
if({TimeH,TimeL}==8'h00)
state_n=IDLE;
else
state_n=S2;
end
default:
state_n=state_c;
endcase
end
always@(posedge ext_clk_25m or negedge ext_rst_n)
begin
if(!ext_rst_n)
times <=8'd00;
else if(state_c==IDLE)
begin
times <=8'h20;
end
else if(state_c==S1)
begin
times <=8'h15;
end
else if(state_c==S2)
begin
times <=8'd5;
end
else;
end
always@(posedge mclk or negedge ext_rst_n)
begin
if(!ext_rst_n)
led = 3'b111;
else if(state_c==IDLE)
begin
led[2]=1'b1;
led[0]=1'b0;
end
else if(state_c==S1)
begin
led[0]=1'b1;
led[1]=1'b0;
end
else if(state_c==S2)
begin
led[1]=1'b1;
led[2]=1'b0;
end
else
led = 3'b111;
end
initial TimeH = times[7:4]; //计数器赋初值
//计数器模块高位
always@(posedge mclk or negedge ext_rst_n)
begin
if(!ext_rst_n)
TimeH <=times[7:4]; //计数器赋初值
else if({TimeH,TimeL}==8'h00)
begin
TimeH <=times[7:4]; //计数器赋初值
end
else if(TimeL==4'h0)
begin
TimeH <=TimeH-1'b1;
end
else
begin
TimeH <=TimeH;
end
end
initial TimeL = times[3:0];
//计数器模块低位
always@(posedge mclk or negedge ext_rst_n)
begin
if(!ext_rst_n)
begin
TimeL <=times[3:0];
end
else if({TimeH,TimeL}==8'h00)
begin
TimeL <=times[3:0];
end
else if(TimeL==4'h0)
begin
TimeL <=4'h9;
end
else
begin
TimeL <=TimeL-1'b1;
end
end
endmodule
计数器模块(南北)
module counter1(ext_clk_25m,mclk,ext_rst_n,TimeH1,TimeL1,led
);
input ext_clk_25m;
input mclk;//时钟信号
input ext_rst_n;//复位信号
output reg [3:0]TimeH1;//两位数码管显示高位
output reg [3:0]TimeL1;//两位数码管显示低位
output reg [5:3] led;
//状态机实现三种状态切换
reg[2:0] state_c,state_n;
reg [7:0] times1;
parameter [2:0] IDLE = 3'b001,
S1 = 3'b010,
S2 = 3'b100;
//状态切换模块
initial state_c = IDLE;
always@(posedge ext_clk_25m or negedge ext_rst_n)
begin
if(!ext_rst_n)
state_c <=IDLE;
else
state_c <= state_n;
end
//状态切换
always@(*)
begin
case(state_c)
IDLE:
begin
if({TimeH1,TimeL1}==8'h01)
state_n=S1;
else
state_n=IDLE;
end
S1:
begin
if({TimeH1,TimeL1}==8'h01)
state_n=S2;
else
state_n=S1;
end
S2:
begin
if({TimeH1,TimeL1}==8'h01)
state_n=IDLE;
else
state_n=S2;
end
default:
state_n=state_c;
endcase
end
always@(posedge ext_clk_25m or negedge ext_rst_n)
begin
if(!ext_rst_n)
times1 <=8'd00;
else if(state_c==IDLE)
begin
times1 <=8'h15;
end
else if(state_c==S1)
begin
times1 <=8'h5;
end
else if(state_c==S2)
begin
times1 <=8'h20;
end
else;
end
always@(posedge mclk or negedge ext_rst_n)
begin
if(!ext_rst_n)
led = 3'b111;
else if(state_c==IDLE)
begin
led[3]=1'b1;
led[4]=1'b0;
end
else if(state_c==S1)
begin
led[4]=1'b1;
led[5]=1'b0;
end
else if(state_c==S2)
begin
led[5]=1'b1;
led[3]=1'b0;
end
else
led = 3'b111;
end
initial TimeH1 = times1[7:4]; //计数器赋初值
//计数器模块高位
always@(posedge mclk or negedge ext_rst_n)
begin
if(!ext_rst_n)
TimeH1 <=times1[7:4]; //计数器赋初值
else if({TimeH1,TimeL1}==8'h00)
begin
TimeH1 <=times1[7:4]; //计数器赋初值
end
else if(TimeL1==4'h0)
begin
TimeH1 <=TimeH1-1'b1;
end
else
begin
TimeH1 <=TimeH1;
end
end
initial TimeL1 = times1[3:0];
//计数器模块低位
always@(posedge mclk or negedge ext_rst_n)
begin
if(!ext_rst_n)
begin
TimeL1 <=times1[3:0];
end
else if({TimeH1,TimeL1}==8'h00)
begin
TimeL1 <=times1[3:0];
end
else if(TimeL1==4'h0)
begin
TimeL1 <=4'h9;
end
else
begin
TimeL1 <=TimeL1-1'b1;
end
end
endmodule