查看完整版本: Verilog HDL基础之:实例5 交通灯控制器

admin 发表于 2015-4-27 16:43:23

Verilog HDL基础之:实例5 交通灯控制器

        实例的内容及目标

        1.实例的主要训练内容

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

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

       
[*]                 掌握Verilog设计一个交通等控制器的方法。        
[*]                 初步掌握Verilog语言的设计方法。
       
        原理简介

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

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

       
[*]                 CLK:同步时钟。        
[*]                 EN:使能信号,为高电平时,控制器开始工作。        
[*]                 LAMPA:控制A方向4盏灯的状态;其中,LAMPA0~LAMPA3分别控制A 方向的左拐灯、绿灯、黄灯和红灯。        
[*]                 LAMPB:控制B方向4盏灯的状态;其中,LAMPB0~LAMPB3分别控制B 方向的左拐灯、绿灯、黄灯和红灯。        
[*]                 ACOUNT:用于A方向灯的时间显示,8位,可驱动两个数码管。        
[*]                 BCOUNT:用于B方向灯的时间显示,8位,可驱动两个数码管。
       
        下面是交通灯的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灯及数码管等资源即可完成硬件实现。
页: [1]
查看完整版本: Verilog HDL基础之:实例5 交通灯控制器