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
//延时计数器模块
	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

猜你喜欢

转载自blog.csdn.net/weixin_41445387/article/details/83148379