基于FPGA实现交通灯——有限状态机设计

1.设计一个简单的十字路口交通灯控制系统, 实现如下3个功能:

➢ 1.十字路分为横向路H_road和纵向路V_road。

➢ 2.Hroad和Vroad交替通行,每条路的绿灯保持一段时间 (30秒)才通过黄灯(3秒)变为红灯,同时另一条路的 交通灯从红灯变为绿灯。

➢ 3.使用板载的LED灯代表交通灯上的红、黄、绿灯, 两块数码管分别显示两条路上的绿灯和红灯最后15秒倒计时和黄灯3秒倒计时。

2.交通灯状态提取:

➢ 抽象出6种状态:H_red、H_green、H_yellow、V_green、V_yellow、V_red 

➢ 注意到 H_red、V_red 包含在 H_green、H_yellow、V_green、V_yellow四个状态里 ➢ 我们提取以下四种状态:

                        H_green(横向路绿灯状态)、H_yellow(横向路黄灯状态)

                        V_green(纵向路绿灯状态)、V_yellow(纵向路黄灯状态)

➢ 交通灯输出既和现状态有关,又和输入(计数值)有关,为 Melay状态机。

3.交通灯状态转换表

状态转换图:

4.交通灯代码实现(verilog)
module traffic(
    input clk_1,
    input reset,
    input[7:0] counter_33,               //33秒计数器
    output reg Start_timer_33,          //开始计数信号
    output reg [1:0] H_display_en,      //横向道路倒计时显示使能
    output reg [7:0] H_count,           //横向道路倒计时数值
    output reg [1:0] V_display_en,      //纵向道路倒计时显示使能
    output reg [7:0] V_count,           //纵向道路倒计时数值
    output reg H_light_green,           //横向绿灯
    output reg H_light_yellow,          //横向黄灯
    output reg H_light_red,             //横向红灯
    output reg V_light_green,           //纵向绿灯
    output reg V_light_yellow,          //纵向黄灯
    output reg V_light_red              //纵向红灯
    );
	
    parameter H_green   = 4'b0001;
    parameter H_yellow  = 4'b0010;
    parameter V_green   = 4'b0100;
    parameter V_yellow  = 4'b1000;
    parameter YES = 1'b1;
    parameter NO = 1'b0;
    parameter ON  = 1'b1;
    parameter OFF = 1'b0;
    parameter DISPLAY_ON = 2'b00;
    parameter DISPLAY_OFF = 2'b11;
    
    reg [3:0] state;
    reg [3:0] next_state;
    
//第一个进程,同步时序always模块,格式化描述次态寄存器转移到现态寄存器;
    always@(posedge clk_1 ,negedge reset)
	begin
		if(!reset)  
			state <= H_green;             
		else
			state <= next_state;    
	end
    
//第二个进程,同步时序always模块,描述次态寄存器的状态转移条件
    always@ (posedge clk_1 ,negedge reset)
		if(!reset)
			 next_state <= H_green;
		else
		begin
			case(next_state)
				H_green:
					if(counter_33 == 4)
						next_state <= H_yellow;    
					else
						next_state <= H_green;
				H_yellow:
					if(counter_33 == 1)
						next_state <= V_green;
					else
						next_state <= H_yellow;
				V_green:
					if(counter_33 == 4)
                        next_state <= V_yellow;
                    else
                        next_state <= V_green;  
				V_yellow:
					if(counter_33 == 1)
                         next_state <= H_green;
                    else
                         next_state <= V_yellow;
				default:
					next_state <= H_green;
			endcase
        end
    
