1. 程式人生 > >FPGA-08-任務五、十字路口交通控制燈器系統設計(一)

FPGA-08-任務五、十字路口交通控制燈器系統設計(一)

      設計一個十字路口交通控制系統,其東西、南北兩個方向除了有紅、黃、綠燈指示是否允許通行外,還設有時間顯示,以倒計時方式顯示每一路允許通行的時間,綠燈、黃燈、紅燈的持續時間分別是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
//延時計數器模組
	
[email protected]
(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
	[email protected](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;
	//狀態切換模組
	[email protected](posedge ext_clk_25m or negedge ext_rst_n)
	begin
		if(!ext_rst_n)
			state_c <=IDLE;
		else
			state_c <= state_n;
	end
	//狀態切換
	[email protected](*)
	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	
	
	[email protected](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
	
	[email protected](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]; //計數器賦初值
//計數器模組高位
	[email protected](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];
//計數器模組低位
	[email protected](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;
	[email protected](posedge ext_clk_25m or negedge ext_rst_n)
	begin
		if(!ext_rst_n)
			state_c <=IDLE;
		else
			state_c <= state_n;
	end
	//狀態切換
	[email protected](*)
	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		
	[email protected](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
[email protected](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]; //計數器賦初值
//計數器模組高位
[email protected](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];
//計數器模組低位
[email protected](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