設計一個十字路口交通控制系統,其東西、南北兩個方向除了有紅、黃、綠燈指示是否允許通行外,還設有時間顯示,以倒計時方式顯示每一路允許通行的時間,綠燈、黃燈、紅燈的持續時間分別是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