题解 | 交通灯(三段式)
交通灯
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



