首先需要定义输入输出端口:

module traffic_light_controller(
    input clk,
    input reset,
    output reg [2:0] ew_light, //东西方向的红绿黄灯
    output reg [2:0] ns_light, //南北方向的红绿黄灯
    output reg [7:0] display   //数码管显示
);

为方便起见,我们使用 'ew_light' 和 'ns_light' 来表示东西方向和南北方向的红绿黄灯状态,分别使用 3 位二进制数表示,其中第 0 位表示绿灯状态,第 1 位表示黄灯状态,第 2 位表示红灯状态。例如,当 'ew_light' 的值为 3'b010 时,表示东西方向的黄灯亮,其他灯都不亮。

接下来,我们需要定义状态机来控制交通灯的状态转移。在这个状态机中,我们需要考虑交通灯的 3 种状态(绿灯、黄灯、红灯),以及两个方向的交通灯状态转移的同步问题。

reg [2:0] ew_state; //东西方向交通灯状态
reg [2:0] ns_state; //南北方向交通灯状态

parameter EW_GREEN = 3'b001;
parameter EW_YELLOW = 3'b010;
parameter EW_RED = 3'b100;
parameter NS_GREEN = 3'b100;
parameter NS_YELLOW = 3'b010;
parameter NS_RED = 3'b001;

//状态转移
always @(posedge clk, negedge reset) begin
    if (reset) begin //复位状态
        ew_state <= EW_RED;
        ns_state <= NS_GREEN;
    end else begin
        case (ew_state)
            EW_GREEN: begin
                if (ns_state == NS_RED) begin
                    ew_state <= EW_YELLOW;
                    ns_state <= NS_RED;
                end else begin
                    ew_state <= EW_YELLOW;
                    ns_state <= NS_GREEN;
                end
            end
            EW_YELLOW: begin
                ew_state <= EW_RED;
                ns_state <= NS_RED;
            end
            EW_RED: begin
                if (ns_state == NS_GREEN) begin
                    ew_state <= EW_GREEN;
                    ns_state <= NS_YELLOW;
                end else begin
                    ew_state <= EW_GREEN;
                    ns_state <= NS_GREEN;
                end
            end
        endcase

        case (ns_state)
            NS_GREEN: begin
                if (ew_state == EW_RED) begin
                    ns_state <= NS_YELLOW;
                    ew_state <= EW_RED;
                end else begin
                    ns_state <= NS_YELLOW;
                    ew_state <= EW_GREEN;
                end
            end
            NS_YELLOW: begin
                ns_state <= NS_RED;
                ew_state <= EW_RED;
            end
            NS_RED: begin
                if (ew_state == EW_GREEN) begin
                    ns_state <= NS_GREEN;
                    ew_state <= EW_YELLOW;
                end else begin
                    ns_state <= NS_GREEN;
                    ew_state <= EW_GREEN;
                end
            end
        endcase
    end
end

在状态转移过程中,我们需要注意同步问题。例如,在东西方向的绿灯状态下,如果南北方向的交通灯状态为红灯,那么在东西方向的黄灯状态下,南北方向的交通灯状态依然应该是红灯。

接下来,我们需要根据交通灯状态来控制红绿黄灯的亮灭。同时,我们也需要设计一个倒计时电路来控制数码管的显示。

reg [3:0] countdown; //倒计时计数器

always @(posedge clk, negedge reset) begin
    if (reset) begin //复位状态
        countdown <= 4'b0000;
        ew_light <= EW_RED;
        ns_light <= NS_GREEN;
        display <= 8'b00000000;
    end else begin
        countdown <= countdown + 1;
        case (ew_state)
            EW_GREEN: begin
                ew_light <= 3'b001; //绿灯亮
                ns_light <= 3'b100; //红灯亮
                if (countdown == 5000) begin //倒计时 5s
                    countdown <= 4'b0000;
                    ew_light <= 3'b010; //黄灯亮
                end
            end
            EW_YELLOW: begin
                ew_light <= 3'b010; //黄灯亮
                ns_light <= 3'b100; //红灯亮
                if (countdown == 3000) begin //倒计时 3s
                    countdown <= 4'b0000;
                    ew_light <= 3'b100; //红灯亮
                end
            end
            EW_RED: begin
                ew_light <= 3'b100; //红灯亮
                ns_light <= 3'b001; //绿灯亮
                if (countdown == 8000) begin //倒计时 8s
                    countdown <= 4'b0000;
                    ns_light <= 3'b010; //黄灯亮
                end
            end
        endcase

        case (ns_state)
            NS_GREEN: begin
                ns_light <= 3'b001; //绿灯亮
                ew_light <= 3'b100; //红灯亮
                if (countdown == 5000) begin //倒计时 5s
                    countdown <= 4'b0000;
                    ns_light <= 3'b010; //黄灯亮
                end
            end
            NS_YELLOW: begin
                ns_light <= 3'b010; //黄灯亮
                ew_light <= 3'b100; //红灯亮
                if (countdown == 3000) begin //倒计时 3s
                    countdown <= 4'b0000;
                    ns_light <= 3'b100; //红灯亮
                end
            end
            NS_RED: begin
                ns_light <= 3'b100; //红灯亮
                ew_light <= 3'b001; //绿灯亮
                if (countdown == 8000) begin //倒计时 8s
                    countdown <= 4'b0000;
                    ew_light <= 3'b010; //黄灯亮
                end
            end
        endcase

        //倒计时电路
        case ({ew_light, ns_light})
            6'b001100, 6'b001010, 6'b100001, 6'b010001: display <= 8'b00001000; //绿灯,显示 5s
            6'b010100, 6'b100010, 6'b001001, 6'b000101: display <= 8'b00000100; //黄灯,显示 3s
            6'b100010, 6'b010001, 6'b001100, 6'b000110: display <= 8'b00001000; //红灯,显示 8s
            default: display <= 8'b00000000;
        endcase
    end
