基于BASYS 3的双路红绿灯控制器(Verilog)

实现功能:十字路口A和B两个方向用红灯20秒、黄灯5秒、绿灯9秒的方式变化,数码管同时倒计时显示通行或禁止通行时间。

         

      

所需模块:

1.数码管动态扫描子模块

2.数码管显示子模块

3.1秒时钟产生子模块

4.9s-5s-20s-20s顺序计时子模块

5.20s-20s-9s-5s顺序计时子模块

6.mealy四状态机子模块

7.顶层运用模块

应用原理及方法:

状态机:MOORE状态机、MEALY状态机

仿真:

1.将各个功能模块化,分别测试各个模块的功能是否正确。

2.仿真初值设置,采用rst按键复位产生初值。

代码:

顶层模块:

module main(clk,dig,rst,seg,ledA,ledB);
input clk;
output ledA,ledB;
input rst;
output dig;
output seg;
wire [3:0]dig;
wire [7:0]seg;
wire [2:0]ledA,ledB;
wire clk_1Hz;//1Hz
wire clkA,clkB;//15s
wire clk_scan;//动态扫描频率
wire [3:0]cntA_1,cntA_2;
wire [3:0]cntB_1,cntB_2;

CLK_1S      CLK1S(.clk_100MHz(clk),.clk_1Hz(clk_1Hz));//产生1Hz时钟
CLK_A       A1(.clk_1Hz(clk_1Hz),.clk_out(clkA),.cnt_1(cntA_1),.cnt_2(cntA_2));//产生周期为15秒时钟
CLK_B       B1(.clk_1Hz(clk_1Hz),.clk_out(clkB),.cnt_1(cntB_1),.cnt_2(cntB_2));
CLK_SCAN    S1(.clk_100MHz(clk),.clk_scan(clk_scan));//产生3KHz扫描时钟
DIG_SEG     D1(.clk_sel(clk_scan),.dig(dig),.seg(seg),.seg1(cntB_2),.seg2(cntB_1),.seg3(cntA_2),.seg4(cntA_1));//数码管显示
STATEA      L1(.clk_in(clkA),.rst(rst),.currentstate(ledA));
STATEB      L2(.clk_in(clkB),.rst(rst),.currentstate(ledB));
endmodule

1秒时钟产生子模块:

BASYS 3的时钟为100MHz,100M个周期,即是一秒。T=1S时,0.5S反转一次。所以这里用到一个cnt,计数50M满,1s输出信号跳变,cnt==28'b10111110101111000010000000,50 000 000。

//时钟分频模块:将Basys3上的100MHz时钟clk分频到1Hz输出,作为15秒倒计时计数时钟clk_1hz ;
module CLK_1S(clk_100MHz,clk_1Hz);
input clk_100MHz;//100M时钟输入
output reg clk_1Hz;//输出1s
reg [27:0] cnt;

