0
点赞
收藏
分享

微信扫一扫

习题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所示:

习题8 #第8章 Verilog有限状态机设计-4 #Verilog #Quartus #modelsim_d3

 

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

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

4.6  参照,找到方法,计时模块,状态转换,状态输出,条理清晰的分开写,难点在        于计数器还是只需要一个,控制模不同即可,产生计时的效果,也就是需要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

 

举报

相关推荐

0 条评论