//第三个进程,同步时序always块,格式化描述次态寄存器的输出
	always@(posedge clk_1 ,negedge reset)
        if(!reset)  
		begin
			H_light_green <= ON;
			H_light_yellow <= OFF;
			H_light_red <= OFF;
			V_light_green <= OFF;
			V_light_yellow <= OFF;
			V_light_red <= ON;
			H_count <= 4'b0000;
			V_count <= 4'b0000;
			H_display_en <= DISPLAY_OFF;
			V_display_en <= DISPLAY_OFF; 
			Start_timer_33 <= YES;
		end
        else
		begin
			case(next_state)
				H_green:
					begin
						H_light_green <= ON;
						H_light_yellow <= OFF;
						H_light_red <= OFF;
						V_light_green <= OFF;
						V_light_yellow <= OFF;
						V_light_red <= ON;
						Start_timer_33 <= NO; 
						if(counter_33 <= 18 && counter_33 >= 4)
						begin
							H_count <= counter_33 - 3;
							H_display_en <= DISPLAY_ON;
						end
						else
							H_display_en <= DISPLAY_OFF;
						if(counter_33 <= 15 && counter_33 >= 1)
						begin
							V_count <= counter_33;
							V_display_en <= DISPLAY_ON;
						end
						else
							V_display_en <= DISPLAY_OFF;
					end
				H_yellow:
					begin
						H_light_green <= OFF;
						H_light_yellow <= ON;
						H_light_red <= OFF;
						V_light_green <= OFF;
						V_light_yellow <= OFF;
						V_light_red <= ON;              
						if(counter_33 <= 3 && counter_33 >= 1)
						begin
							H_count <= counter_33;
							H_display_en <= DISPLAY_ON;
						end
						else
							H_display_en <= DISPLAY_OFF;
						if(counter_33 <= 15 && counter_33 >= 1)
						begin
							V_count <= counter_33;
							V_display_en <= DISPLAY_ON;
						end
						else
							V_display_en <= DISPLAY_OFF;
						if(counter_33 == 1)
							Start_timer_33 <= YES;
						else
							Start_timer_33 <= NO;
					end                             
				V_green:
					begin
						H_light_green <= OFF;
						H_light_yellow <= OFF;
						H_light_red <= ON;
						V_light_green <= ON;
						V_light_yellow <= OFF;
						V_light_red <= OFF;
						Start_timer_33 <= NO;               
						if(counter_33 <= 18 && counter_33 >= 4)
                        begin
							V_count <= counter_33 - 3;
                            V_display_en <= DISPLAY_ON;
                            end
						else
							V_display_en <= DISPLAY_OFF;
						if(counter_33 <= 15 && counter_33 >= 1)
                        begin
							H_count <= counter_33;
                            H_display_en <= DISPLAY_ON;
                            end
						else
							H_display_en <= DISPLAY_OFF;
					end 
				V_yellow:
					begin
						H_light_green <= OFF;
						H_light_yellow <= OFF;
						H_light_red <= ON;
						V_light_green <= OFF;
						V_light_yellow <= ON;
						V_light_red <= OFF;              
						if(counter_33 <= 3 && counter_33 >= 1)
						begin
							V_count <= counter_33;
							V_display_en <= DISPLAY_ON;
						end
						else
							V_display_en <= DISPLAY_OFF;
						if(counter_33 <= 15 && counter_33 >= 1)
						begin
							H_count <= counter_33;
							H_display_en <= DISPLAY_ON;
						end
						else
							H_display_en <= DISPLAY_OFF;
						if(counter_33 == 1)
							Start_timer_33 <= YES;
						else
							Start_timer_33 <= NO;
					end
				default:
					begin
						H_light_green <= ON;
						H_light_yellow <= OFF;
						H_light_red <= OFF;
						V_light_green <= OFF;
						V_light_yellow <= OFF;
						V_light_red <= ON;
						H_count <= 4'b0000;
						V_count <= 4'b0000;
						H_display_en <= DISPLAY_OFF;
						V_display_en <= DISPLAY_OFF; 
						Start_timer_33 <= YES;
					end
			endcase
		end

endmodule
5.模块框图

➢ 分频器模块

➢ 计数器模块

➢ 有限状态机模块

➢ 逻辑译码及显示模块

6.交通灯代码实现:分频器
module clk_div(
   input clk_100M,
   input reset,
   output clk_200,
   output clk_1
 );
   reg[15:0] cnt_2khz;
   reg[7:0] cnt_200hz;
   reg[7:0]  cnt_1hz; 
   reg clk_2k;
   reg clk_200_reg;
   reg clk_1_reg;
