详细解释以下所有代码`timescale 1ns / 1ps
module led_controller_top (
input wire clk100m, // 100MHz 主时钟
input wire rst_n, // 复位按钮(通常连接到BTNC)
input wire [3:0] btn_c, // BTN0~BTN3,低有效
output wire [8:0] led // LED0~LED8
);
wire clk_1hz, clk_5hz, clk_10hz;
wire [3:0] btn_debounced;
// 分频模块
clk_divider u_clkdiv (
.clk_in(clk100m),
.rst_n(rst_n),
.clk_1hz(clk_1hz),
.clk_5hz(clk_5hz),
.clk_10hz(clk_10hz)
);
// 四个按键分别消抖
genvar i;
generate
for (i = 0; i < 4; i = i + 1) begin : debouncer_gen
debounce u_debounce (
.clk(clk100m),
.rst_n(rst_n),
.btn_in(btn_c[i]),
.btn_out(btn_debounced[i])
);
end
endgenerate
// 状态机主控
led_fsm u_fsm (
.clk(clk100m),
.rst_n(rst_n),
.key1(btn_debounced[0]),
.key2(btn_debounced[1]),
.key3(btn_debounced[2]),
.key4(btn_debounced[3]),
.clk_1hz(clk_1hz),
.clk_5hz(clk_5hz),
.clk_10hz(clk_10hz),
.led(led)
);
endmodule
`timescale 1ns / 1ps
module clk_divider (
input wire clk_in, // 输入时钟:100MHz
input wire rst_n, // 低电平复位(异步)
output reg clk_1hz, // 输出:1Hz
output reg clk_5hz, // 输出:5Hz
output reg clk_10hz // 输出:10Hz
);
// 定义主时钟频率
parameter CLK_FREQ = 100_000_000; // 100MHz
// 各分频计数器(分别用于1Hz, 5Hz, 10Hz)
reg [31:0] count_1hz;
reg [26:0] count_5hz; // ~5Hz: 计数到 10,000,000
reg [24:0] count_10hz; // ~10Hz: 计数到 5,000,000
// ------------------------
// 生成 1Hz 时钟
// 周期 = 1s → 半周期 = 500ms → 计数 50,000,000 个 100MHz 周期
// ------------------------
always @(posedge clk_in or negedge rst_n) begin
if (!rst_n) begin
count_1hz <= 0;
clk_1hz <= 0;
end else begin
if (count_1hz >= 50_000_000 - 1) begin
clk_1hz <= ~clk_1hz; // 翻转输出
count_1hz <= 0; // 重载计数器
end else begin
count_1hz <= count_1hz + 1;
end
end
end
// ------------------------
// 生成 5Hz 时钟
// 周期 = 200ms → 半周期 = 100ms → 计数 10,000,000
// ------------------------
always @(posedge clk_in or negedge rst_n) begin
if (!rst_n) begin
count_5hz <= 0;
clk_5hz <= 0;
end else begin
if (count_5hz >= 10_000_000 - 1) begin
clk_5hz <= ~clk_5hz;
count_5hz <= 0;
end else begin
count_5hz <= count_5hz + 1;
end
end
end
// ------------------------
// 生成 10Hz 时钟
// 周期 = 100ms → 半周期 = 50ms → 计数 5,000,000
// ------------------------
always @(posedge clk_in or negedge rst_n) begin
if (!rst_n) begin
count_10hz <= 0;
clk_10hz <= 0;
end else begin
if (count_10hz >= 5_000_000 - 1) begin
clk_10hz <= ~clk_10hz;
count_10hz <= 0;
end else begin
count_10hz <= count_10hz + 1;
end
end
end
endmodule
`timescale 1ns / 1ps
module led_fsm (
input wire clk, // 主时钟
input wire rst_n, // 复位(低有效)
input wire key1, // 消抖后的按键信号(低有效 -> 高表示按下)
input wire key2,
input wire key3,
input wire key4,
input wire clk_1hz, // 1Hz 节拍
input wire clk_5hz, // 5Hz 节拍
input wire clk_10hz, // 10Hz 节拍
output reg [8:0] led // 9个LED输出
);
// 状态定义
parameter IDLE = 3'd0,
LEFT_MOVE = 3'd1,
RIGHT_MOVE= 3'd2,
BLINK_ALL = 3'd3,
LIGHT_8 = 3'd4;
// 三段式:状态寄存器
reg [2:0] current_state, next_state;
// 第一段:时序逻辑 - 当前状态更新
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
current_state <= IDLE;
else
current_state <= next_state;
end
// 第二段:组合逻辑 - 下一状态判断
always @(*) begin
case (current_state)
IDLE:
if (key1 == 0) next_state = LEFT_MOVE;
else if (key2 == 0) next_state = RIGHT_MOVE;
else if (key3 == 0) next_state = BLINK_ALL;
else if (key4 == 0) next_state = LIGHT_8;
else next_state = IDLE;
LEFT_MOVE:
if (key1 == 1 && key2 == 1 && key3 == 1 && key4 == 1)
next_state = IDLE;
else
next_state = LEFT_MOVE;
RIGHT_MOVE:
if (key1 == 1 && key2 == 1 && key3 == 1 && key4 == 1)
next_state = IDLE;
else
next_state = RIGHT_MOVE;
BLINK_ALL:
if (key1 == 1 && key2 == 1 && key3 == 1 && key4 == 1)
next_state = IDLE;
else
next_state = BLINK_ALL;
LIGHT_8:
if (key1 == 1 && key2 == 1 && key3 == 1 && key4 == 1)
next_state = IDLE;
else
next_state = LIGHT_8;
default: next_state = IDLE;
endcase
end
// 第三段:组合逻辑 - 输出解码(Moore型:只依赖当前状态)
reg [8:0] shift_reg_left;
reg [8:0] shift_reg_right;
reg blink_counter;
reg [2:0] pos; // 流水灯位置
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
shift_reg_left <= 9'b000000001;
shift_reg_right <= 9'b100000000;
blink_counter <= 0;
pos <= 0;
led <= 9'b0;
end else begin
case (current_state)
IDLE:
led <= 9'b0;
LEFT_MOVE: begin
if (clk_5hz) begin // 每次5Hz脉冲移动一次
shift_reg_left <= {shift_reg_left[7:0], shift_reg_left[8]};
led <= shift_reg_left;
end
end
RIGHT_MOVE: begin
if (clk_5hz) begin
shift_reg_right <= {shift_reg_right[0], shift_reg_right[8:1]};
led <= shift_reg_right;
end
end
BLINK_ALL: begin
if (clk_1hz) begin
blink_counter <= ~blink_counter;
led <= blink_counter ? 9'b111111111 : 9'b000000000;
end
end
LIGHT_8: begin
led <= 9'b000001000; // 第8位点亮(索引从0开始,第8位是第9个LED?注意!)
// 注意:Basys 3 的LED是LED0~LED8,共9个
// 如果"点亮第8个"是指编号为8的LED,则对应 bit[8]
end
default: led <= 9'b0;
endcase
end
end
endmodule
`timescale 1ns / 1ps
module debounce (
input wire clk, // 主时钟(如100MHz)
input wire rst_n, // 复位
input wire btn_in, // 原始按键输入(低有效)
output reg btn_out // 消抖后输出(仍为低有效)
);
parameter DEBOUNCE_TIME = 50000; // 约5ms @ 100MHz
reg [15:0] counter;
reg btn_sync1, btn_sync2;
// 同步双触发器防亚稳态
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
btn_sync1 <= 1'b1;
btn_sync2 <= 1'b1;
end else begin
btn_sync1 <= btn_in;
btn_sync2 <= btn_sync1;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
counter <= 0;
btn_out <= 1'b1;
end else begin
if (btn_sync2 != btn_out) begin
counter <= counter + 1;
if (counter >= DEBOUNCE_TIME - 1) begin
btn_out <= btn_sync2;
counter <= 0;
end
end else begin
counter <= 0;
end
end
end
endmodule
set_property IOSTANDARD LVCMOS33 [get_ports]
set_property PACKAGE_PIN U16 [get_ports {led[0]}];
set_property PACKAGE_PIN E19 [get_ports {led[1]}];
set_property PACKAGE_PIN U19 [get_ports {led[2]}];
set_property PACKAGE_PIN V19 [get_ports {led[3]}];
set_property PACKAGE_PIN W18 [get_ports {led[4]}];
set_property PACKAGE_PIN U15 [get_ports {led[5]}];
set_property PACKAGE_PIN U14 [get_ports {led[6]}];
set_property PACKAGE_PIN V14 [get_ports {led[7]}];
set_property PACKAGE_PIN V13 [get_ports {led[8]}];
# 可选:如果你真有一个 LED 接在 N4 上再启用
# set_property PACKAGE_PIN N4 [get_ports {led[8]}];
# === 按键输入(主动低电平)===
set_property PACKAGE_PIN U18 [get_ports {btn_c[0]}]; # BTNC
set_property PACKAGE_PIN T18 [get_ports {btn_c[1]}]; # BTNU
set_property PACKAGE_PIN W19 [get_ports {btn_c[2]}]; # BTNL
set_property PACKAGE_PIN T17 [get_ports {btn_c[3]}]; # BTNR
# === 复位输入 ===
set_property PACKAGE_PIN V17 [get_ports {rst_n}]; # 接 SW0 或独立按键
# === 主时钟输入 ===
set_property PACKAGE_PIN W5 [get_ports {clk100m}]; # 100MHz crystal
# === 创建时钟约束 ===
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} [get_ports clk100m]
`timescale 1ns / 1ps
module tb_led_controller;
reg clk100m;
reg rst_n;
reg [3:0] btn_c;
wire [8:0] led;
// 实例化顶层
led_controller_top uut (
.clk100m(clk100m),
.rst_n(rst_n),
.btn_c(btn_c),
.led(led)
);
// 生成时钟
initial begin
clk100m = 0;
forever #5 clk100m = ~clk100m; // 100MHz
end
initial begin
// 初始化
rst_n = 0;
btn_c = 4'b1111;
#100
rst_n = 1;
// 按键1按下(左移)
#1000
btn_c = 4'b1110;
#500000000; // 等待几秒看效果
// 释放
btn_c = 4'b1111;
#100000000;
// 按键2按下(右移)
btn_c = 4'b1101;
#500000000;
btn_c = 4'b1111;
#100000000;
// 按键3按下(闪烁)
btn_c = 4'b1011;
#800000000;
btn_c = 4'b1111;
#100000000;
// 按键4按下(点亮LED8)
btn_c = 4'b0111;
#500000000;
$stop;
end
endmodule
最新发布