一、顶层代码
module test#(
parameter SYS_CLK_FREQ = 26'd50_000_000, // 系统时钟频率50MHz
parameter BAUD_RATE = 9600, // 串口波特率
parameter CHECK_BIT = "None" // 校验位类型(None表示无校验)
)(
input wire sys_clk, // 系统时钟输入
input wire sys_rst, // 系统复位(低电平有效)
input wire [3:0] key_in, // 按键输入
output wire [7:0] sel, // 数码管位选信号
output wire [7:0] seg, // 数码管段选信号
output reg [7:0] led, // LED指示灯
output wire tx // 串口发送线
);
// ========== 状态定义 ==========
localparam STOP = 3'd0; // 停止状态
localparam START = 3'd1; // 启动状态
// ========== 信号定义 ==========
wire [3:0] key_data; // 按键消抖后的数据
reg [31:0] data; // 数码管显示数据(8位BCD码)
reg [3:0] status_count; // 当前状态(START/STOP)
reg [7:0] data_count; // 计数器值
reg [3:0] tx_len; // 串口发送数据长度
wire start_send; // 发送启动信号
reg start_send_char; // 字符发送启动标志
reg start_send_status; // 状态发送启动标志
wire tx_done; // 发送完成标志
reg [7:0] char_idx; // 当前发送字符索引
reg [7:0] tx_buffer[0:255]; // 发送缓冲区(存储ASCII字符)
reg tx_done0; // 发送完成信号打拍(同步用)
reg tx_done1; // 发送完成信号打拍(同步用)
wire send_next; // 发送下一个字符的触发信号
// ========== 模块实例化 ==========
// 数码管显示模块
seg seg_inst(
.clk (sys_clk),
.rst (sys_rst),
.seg (seg),
.sel (sel),
.dsp_data (data) // 显示数据输入
);
// 按键消抖模块
key key_inst(
.sys_clk (sys_clk),
.sys_rst (sys_rst),
.key_in (key_in),
.key_data (key_data) // 消抖后的按键数据
);
// 串口发送模块
uart_tx#(
.CLOCK (SYS_CLK_FREQ),
.BUAD (BAUD_RATE),
.CHECK_BIT(CHECK_BIT)
) uart_tx_list(
.clk (sys_clk),
.rst (sys_rst),
.tx_data (tx_buffer[char_idx]), // 当前发送字符
.tx_data_vld (start_send), // 发送使能
.ready (tx_done), // 发送完成标志
.tx (tx) // 串口输出
);
// ========== LED控制逻辑 ==========
always @(posedge sys_clk or negedge sys_rst) begin
if (!sys_rst)
led <= 8'b1111_1111; // 复位时LED全灭
else if (status_count == START)
led <= 8'b1111_1110; // START状态时点亮最低位LED
else
led <= 8'b1111_1111; // 其他状态LED全灭
end
// ========== 数码管显示数据处理 ==========
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0)
// 复位时显示" 0"(11表示不显示)
data <= {4'd10, 4'd11, 4'd11, 4'd11, 4'd11, 4'd11, 4'd11, 4'd0};
else begin
// 动态更新显示数据(BCD码转换)
data[11:8] <= (data_count > 99) ? (data_count / 100) : 4'd11; // 百位
data[7:4] <= (data_count > 9) ? (data_count % 100 / 10) : 4'd11; // 十位
data[3:0] <= data_count % 10; // 个位
end
end
// ========== 按键处理逻辑 ==========
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0) begin
data_count <= 8'b0; // 计数器清零
status_count <= START; // 初始状态为START
start_send_char <= 0; // 发送标志清零
end else begin
case (key_data) // 根据按键值更新状态
4'b0001: begin // 按键1:切换START/STOP状态
if (status_count == START)
status_count <= STOP;
else if (status_count == STOP)
status_count <= START;
end
4'b0010: begin // 按键2:计数器加1(仅在START状态)
if (status_count == START)
data_count <= data_count + 8'd1;
end
4'b0100: begin // 按键3:计数器减1(仅在STOP状态且值>0)
if ((status_count == STOP) && (data_count > 0))
data_count <= data_count - 1;