//2KHz 分频代码:
 always @ (posedge clk_100M,negedge reset)
   begin
     if(!reset)
       begin
         cnt_2khz <= 1'b0;
         clk_2k <= 1'b0; 
       end
    else
    begin
       if(cnt_2khz==16'h61A7)//24999
           begin
             clk_2k<=~clk_2k;// 1*108/5*104=2000
             cnt_2khz <= 0;
           end
       else
           cnt_2khz<=cnt_2khz+1;  
     end 
  end
 
//200Hz 分频代码:
always@(posedge clk_2k,negedge reset)
   begin
      if(!reset)
         begin
            cnt_200hz<=1'b0;
            clk_200_reg<=1'b0;
         end
      else
         begin
             if(cnt_200hz == 4)        //计数5次
                 begin
                    clk_200_reg<=~clk_200_reg;
                    cnt_200hz <= 0;
                  end           
             else
                 cnt_200hz<=cnt_200hz+1;
          end
   end
//1Hz 分频代码:
 always@(posedge clk_200_reg,negedge reset)
    begin
        if(!reset)
            begin
               cnt_1hz<=1'b0;
               clk_1_reg<=1'b0; 
            end
        else
            begin
               if(cnt_1hz == 99) 
                      begin
                          clk_1_reg<=~clk_1_reg;
                          cnt_1hz <= 0;
                      end
              else
                      cnt_1hz<=cnt_1hz+1; 
            end 
   end  

   assign clk_200=clk_200_reg;
   assign clk_1=clk_1_reg;
 endmodul

7.交通灯代码实现:计数器
module counter(
   input clk_1,
   input reset,
   input Start_timer_33,
   output reg[7:0] counter_33 
);
 always@(posedge clk_1, negedge reset)
   if(!reset)
     counter_33 <= 32;
   else if(Start_timer_33)
     counter_33 <= 32;
   else
     counter_33 <= counter_33 -1;
 endmodule
8.交通灯代码实现 :14位二进制-BCD码转换器
module bin2bcd(
    input [7:0] data_bin,
    output reg[7:0] data_bcd
    );
    reg[17:0] z;    //中间变量,z的位数根据待转换的数字确定
    integer i;
    always@(*)  
    begin  
        for(i=0;i<=17;i=i+1)  //赋初值0  
            z[i]=0;     
        z[10:3]=data_bin;      //shift 3 places(3次后才判断是否需要+3  
        repeat(5)   //此处填入重复的次数  
        begin  
            if(z[11:8]>4) //个位>4则+3  
                z[11:8]=z[11:8]+3; 
            if(z[15:12]>4) //十位>4则+3  
                z[15:12]=z[15:12]+3;  
            z[17:1]=z[16:0];  
        end  
        data_bcd=z[15:8];  
    end
endmodule
9.交通灯代码实现:显示display
module display(
    input clk_200,
    input [3:0] hex3,
    input [3:0] hex2,   
    input [3:0] hex1,
    input [3:0] hex0,
    input [3:0]display_en, //用两个信号H_display_en和V_display_en拼接成输入{H_display_en,V_display_en}
    output reg [3:0] an,
    output reg [7:0] sseg
    );
    reg [1:0] regN;
    reg [3:0] hex_in;
    reg dp;
    initial 
    begin 
        regN = 0;
    end
    always@(posedge clk_200)
        regN <= regN + 1;
    always@*
    begin
        dp = 1'b0;
        case(regN)
            2'b00:
                begin
                    an=4'b1110 | display_en;
                    hex_in=hex0;
                end                            
            2'b01:
                begin
                    an=4'b1101 | display_en;
                    hex_in=hex1;
                end    
            2'b10:
                begin
                    an=4'b1011 | display_en;
                    hex_in=hex2;
                end    
            2'b11:
                begin
                    an=4'b0111 | display_en;
                    hex_in=hex3;
                end   
            default:
                begin
                    an = 4'b1111;
                    hex_in = 4'b0000;
                end                              
        endcase
    end
    always @ *   
    begin
        case(hex_in)
            4'h0: sseg[7:1] = 7'b1111110;
            4'h1: sseg[7:1] = 7'b0110000;
            4'h2: sseg[7:1] = 7'b1101101;
            4'h3: sseg[7:1] = 7'b1111001;
            4'h4: sseg[7:1] = 7'b0110011;
            4'h5: sseg[7:1] = 7'b1011011;
            4'h6: sseg[7:1] = 7'b1011111;
            4'h7: sseg[7:1] = 7'b1110000;
            4'h8: sseg[7:1] = 7'b1111111;
            4'h9: sseg[7:1] = 7'b1111011;
            4'ha: sseg[7:1] = 7'b1110111;
            4'hb: sseg[7:1] = 7'b0011111;
            4'hc: sseg[7:1] = 7'b1001110;
            4'hd: sseg[7:1] = 7'b0111101;
            4'he: sseg[7:1] = 7'b1001111;
            default: sseg[7:1] = 7'b1000111;  //4'hf        
        endcase
        sseg[0]=dp;
    end
endmodule

到这里所有所需模块已经搭建完成,现在需要一个顶层模块来集成上面的所有模块,以及定义外部接口,以实现与外部的交互。

10.交通灯顶层代码
 module traffic_top(
     input clk,
     input reset, 
     output H_light_green,
     output H_light_yellow,
     output H_light_red,
     output V_light_green,
     output V_light_yellow,
     output V_light_red,
     output [3:0] an,
     output [7:0] sseg 
 );
     wire clk_200;
     wire clk_1;
   
clk_div U1(
 .clk_100M(clk),
 .reset(reset),
 .clk_200(clk_200),
 .clk_1(clk_1)
 );
 
    wire Start_timer_33;
    wire [7:0] counter_33;
    counter U2(
        .clk_1(clk_1),
        .reset(reset),
        .Start_timer_33(Start_timer_33),
        .counter_33(counter_33)   
        );

wire [3:0] H_count; 
wire [3:0] V_count;
wire [1:0] H_display_en;
wire [1:0] V_display_en;

traffic U3(
 .clk_1(clk_1),
 .reset(reset),
 .counter_33(counter_33),
 .Start_timer_33(Start_timer_33),
 .H_count(H_count),  
 .V_count(V_count), 
 .H_light_green(H_light_green),
 .H_light_yellow(H_light_yellow),
 .H_light_red(H_light_red),
 .V_light_green(V_light_green),
 .V_light_yellow(V_light_yellow),
 .V_light_red(V_light_red) 
 ); 

    wire [7:0] H_bcd;
    wire [7:0] V_bcd;
    bin2bcd U4(
        .data_bin(H_count),
        .data_bcd(H_bcd)
        ); 
    bin2bcd U5(
        .data_bin(V_count),
        .data_bcd(V_bcd)
        );
    bin2bcd U6(
        .data_bin(counter_33),
        .data_bcd(counter)
        );
    display U7(
        .clk_200(clk_200),
        .hex3(H_bcd[7:4]),
        .hex2(H_bcd[3:0]),
        .hex1(V_bcd[7:4]),
        .hex0(V_bcd[3:0]),
        .display_en({H_display_en,V_display_en}),    
        .an(an),
        .sseg(sseg)
        );
endmodule
11.硬件配置

到此整个实验的主要内容已经是完成了,接下来是硬件的配置,此次实验使用的开发板为硬木课堂提供的ACE—7A75T,(可根据板子的型号而选定相适合的接口配置)因为上面只有红色LED灯,所以用红灯来代替绿黄,如下:

1.根据数据手册,进行红绿灯管脚分配

H_Light_green     U21

H_Light_red         R19

H_Light_yellow    P19

V_Light_green    W22

V_light_red         AA21

V_light_yellow    AA20

2.再进行红绿灯倒计时管脚的配置

an[3]          R14

an[2]          R18

an[1]         T18

an[0]         N17

3.对计数器进行配置

将counter计数器接入右上角的两个带译码的数码管DIG2,来显示counter33的值

最后再将时钟等其他接口接上,便完成了。

4.成品

交通灯

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值