题解 | 交通灯(三段式)
交通灯
https://www.nowcoder.com/practice/b5ae79ff08804b61ad61f749eaf157ba
这里采用三段式状态机,分析状态转换和输出逻辑
状态转换
分析波形图发现和实际情况不符,在生活中是绿黄红循环,而题中是红黄绿循环,因此状态转移有不同
默认IDLE打两拍后进入RED,此后一直在cnt为1时状态切换,因此用状态切换做计数器的重新赋值,即用cs和ns的组合逻辑作为控制表达式
计数器在状态切换时 或 GREEN下pass_request拉高时更新对应的数值
输出逻辑
由于现态和次态存在一拍的延迟,因此交通灯下一状态应采用次态对应的红黄绿灯编码
`timescale 1ns / 1ns module triffic_light ( input rst_n, //异位复位信号,低电平有效 input clk, //时钟信号 input pass_request, output wire [7:0] clock, output reg red, output reg yellow, output reg green ); localparam [1:0] IDLE = 2'b00; localparam [1:0] GREEN = 2'b01; localparam [1:0] YELLOW = 2'b10; localparam [1:0] RED = 2'b11; reg [1:0] cs, ns; reg [7:0] cnt; assign clock = cnt; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cs <= IDLE; end else begin cs <= ns; end end always @(*) begin case (cs) IDLE: ns = (cnt == 'd8) ? RED : IDLE; GREEN: ns = (cnt == 'd1) ? RED : GREEN; YELLOW: ns = (cnt == 'd1) ? GREEN : YELLOW; RED: ns = (cnt == 'd1) ? YELLOW : RED; endcase end always @(posedge clk or negedge rst_n) begin if (!rst_n) cnt <= 10; else if (cs == GREEN && pass_request) cnt <= (cnt > 10) ? 10 : cnt; else if (cs == YELLOW && ns == GREEN) cnt <= 60; else if (cs == RED && ns == YELLOW) cnt <= 5; else if (cs == GREEN && ns == RED || cs == IDLE && ns == RED) cnt <= 10; else cnt <= cnt - 1; end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin {green, yellow, red} <= 3'b000; end else begin case (ns) IDLE: {green, yellow, red} <= 3'b000; GREEN: {green, yellow, red} <= 3'b100; YELLOW: {green, yellow, red} <= 3'b010; RED: {green, yellow, red} <= 3'b001; endcase end end endmodule