module top(
input clk_50m, // 50MHz主时钟
input reset_n, // 全局复位(低有效)
input key_start_stop, // 启动/停止按键
input key_pause, // 暂停按键
input key_reset, // 重置按键
output [7:0] seg, // 7段数码管段选信号
output [3:0] dig // 数码管位选信号
);
// 内部信号声明
wire clk_sys; // 系统时钟
wire en_1hz; // 1Hz使能信号
wire en_1khz; // 1KHz扫描使能信号
wire db_start_stop; // 消抖后启动/停止
wire db_pause; // 消抖后暂停
wire db_reset; // 消抖后重置
wire [1:0] state; // 状态机状态
wire [4:0] count_value; // 倒计数值(0-30)
wire [3:0] bcd_ten; // BCD十位
wire [3:0] bcd_unit; // BCD个位
wire count_end; // 计数结束标志
// ====================
// PLL时钟优化模块
// ====================
pll u_pll(
.inclk0(clk_50m),
.c0(clk_sys)
);
// ====================
// 时钟分频模块
// ====================
clk_div u_clk_div(
.clk(clk_sys),
.reset_n(reset_n),
.en_1hz(en_1hz),
.en_1khz(en_1khz)
);
// ====================
// 按键消抖模块(三个按键共用一个模块)
// ====================
debounce u_debounce_start(
.clk(clk_sys),
.reset_n(reset_n),
.key_in(key_start_stop),
.key_out(db_start_stop)
);
debounce u_debounce_pause(
.clk(clk_sys),
.reset_n(reset_n),
.key_in(key_pause),
.key_out(db_pause)
);
debounce u_debounce_reset(
.clk(clk_sys),
.reset_n(reset_n),
.key_in(key_reset),
.key_out(db_reset)
);
// ====================
// 状态机控制模块
// ====================
fsm_control u_fsm(
.clk(clk_sys),
.reset_n(reset_n),
.key_start_stop(db_start_stop),
.key_pause(db_pause),
.key_reset(db_reset),
.count_end(count_end),
.state(state)
);
// ====================
// 30秒倒计时计数器
// ====================
timer_counter u_timer(
.clk(clk_sys),
.reset_n(reset_n),
.en_1hz(en_1hz),
.state(state),
.count_value(count_value),
.count_end(count_end)
);
// ====================
// BCD码转换模块
// ====================
bin2bcd u_bin2bcd(
.bin_value(count_value),
.bcd_ten(bcd_ten),
.bcd_unit(bcd_unit)
);
// ====================
// 数码管动态扫描模块
// ====================
seg_display u_display(
.clk(clk_sys),
.en_1khz(en_1khz),
.bcd_ten(bcd_ten),
.bcd_unit(bcd_unit),
.seg(seg),
.dig(dig)
);
endmodule
// ====================
// PLL模块(Altera IP核)
// ====================
module pll(
input inclk0,
output c0
);
// 实际使用Altera的PLL IP核生成
// 此处仅为占位符,实际项目中需替换为IP核实例化
assign c0 = inclk0;
endmodule
// ====================
// 时钟分频模块(优化计数器位宽)
// ====================
module clk_div(
input clk,
input reset_n,
output reg en_1hz,
output reg en_1khz
);
// 1Hz分频计数器(50,000,000分频)
reg [25:0] cnt_1hz;
always @(posedge clk or negedge reset_n) begin
if(!reset_n) begin
cnt_1hz <= 0;
en_1hz <= 0;
end else begin
en_1hz <= (cnt_1hz == 26'd49_999_999);
cnt_1hz <= (cnt_1hz == 26'd49_999_999) ? 0 : cnt_1hz + 1;
end
end
// 1KHz分频计数器(50,000分频,优化位宽)
reg [15:0] cnt_1khz;
always @(posedge clk or negedge reset_n) begin
if(!reset_n) begin
cnt_1khz <= 0;
en_1khz <= 0;
end else begin
en_1khz <= (cnt_1khz == 16'd49_999);
cnt_1khz <= (cnt_1khz == 16'd49_999) ? 0 : cnt_1khz + 1;
end
end
endmodule
// ====================
// 按键消抖模块(参数化设计)
// ====================
module debounce #(
parameter DEBOUNCE_MS = 20, // 消抖时间(毫秒)
parameter SYS_FREQ = 50_000_000 // 系统时钟频率(Hz)
)(
input clk,
input reset_n,
input key_in,
output reg key_out
);
localparam DELAY = SYS_FREQ / 1000 * DEBOUNCE_MS; // 计算延时计数
reg [19:0] counter;
reg key_sync;
reg key_reg;
always @(posedge clk or negedge reset_n) begin
if(!reset_n) begin
key_sync <= 1'b0;
counter <= 20'd0;
key_out <= 1'b0;
key_reg <= 1'b0;
end else begin
// 两级同步消除亚稳态
key_sync <= key_in;
key_reg <= key_sync;
if(key_reg != key_out) begin
if(counter == DELAY) begin
key_out <= key_reg;
counter <= 20'd0;
end else counter <= counter + 1;
end else counter <= 20'd0;
end
end
endmodule
// ====================
// 状态机控制模块(优化状态转移逻辑)
// ====================
module fsm_control(
input clk,
input reset_n,
input key_start_stop,
input key_pause,
input key_reset,
input count_end,
output reg [1:0] state
);
// 状态定义(使用参数增强可读性)
localparam IDLE = 2'b00;
localparam RUN = 2'b01;
localparam PAUSE = 2'b10;
always @(posedge clk or negedge reset_n) begin
if(!reset_n) begin
state <= IDLE;
end else begin
case(state)
IDLE:
if(key_start_stop) state <= RUN;
RUN: begin
if(key_reset) state <= IDLE;
else if(key_pause) state <= PAUSE;
else if(key_start_stop || count_end) state <= IDLE;
end
PAUSE: begin
if(key_reset) state <= IDLE;
else if(key_pause || key_start_stop) state <= RUN;
end
default: state <= IDLE;
endcase
end
end
endmodule
// ====================
// 30秒倒计时计数器(新增计数结束标志)
// ====================
module timer_counter(
input clk,
input reset_n,
input en_1hz,
input [1:0] state,
output reg [4:0] count_value,
output reg count_end
);
always @(posedge clk or negedge reset_n) begin
if(!reset_n) begin
count_value <= 5'd30;
count_end <= 1'b0;
end else begin
case(state)
// 重置状态
IDLE: begin
count_value <= 5'd30;
count_end <= 1'b0;
end
// 运行状态
RUN: begin
if(en_1hz) begin
if(count_value > 0)
count_value <= count_value - 1;
else
count_end <= 1'b1; // 计数结束
end
end
// 暂停状态:保持当前值
default: begin
count_end <= 1'b0; // 清除结束标志
end
endcase
end
end
endmodule
// ====================
// 二进制转BCD模块(优化逻辑)
// ====================
module bin2bcd(
input [4:0] bin_value, // 0-30
output reg [3:0] bcd_ten,
output reg [3:0] bcd_unit
);
always @(*) begin
bcd_ten = bin_value / 10; // 十位直接整除
bcd_unit = bin_value % 10; // 个位取余
end
endmodule
// ====================
// 数码管动态扫描模块(优化扫描逻辑)
// ====================
module seg_display(
input clk,
input en_1khz,
input [3:0] bcd_ten,
input [3:0] bcd_unit,
output reg [7:0] seg,
output reg [3:0] dig
);
reg [1:0] scan_cnt = 0; // 扫描计数器(2位足够)
reg [3:0] curr_digit; // 当前显示数字
// 7段译码器(共阳极,优化代码结构)
function [7:0] get_seg_code;
input [3:0] digit;
begin
case(digit)
4'd0: get_seg_code = 8'b11000000; // 0
4'd1: get_seg_code = 8'b11111001; // 1
4'd2: get_seg_code = 8'b10100100; // 2
4'd3: get_seg_code = 8'b10110000; // 3
4'd4: get_seg_code = 8'b10011001; // 4
4'd5: get_seg_code = 8'b10010010; // 5
4'd6: get_seg_code = 8'b10000010; // 6
4'd7: get_seg_code = 8'b11111000; // 7
4'd8: get_seg_code = 8'b10000000; // 8
4'd9: get_seg_code = 8'b10010000; // 9
default: get_seg_code = 8'b11111111; // 灭
endcase
end
endfunction
always @(posedge clk) begin
if(en_1khz) begin
scan_cnt <= scan_cnt + 1;
case(scan_cnt)
2'd0: begin // 十位
curr_digit <= bcd_ten;
dig <= 4'b1110;
end
2'd1: begin // 个位
curr_digit <= bcd_unit;
dig <= 4'b1101;
end
default: begin // 无显示(消隐)
curr_digit <= 4'd0;
dig <= 4'b1111;
end
endcase
seg <= get_seg_code(curr_digit);
end
end
endmodule
优化此代码生成新的代码
最新发布