pause or resume timer

- (void)pauseTimer
{
    if (_timer) {
        _pauseStart = [NSDate dateWithTimeIntervalSinceNow:0];
        _previousFireDate = [_timer fireDate];
        [_timer setFireDate:[NSDate distantFuture]];
        // 停止动画
        CFTimeInterval pauseTime = [_timerLayer convertTime:CACurrentMediaTime() fromLayer:nil];
        _timerLayer.speed = 0.0;
        _timerLayer.timeOffset = pauseTime;
    }
}


- (void)resumeTimer
{
    if (_timer) {

        float pauseTime = -1 * [_pauseStart timeIntervalSinceNow];
        [_timer setFireDate:[_previousFireDate initWithTimeInterval:pauseTime sinceDate:_previousFireDate]];

        CFTimeInterval pausedTime = [_timerLayer timeOffset];
        _timerLayer.speed = 1.0;
        _timerLayer.timeOffset = 0.0;
        _timerLayer.beginTime = 0.0;
        CFTimeInterval timeSincePause = [_timerLayer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
        _timerLayer.beginTime = timeSincePause;
    }
}
`timescale 1ns/1ps module tb_top(); // 输入信号声明 reg clk_50m; reg reset_n; reg key_start_stop; reg key_pause; reg key_reset; // 输出信号声明 wire [7:0] seg; wire [3:0] dig; // 内部信号声明 - 便于测试访问 wire timer_en; wire timer_pause; wire [4:0] count_value; // 实例化被测模块 - 增加内部信号连接 top uut( .clk_50m(clk_50m), .reset_n(reset_n), .key_start_stop(key_start_stop), .key_pause(key_pause), .key_reset(key_reset), .seg(seg), .dig(dig), .timer_en(timer_en), // 新增内部信号输出 .timer_pause(timer_pause), // 新增内部信号输出 .count_value(count_value) // 新增内部信号输出 ); // 生成50MHz时钟(周期20ns) initial begin clk_50m = 0; forever #10 clk_50m = ~clk_50m; end // 初始化信号 initial begin // 信号初始化 reset_n = 0; key_start_stop = 0; key_pause = 0; key_reset = 0; // 复位操作 #200; reset_n = 1; #100; // 等待系统稳定 // 运行测试场景 run_all_tests(); // 结束仿真 #1000; $finish; end // 统一测试运行任务 task run_all_tests; begin $display("===== 开始测试 ====="); // 测试场景1:正常启动-运行-结束流程 test_start_run_end(); // 测试场景2:启动后暂停再恢复 test_pause_resume(); // 测试场景3:运行中重置 test_reset_during_run(); // 测试场景4:暂停时重置 test_reset_during_pause(); $display("===== 所有测试完成 ====="); end endtask // 任务:正常启动-运行-结束流程 task test_start_run_end; begin $display("--- 测试场景1: 正常启动-运行-结束 ---"); // 等待复位释放 @(posedge reset_n); // 按下启动键 key_start_stop = 1; #200; key_start_stop = 0; // 等待倒计时结束(30秒=301Hz周期) wait_for_ticks(30); // 检查计时器是否停止 if(timer_en === 1'b0) $display("测试场景1通过: 正常倒计时结束"); else $error("测试场景1失败: 倒计时未结束"); end endtask // 任务:启动后暂停再恢复 task test_pause_resume; begin $display("--- 测试场景2: 启动后暂停再恢复 ---"); // 复位后启动 reset_system(); start_timer(); // 运行5秒后暂停 wait_for_ticks(5); pause_timer(); // 等待5秒(应保持当前值) wait_for_ticks(5); if(count_value === 5'd25) $display("暂停状态保持正确,当前值: %d", count_value); else $error("暂停状态错误,当前值: %d", count_value); // 恢复运行 resume_timer(); // 等待剩余20秒结束 wait_for_ticks(20); if(timer_en === 1'b0) $display("测试场景2通过: 暂停恢复功能正常"); else $error("测试场景2失败: 暂停恢复功能异常"); end endtask // 任务:运行中重置 task test_reset_during_run; begin $display("--- 测试场景3: 运行中重置 ---"); // 复位后启动 reset_system(); start_timer(); // 运行10秒后重置 wait_for_ticks(10); reset_timer(); // 检查是否回到30秒 if(count_value === 5'd30) $display("测试场景3通过: 运行中重置功能正常"); else $error("测试场景3失败: 重置后计数值错误,当前值: %d", count_value); end endtask // 任务:暂停时重置 task test_reset_during_pause; begin $display("--- 测试场景4: 暂停时重置 ---"); // 复位后启动并暂停 reset_system(); start_timer(); wait_for_ticks(3); pause_timer(); // 暂停状态下重置 reset_timer(); // 检查是否回到30秒 if(count_value === 5'd30) $display("测试场景4通过: 暂停时重置功能正常"); else $error("测试场景4失败: 重置后计数值错误,当前值: %d", count_value); end endtask // 辅助任务:系统复位 task reset_system; begin reset_n = 0; #200; reset_n = 1; #100; // 等待系统稳定 end endtask // 辅助任务:启动计时器 task start_timer; begin key_start_stop = 1; #200; key_start_stop = 0; end endtask // 辅助任务:暂停计时器 task pause_timer; begin key_pause = 1; #200; key_pause = 0; end endtask // 辅助任务:恢复计时器 task resume_timer; begin key_pause = 1; #200; key_pause = 0; end endtask // 辅助任务:重置计时器 task reset_timer; begin key_reset = 1; #200; key_reset = 0; end endtask // 辅助任务:等待指定tick数 task wait_for_ticks; input [31:0] ticks; integer i; begin for(i=0; i<ticks; i=i+1) begin @(posedge uut.u_clk_div.en_1hz); end end endtask endmodule 优化此代码
06-20
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 优化此代码生成新的代码
最新发布
06-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值