Vivado下Verilog交通灯控制器设计

一、设计概述

本设计实现一个完整的交通灯控制系统,包含主干道和支干道两组信号灯,具有自动循环、行人请求、紧急模式等功能。系统采用有限状态机(FSM)实现,具有清晰的时序逻辑和状态转换。

二、系统设计

1. 系统框图

复制代码
+-----------------+     +-----------------+     +-----------------+
|  时钟分频模块    |     |  状态机控制      |     |  输出控制        |
| (Clock Divider)  |---->| (State Machine) |---->| (Output Logic)  |
+-----------------+     +-----------------+     +-----------------+
        |                      |                         |
        v                      v                         v
+-----------------+     +-----------------+     +-----------------+
|  复位信号        |     |  时间计数器      |     |  LED显示驱动     |
| (Reset Signal)   |     | (Time Counter)  |     | (LED Driver)    |
+-----------------+     +-----------------+     +-----------------+

2. 功能规格

  • 主干道绿灯时间:30秒
  • 支干道绿灯时间:20秒
  • 黄灯时间:3秒
  • 支持行人请求按钮
  • 支持紧急模式开关
  • 倒计时显示功能

三、Verilog实现

1. 顶层模块 (traffic_light_top.v)

v 复制代码
module traffic_light_top(
    input clk,          // 100MHz系统时钟
    input reset,        // 复位信号
    input ped_request,  // 行人请求按钮
    input emergency,    // 紧急模式开关
    output [2:0] main_light,  // 主干道灯 [红,黄,绿]
    output [2:0] side_light,  // 支干道灯 [红,黄,绿]
    output [6:0] seg,   // 7段数码管
    output [3:0] an     // 数码管位选
);

// 时钟分频
wire clk_1Hz;
clock_divider #(.DIVIDER(100_000_000)) u_clk_divider(
    .clk(clk),
    .reset(reset),
    .clk_out(clk_1Hz)
);

// 状态机控制
wire [1:0] state;
wire [5:0] timer;
wire ped_wait;
state_machine u_state_machine(
    .clk(clk_1Hz),
    .reset(reset),
    .ped_request(ped_request),
    .emergency(emergency),
    .state(state),
    .timer(timer),
    .ped_wait(ped_wait)
);

// 输出控制
output_logic u_output_logic(
    .state(state),
    .emergency(emergency),
    .main_light(main_light),
    .side_light(side_light)
);

// 倒计时显示
display_driver u_display_driver(
    .clk(clk),
    .reset(reset),
    .state(state),
    .timer(timer),
    .ped_wait(ped_wait),
    .seg(seg),
    .an(an)
);

endmodule

2. 时钟分频模块 (clock_divider.v)

v 复制代码
module clock_divider #(
    parameter DIVIDER = 100_000_000  // 100MHz -> 1Hz
)(
    input clk,
    input reset,
    output reg clk_out
);

reg [31:0] counter;

always @(posedge clk or posedge reset) begin
    if (reset) begin
        counter <= 0;
        clk_out <= 0;
    end else begin
        if (counter == DIVIDER/2 - 1) begin
            counter <= 0;
            clk_out <= ~clk_out;
        end else begin
            counter <= counter + 1;
        end
    end
end

endmodule

3. 状态机控制 (state_machine.v)

v 复制代码
module state_machine(
    input clk,
    input reset,
    input ped_request,
    input emergency,
    output reg [1:0] state,
    output reg [5:0] timer,
    output reg ped_wait
);

// 状态定义
localparam MAIN_GREEN = 2'b00;
localparam MAIN_YELLOW = 2'b01;
localparam SIDE_GREEN = 2'b10;
localparam SIDE_YELLOW = 2'b11;

// 时间参数
localparam MAIN_GREEN_TIME = 6'd30;
localparam MAIN_YELLOW_TIME = 6'd3;
localparam SIDE_GREEN_TIME = 6'd20;
localparam SIDE_YELLOW_TIME = 6'd3;

