用Verilog写基于三段式状态机设计的思想实现流水灯,花型要求如下: • 从左到右依次点亮,从左到右依次灭 • 从中间向两边依次亮,从中间向两边依次灭(2 遍) • 从两边向中间依次亮,从两边向中间依次灭(2 遍) • 如此反复循环…… 完成基于状态机的流水灯设计,并下板实现。 基础要求: 使用 EG4S20 使用 PLL 生成 50M 时钟, 0.5S 移位一次 使用 8 个 LED 使用移位寄存器控制 LED 代码限制到 200 行内
时间: 2024-03-25 10:39:33 浏览: 49
Verilog FPGA 交通灯 设计(基于Basys2设计,使用者只需移植到板子上即可使用,三段式状态机编写)
5星 · 资源好评率100%
好的,让我来为你解答这个问题。首先,我们需要了解三段式状态机的设计思想。三段式状态机是基于有限状态机的一种设计思想,将有限状态机的状态分为三个阶段:启动阶段、运行阶段和停止阶段。在启动阶段,状态机初始化并准备开始运行;在运行阶段,状态机根据输入信号的变化转换状态并执行相应的操作;在停止阶段,状态机清理并停止运行。
接下来,我们可以根据题目要求设计如下的三段式状态机:
启动阶段:LED1 亮,其他 LED 灭;
运行阶段:
状态1:从左到右依次点亮,从左到右依次灭;
状态2:从中间向两边依次亮,从中间向两边依次灭(2 遍);
状态3:从两边向中间依次亮,从两边向中间依次灭(2 遍);
状态4:重复状态1~3;
停止阶段:LED1 灭,其他 LED 灭。
接下来,我们需要根据状态机的设计来编写 Verilog 代码。代码如下:
```verilog
module flow_light(input clk,
output reg[7:0] led);
// 状态定义
parameter STATE_START = 0; // 启动阶段
parameter STATE_LEFT_RIGHT = 1; // 从左到右
parameter STATE_MIDDLE_OUT = 2; // 从中间向两边
parameter STATE_OUT_MIDDLE = 3; // 从两边向中间
parameter STATE_REPEAT = 4; // 重复状态1~3
parameter STATE_STOP = 5; // 停止阶段
// 定义 LED 状态数组
reg[7:0] led_state = 8'b00000001; // 初始化 LED1 亮,其他灭
// 定义计时器变量和计时器常量
reg[5:0] timer = 6'd0;
parameter TIMER_MAX = 6'd25; // 0.5s 移位一次
// 定义状态机变量和状态机常量
reg[2:0] state = STATE_START;
parameter STATE_MAX = 3'd5; // 状态数为5
// 状态机
always @(posedge clk) begin
case(state)
STATE_START: begin
// 启动阶段,初始化 LED 状态数组
led_state = 8'b00000001;
// 转换到状态1
state = STATE_LEFT_RIGHT;
end
STATE_LEFT_RIGHT: begin
// 从左到右依次点亮,从左到右依次灭
if(timer == TIMER_MAX) begin
// 移位
led_state = {led_state[6:0], 1'b0};
// 判断是否完成状态
if(led_state[7] == 1) begin
// 完成状态,转换到状态2
state = STATE_MIDDLE_OUT;
end
// 重置计时器
timer <= 6'd0;
end else begin
timer <= timer + 6'd1;
end
end
STATE_MIDDLE_OUT: begin
// 从中间向两边依次亮,从中间向两边依次灭(2 遍)
if(timer == TIMER_MAX) begin
// 移位
led_state = {led_state[3:0], 4'b0000, led_state[7:4]};
// 判断是否完成状态
if(led_state[3] == 1) begin
// 完成状态,转换到状态3
state = STATE_OUT_MIDDLE;
end
// 重置计时器
timer <= 6'd0;
end else begin
timer <= timer + 6'd1;
end
end
STATE_OUT_MIDDLE: begin
// 从两边向中间依次亮,从两边向中间依次灭(2 遍)
if(timer == TIMER_MAX) begin
// 移位
led_state = 8'b00001111;
// 判断是否完成状态
if(led_state == 8'b11110000) begin
// 完成状态,转换到状态4
state = STATE_REPEAT;
end
// 重置计时器
timer <= 6'd0;
end else begin
timer <= timer + 6'd1;
end
end
STATE_REPEAT: begin
// 重复状态1~3
if(timer == TIMER_MAX) begin
// 判断是否完成状态
if(state != STATE_LEFT_RIGHT) begin
// 未完成,返回状态1
state = STATE_LEFT_RIGHT;
end else begin
// 已完成,转换到状态2
state = STATE_MIDDLE_OUT;
end
// 重置计时器
timer <= 6'd0;
end else begin
timer <= timer + 6'd1;
end
end
STATE_STOP: begin
// 停止阶段,灭掉所有 LED
led_state = 8'b00000000;
end
endcase
end
// 更新移位寄存器
always @(posedge clk) begin
led <= led_state;
end
endmodule
```
代码限制在 200 行内,所以注释不是很详细。如果有疑问,请随时提出。
阅读全文