赞
踩
交通信号灯往往由红、绿、黄三种颜色的灯组成。红灯亮的时候,禁止通行;绿灯亮的时候,可以通行;黄灯亮的时候,提示通行时间已经结束,马上要转换为红灯。
本设计采用Verilog HDL语言编写,实现了十字路口的交通灯设计。
根据实验任务,我们可以大致规划出系统的控制流程:交通灯控制模块将需要显示的时间 数据连接到数码管显示模块,同时将状态信号连接到led灯控制模块,然后数码管显示模块和 led灯控制模块驱动交通信号灯外设工作。系统总体框架图如图所示
拓展外接电路如下:
顶层设计完成了对其它三个子模块的例化、实现了子模块间 的信号连接、并将led灯和数码管的驱动信号输出给外接设备(交通信号灯外设)。
traffic_light u0_traffic_light( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .ew_time (ew_time), .sn_time (sn_time), .state (state) ); seg_led u1_seg_led( .sys_clk (sys_clk) , .sys_rst_n (sys_rst_n), .ew_time (ew_time), .sn_time (sn_time), .en (1'b1), .sel (sel), .seg_led (seg_led) ); led u2_led( .sys_clk (sys_clk ), .sys_rst_n (sys_rst_n), .state (state ), .led (led ) );
交通灯控制模块是本次实验的核心代码,这个模块 控制信号灯的状态转换,将实时的状态信号state[1:0]输出给led灯控制模块(led),同时将各个方向的实时时间数据输出给数码管显示模块 (seg_led)。
//计数周期为0.5s的计数器 always @ (posedge sys_clk or negedge sys_rst_n)begin if(!sys_rst_n) clk_cnt <= 25'b0; else if (clk_cnt < WIDTH - 1'b1) clk_cnt <= clk_cnt + 1'b1; else clk_cnt <= 25'b0; end //产生频率为1hz的时钟 always @(posedge sys_clk or negedge sys_rst_n)begin if(!sys_rst_n) clk_1hz <= 1'b0; else if(clk_cnt == WIDTH - 1'b1) clk_1hz <= ~ clk_1hz; else clk_1hz <= clk_1hz; end /切换交通信号灯工作的4个状态,并产生数码管要显示的时间数据 always @(posedge clk_1hz or negedge sys_rst_n)begin if(!sys_rst_n)begin state <= 2'd0; time_cnt <= TIME_LED_G ; //状态1持续的时间 end else begin case (state) 2'b0: begin //状态1 ew_time <= time_cnt + TIME_LED_Y - 1'b1;//东西方向数码管要显示的时间数据 sn_time <= time_cnt - 1'b1; //南北方向数码管要显示的时间数据 if (time_cnt > 1)begin //time_cnt等于1的时候切换状态 time_cnt <= time_cnt - 1'b1; state <= state; end else begin time_cnt <= TIME_LED_Y; //状态2持续的时间 state <= 2'b01; //切换到状态2 end end 2'b01: begin //状态2 ew_time <= time_cnt - 1'b1; sn_time <= time_cnt - 1'b1; if (time_cnt > 1)begin time_cnt <= time_cnt - 1'b1; state <= state; end else begin time_cnt <= TIME_LED_G; //状态3持续的时间 state <= 2'b10; //切换到状态3 end end 2'b10: begin //状态3 ew_time <= time_cnt - 1'b1; sn_time <= time_cnt + TIME_LED_Y - 1'b1; if (time_cnt > 1)begin time_cnt <= time_cnt - 1'b1; state <= state; end else begin time_cnt <= TIME_LED_Y; //状态4持续的时间 state <= 2'b11; //切换到转态4 end end 2'b11: begin //状态4 ew_time <= time_cnt - 1'b1; sn_time <= time_cnt - 1'b1; if (time_cnt > 1)begin time_cnt <= time_cnt - 1'b1; state <= state; end else begin time_cnt <= TIME_LED_G; state <= 2'b0; //切换到状态1 end end default: begin state <= 2'b0; time_cnt <= TIME_LED_G; end endcase end end
接收交通灯控制模块传递过来的实时时间数据,并以此驱动对应的数码管,将数据显示出来。
//计数1ms always @ (posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) cnt_1ms <= 15'b0; else if (cnt_1ms < WIDTH - 1'b1) cnt_1ms <= cnt_1ms + 1'b1; else cnt_1ms <= 15'b0; end //计数器,用来切换数码管点亮的4个状态 always @ (posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) cnt_state <= 2'd0; else if (cnt_1ms == WIDTH - 1'b1) cnt_state <= cnt_state + 1'b1; else cnt_state <= cnt_state; end //先显示东西方向数码管的十位,然后是个位。再显示南北方向数码管的十位,然后个位 always @ (posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) begin sel <= 4'b1111; num <= 4'b0; end else if(en) begin case (cnt_state) 3'd0 : begin sel <= 4'b1110; //驱动东西方向数码管的十位 num <= data_ew_0; end 3'd1 : begin sel <= 4'b1101; //驱动东西方向数码管的个位 num <= data_ew_1; end 3'd2 : begin sel <= 4'b1011; //驱动南北方向数码管的十位 num <= data_sn_0; end 3'd3 : begin sel <= 4'b0111; //驱动南北方向数码管的个位 num <= data_sn_1 ; end default : begin sel <= 4'b1111; num <= 4'b0; end endcase end else begin sel <= 4'b1111; num <= 4'b0; end end //数码管要显示的数值所对应的段选信号 always @ (posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) seg_led <= 8'b0; else begin case (num) 4'd0 : seg_led <= 8'b1100_0000; 4'd1 : seg_led <= 8'b1111_1001; 4'd2 : seg_led <= 8'b1010_0100; 4'd3 : seg_led <= 8'b1011_0000; 4'd4 : seg_led <= 8'b1001_1001; 4'd5 : seg_led <= 8'b1001_0010; 4'd6 : seg_led <= 8'b1000_0010; 4'd7 : seg_led <= 8'b1111_1000; 4'd8 : seg_led <= 8'b1000_0000; 4'd9 : seg_led <= 8'b1001_0000; default : seg_led <= 8'b1100_0000; endcase end end
根据接收到的实时状态信号state[1:0],驱动led发光。
//计数时间为0.2s的计数器,用于让黄灯闪烁 always @(posedge sys_clk or negedge sys_rst_n)begin if(!sys_rst_n) cnt <= 25'b0; else if (cnt < TWINKLE_CNT - 1'b1) cnt <= cnt + 1'b1; else cnt <= 25'b0; end //在交通灯的四个状态里,使相应的led灯发光 always @(posedge sys_clk or negedge sys_rst_n)begin if(!sys_rst_n) led <= 6'b100100; else begin case(state) 2'b00:led<=6'b100010; //led寄存器从高到低分别驱动:东西向 //红绿黄灯,南北向红绿黄灯 2'b01: begin led[5:1]<=5'b10000; if(cnt == TWINKLE_CNT - 1'b1) //计数满0.2秒让黄灯的亮灭状况切换一次 //产生闪烁的效果 led[0] <= ~led[0]; else led[0] <= led[0]; end 2'b10:led<=6'b010100; 2'b11: begin led[5:4]<=2'b00; led[2:0]<=3'b100; if(cnt == TWINKLE_CNT - 1'b1) led[3] <= ~led[3]; else led[3] <= led[3]; end default:led<=6'b100100; endcase end end endmodule
实现了简单十字路口的控制,可以调整切换时间。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。