交通灯控制器如何实现课程设计?

99ANYc3cd6 课程介绍 1

交通灯控制器课程设计

设计任务与要求

1 设计任务 设计一个十字路口的交通灯控制系统,用于主干道(A方向)和支干道(B方向)的车辆与行人通行。

2 具体功能要求

交通灯控制器如何实现课程设计?-第1张图片-指南针培训网
  1. 基本功能:

    • 主干道(A方向): 通行时间较长,设有绿灯、黄灯。
    • 支干道(B方向): 通行时间较短,设有绿灯、黄灯。
    • 行人过街信号: 分别为主干道和支干道的行人设置红绿灯,行人绿灯亮时,对应车道的车灯必须为红灯。
    • 正常时序循环:
      • 状态1(主干道通行): A方向车绿灯亮,B方向车红灯亮,A方向行人红灯亮,B方向行人绿灯亮。
      • 状态2(主干道过渡): A方向车黄灯亮,B方向车红灯亮,A方向行人红灯亮,B方向行人绿灯亮(黄灯亮时,行人绿灯通常保持不变或闪烁,这里简化为保持)。
      • 状态3(支干道通行): A方向车红灯亮,B方向车绿灯亮,A方向行人绿灯亮,B方向行人红灯亮。
      • 状态4(支干道过渡): A方向车红灯亮,B方向车黄灯亮,A方向行人绿灯亮,B方向行人红灯亮。
    • 系统能够按照上述状态自动循环。
  2. 扩展功能(可选,用于提高设计难度和完整性):

    • 紧急车辆优先: 当有紧急车辆(如消防车、救护车)通过时,两个方向的车灯全部变为红灯,以便紧急车辆快速通过,可以使用一个外部中断按键来模拟。
    • 手动切换模式: 在特定情况下(如夜间车流量少),可以手动将系统切换到“闪烁黄灯”模式,提醒车辆慢行。
    • 倒计时显示: 使用数码管或LED点阵显示当前状态剩余的秒数,增强人机交互性。
  3. 技术指标:

    • 时钟频率: 使用实验箱提供的时钟信号(如1Hz或4Hz)。
    • 绿灯时间: 主干道绿灯 45秒,支干道绿灯 25秒。
    • 黄灯时间: 两个方向的黄灯均为 5秒。
    • 输出驱动: 能驱动LED指示灯。

方案论证与选择

1 核心思想 交通灯控制器的核心是一个状态机,系统在不同时间处于不同的状态,每个状态对应一组特定的灯亮或灭,控制器的作用就是在时钟的驱动下,按照预设的时序,从一个状态平稳地切换到下一个状态。

交通灯控制器如何实现课程设计?-第2张图片-指南针培训网

2 实现方案对比

方案 优点 缺点 适用性
纯计数器方案 设计简单,逻辑清晰,易于理解,对于固定时序的系统非常可靠。 灵活性差,若需修改时间,需重新设计计数器,扩展功能(如紧急模式)实现较复杂。 非常适合作为课程设计的入门方案,能很好地掌握时序逻辑设计。
微控制器/单片机方案 功能强大,灵活性极高,编程实现简单,易于添加复杂功能(如倒计时显示、串口通信)。 需要软件编程知识,偏离了“数字逻辑”课程设计的初衷(硬件描述语言/逻辑门电路)。 适合电子综合设计或嵌入式系统课程,不适合本课程。
状态机 + 可编程逻辑器件 灵活性介于前两者之间,可以修改代码来改变时序,是现代数字设计的标准方法。 需要掌握硬件描述语言(如Verilog/VHDL)和EDA工具。 本课程设计的最佳选择,既能体现硬件设计的思想,又具备现代设计的灵活性。

3 方案选择 我们选择方案1(纯计数器方案)作为基础,并采用方案3(状态机 + HDL)的实现方式,这样既能保证设计的严谨性,又能通过代码的修改轻松调整时间参数,并方便地加入扩展功能。

详细设计

1 系统总体框图

          +-----------------+
          |     时钟源      | (如 1Hz)
          +-------+---------+
                  |
                  v
          +-------+---------+
          |     控制器      | <----+
          | (状态机+计数器)  |      |
          +-------+---------+      |
                  |                |
                  v (控制信号)      |
          +-------+---------+      |
          |     译码驱动    |      |
          | (LED灯显示电路) |      |
          +-------+---------+      |
                  |                |
                  v (输出)         |
          +-------+---------+      |
          |   交通灯        |      |
          | (车灯, 人灯)    |      |
          +-----------------+      |
                  ^                |
          +-------+---------+      |
          |   紧急信号      | (按键/中断)
          +-----------------+