// 状态转移逻辑
always @(posedge clk or posedge reset) begin
    if (reset) begin
        state <= MAIN_GREEN;
        timer <= MAIN_GREEN_TIME;
        ped_wait <= 0;
    end else if (emergency) begin
        // 紧急模式:所有方向红灯
        state <= MAIN_GREEN;  // 任意状态,实际输出会覆盖
        timer <= 0;
    end else begin
        // 行人请求处理
        if (ped_request && state == SIDE_GREEN && timer > 6'd5) begin
            ped_wait <= 1;
        end
        
        // 状态转移
        if (timer == 0) begin
            case (state)
                MAIN_GREEN: begin
                    state <= MAIN_YELLOW;
                    timer <= MAIN_YELLOW_TIME;
                end
                MAIN_YELLOW: begin
                    state <= SIDE_GREEN;
                    timer <= (ped_wait) ? 6'd5 : SIDE_GREEN_TIME;
                    ped_wait <= 0;
                end
                SIDE_GREEN: begin
                    state <= SIDE_YELLOW;
                    timer <= SIDE_YELLOW_TIME;
                end
                SIDE_YELLOW: begin
                    state <= MAIN_GREEN;
                    timer <= MAIN_GREEN_TIME;
                end
            endcase
        end else begin
            timer <= timer - 1;
        end
    end
end

endmodule

4. 输出逻辑 (output_logic.v)

v 复制代码
module output_logic(
    input [1:0] state,
    input emergency,
    output reg [2:0] main_light,
    output reg [2:0] side_light
);

// 灯定义: [红, 黄, 绿]
localparam RED   = 3'b100;
localparam YELLOW = 3'b010;
localparam GREEN = 3'b001;

always @(*) begin
    if (emergency) begin
        // 紧急模式:所有方向红灯
        main_light = RED;
        side_light = RED;
    end else begin
        case (state)
            // 主干道绿灯,支干道红灯
            2'b00: begin
                main_light = GREEN;
                side_light = RED;
            end
            // 主干道黄灯,支干道红灯
            2'b01: begin
                main_light = YELLOW;
                side_light = RED;
            end
            // 主干道红灯,支干道绿灯
            2'b10: begin
                main_light = RED;
                side_light = GREEN;
            end
            // 主干道红灯,支干道黄灯
            2'b11: begin
                main_light = RED;
                side_light = YELLOW;
            end
            default: begin
                main_light = RED;
                side_light = RED;
            end
        endcase
    end
end

endmodule

5. 显示驱动 (display_driver.v)

v 复制代码
module display_driver(
    input clk,
    input reset,
    input [1:0] state,
    input [5:0] timer,
    input ped_wait,
    output reg [6:0] seg,
    output reg [3:0] an
);

// 数码管显示值
reg [3:0] digit0, digit1;
reg [3:0] digit2, digit3;

// 数码管译码
always @(*) begin
    case(digit0)
        0: seg = 7'b1000000; 1: seg = 7'b1111001;
        2: seg = 7'b0100100; 3: seg = 7'b0110000;
        4: seg = 7'b0011001; 5: seg = 7'b0010010;
        6: seg = 7'b0000010; 7: seg = 7'b1111000;
        8: seg = 7'b0000000; 9: seg = 7'b0010000;
        default: seg = 7'b1111111;
    endcase
end

// 时间显示逻辑
always @(posedge clk or posedge reset) begin
    if (reset) begin
        digit0 <= 0; digit1 <= 0;
        digit2 <= 0; digit3 <= 0;
        an <= 4'b1110;
    end else begin
        // 根据状态选择显示内容
        case(state)
            2'b00: begin // 主干道绿灯
                digit1 <= timer / 10;
                digit0 <= timer % 10;
                digit3 <= 4'hM; // M表示Main
                digit2 <= 4'hG; // G表示Green
            end
            2'b01: begin // 主干道黄灯
                digit1 <= timer / 10;
                digit0 <= timer % 10;
                digit3 <= 4'hM;
                digit2 <= 4'hY; // Y表示Yellow
            end
            2'b10: begin // 支干道绿灯
                digit1 <= timer / 10;
                digit0 <= timer % 10;
                digit3 <= 4'hS; // S表示Side
                digit2 <= 4'hG;
            end
            2'b11: begin // 支干道黄灯
                digit1 <= timer / 10;
                digit0 <= timer % 10;
                digit3 <= 4'hS;
                digit2 <= 4'hY;
            end
        endcase
        
        // 行人等待状态
        if (ped_wait) begin
            digit3 <= 4'hP; // P表示Pedestrian
            digit2 <= 4'hW; // W表示Wait
        end
    end
end

endmodule

四、约束文件 (traffic_light.xdc)

v 复制代码
# 时钟信号
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]

