習題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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM