zoukankan      html  css  js  c++  java
  • 交通灯控制器的verilog实现

    用状态机实现交通灯控制器,仿真通过,有代码以及testbench。


    要求:

    方向1是主干道,绿灯时间较长,交通灯状态循环为:

    绿:40

    黄:5

    左:15

    黄:5

    红:55

    方向2不是主干道,绿灯时间较少,交通灯状态循环为:

    红:65

    绿:30

    黄:5

    左:15

    黄:5


     注意:

    1. 此处将两个交通灯的状态合在一起,从而便于对两个等进行同步控制。将两个灯的5个状态合为8个状态,即:

    绿1:40

    黄1:5

    左1:15

    黄1:5

    绿2:30

    黄2:5

    左2:15

    黄2:5

    对状态转换以及输出控制采用组合逻辑,在调试的过程中也曾使用时序逻辑来实现,仿真发现各种时序混乱。

    在状态转换控制中,在change有效后,马上将其清零,代码如下,这是为了便于控制,调试时,发现这样比较方便,其他方法易出错。

    在仿真图上就看不到change有效过,但仿真图上的其他信号是正确的。

    1     G2   : if(trigger)  
    2                            nxt_state = G1;
    3            else if(change)  
    5                   begin
    6                         change = 1'b0;
    7                         nxt_state = Y2_1;

    代码如下:

      1 module traffic_light(rst_n,
      2                             clk,
      3                             trigger, //触发信号,使得状态机进入循环
      4                             light1,
      5                             light2
      6                                  );
      7 input rst_n;
      8 input clk;
      9 input trigger;
     10 
     11 output [3:0] light1;   //4bit分别对应绿、黄、左、红灯
     12 output [3:0] light2;
     13 
     14 //灯亮时间
     15 parameter G1_T = 7'd40;  //方向1的亮灯时间
     16 parameter Y1_T = 7'd5;
     17 parameter L1_T = 7'd15;
     18 
     19 parameter G2_T = 7'd30;    //方向2的亮灯时间
     20 parameter Y2_T = 7'd5;
     21 parameter L2_T = 7'd15;
     22 
     23 //状态编码
     24 parameter IDLE = 4'd0;    //此处为了方便采用简单的binary编码,可用one-hot或gray提高性能
     25 parameter G1 = 4'd1;
     26 parameter Y1_1 = 4'd2;
     27 parameter L1 = 4'd3;
     28 parameter Y1_2 = 4'd4;
     29 
     30 parameter G2 = 4'd5;
     31 parameter Y2_1 = 4'd6;
     32 parameter L2 = 4'd7;
     33 parameter Y2_2 = 4'd8;
     34 
     35 reg [3:0] cur_state;
     36 reg [3:0] nxt_state;
     37 
     38 reg [3:0] light1;
     39 reg [3:0] light2;
     40 
     41 reg [3:0] light1_tmp;
     42 reg [3:0] light2_tmp;
     43 
     44 reg [6:0] light_t_tmp;
     45 reg [6:0] light_t;
     46 
     47 reg change;
     48 reg start;
     49 
     50 //状态寄存,时序逻辑
     51 always@(posedge clk)
     52     if(!rst_n)
     53         cur_state <= IDLE;
     54     else
     55         cur_state <= nxt_state;
     56 
     57 //状态转换,组合逻辑        
     58 always@(*)
     59     if(!rst_n)
     60         begin
     61             //start <= 1'b0;
     62             nxt_state = IDLE;
     63         end
     64     else  
     65         begin
     66             case(cur_state)
     67                 IDLE : //if(change) 
     68                         if(trigger)  //状态机通过trigger进入状态循环
     69                             begin
     70                                 //start <= 1'b1;  //start与计数值light_t_tmp是同步的,因此一同写在输出控制中 
     71                                 nxt_state = G1;  //状态变换由组合逻辑实现,采用阻塞赋值即=,而非<=
     72                             end
     73                 G1   : if(trigger)  
     74                             begin
     75                                 //start <= 1'b1;
     76                                 nxt_state = G1;
     77                             end
     78                         else if(change)  
     79                                 begin
     80                                     //start <= 1'b1;
     81                                     change = 1'b0;
     82                                     nxt_state = Y1_1;
     83                                 end
     84                 Y1_1 : if(trigger)  
     85                             begin
     86                                 //start <= 1'b1;
     87                                 nxt_state = G1;
     88                             end
     89                         else if(change)  
     90                             begin
     91                                 //start <= 1'b1;
     92                                 change = 1'b0;
     93                                 nxt_state = L1;
     94                             end
     95                 L1   : if(trigger)  
     96                             begin
     97                                 //start <= 1'b1;
     98                                 nxt_state = G1;
     99                             end
    100                         else if(change)  
    101                             begin
    102                                 //start <= 1'b1;
    103                                 change = 1'b0;
    104                                 nxt_state = Y1_2;
    105                             end
    106                 Y1_2 : if(trigger)  
    107                             begin
    108                                 //start <= 1'b1;
    109                                 nxt_state = G1;
    110                             end
    111                         else if(change)  
    112                             begin
    113                                 //start <= 1'b1;
    114                                 change = 1'b0;
    115                                 nxt_state = G2;
    116                             end
    117                 G2   : if(trigger)  
    118                             begin
    119                                 //start <= 1'b1;
    120                                 nxt_state = G1;
    121                             end
    122                         else if(change)  
    123                             begin
    124                                 //start <= 1'b1;
    125                                 change = 1'b0;
    126                                 nxt_state = Y2_1;
    127                             end
    128                 Y2_1 : if(trigger)  
    129                             begin
    130                                 //start <= 1'b1;
    131                                 nxt_state = G1;
    132                             end
    133                         else if(change)  
    134                             begin
    135                                 //start <= 1'b1;
    136                                 change = 1'b0;
    137                                 nxt_state= L2;
    138                             end
    139                 L2   : if(trigger)  
    140                             begin
    141                                 //start <= 1'b1;
    142                                 nxt_state = G1;
    143                             end
    144                         else if(change)  
    145                             begin
    146                                 //start <= 1'b1;
    147                                 change = 1'b0;
    148                                 nxt_state = Y2_2;
    149                             end
    150                 Y2_2 : if(trigger)  
    151                             begin
    152                                 //start <= 1'b1;
    153                                 nxt_state = G1;
    154                             end
    155                         else if(change)  
    156                             begin
    157                                 //start <= 1'b1;
    158                                 change = 1'b0;
    159                                 nxt_state = G1;
    160                             end
    161                 default : nxt_state = IDLE;
    162             endcase
    163         end        
    164         
    165 //输出控制,组合逻辑
    166 //start与计数值light_t_tmp是同步的,因此一同写在输出控制中 
    167 //always@(posedge clk)   //输出为组合逻辑,因此不在clk下动作
    168 always@(*)
    169     if(!rst_n)
    170         begin
    171             start = 1'b0;
    172             light_t_tmp = 7'd0;
    173             light1_tmp = 4'b0000;
    174             light2_tmp = 4'b0000;
    175         end
    176     else case(cur_state)
    177             G1   : begin
    178                         start = 1'b1;
    179                         light_t_tmp = G1_T;
    180                         light1_tmp = 4'b1000;
    181                         light2_tmp = 4'b0001;                    
    182                      end
    183             Y1_1 : begin
    184                         start = 1'b1;
    185                         light_t_tmp = Y1_T;
    186                         light1_tmp = 4'b0100;
    187                         light2_tmp = 4'b0001;                
    188                      end
    189             L1   : begin
    190                         start = 1'b1;
    191                         light_t_tmp = L1_T;
    192                         light1_tmp = 4'b0010;
    193                         light2_tmp = 4'b0001;                
    194                      end
    195             Y1_2 : begin
    196                         start = 1'b1;
    197                         light_t_tmp = Y1_T;
    198                         light1_tmp = 4'b0100;
    199                         light2_tmp = 4'b0001;                
    200                      end
    201             G2   : begin
    202                         start = 1'b1;
    203                         light_t_tmp = G2_T;
    204                         light1_tmp = 4'b0001;
    205                         light2_tmp = 4'b1000;                
    206                      end
    207             Y2_1 : begin
    208                         start = 1'b1;
    209                         light_t_tmp = Y2_T;
    210                         light1_tmp = 4'b0001;
    211                         light2_tmp = 4'b0100;                
    212                      end
    213             L2   : begin
    214                         start = 1'b1;
    215                         light_t_tmp = L2_T;
    216                         light1_tmp = 4'b0001;
    217                         light2_tmp = 4'b0010;                
    218                      end
    219             Y2_2 : begin
    220                         start = 1'b1;
    221                         light_t_tmp = Y2_T;
    222                         light1_tmp = 4'b0001;
    223                         light2_tmp = 4'b0100;                
    224                      end
    225         endcase
    226 
    227 //灯亮时间倒计时
    228 //时序逻辑,要在clk时钟下动作
    229 always@(posedge clk)
    230     if(!rst_n)
    231         begin
    232             light_t <= 7'd0;
    233         end
    234     else if(start)
    235                 begin
    236                     start <= 1'b0;
    237                     light_t <= light_t_tmp;
    238                 end
    239          else
    240             begin
    241                 light_t <= light_t - 1'b1;
    242             end
    243             
    244 //在light_t减到2时,置为change信号
    245 //用组合逻辑
    246 always@(*)
    247     if(!rst_n)
    248         change = 1'b0;  
    249     else if(light_t == 4'd2)
    250         change = 1'b1;
    251         
    252 //输出寄存    
    253 always@(posedge clk)
    254     if(!rst_n)
    255         begin
    256             light1 <= 4'd0;
    257             light2 <= 4'd0;
    258         end
    259     else
    260         begin
    261             light1 <= light1_tmp;
    262             light2 <= light2_tmp;
    263         end
    264         
    265 //下面是调试过程中对change以及start的控制    
    266 //因为使用了时序逻辑,导致各种错误
    267 /*
    268 always@(posedge clk)
    269     if(!rst_n)
    270         begin
    271             light_t <= 7'd0;
    272             //change <= 1'b0;  //复位,开始状态转换
    273         end
    274     else if(start)
    275                 begin
    276                     start <= 1'b0;
    277                     //change <= 1'b0;
    278                     //change_r <= 1'b0;
    279                     light_t <= light_t_tmp;
    280                 end
    281             //else if(light_t == 4'd1)
    282             //        change <= 1'b1;
    283                  else
    284                     begin
    285                         light_t <= light_t - 1'b1;
    286                         //change <= 1'b0;
    287                     end
    288 */
    289             
    290 /*            
    291 always@(*)
    292     if(!rst_n)
    293         change = 1'b0;  //复位,开始状态转换
    294     else if(start)
    295             change = 1'b0;
    296         else if(light_t == 4'd1)
    297         else if(light_t == 4'd2)
    298             change = 1'b1;        
    299 */    
    300 
    301 endmodule

    testbench如下:

     1 module traffic_light_tb;
     2 
     3     // Inputs
     4     reg rst_n;
     5     reg clk;
     6     reg trigger;
     7 
     8     // Outputs
     9     wire [3:0] light1;
    10     wire [3:0] light2;
    11 
    12     // Instantiate the Unit Under Test (UUT)
    13     traffic_light uut (
    14         .rst_n(rst_n), 
    15         .clk(clk), 
    16         .trigger(trigger),
    17         .light1(light1), 
    18         .light2(light2)
    19     );
    20     
    21     parameter CLK_PERIOD = 10;
    22 
    23     initial begin
    24         rst_n = 0;
    25         clk = 1;
    26         trigger = 0;
    27 
    28         #100;    
    29         rst_n = 1;
    30         trigger = 1;   //初始给出trigger信号,使得状态机进行状态循环
    31         #CLK_PERIOD trigger = 0;
    32         
    33         //#1000 trigger = 1;  //trigger复位状态机
    34         //#100 trigger = 0;
    35         
    36     end
    37     
    38     always #(CLK_PERIOD/2) clk = ~clk;
    39       
    40 endmodule

    ISIM仿真结果:

    可以看到,两个交通灯从给定的状态间循环,且时间同步。

  • 相关阅读:
    MySQL 8 新特性之Clone Plugin
    哈尔滨工业大学(威海)第九届ACM程序设计竞赛
    我回来了
    正则表达式(五):正则表达式的高阶使用
    正则表达式(四):正则表达式中的分组的概念
    正则表达式(三):正则表达式中的重复
    正则表达式(二):正则表达式的元字符
    正则表达式(一):正则表达式的概念
    Android NDK 跨平台构建工具 CMake 使用笔记
    字节序问题之大小端模式讲解
  • 原文地址:https://www.cnblogs.com/youngforever/p/3119497.html
Copyright © 2011-2022 走看看