zoukankan      html  css  js  c++  java
  • 习题8 #第8章 Verilog有限状态机设计-4 #Verilog #Quartus #modelsim

    4. 用状态机设计交通灯控制器,设计要求:A路和B路,每路都有红、黄、绿三种灯,持续时间为:红灯45s,黄灯5s,绿灯40秒。

        A路和B路灯的状态转换是:

        (1) A红,B绿(持续时间40s);

        (2) A红,B黄(持续时间5s);

        (1) A绿,B红(持续时间40s);

        (1) A绿,B黄(持续时间5s);

    4.1 设计思路:

          由题知共4个状态,每个状态及其输出持续的时间分别为40s或5秒。故设计一个模为90的计数器,分4段,对应每个状态持续的

          时间,然后顺序循环。

    4.2 两路交通灯控制电路源码如下:

         

     1 //triffic lights
     2 //ex8_4
     3 //2020-10-14
     4 //by YongFengXie
     5 module ex8_4(clk,rst_n,lights);
     6 input clk;
     7 input rst_n;
     8 output reg [5:0] lights; //A and B light
     9 
    10 reg [6:0] cnt;  // counter 90
    11 reg [3:0] state;
    12 
    13 parameter s0=4'b0001,s1=4'b0010,s2=4'b0100,
    14           s3=4'b1000;
    15 
    16 always @(posedge clk or negedge rst_n)
    17 begin
    18   if(!rst_n)
    19     cnt<=7'd0;
    20   else if(cnt<7'd90)
    21     cnt<=cnt+1'b1;
    22   else
    23     cnt<=7'd0;
    24 end
    25 
    26 always @(posedge clk or negedge rst_n)
    27 begin
    28   if(!rst_n)
    29     begin
    30       state<=s0;
    31       lights<=6'b100_001;
    32     end
    33   else if(cnt<7'd40)
    34     begin
    35       state<=s0;
    36       lights<=6'b100_001;  //RYG(A)_RYG(B)
    37     end
    38   else if(cnt>7'd39 &&cnt<7'd45)
    39     begin
    40       state<=s1;
    41       lights<=6'b100_010;  //RYG(A)_RYG(B)
    42     end
    43   else if(cnt>7'd44 && cnt<7'd85)
    44     begin
    45       state<=s2;
    46       lights<=6'b001_100;  //RYG(A)_RYG(B)
    47     end
    48   else 
    49     begin
    50       state<=s3;
    51       lights<=6'b001_010;  //RYG(A)_RYG(B)
    52     end
    53 end
    54 
    55 endmodule

    4.3 交通灯控制器的测试代码:

      

     1 //ex8_4 testbench
     2 //2020-10-14
     3 //by YongFengXie
     4 `timescale 1ns/1ns
     5 module ex8_4tb;
     6 reg clk;
     7 reg rst_n;
     8 wire [5:0] lights;
     9 
    10 ex8_4 ub(clk,rst_n,lights);
    11 
    12 initial begin
    13           clk=1'b0;
    14           rst_n=1'b0;
    15           #20 rst_n=1'b1;
    16           #1000 $stop;
    17         end
    18 
    19 always #5 clk=~clk;
    20 
    21 endmodule 

    4.4 交通灯控制器的仿真结果如图ex8_4_1所示:

       图ex8_4_1 交通灯控制器仿真结果

    4.5  总结:交通灯控制器这个电路的状态转换挺简单,题目里已经详细列出。难在每种状态持续时间不一样,这是跟前面的序列检测不同的地               方。按照上述设计,在Quartus里未生成状态转换图,仿真和DE2-115上皆可验证正确。期待更好的解法。 

    4.6  参照https://blog.csdn.net/qq_38318540/article/details/107401152,找到方法,计时模块,状态转换,状态输出,条理清晰的分开写,难点在        于计数器还是只需要一个,控制模不同即可,产生计时的效果,也就是需要40s,5s的计时,设计里在状态发生转换时产生一个标志st,同时          这个st,在计时模块里又扮演计数器清零的一个功能,达到计时到不同值,计数器清零重新开始计数的目的,看似无用的st,关联器状态变化

         的节奏。

          另一种交通灯控制器的Verilog代码如下:

         

      1 //triffic lights
      2 //ex8_4
      3 //2020-10-14
      4 //by YongFengXie
      5 module ex8_4(clk,rst_n,lights);
      6 input clk;
      7 input rst_n;
      8 output reg [5:0] lights; //A and B light
      9 
     10 reg [6:0] cnt;  // counter 90
     11 reg [3:0] state,nextstate;
     12 wire t1,t2;    // t1-40s,t2-5s
     13 reg st;        // state transition signal
     14 
     15 parameter s0=4'b0001,s1=4'b0010,s2=4'b0100,
     16           s3=4'b1000;
     17 
     18 //timing module
     19 always @(posedge clk or negedge rst_n)
     20 begin
     21   if(!rst_n)
     22     cnt<=7'd0;
     23   else if(st)
     24     cnt<=7'd0;
     25   else if(cnt<7'd40)
     26     cnt<=cnt+1'b1;
     27   else
     28     cnt<=7'd0;
     29 end
     30 
     31 assign t1=(cnt==7'd39)?1'b1:1'b0;
     32 assign t2=(cnt==7'd4)?1'b1:1'b0;
     33 
     34 /*
     35 always @(posedge clk or negedge rst_n)
     36 begin
     37   if(!rst_n)
     38     begin
     39       state<=s0;
     40       lights<=6'b100_001;
     41     end
     42   else if(cnt<7'd40)
     43     begin
     44       state<=s0;
     45       lights<=6'b100_001;  //RYG(A)_RYG(B)
     46     end
     47   else if(cnt>7'd39 &&cnt<7'd45)
     48     begin
     49       state<=s1;
     50       lights<=6'b100_010;  //RYG(A)_RYG(B)
     51     end
     52   else if(cnt>7'd44 && cnt<7'd85)
     53     begin
     54       state<=s2;
     55       lights<=6'b001_100;  //RYG(A)_RYG(B)
     56     end
     57   else 
     58     begin
     59       state<=s3;
     60       lights<=6'b001_010;  //RYG(A)_RYG(B)
     61     end
     62 end
     63 */
     64 
     65 //state transition module
     66 always @(posedge clk or negedge rst_n)
     67 begin
     68   if(!rst_n)
     69     state<=s0;
     70   else
     71     state<=nextstate;
     72 end
     73 
     74 always @(state,t1,t2)
     75 begin
     76   case(state)
     77     s0: begin
     78           nextstate<=t1?s1:s0;
     79           st<=t1?1'b1:1'b0;
     80         end
     81     s1: begin
     82           nextstate<=t2?s2:s1;
     83           st<=t2?1'b1:1'b0;
     84         end
     85     s2: begin
     86           nextstate<=t1?s3:s2;
     87           st<=t1?1'b1:1'b0;
     88         end
     89     s3: begin
     90           nextstate<=t2?s0:s3;
     91           st<=t2?1'b1:1'b0;
     92         end
     93     default: begin
     94                nextstate<=s0;
     95                st<=1'b0;
     96              end
     97   endcase
     98 end
     99 
    100 //state corresponding output
    101 always @(state)
    102 begin
    103   case(state)
    104     s0:lights=6'b100_001; //A-R,B-G
    105     s1:lights=6'b100_010; //A-R,B-Y
    106     s2:lights=6'b001_100; //A-G,B-R
    107     s3:lights=6'b010_100; //A-Y,B-R
    108     default:lights=6'b100_001; //A-R,B-G
    109   endcase
    110 end
    111 
    112 endmodule


     上面的代码不够简洁,还是有个固定思维的问题,其中从18行开始的计时模块做成模可变的计数器更优,所以,这段,修改如下:

     1 //timing module
     2 always @(posedge clk or negedge rst_n)
     3 begin
     4   if(!rst_n)
     5     cnt<=7'd0;
     6   else if(st)
     7     cnt<=7'd0;
     8   else
     9     cnt<=cnt+1'b1;
    10   /*else if(cnt<7'd40)
    11     cnt<=cnt+1'b1;
    12   else
    13     cnt<=7'd0;*/
    14 end
  • 相关阅读:
    浅析C++:private、protected和public
    数据结构关于简单顺序表的构建(C++)
    小小的项目——简单的注释转换
    宏定义实现两数交换
    简易小程序(将字符型数据转换为浮点型数据)
    小小比较格式运算符及截图显示
    python __call__() 方法
    python_selenium简单的滑动验证码
    scrapy 爬虫学习二[中间件的学习]
    scrapy 爬虫学习一
  • 原文地址:https://www.cnblogs.com/halflife/p/13814068.html
Copyright © 2011-2022 走看看