end

在倒计时电路中,我们根据当前的红绿黄灯状态来判断需要显示多长时间,然后将倒计时的值通过 'display' 输出到数码管上。

完整代码如下:

module traffic_light_controller(
    input clk,
    input reset,
    output reg [2:0] ew_light, //东西方向的红绿黄灯
    output reg [2:0] ns_light, //南北方向的红绿黄灯
    output reg [7:0] display   //数码管显示
);

    reg [2:0] ew_state; //东西方向交通灯状态
    reg [2:0] ns_state; //南北方向交通灯状态
    reg [3:0] countdown; //倒计时计数器

    parameter EW_GREEN = 3'b001;
    parameter EW_YELLOW = 3'b010;
    parameter EW_RED = 3'b100;
    parameter NS_GREEN = 3'b100;
    parameter NS_YELLOW = 3'b010;
    parameter NS_RED = 3'b001;

    //状态转移
always @(posedge clk, negedge reset) begin
        if (reset) begin //复位状态
            ew_state <= EW_RED;
            ns_state <= NS_GREEN;
        end else begin
            countdown <= countdown + 1;
            case (ew_state)
                EW_GREEN: begin
                    ew_light <= 3'b001; //绿灯亮
                    ns_light <= 3'b100; //红灯亮
                    if (countdown == 5000) begin //倒计时 5s
                        countdown <= 4'b0000;
                        ew_light <= 3'b010; //黄灯亮
                    end
                end
                EW_YELLOW: begin
                    ew_light <= 3'b010; //黄灯亮
                    ns_light <= 3'b100; //红灯亮
                    if (countdown == 3000) begin //倒计时 3s
                        countdown <= 4'b0000;
                        ew_light <= 3'b100; //红灯亮
                    end
                end
                EW_RED: begin
                    ew_light <= 3'b100; //红灯亮
                    ns_light <= 3'b001; //绿灯亮
                    if (countdown == 8000) begin //倒计时 8s
                        countdown <= 4'b0000;
                        ns_light <= 3'b010; //黄灯亮
                    end
                end
            endcase

            case (ns_state)
                NS_GREEN: begin
                    ns_light <= 3'b001; //绿灯亮
                    ew_light <= 3'b100; //红灯亮
                    if (countdown == 5000) begin //倒计时 5s
                        countdown <= 4'b0000;
                        ns_light <= 3'b010; //黄灯亮
                    end
                end
                NS_YELLOW: begin
                    ns_light <= 3'b010; //黄灯亮
                    ew_light <= 3'b100; //红灯亮
                    if (countdown == 3000) begin //倒计时 3s
                        countdown <= 4'b0000;
                        ns_light <= 3'b100; //红灯亮
                    end
                end
                NS_RED: begin
                    ns_light <= 3'b100; //红灯亮
                    ew_light <= 3'b001; //绿灯亮
                    if (countdown == 8000) begin //倒计时 8s
                        countdown <= 4'b0000;
                        ew_light <= 3'b010; //黄灯亮
                    end
                end
            endcase

            //倒计时电路
            case ({ew_light, ns_light})
                6'b001100, 6'b001010, 6'b100001, 6'b010001: display <= 8'b00001000; //绿灯,显示 5s
                6'b010100, 6'b100010, 6'b001001, 6'b000101: display <= 8'b00000100; //黄灯,显示 3s
                6'b100010, 6'b010001, 6'b001100, 6'b000110: display <= 8'b00001000; //红灯,显示 8s
                default: display <= 8'b00000000;
            endcase
        end
    end

endmodule
Verilog 实现十字路口交通灯控制器设计

原文地址: https://www.cveoy.top/t/topic/lxzU 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录