# 复位按钮
set_property -dict {PACKAGE_PIN C12 IOSTANDARD LVCMOS33} [get_ports reset]

# 行人请求按钮
set_property -dict {PACKAGE_PIN D12 IOSTANDARD LVCMOS33} [get_ports ped_request]

# 紧急模式开关
set_property -dict {PACKAGE_PIN A3 IOSTANDARD LVCMOS33} [get_ports emergency]

# 主干道信号灯
set_property -dict {PACKAGE_PIN F5 IOSTANDARD LVCMOS33} [get_ports {main_light[0]}] # 红
set_property -dict {PACKAGE_PIN G4 IOSTANDARD LVCMOS33} [get_ports {main_light[1]}] # 黄
set_property -dict {PACKAGE_PIN J3 IOSTANDARD LVCMOS33} [get_ports {main_light[2]}] # 绿

# 支干道信号灯
set_property -dict {PACKAGE_PIN B4 IOSTANDARD LVCMOS33} [get_ports {side_light[0]}] # 红
set_property -dict {PACKAGE_PIN C3 IOSTANDARD LVCMOS33} [get_ports {side_light[1]}] # 黄
set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports {side_light[2]}] # 绿

# 数码管段选
set_property -dict {PACKAGE_PIN H19 IOSTANDARD LVCMOS33} [get_ports {seg[0]}]
set_property -dict {PACKAGE_PIN G20 IOSTANDARD LVCMOS33} [get_ports {seg[1]}]
set_property -dict {PACKAGE_PIN J22 IOSTANDARD LVCMOS33} [get_ports {seg[2]}]
set_property -dict {PACKAGE_PIN K22 IOSTANDARD LVCMOS33} [get_ports {seg[3]}]
set_property -dict {PACKAGE_PIN K21 IOSTANDARD LVCMOS33} [get_ports {seg[4]}]
set_property -dict {PACKAGE_PIN H20 IOSTANDARD LVCMOS33} [get_ports {seg[5]}]
set_property -dict {PACKAGE_PIN H22 IOSTANDARD LVCMOS33} [get_ports {seg[6]}]

# 数码管位选
set_property -dict {PACKAGE_PIN F17 IOSTANDARD LVCMOS33} [get_ports {an[0]}]
set_property -dict {PACKAGE_PIN H18 IOSTANDARD LVCMOS33} [get_ports {an[1]}]
set_property -dict {PACKAGE_PIN C19 IOSTANDARD LVCMOS33} [get_ports {an[2]}]
set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {an[3]}]

参考代码 Vivado下verilog编写完整交通灯 www.youwenfan.com/contentcss/182616.html

五、仿真测试

1. 测试平台 (tb_traffic_light.sv)