2 状态机设计

交通灯控制器如何实现课程设计?-第3张图片-指南针培训网

我们将系统划分为4个主要状态。

状态名 车A 车B 人A 人B 持续时间
S_A_GREEN 绿 绿 45s
S_A_YELLOW 绿 5s
S_B_GREEN 绿 绿 25s
S_B_YELLOW 绿 5s
  • 状态编码:使用2位二进制编码。
    • S_A_GREEN = 00
    • S_A_YELLOW = 01
    • S_B_GREEN = 10
    • S_B_YELLOW = 11

3 模块划分(Verilog HDL实现)

我们可以将整个系统划分为以下几个模块:

  1. 顶层模块 (traffic_light_top): 例化所有子模块,连接输入输出。
  2. 状态机控制模块 (state_machine): 核心控制逻辑。
    • 包含一个状态寄存器(reg [1:0] current_state, next_state)。
    • 包含一个计时器(reg [5:0] timer)。
    • 状态转移逻辑:always @(posedge clk),根据当前状态和计时器值决定下一个状态。
    • 计时逻辑:always @(posedge clk),在每个时钟周期递增计时器,并在状态切换时清零。
  3. 紧急模式处理模块 (emergency_handler): (可选)
    • 检测紧急信号(emergency)。
    • 如果有紧急信号,强制状态机进入一个“全红灯”状态,直到紧急信号解除。
  4. 输出译码模块 (decoder):
    • 根据当前状态 current_state,译码出控制8个灯(车A绿/黄/红,车B绿/黄/红,人A绿/红,人B绿/红)的控制信号。

Verilog HDL 代码示例 (基础版)

