基于BASYS2的交通灯控制系统

设计要求:设计一个十字路口交通控制系统,其东西、南北两个方向除了有红、黄、绿灯指示是否允许通行外,还设有时间显示,以倒计时方式显示每一路允许通行的时间,绿灯、黄灯、红灯的持续时间分别是45、5和50秒。当东西或南北两路中任一道上出现特殊情况,例如有消防车,警车要去执行任务,此时交通控制系统应可由交警手动控制立即进入特殊运行状态,即两条道上的所有车辆皆停止通行,红灯全亮,时钟停止计时,且其数字在闪烁。当特殊运行状态结束后,管理系统恢复原来的状态,继续正常运行。
实现主干道和支干道的红绿灯,并实现时间显示功能;
实现绿灯,黄灯,红灯的持续时间固定的交通控制功能;
当东西或南北两路中任一道上出现特殊情况,交通控制系统应可由交警手动控制立即进入特殊运行状态的功能;
实现绿灯,黄灯,红灯的持续时间可调的交通控制功能;

此设计使用一个译码器。
在这里插入图片描述

发现了一个有意思的现象。十六进制数有着一种性质。例如8‘h52化为二进制数就是8’h0101_00104’h0101是十进制的54’h0010是十进制的2。(大佬勿喷!!!)

这为接下来的译码提供了很大的便利。因为是利用四位数码管显示。故使用一个16位的数来存储倒计数值。数码管的动态显示方面读者自行查询原理。我在此就不再详细叙述。

以下将详细讲解各个模块的代码。

1.分频模块:红绿灯的基础时钟是一秒。故先将50MHZ时钟进行分频,在连接到倒计时模块中去。分频模块代码应该是很好写的。在此也不详细叙说了。此模块中引入了R_key_set,G_key_set,Y_key_set,key.当key按下时是暂停。当检测到R_key_set,G_key_set,Y_key_set三个中任意一个上升沿将分频计数器清零(这波操作的意义我也说不清楚,读者自行理解,哈哈哈!)

2.倒计时模块:前面讲述过十六进制数的特点。在此模块中定义了一个16位的dis_num.dis_num的前八位代表一个方向的时间,后八位代表另外一个方向的时间。当复位时回到红灯50s,绿灯45s的初始状态。当检测到R_key_set,G_key_set,Y_key_set任意一个处于低电平表示此时正在调整红绿灯的倒计时时间。所以将此时调整好的值Time_red,Time_green,Time_yellow赋值给dis_num,从预定值开始倒计时。此模块中引出了两个信号S1,S2是连接进亮灯模块的。后面再说。
每个方向的倒计时都有三个状态。红灯态,绿灯态黄灯态。S1表示一个方向的状态,S2表示另一个方向状态。倒计时的设计思路还是挺简单的,每来一个1s的时钟上升沿就时间的个位减一。到了x_0的时候跳转到(x-1)_9即可。
dis_num[3:0]表示个位,[7:4]表示十位
计时到00的时候跳转到下一个亮灯状态继续倒计时就可以了

3.数码管显模块:在之前的设计中总喜欢使用1kHZ的时钟来进行数码管的动态显示。这次设计使用了另外一种思路在这里插入图片描述
两种方法均可行。看读者的习惯了。
在此模块中有三种显示状态1.倒计时 2.暂停闪烁 3.时间设置
数码管的段选值取决于state的值由于上面叙说过十六进制的好处。在此时便能译出你所需要的段码。具体见下方代码。

4.time_set_key模块:此次设计使用的BASYS2开发板板子自带按键消抖所以此次设计未使用按键消抖。此次按键反应是按下有效。当按下后会产生一个20ns的尖峰脉冲。输出到时间设置模块。关于尖峰脉冲的产生方法以后会更新的。

下面的两个模块就比较简单了。就不叙述了。请读者依据代码分析。
下面是源码。亲测可以使用。

顶层模块:

