DIY编程器网

标题: Verilog HDL基础之:实例5 交通灯控制器 [打印本页]

作者: admin    时间: 2015-4-27 16:43
标题: Verilog HDL基础之:实例5 交通灯控制器
        实例的内容及目标

        1.实例的主要训练内容

          本实例通过Verilog HDL语言设计一个简易的交通等控制器,实现一个具有两个方向、共8个灯并具有时间倒计时功能的交通灯功能。
           
        2.实例目标

          通过本实例,读者应达到下面的目标。

           
        原理简介

          交通灯是城市交通中不可缺少的重要工具,是城市交通秩序的重要保障。本实例就是实现一个常见的十字路口交通灯功能。读者通过学习这个交通灯控制器,可以实现一个更加完整的交通灯。例如实现实时配置各种灯的时间,手动控制各个灯的状态等。
           
          一个十字路口的交通一般分为两个方向,每个方向具有红灯、绿灯和黄灯3种,另外每个方向还具有左转灯,因此每个方向具有4个灯。
           
          这个交通灯还为每一个灯的状态设计了倒计时数码管显示功能。可以为每一个灯的状态设置一个初始值,灯状态改变后,开始按照这个初始值倒计时。倒计时归零后,灯的状态将会改变至下一个状态。
           
          值得注意的是,交通灯两个方向的灯的状态是相关的。也就是说,每个方向的灯的状态影响着另外一个方向的灯的状态,这样才能够协调两个方向的车流。如果每个方向的灯是独立变化的,那么交通灯就没有了意义。
           
          如表1所示是两个方向(假设为A,B方向)灯的状态的对应情况。
          表1                                              交通灯两个方向灯状态对应表
                                                                         方向A
                       
                                                                         方向B
                       
                                                                         红灯亮
                       
                                                                         黄灯亮或绿灯亮
                       
                                                                         直行绿灯亮
                       
                                                                         红灯亮
                       
                                                                         黄灯亮
                       
                                                                         红灯亮
                       
                                                                         左转灯
                       
                                                                         红灯亮
                       
           
          在实际的交通系统中,直行绿灯、左转绿灯和红灯的变化之间都应该有黄灯作为缓冲,以保证交通的安全。因此假如我们假设方向A的黄灯亮的时间持续5s,直行绿灯灯亮的时间持续40s,左转灯灯亮的时间持续15s,则方向B红灯灯亮的时间持续为(直行绿灯+黄灯+左转绿灯+黄灯)所消耗的时间,一共为65s。
           
          同样假设方向B黄灯亮的时间持续5s,直行绿灯灯亮的时间持续30s,左转灯灯亮的时间持续15s,则方向B红灯灯亮的时间持续为(直行绿灯+黄灯+左转绿灯+黄灯)所消耗的时间,一共为55s。
           
          具体时间参数的设定读者可以根据需要进行修改,但是一定要保证两个方向的灯的状态符合表1的要求。
           
        代码分析

          下面给出交通灯控制器的Verilog HDL源代码,首先介绍交通灯端口信号的定义及说明,读者可以通过这些端口将此交通灯模块实例化至自己的工程设计中。

           
          下面是交通灯的Verilog HDL源代码及说明。
           
          module traffic(CLK,EN,LAMPA,LAMPB,ACOUNT,BCOUNT);     //端口说明
               output[7:0] ACOUNT,BCOUNT;
               output[3:0] LAMPA,LAMPB;
               input CLK,EN;                                  //内部信号说明
               reg[7:0] numa,numb;                         //ACOUNT和BCOUNT的内部信号
               reg tempa,tempb;               
               reg[2:0] counta,countb;                    //方向A和方向B的灯的状态
               reg[7:0] ared,ayellow,agreen,aleft,bred,byellow,bgreen,bleft;
               reg[3:0] LAMPA,LAMPB;
              
               //设置各交通灯的持续时间初始化值,红灯的值由另一个方向的黄灯和绿灯计算得出。
               always @(EN)
                    if(!EN) begin                //使能信号EN无效时,对交通灯的计数值进行初始化
                         ared       <=8'd55;    //55 s , 30 + 5 + 15 + 5
                         ayellow    <=8'd5;     //5 s
                         agreen     <=8'd40;    //40 s
                         aleft      <=8'd15;     //15 s
                         bred      <=8'd65;      //65 s , 40 + 5 + 15 + 5
                         byellow    <=8'd5;      //5 s
                         bleft      <=8'd15;     //15 s
                         bgreen     <=8'd30;     //30 s
                    end
                    assign ACOUNT=numa;                   //8位数码管输出
               assign BCOUNT=numb;                       //8位数码管输出
                    //控制A方向4种灯的模块
               always @(posedge CLK) begin        
                    if(EN) begin                         //使能有效时,交通灯开始工作
                         if(!tempa) begin
                              tempa<=1;
                              case(counta)               //控制灯状态的顺序
                                   0: begin              //状态0
                                        numa<=agreen;    //直行绿灯亮
                                        LAMPA<=2;          //输出0010
                                        counta<=1;         //进入下一个状态
                                   end
                                   1: begin                //状态1
                                        numa<=ayellow; //黄灯亮
                                        LAMPA<=4;          //输出0100
                                        counta<=2;         //进入下一个状态
                                   end
                                   2: begin                 //状态2
                                        numa<=aleft;       //左转绿灯亮
                                        LAMPA<=1;          //输出0001
                                        counta<=3;         //进入下一个状态
                                   end
         
                                   3: begin                 //状态3
                                        numa<=ayellow;    //黄灯亮
                                        LAMPA<=4;          //输出0100
                                        counta<=4;         //进入下一个状态
                                   end
                                   4: begin                 //状态4
                                        numa<=ared;        //红灯亮
                                        LAMPA<=8;          //输出1000
                                        counta<=0;         //进入下一个状态(状态0)
                                   end
                                   default:                 //默认状态
                                        LAMPA<=8;          //红灯亮,输出1000
                              endcase
                         end
                         else begin                    //每一个状态的倒计时
                             if(numa>1)                //判断倒计时未归零时分别对高地位进行递减
                                   if(numa[3:0]==0) begin
                                        numa[3:0]<=4'b1001;
                                        numa[7:4]<=numa[7:4]-1;
                                   end
                                   else
                                        numa[3:0]<=numa[3:0]-1;
                              if (numa==2)
                                   tempa<=0;   //倒计时结束,返回灯状态变化判断,将进入下一个状态
                         end
                    end
                    else begin
                         LAMPA<=4'b1000;         //使能无效时,红灯亮
                         counta<=0;               //返回方向A的状态0(绿灯状态)
                         tempa<=0;                //进入状态变化判断
                    end
               end
                   //控制B方向4种灯的模块,模块的语言描述与方向A的描述基本一致,这里不再重复注释
               always @(posedge CLK) begin
                    if (EN) begin
                         if(!tempb) begin
                              tempb<=1;
                              case (countb)
                                   0: begin
                                        numb<=bred;
                                        LAMPB<=8;
                                        countb<=1;
                                   end
                                   1: begin
                                        numb<=bgreen;
                                        LAMPB<=2;
                                        countb<=2;
                                   end
                                   2: begin
                                        numb<=byellow;
                                        LAMPB<=4;
                                        countb<=3;
                                   end
                                   3: begin
                                        numb<=bleft;
                                        LAMPB<=1;
                                        countb<=4;
                                   end
                                   4: begin
                                        numb<=byellow;
                                        LAMPB<=4;
                                        countb<=0;
                                   end
                                   default:
                                        LAMPB<=8;
                              endcase
                         end
                         else begin //倒计时
                              if(numb>1)
                                   if(!numb[3:0]) begin
                                        numb[3:0]<=9;
                                        numb[7:4]<=numb[7:4]-1;
                                   end
                              else
                                   numb[3:0]<=numb[3:0]-1;
                              if(numb==2)
                                   tempb<=0;
                         end
                    end
                    else begin
                         LAMPB<=4'b1000;
                         tempb<=0;
                         countb<=0;
                    end
               end
          endmodule
           
          通过上面这个Verilog HDL模块,基本实现了交通灯控制器的基本功能。读者可将此设计应用于实际的硬件系统中,通过晶振、FPGA、开关、LED灯及数码管等资源即可完成硬件实现。




欢迎光临 DIY编程器网 (http://diybcq.com/) Powered by Discuz! X3.2