// traffic_light.v
`timescale 1ns / 1ps
module traffic_light(
    input clk,          // 1Hz 时钟信号
    input reset_n,      // 低电平复位
    output reg car_a_g, // 主干道车绿灯
    output reg car_a_y, // 主干道车黄灯
    output reg car_a_r, // 主干道车红灯
    output reg car_b_g, // 支干道车绿灯
    output reg car_b_y, // 支干道车黄灯
    output reg car_b_r, // 支干道车红灯
    output reg ped_a_g, // 主干道人绿灯
    output reg ped_a_r, // 主干道人红灯
    output reg ped_b_g, // 支干道人绿灯
    output reg ped_b_r  // 支干道人红灯
);
    // 定义状态编码
    parameter S_A_GREEN = 2'b00;
    parameter S_A_YELLOW = 2'b01;
    parameter S_B_GREEN = 2'b10;
    parameter S_B_YELLOW = 2'b11;
    // 定义时间参数 (单位: 秒)
    parameter T_A_GREEN = 45;
    parameter T_A_YELLOW = 5;
    parameter T_B_GREEN = 25;
    parameter T_B_YELLOW = 5;
    // 内部信号
    reg [1:0] current_state, next_state;
    reg [5:0] timer; // 6位计数器,最大可计数63秒,足够用
    // 状态寄存器
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            current_state <= S_A_GREEN;
        end else begin
            current_state <= next_state;
        end
    end
    // 计时器逻辑
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            timer <= 6'd0;
        end else if (current_state != next_state) begin
            timer <= 6'd0; // 状态切换时,计时器清零
        end else begin
            timer <= timer + 1; // 每个时钟周期加1
        end
    end
    // 状态转移逻辑 (组合逻辑)
    always @(*) begin
        next_state = current_state; // 默认保持当前状态
        case (current_state)
            S_A_GREEN: begin
                if (timer == T_A_GREEN - 1) begin // 计时到T_A_GREEN-1,下一个时钟周期切换
                    next_state = S_A_YELLOW;
                end
            end
            S_A_YELLOW: begin
                if (timer == T_A_YELLOW - 1) begin
                    next_state = S_B_GREEN;
                end
            end
            S_B_GREEN: begin
                if (timer == T_B_GREEN - 1) begin
                    next_state = S_B_YELLOW;
                end
            end
            S_B_YELLOW: begin
                if (timer == T_B_YELLOW - 1) begin
                    next_state = S_A_GREEN;
                end
            end
            default: next_state = S_A_GREEN;
        endcase
    end
    // 输出译码逻辑 (组合逻辑)
    always @(*) begin
        // 默认所有灯灭,避免锁存器
        car_a_g = 1'b0;
        car_a_y = 1'b0;
        car_a_r = 1'b0;
        car_b_g = 1'b0;
        car_b_y = 1'b0;
        car_b_r = 1'b0;
        ped_a_g = 1'b0;
        ped_a_r = 1'b0;
        ped_b_g = 1'b0;
        ped_b_r = 1'b0;
        case (current_state)
            S_A_GREEN: begin // 主干道通行
                car_a_g = 1'b1;
                car_b_r = 1'b1;
                ped_a_r = 1'b1;
                ped_b_g = 1'b1;
            end
            S_A_YELLOW: begin // 主干道过渡
                car_a_y = 1'b1;
                car_b_r = 1'b1;
                ped_a_r = 1'b1;
                ped_b_g = 1'b1;
            end
            S_B_GREEN: begin // 支干道通行
                car_a_r = 1'b1;
                car_b_g = 1'b1;
                ped_a_g = 1'b1;
                ped_b_r = 1'b1;
            end
            S_B_YELLOW: begin // 支干道过渡
                car_a_r = 1'b1;
                car_b_y = 1'b1;
                ped_a_g = 1'b1;
                ped_b_r = 1'b1;
            end
        endcase
    end
endmodule

仿真与验证

1 仿真工具 使用 ModelSim, Vivado, Quartus 等 EDA 工具进行行为级或时序仿真。

1 测试平台 (Testbench) 思路

  1. 生成时钟和复位信号:在 initial 块中定义。
  2. 实例化被测模块:将上面的 traffic_light 模例化。
  3. 编写激励
    • 先进行复位操作。
    • 然后等待足够长的时间,观察 current_statetimer 的变化,以及各个输出引脚的信号是否按预期时序变化。
    • 检查点
      • S_A_GREEN 状态是否持续 45 个时钟周期?
      • 之后是否切换到 S_A_YELLOW
      • S_A_YELLOW 状态是否持续 5 个时钟周期?
      • 之后是否切换到 S_B_GREEN
      • ...如此循环往复,检查所有状态。

2 硬件验证

  1. 引脚锁定:在 Quartus/Vivado 中,将设计中的输入输出信号(clk, reset_n, car_a_g...)锁定到 FPGA 开发板或实验箱的实际物理引脚上。
  2. 下载配置:将生成的 .sof.bit 文件下载到 FPGA 芯片中。
  3. 观察结果:通过开发板上的 LED 指示灯观察交通灯的运行情况,看是否符合设计要求。

扩展功能设计思路

1 紧急车辆优先

  1. 增加输入:增加一个输入 emergency
  2. 修改状态机:增加一个 S_EMERGENCY 状态(编码为 2'bxx)。
  3. 修改转移逻辑:在 always @(*) 块中,emergency 为高电平,则无条件将 next_state 设为 S_EMERGENCY
  4. 修改输出逻辑:在 S_EMERGENCY 状态下,所有车灯(car_a_g/y/r, car_b_g/y/r)都输出红灯,行人灯保持不变或全灭。
  5. 退出条件:当 emergency 信号变为低电平时,状态机应从 S_EMERGENCY 切换到之前的状态,可以增加一个 prev_state 寄存器来记录进入紧急前的状态。

2 倒计时显示

  1. 增加模块:增加一个 BCD_Driver 模块,将6位的计时器 timer 转换成两位 BCD 码(十位和个位)。
  2. 增加输出:增加8个输出,用于驱动两个7段数码管(分别显示十位和个位)。
  3. 连接:将 timer 的值连接到 BCD_Driver 的输入,再将 BCD_Driver 的输出连接到顶层模块的数码管引脚。

设计总结

本设计成功地实现了一个基于有限状态机的十字路口交通灯控制器,通过采用 Verilog HDL 进行硬件描述,设计具有结构清晰、易于修改和扩展的优点。

  • 优点:方案可靠,时序精确,完全符合数字逻辑课程设计的要求,并锻炼了状态机设计、模块化编程和仿真验证的能力。
  • 不足与展望:基础版本功能相对简单,未来可以进一步研究更复杂的交通流模型,例如根据传感器检测到的车流量动态调整绿灯时间,这将引入更复杂的控制算法,是很好的深化方向。

标签: Verilog 分频

抱歉,评论功能暂时关闭!