module top(
      clk,        //clock signal
	  rst_n,      //restoration key
	  key,	     //pause key
	  R_key_set,  //Red light time setting key
	  G_key_set,  //Green light time setting key
	  Y_key_set,  //Yellow light time setting key
	  key_up,     //time adds key
	  key_down,   //time degradation key
	  light_1,    //east-west direction light
	  light_2,    //south-north direction light
	  sel,        //Nixie tube selected
	  seg         //Nixie tube segment 
    );
input clk;
input key;
input rst_n;
input key_up;
input key_down;
input R_key_set;
input G_key_set;
input Y_key_set;
output [3:0]sel;
output [7:0]seg;
output [2:0]light_1;
output [2:0]light_2;

wire clk_1s;             //分频产生的1S时钟
wire [15:0]dis_num;      //数码管译码
wire [7:0]Time_red;      //红灯持续时间
wire [7:0]Time_green;    //绿灯持续时间
wire [7:0]Time_yellow;   //黄灯持续时间
wire flag_up;            //时间增加按键(key_up)按下产生的尖峰脉冲
wire flag_down;          //时间减少按键(key_down)按下产生的尖峰脉冲
wire [1:0]S1;            //东西方向红绿灯亮灯的状态
wire [1:0]S2;            //南北方向红绿灯亮灯的状态


/*****************************分频模块*****************************************/
/****************************************************************************/
div1 uut_div1(
    .key(key),
    .clk(clk),
	 .rst_n(rst_n),
	 .R_key_set(R_key_set),
	 .G_key_set(G_key_set),
	 .Y_key_set(Y_key_set),
	 .clk_1s(clk_1s)
);
/****************************************************************************/
/****************************************************************************/




/***************************正常倒计时模块**************************************/
/****************************************************************************/
normal uut_normal(
  .rst_n(rst_n),
  .clk_1s(clk_1s),
  .key(key),
  .S1(S1),
  .S2(S2),
  .R_key_set(R_key_set),
  .G_key_set(G_key_set),
  .Y_key_set(Y_key_set),
  .Time_red(Time_red),
  .Time_green(Time_green),
  .Time_yellow(Time_yellow),
  .dis_num(dis_num)
);
/****************************************************************************/
/****************************************************************************/





/**************************数码管显示模块***************************************/
/****************************************************************************/
decode uut_decode(
   .clk(clk),
	.rst_n(rst_n),
	.key(key),
	.seg(seg),
	.sel(sel),
	.R_key_set(R_key_set), 
	.G_key_set(G_key_set),
	.Y_key_set(Y_key_set),
   .Time_red(Time_red),
	.Time_green(Time_green),
	.Time_yellow(Time_yellow),
	.dis_num(dis_num)
);

/****************************************************************************/
/****************************************************************************/





/****************************时间设置(加减按键)模块******************************/
/****************************************************************************/
time_set_key uut_time_set_key(
    .clk(clk), 
    .rst_n(rst_n), 
    .key_up(key_up), 
	 .key_down(key_down),
    .flag_up(flag_up),
	 .flag_down(flag_down)
    );
/****************************************************************************/
/****************************************************************************/




/**************************时间设置模块****************************************/
/****************************************************************************/
time_set uut_time_set(
    .clk(clk), 
    .rst_n(rst_n), 
    .flag_up(flag_up),
    .flag_down(flag_down),	 
    .R_key_set(R_key_set), 
	 .G_key_set(G_key_set),
	 .Y_key_set(Y_key_set),
    .Time_red(Time_red),
	 .Time_green(Time_green),
	 .Time_yellow(Time_yellow)
    );
/****************************************************************************/
/****************************************************************************/	 
	 



	 
/**************************红绿灯的亮灯模块*************************************/
/****************************************************************************/	 
light uut_light(
    .clk(clk), 
    .rst_n(rst_n), 
    .key(key), 
    .S1(S1), 
    .S2(S2), 
    .light_1(light_1), 
    .light_2(light_2)
    );
/****************************************************************************/
/****************************************************************************/	
	
endmodule

分频模块代码:

module div1(
   key,
   clk,
	R_key_set,
	G_key_set,
	Y_key_set,
	rst_n,
	clk_1s
    );
