习题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
原文地址:https://www.cnblogs.com/halflife/p/13814068.html