always @(posedge clk_100MHz)
begin
    if(cnt==28'b0010_1111_1010_1111_0000_1000_0000)//100MHz/1Hz
    begin
    cnt <=0;//清零
    clk_1Hz <= ~clk_1Hz;
     end
     
     else
     cnt <= cnt + 1;
end

endmodule

9s-5s-20s-20s顺序计时子模块:

module CLK_A(clk_1Hz,clk_out,cnt_1,cnt_2);
input clk_1Hz;//1s
output reg clk_out;//15s
output cnt_1,cnt_2;//两位记数 0-9
reg [4:0]cnt;//0-15
wire [3:0]cnt_1;//十位
wire [3:0]cnt_2;//个位
reg [1:0]sig;

assign   cnt_1 =cnt/'b1010; //十位除10
assign   cnt_2 =cnt%'b1010;//各位余10




always @(posedge clk_1Hz)//产生两位数
begin
    if(cnt==5'b00000||cnt==5'b11111)begin    // cnt0-14 不需要到达1
     case(sig)
     2'b00:begin 
        cnt<=5'b01001; //9
        sig<=sig+'b1;
        clk_out<=1;
           end
     2'b01:begin 
         cnt<=5'b00101; //5
         sig<=sig+'b1;
          clk_out<=1;
           end  
     2'b10:begin 
          cnt<=5'b10100; //20
         sig<=sig+'b1;
          clk_out<=1;
           end  
      2'b11:begin 
         cnt<=5'b10100; //20
         sig<=sig+'b1;
          clk_out<=1;
           end       
     endcase    
     end
   
    else begin
         cnt <= cnt -'b1;
         clk_out<=0;
         end
end

endmodule

20s-20s-9s-5s顺序计时子模块:

module CLK_B(clk_1Hz,clk_out,cnt_1,cnt_2);
input clk_1Hz;//1s
output reg clk_out;//15s
output cnt_1,cnt_2;//两位记数 0-9
reg [4:0]cnt;//0-15
wire [3:0]cnt_1;//十位
wire [3:0]cnt_2;//个位
reg [1:0]sig;

assign   cnt_1 =cnt/'b1010; //十位除10
assign   cnt_2 =cnt%'b1010;//各位余10



always @(posedge clk_1Hz)//产生两位数
begin
    if(cnt==5'b00000||cnt==5'b11111)begin    // cnt0-14 不需要到达1
     case(sig)
     2'b00:begin 
         cnt<=5'b10100; //20
          sig<=sig+'b1;
          clk_out<=1;
        
           end
     2'b01:begin 
     cnt<=5'b10100; //20
         sig<=sig+'b1;
          clk_out<=1;
           end  
     2'b10:begin 
          cnt<=5'b01001; //9
        sig<=sig+'b1;
        clk_out<=1;
           end  
      2'b11:begin 
         cnt<=5'b00101; //5
         sig<=sig+'b1;
          clk_out<=1;
           end       
     endcase    
     end
   
    else begin
         cnt <= cnt -'b1;
         clk_out<=0;
         end
end

endmodule

数码管动态扫描子模块:

//100MHz分频到2.5KHz~4KHz输出,作为数码管动态显示的扫描频率clk-scan,3Khz动态扫描
module CLK_SCAN(clk_100MHz,clk_scan);
input clk_100MHz;
output reg clk_scan;
reg [15:0] cnt;

always @(posedge clk_100MHz)
begin
    cnt <= cnt + 1;
    if(cnt==16'b1000_0010_0011_0101)//100MHz/33333Hz
    begin
      cnt <=0;//清零
    clk_scan <= ~clk_scan;
     end
end

endmodule

数码管显示子模块:

odule DIG_SEG(clk_sel,seg1,seg2,seg3,seg4,dig,seg);
input  clk_sel;
input  [3:0]seg1,seg2,seg3,seg4;
output dig,seg;
reg [3:0]dig;
reg [7:0]seg;
reg [1:0]selcnt;


//parameter     seg_0=8'b11000000;
//parameter     seg_1=8'b11111001;
//parameter     seg_2=8'b10100100;
//parameter     seg_3=8'b10110000;
//parameter     seg_4=8'b10011001;
//parameter     seg_5=8'b10010010;
//parameter     seg_6=8'b10000010;
//parameter     seg_7=8'b11111000;
//parameter     seg_8=8'b10000000;
//parameter     seg_9=8'b10010000;


always @(posedge clk_sel)//位选标志位
begin
   selcnt <= selcnt + 1;//标志位+1,11记满后加一回到00
end

always @(selcnt)      //位选信号控制
begin
 case (selcnt)
  2'b00: begin dig <= 4'b0111;end //1号数码管显示ain对应的段码
  2'b01: begin dig <= 4'b1011;end
  2'b10: begin dig <= 4'b1101;end
  2'b11: begin dig <= 4'b1110;end
 endcase
end

always @(selcnt or seg1 or seg2 or seg3 or seg4)      //位选信号控制
begin
if (selcnt==2'b00)
begin
         case(seg1)
        4'b0000:seg <= 8'b11000000;
        4'b0001:seg <= 8'b11111001;
        4'b0010:seg <= 8'b10100100;
        4'b0011:seg <= 8'b10110000;
    
        4'b0100:seg <= 8'b10011001;
        4'b0101:seg <= 8'b10010010;
        4'b0110:seg <= 8'b10000010;
        4'b0111:seg <= 8'b11111000;
    
        4'b1000:seg <= 8'b10000000;
        4'b1001:seg <= 8'b10010000;
         default: seg<=8'b11000000;
         endcase
 end 
 
 if (selcnt==2'b01)
begin
         case(seg2)
        4'b0000:seg <= 8'b11000000;
        4'b0001:seg <= 8'b11111001;
        4'b0010:seg <= 8'b10100100;
        4'b0011:seg <= 8'b10110000;
    
        4'b0100:seg <= 8'b10011001;
        4'b0101:seg <= 8'b10010010;
        4'b0110:seg <= 8'b10000010;
        4'b0111:seg <= 8'b11111000;
    
        4'b1000:seg <= 8'b10000000;
        4'b1001:seg <= 8'b10010000;
         default: seg<=8'b11000000;
         endcase
end 
  
  if (selcnt==2'b10)
begin
         case(seg3)
        4'b0000:seg <= 8'b11000000;
        4'b0001:seg <= 8'b11111001;
        4'b0010:seg <= 8'b10100100;
        4'b0011:seg <= 8'b10110000;
    
        4'b0100:seg <= 8'b10011001;
        4'b0101:seg <= 8'b10010010;
        4'b0110:seg <= 8'b10000010;
        4'b0111:seg <= 8'b11111000;
    
        4'b1000:seg <= 8'b10000000;
        4'b1001:seg <= 8'b10010000;
         default: seg<=8'b11000000;
         endcase
end 
  
  if (selcnt==2'b11)
begin
         case(seg4)
        4'b0000:seg <= 8'b11000000;
        4'b0001:seg <= 8'b11111001;
        4'b0010:seg <= 8'b10100100;
        4'b0011:seg <= 8'b10110000;
    
        4'b0100:seg <= 8'b10011001;
        4'b0101:seg <= 8'b10010010;
        4'b0110:seg <= 8'b10000010;
        4'b0111:seg <= 8'b11111000;
    
        4'b1000:seg <= 8'b10000000;
        4'b1001:seg <= 8'b10010000;
         default: seg<=8'b11000000;
         endcase
end 
 
end

endmodule

A路状态机:利用sig标志位控制红灯亮两次,sig=0,为红灯时,状态不跳转,红灯显示一次,sig加1。sig=1,为红灯时,状态下一次翻转。

module STATEA(clk_in,rst,currentstate);
input clk_in;
input rst;
output reg [2:0]currentstate;
reg [2:0]nextstate;
reg sig;
parameter S0=3'b001;
parameter S1=3'b010;
parameter S2=3'b100;


always @(posedge clk_in or posedge rst)
begin
       if(rst) 
         currentstate<=S0;
       else begin
        currentstate<=nextstate;
        if(currentstate==S2)
          sig<=sig+1;
          end
end

always @(currentstate or sig)
begin
    case(currentstate)
        S0:nextstate=S1;
        S1:nextstate=S2;
       S2:begin 
        if(sig) 
            nextstate=S0;
        else 
            nextstate=S2;
           end
          default: nextstate=S1;
    endcase
end


endmodule

B路状态机:

module STATEB(clk_in,rst,currentstate);
input clk_in;
input rst;
output reg [2:0]currentstate;
reg [2:0]nextstate;
reg sig;
parameter S0=3'b001;
parameter S1=3'b010;
parameter S2=3'b100;


always @(posedge clk_in or posedge rst)
begin
       if(rst) 
         currentstate<=S2;
       else begin
        currentstate<=nextstate;
        if(currentstate==S2)
          sig<=sig+1;
          end
end

always @(currentstate or sig)
begin
    case(currentstate)
        S0:nextstate=S1;
        S1:nextstate=S2;
       S2:begin 
        if(sig) 
            nextstate=S0;
        else 
            nextstate=S2;
           end
          default: nextstate=S1;
    endcase
end


endmodule

工程文件实例:

代码改进,若需要不同时间的红绿灯,只需要重新设置在顺序计时模块中的时间条件即可。

         红绿灯系统的目标是优化交通流量,提高交通效率和安全性。单个的红绿灯设计可以帮助我们对状态机的理解。

        但是在实际生活中,红绿灯是一个庞大的系统,一条主干道上有很多的红绿灯,需要对实际路况和车流量和道路宽窄设计转换时间,并且需要和多个红绿灯协同运作。这样的设计才能解决实际性问题。

        当然,现代的红绿灯系统已经很完善了,缺少的是对路况和人车流量的智能检测和分析。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值