input key;
input clk;
input rst_n;
input R_key_set;
input G_key_set;
input Y_key_set;
output reg clk_1s;
reg [27:0]cnt;
/******************************上升沿判断************************************/
/**************************************************************************/
reg R_key_set_temp;
reg G_key_set_temp;
reg Y_key_set_temp;
wire pedge;
assign pedge = ((~R_key_set_temp)&R_key_set)|((~G_key_set_temp)&G_key_set)|((~Y_key_set_temp)&Y_key_set);
always@(posedge clk or negedge rst_n)
 if(!rst_n) begin
   R_key_set_temp <= 1'b0;
	G_key_set_temp <= 1'b0;
	Y_key_set_temp <= 1'b0;
	 end
 else begin	
   R_key_set_temp <= R_key_set;
   G_key_set_temp <= G_key_set;
   Y_key_set_temp <= Y_key_set;
    end
  
 
/**************************************************************************/ 
/**************************************************************************/
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
	 cnt <= 0;
	 clk_1s <= 0;
  end 
  
else if(!key) 
  cnt <= cnt;
  
else if(pedge) 
  cnt <= 0;	
	
else begin
	 if(cnt < 28'd24999999)
		cnt <= cnt+1'b1;
		else 
		 begin
			cnt <= 0;
			clk_1s <= ~clk_1s;
		  end
  end
 
endmodule

倒计时模块代码:

module normal(
    clk_1s,
	 rst_n,
	 key,
	 R_key_set,
	 Time_red,
	 G_key_set,
	 Time_green,
	 Y_key_set,
	 Time_yellow,
	 dis_num,
	 S1,
	 S2
    );
input clk_1s;
input rst_n;
input key;
input R_key_set;
input [7:0]Time_red;
input G_key_set;
input [7:0]Time_green;
input Y_key_set;
input [7:0]Time_yellow;
output reg [15:0]dis_num;
output reg [1:0]S1,S2;

always@(posedge clk_1s or negedge rst_n)
begin
 if(!rst_n)
 begin
   dis_num[7:0] <= 8'h45;
	S1 <= 2'd0;
 end
  
 else if((!G_key_set)|(!R_key_set)|(!Y_key_set))begin
   S1 <= 2'd0;
	dis_num[7:0] <= Time_green;
  end
 
 else if(!key)
   S1 <= S1; 
	
 else begin
	  case(S1)
	  2'd0:begin 
	  dis_num[3:0] <= dis_num[3:0]-1;
	    if(dis_num[3:0]==4'h0)
		   begin
			  dis_num[3:0] <= 4'h9;
			  dis_num[7:4] <= dis_num[7:4]-1;
			end
			if(dis_num[7:0]==8'h0)
		   begin
			  dis_num[7:0] <= Time_yellow;
			  S1 <= 2'd1;
			end
			  end
		2'd1:begin
          dis_num[3:0] <= dis_num[3:0]-1;
	    if(dis_num[3:0]==4'h0)
		   begin
			  dis_num[3:0] <= 4'h9;
			  dis_num[7:4] <= dis_num[7:4]-1;
			end
			if(dis_num[7:0]==8'h0)
		   begin
			  dis_num[7:0] <= Time_red;
			  S1 <= 2'd2;
			end
        end		
		2'd2:begin
          dis_num[3:0] <= dis_num[3:0]-1;
	    if(dis_num[3:0]==4'h0)
		   begin
			  dis_num[3:0] <= 4'h9;
			  dis_num[7:4] <= dis_num[7:4]-1;
			end
			if(dis_num[7:0]==8'h0)
		   begin
			  dis_num[7:0] <= Time_green;
			  S1 <= 2'd0;
			end
        end		
     endcase		  
	end
end


always@(posedge clk_1s or negedge rst_n)
 if(!rst_n)
 begin
   dis_num[15:8] <= 8'h50;
	S2 <= 2'd0;
 end
 
else if((!G_key_set)|(!R_key_set)|(!Y_key_set))begin
   S2 <= 2'd0;
	dis_num[15:8] <= Time_red;
  end 
 
else if(!key)
   S2 <= S2;
 
	else begin
	  case(S2)
	  2'd0:begin 
	   dis_num[11:8] <= dis_num[11:8]-1;
	    if(dis_num[11:8]==4'h0)
		   begin
			  dis_num[11:8] <= 4'h9;
			  dis_num[15:12] <= dis_num[15:12]-1;
			end
			if(dis_num[15:8]==8'h0)
		   begin
			  dis_num[15:8] <= Time_green;
			  S2 <= 2'd1;
			end
			  end
		2'd1:begin
          dis_num[11:8] <= dis_num[11:8]-1;
	    if(dis_num[11:8]==4'h0)
		   begin
			  dis_num[11:8] <= 4'h9;
			  dis_num[15:12] <= dis_num[15:12]-1;
			end
			if(dis_num[15:8]==8'h0)
		   begin
			  dis_num[15:8] <= Time_yellow;
			  S2 <= 2'd2;
			end
        end		
		2'd2:begin
          dis_num[11:8] <= dis_num[11:8]-1;
	    if(dis_num[11:8]==4'h0)
		   begin
			  dis_num[11:8] <= 4'h9;
			  dis_num[15:12] <= dis_num[15:12]-1;
			end
			if(dis_num[15:8]==8'h0)
		   begin
			  dis_num[15:8] <= Time_red;
			  S2 <= 2'd0;
			end
        end		
     endcase		  
	end


endmodule

译码模块:

module decode(
    dis_num,
    clk,
	 rst_n,
	 R_key_set,
	 G_key_set,
	 Y_key_set,
	 Time_red,
	 Time_green,
	 Time_yellow,
	 seg,
	 key,
	 sel
    );
input clk;
input key;//紧急按键
input rst_n;
input R_key_set;
input G_key_set;
input Y_key_set;
input [7:0]Time_green;
input [7:0]Time_red;
input [7:0]Time_yellow;
input [15:0]dis_num;
output reg [7:0]seg;
output reg [3:0]sel;
reg [3:0]state;//数据选择
reg [20:0]cnt_1;

/*****************************************************************************************************/
/*****************************************************************************************************/
always@(posedge clk or negedge rst_n)
begin
 if(!rst_n)
   cnt_1 <= 0;
	else begin
	  if(cnt_1 == 21'd100000)
	    cnt_1 <= 21'd0;
		 else 
		 cnt_1 <= cnt_1+1;
	end
end

reg [24:0]cnt_flash;
always@(posedge clk or negedge rst_n)
 if(!rst_n)
  cnt_flash <= 0;
  else if((cnt_flash<25'd25000000) & (!key))
   cnt_flash <= cnt_flash+1'b1;
	else 
	 cnt_flash <= 25'd0;

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	  begin
		sel <= 4'b1111;
	  end
  else if(!key) begin
      if(cnt_flash < 25'd1250_0000)
		  sel <= 4'b1111;
		  else begin
		  if(cnt_1 < 21'd25000)
			sel <= 4'b1110;
		 else if(cnt_1 < 21'd50000)
			sel <= 4'b1101;
		 else if(cnt_1 < 21'd75000)
			sel <= 4'b1011;
		 else if(cnt_1 < 21'd100000)
			sel <= 4'b0111;
		  end
    end 
	else begin
		if(cnt_1 < 21'd25000)
			sel <= 4'b1110;
		 else if(cnt_1 < 21'd50000)
			sel <= 4'b1101;
		 else if(cnt_1 < 21'd75000)
			sel <= 4'b1011;
		 else if(cnt_1 < 21'd100000)
			sel <= 4'b0111;	 
	end
end

/*****************************************************************************************************/
/*****************************************************************************************************/


always@(posedge clk or negedge rst_n)
  if(!rst_n)
     state <= 4'h0;
	  
   else if(!R_key_set)begin
     if(cnt_1 < 21'd25000)
	      state <= 4'h0;
	    else if(cnt_1 < 21'd50000)
	      state <= 4'h0;
	    else if(cnt_1 < 21'd75000)
	      state <= Time_red[3:0];
	    else if(cnt_1 < 21'd100000)
		   state <= Time_red[7:4];	 
    end	
	 
	 else if(!G_key_set)begin
     if(cnt_1 < 21'd25000)
	      state <= 4'h0;
	    else if(cnt_1 < 21'd50000)
	      state <= 4'h0;
	    else if(cnt_1 < 21'd75000)
	      state <= Time_green[3:0];
	    else if(cnt_1 < 21'd100000)
		   state <= Time_green[7:4];	 
    end
	 
	 else if(!Y_key_set)begin
     if(cnt_1 < 21'd25000)
	      state <= 4'h0;
	    else if(cnt_1 < 21'd50000)
	      state <= 4'h0;
	    else if(cnt_1 < 21'd75000)
	      state <= Time_yellow[3:0];
	    else if(cnt_1 < 21'd100000)
		   state <= Time_yellow[7:4];	 
    end
	 
	else begin
	  if(cnt_1 < 21'd25000)
			state <= dis_num[3:0];
		 else if(cnt_1 < 21'd50000)
			state <= dis_num[7:4];
		 else if(cnt_1 < 21'd75000)
			state <= dis_num[11:8];
		 else if(cnt_1 < 21'd100000)
			state <= dis_num[15:12];	 
	 end



always@(posedge clk or negedge rst_n)
begin
 if(!rst_n)
   seg <= 8'b0000_0000;
	else begin
	case(state) 
	4'h0: seg <= 8'b0000_0011;
	4'h1: seg <= 8'b1001_1111;
	4'h2: seg <= 8'b0010_0101;
	4'h3: seg <= 8'b0000_1101;
	4'h4: seg <= 8'b1001_1001;
	4'h5: seg <= 8'b0100_1001;
	4'h6: seg <= 8'b0100_0001;
	4'h7: seg <= 8'b0001_1111;
	4'h8: seg <= 8'b0000_0001;
	4'h9: seg <= 8'b0000_1001;
 default:seg <= 8'b0000_0011;
	endcase
	end
end

endmodule

时间设置(按键时间加减)产生尖峰脉冲:

module time_set_key(
  clk,
  rst_n,
  key_up,
  key_down,
  flag_up,
  flag_down
    );
input clk;
input rst_n;
input key_up;
input key_down;
output reg flag_up;
output reg flag_down;
/****************************时间增加按键尖峰**********************************/
/***************************************************************************/
reg state_up;
always@(posedge clk or negedge rst_n)
  if(!rst_n)
   begin
	 state_up <= 0;
	 flag_up <= 0;
   end
 else begin
    case(state_up)
	 0:begin
		  if(key_up) begin
			state_up <= 1;
			flag_up <= 1;
		 end
	   end
	1:begin
     flag_up <= 0;
	   if(!key_up)
	     state_up <= 0;
      end	
	 default:state_up <= 0;
	 endcase
  end	
 
 /***************************************************************************/
 /***************************************************************************/
 
 
 /****************************时间减少按键尖峰**********************************/
/***************************************************************************/
reg state_down;
always@(posedge clk or negedge rst_n)
  if(!rst_n)
   begin
	 state_down <= 0;
	 flag_down <= 0;
   end
 else begin
    case(state_down)
	 0:begin
		  if(key_down) begin
			state_down <= 1;
			flag_down <= 1;
		 end
	   end
	1:begin
     flag_down <= 0;
	   if(!key_down)
	     state_down <= 0;
      end	
	 default:state_down <= 0;
	 endcase
  end	
 
 /***************************************************************************/
 /***************************************************************************/
 
endmodule

根据尖峰脉冲实现时间加减:

module time_set(
   clk,
	rst_n,
	flag_up,
	flag_down,
	R_key_set,
	G_key_set,
	Y_key_set,
	Time_red,
	Time_green,
	Time_yellow
    );
input clk;
input rst_n;
input flag_up;
input flag_down;
input R_key_set;
input G_key_set;
input Y_key_set;
output reg [7:0]Time_red;
output reg [7:0]Time_green;
output reg [7:0]Time_yellow;

always@(posedge clk or negedge rst_n)
if(!rst_n)begin
 Time_red <= 8'h50;
 Time_green <= 8'h45;
 Time_yellow <= 8'h5;
   end
	else if(!R_key_set)begin
		    if(flag_up)
			  begin
			    Time_red[3:0] <= Time_red[3:0]+1'b1;
				 if(Time_red[3:0]==4'h9)
				   begin
					 Time_red[3:0] <= 4'h0;
					 Time_red[7:4] <= Time_red[7:4]+1'b1;
					end
					if(Time_red == 8'h99)
					   Time_red <= 8'h0;
			  end
			  
			  if(flag_down)
			  begin
			    Time_red[3:0] <= Time_red[3:0]-1'b1;
				 if(Time_red[3:0]==4'h0)
				   begin
					 Time_red[3:0] <= 4'h9;
					 Time_red[7:4] <= Time_red[7:4]-1'b1;
					end
					if(Time_red == 8'h0)
					   Time_red <= 8'h99;
			  end
		end	  
		
	else if(!G_key_set)begin
		    if(flag_up)
			  begin
			    Time_green[3:0] <= Time_green[3:0]+1'b1;
				 if(Time_green[3:0]==4'h9)
				   begin
					 Time_green[3:0] <= 4'h0;
					 Time_green[7:4] <= Time_green[7:4]+1'b1;
					end
					if(Time_green == 8'h99)
					   Time_green <= 8'h0;
			  end
			  
			  if(flag_down)
			  begin
			    Time_green[3:0] <= Time_green[3:0]-1'b1;
				 if(Time_green[3:0]==4'h0)
				   begin
					 Time_green[3:0] <= 4'h9;
					 Time_green[7:4] <= Time_green[7:4]-1'b1;
					end
					if(Time_green == 8'h0)
					   Time_green <= 8'h99;
			  end
		end	
		
		else if(!Y_key_set)begin
		    if(flag_up)
			  begin
			    Time_yellow[3:0] <= Time_yellow[3:0]+1'b1;
				 if(Time_yellow[3:0]==4'h9)
				   begin
					 Time_yellow[3:0] <= 4'h0;
					 Time_yellow[7:4] <= Time_yellow[7:4]+1'b1;
					end
					if(Time_yellow == 8'h99)
					   Time_yellow <= 8'h0;
			  end
			  
			  if(flag_down)
			  begin
			    Time_yellow[3:0] <= Time_yellow[3:0]-1'b1;
				 if(Time_yellow[3:0]==4'h0)
				   begin
					 Time_yellow[3:0] <= 4'h9;
					 Time_yellow[7:4] <= Time_yellow[7:4]-1'b1;
					end
					if(Time_yellow == 8'h0)
					   Time_yellow <= 8'h99;
			  end
		end	
			  
endmodule

红绿亮灯模块:

module light(
       clk,
		 rst_n,
		 key,
		 S1,
		 S2,
		 light_1,
		 light_2
    );
input clk;
input rst_n;
input key;
input [1:0]S1;
input [1:0]S2;	 
	
output reg [2:0]light_1;
output reg [2:0]light_2; 
	
always@(posedge clk or negedge rst_n)
 if(!rst_n)
  light_1 <= 3'b000;
  
  else if(!key)
    light_1 <= 3'b100;
  
  else begin
   case(S1)
	 2'd0:light_1 <= 3'b010;
	 2'd1:light_1 <= 3'b001;
	 2'd2:light_1 <= 3'b100;
 default:light_1 <= 3'b000;
	endcase
  end
  

always@(posedge clk or negedge rst_n)
 if(!rst_n)
  light_2 <= 3'b000;
  
  else if(!key)
    light_2 <= 3'b100;
  
  else begin
   case(S2)
	 2'd0:light_2 <= 3'b100;
	 2'd1:light_2 <= 3'b010;
	 2'd2:light_2 <= 3'b001;
 default:light_2 <= 3'b000;
	endcase
  end  
 
 
endmodule

  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值