v 复制代码
`timescale 1ns / 1ps

module tb_traffic_light();

reg clk;
reg reset;
reg ped_request;
reg emergency;
wire [2:0] main_light;
wire [2:0] side_light;

// 实例化被测设计
traffic_light_top uut (
    .clk(clk),
    .reset(reset),
    .ped_request(ped_request),
    .emergency(emergency),
    .main_light(main_light),
    .side_light(side_light)
);

// 生成时钟
initial begin
    clk = 0;
    forever #5 clk = ~clk; // 100MHz时钟
end

// 测试序列
initial begin
    // 初始化
    reset = 1;
    ped_request = 0;
    emergency = 0;
    #20;
    
    // 释放复位
    reset = 0;
    #100;
    
    // 测试行人请求
    ped_request = 1;
    #10;
    ped_request = 0;
    #200;
    
    // 测试紧急模式
    emergency = 1;
    #100;
    emergency = 0;
    #100;
    
    // 结束仿真
    $finish;
end

// 波形记录
initial begin
    $dumpfile("traffic_light.vcd");
    $dumpvars(0, tb_traffic_light);
end

endmodule

2. 预期仿真结果

  1. 复位后系统进入主干道绿灯状态(30秒)
  2. 30秒后切换到主干道黄灯(3秒)
  3. 3秒后切换到支干道绿灯(20秒)
  4. 20秒后切换到支干道黄灯(3秒)
  5. 3秒后回到主干道绿灯状态
  6. 行人请求在支干道绿灯最后5秒有效
  7. 紧急模式时所有方向显示红灯

六、实现与综合

1. Vivado实现步骤

  1. 创建新项目,选择目标FPGA器件
  2. 添加所有Verilog源文件
  3. 添加约束文件
  4. 运行综合(Synthesis)
  5. 运行实现(Implementation)
  6. 生成比特流(Generate Bitstream)
  7. 下载到开发板

2. 资源占用预估

资源类型 使用量 可用量 利用率
LUT 约200 63400 <1%
FF 约100 126800 <1%
IO 约20 300 <7%
BUFG 1 32 3%

七、扩展功能

1. 夜间模式

v 复制代码
// 在状态机中添加夜间模式
localparam NIGHT_MODE = 2'b00; // 使用相同状态编码

// 添加夜间模式检测
always @(posedge clk or posedge reset) begin
    if (night_mode_button) begin
        night_mode <= ~night_mode;
    end
end

// 修改状态转移
if (night_mode) begin
    // 夜间模式:黄灯闪烁
    main_light = (clk_1Hz) ? YELLOW : OFF;
    side_light = (clk_1Hz) ? YELLOW : OFF;
end

2. 车流量检测

v 复制代码
// 添加车流量传感器输入
input [3:0] car_flow_main;
input [3:0] car_flow_side;

// 在状态机中动态调整时间
if (car_flow_main > 8'h0A) begin
    // 主干道车多,延长绿灯时间
    main_green_time = 40;
end

八、项目总结

本设计实现了一个完整的交通灯控制系统,具有以下特点:

  1. 采用有限状态机实现清晰的交通灯状态转换
  2. 支持行人请求和紧急模式
  3. 提供倒计时显示功能
  4. 模块化设计,便于扩展和维护
  5. 资源占用少,适合在中小规模FPGA上实现
相关推荐
嵌入式-老费3 小时前
vivado hls的应用(开篇)
fpga开发
ARM+FPGA+AI工业主板定制专家4 小时前
基于ARM+FPGA+AI的船舶状态智能监测系统(一)总体设计
网络·arm开发·人工智能·机器学习·fpga开发·自动驾驶
Eidolon_li5 小时前
ARINC429模块规格书(V1.1)
fpga开发
FPGA-ADDA18 小时前
第四篇:嵌入式系统常用通信接口详解(I2C、SPI、UART、RS232/485、CAN、USB)
人工智能·单片机·嵌入式硬件·fpga开发·信息与通信
421!1 天前
ESP32学习笔记之GPIO
开发语言·笔记·单片机·嵌入式硬件·学习·算法·fpga开发
dMing`1 天前
基于FPGA的简易数据采集系统
fpga开发·fpga·adc·dac
LCMICRO-133108477461 天前
长芯微LD9689完全P2P替代AD9689,是一款双通道、14位、2.0 GSPS/2.6 GSPS模数转换器(ADC)
网络·单片机·嵌入式硬件·网络协议·fpga开发·硬件工程·高速adc
萨文 摩尔杰2 天前
GPS原理学习
学习·fpga开发
Huangichin2 天前
跟着Gemini学System Verilog
fpga开发