diff --git a/led_matrix/tb_lm_2.v b/led_matrix/tb_lm_2.v index 05cf7b0..47ae2ce 100644 --- a/led_matrix/tb_lm_2.v +++ b/led_matrix/tb_lm_2.v @@ -2,6 +2,7 @@ module tb_lm(); + reg k_1; // 显示的图像1 reg k_2; // 显示的图像2 @@ -10,13 +11,17 @@ reg key; // 物理按键 开关显示, 该按键异步的, 每次按下 等于 reg key_1; // 物理按键的随时钟同步变化信号 reg key_2; // reg is_show; // 互斥变化的 +reg [4:0] flag_time; -reg flag; // 状态改变周期 现在500ns改变一次状态, 显示相反的图像 +reg flag; // 状态改变周期 现在500纳秒改变一次状态, 显示相反的图像 reg sys_clk; reg sys_rst; +reg [7:0]x; +reg [7:0]y; + always #10 sys_clk = ~sys_clk; initial begin @@ -28,11 +33,21 @@ initial begin // 延迟2000纳秒, 现在x 应该是0 #2000 - // 按下一次key, 持续188纳秒 + key <= 1'b1; - #188 + #120 key <= 1'b0; - #400 + #20 + + key <= 1'b1; + #80 + key <= 1'b0; + #20 + + key <= 1'b1; + #90 + key <= 1'b0; + #20 // 延迟4000纳秒观察 {k_2, k_1} <= 2'b10; @@ -40,29 +55,53 @@ initial begin {k_2, k_1} <= 2'b01; #3800 - // 按下一次key, 持续288纳秒, 现在应该是关闭显示了, x为0 + + key <= 1'b1; + #20 + key <= 1'b0; + #20 + key <= 1'b1; - #288 + #20 key <= 1'b0; + #20 + + key <= 1'b1; + #90 + key <= 1'b0; + #200 + + key <= 1'b1; + #120 + key <= 1'b0; + #20 + + key <= 1'b1; + #120 + key <= 1'b0; + #20 + + key <= 1'b1; + #150 + key <= 1'b0; + end -reg [5:0] CNT; +// 显示的时候计时 always @(posedge sys_clk or negedge sys_rst) begin if (sys_rst == 1'b0) begin - CNT <= 5'd0; + flag_time <= 5'd0; end - else if (CNT < (5'd25 - 5'd1)) begin - CNT <= CNT + 5'd1; + else if (flag_time < (5'd25 - 5'd1) && is_show) begin + flag_time <= flag_time + 5'd1; end else begin - CNT <= 5'b0; + flag_time <= 5'b0; end end -reg [7:0]x; -reg [7:0]y; always @(posedge sys_clk or negedge sys_rst) begin if (sys_rst == 1'b0) begin {k_2, k_1} <= 2'b11; @@ -86,11 +125,12 @@ always @(posedge sys_clk or negedge sys_rst) begin end end +// 每 显示500ns 改变显示的图像 always @(posedge sys_clk or negedge sys_rst) begin if (sys_rst == 1'b0) begin flag <= 1'b0; end - else if (CNT == (5'd25 - 5'd1)) begin + else if (flag_time == (5'd25 - 5'd1)) begin flag <= !flag; end else begin @@ -112,13 +152,47 @@ end // 用一个时钟周期即可判断是否在当前时钟周期上升沿之前, 按下了按键 assign is_click = key_1 && !key_2; + +// 消抖, 在20个时钟周期内, 持续10个周期高电平, 即 按下了 +reg [4:0] down_time; // max: 10 +reg [4:0] click_time; // max: 20 +reg is_lock = 1'b0; // + // 使用时钟约束一下 always @(posedge sys_clk or negedge sys_rst) begin if (sys_rst == 1'b0) begin is_show <= 1'b0; + down_time <= 5'd0; + click_time <= 5'd0; end + // 只要按下就上锁 else if (is_click) begin - is_show <= !is_show; + is_lock <= 1'b1; + end + else begin + end + + // 锁定的时间到了, 解锁, 然后判断并重置 + if (is_lock && click_time == 5'd20 - 5'd1) begin + is_lock <= 1'b0; + click_time <= 5'd0; + down_time <= 5'd0; + // 判断按下的持续时间 + if (down_time > 5'd10 - 5'd1) begin + is_show <= !is_show; + end + else begin + end + end + // 上锁了但是时间没到 + else if (is_lock && click_time < 5'd20 - 5'd1) begin + click_time <= click_time + 5'd1; + // 如果还按着 + if (key_1) begin + down_time <= down_time + 1'd1; + end + else begin + end end else begin end diff --git a/led_matrix/tb_lm_2.v.out b/led_matrix/tb_lm_2.v.out new file mode 100755 index 0000000..c1237ac --- /dev/null +++ b/led_matrix/tb_lm_2.v.out @@ -0,0 +1,75 @@ +#! /usr/local/Cellar/icarus-verilog/12.0/bin/vvp +:ivl_version "12.0 (stable)"; +:ivl_delay_selection "TYPICAL"; +:vpi_time_precision - 9; +:vpi_module "/usr/local/Cellar/icarus-verilog/12.0/lib/ivl/system.vpi"; +:vpi_module "/usr/local/Cellar/icarus-verilog/12.0/lib/ivl/vhdl_sys.vpi"; +:vpi_module "/usr/local/Cellar/icarus-verilog/12.0/lib/ivl/vhdl_textio.vpi"; +:vpi_module "/usr/local/Cellar/icarus-verilog/12.0/lib/ivl/v2005_math.vpi"; +:vpi_module "/usr/local/Cellar/icarus-verilog/12.0/lib/ivl/va_math.vpi"; +S_0x7f94c3905560 .scope module, "tb_lm" "tb_lm" 2 3; + .timescale -9 -9; +v0x7f94c390a240_0 .var "k_1", 0 0; +v0x7f94c3919630_0 .var "k_2", 0 0; +v0x7f94c39196d0_0 .var "key", 0 0; +v0x7f94c3919760_0 .var "sys_clk", 0 0; +v0x7f94c3919800_0 .var "sys_rst", 0 0; + .scope S_0x7f94c3905560; +T_0 ; + %delay 10, 0; + %load/vec4 v0x7f94c3919760_0; + %inv; + %store/vec4 v0x7f94c3919760_0, 0, 1; + %jmp T_0; + .thread T_0; + .scope S_0x7f94c3905560; +T_1 ; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x7f94c3919760_0, 0; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x7f94c3919800_0, 0; + %delay 200, 0; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x7f94c3919800_0, 0; + %delay 2000, 0; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x7f94c39196d0_0, 0; + %delay 2, 0; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x7f94c39196d0_0, 0; + %delay 2, 0; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x7f94c39196d0_0, 0; + %delay 2, 0; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x7f94c39196d0_0, 0; + %delay 2, 0; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x7f94c39196d0_0, 0; + %delay 2, 0; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x7f94c39196d0_0, 0; + %delay 2, 0; + %pushi/vec4 2, 0, 2; + %split/vec4 1; + %assign/vec4 v0x7f94c390a240_0, 0; + %assign/vec4 v0x7f94c3919630_0, 0; + %delay 3900, 0; + %pushi/vec4 1, 0, 2; + %split/vec4 1; + %assign/vec4 v0x7f94c390a240_0, 0; + %assign/vec4 v0x7f94c3919630_0, 0; + %delay 3800, 0; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x7f94c39196d0_0, 0; + %delay 2, 0; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x7f94c39196d0_0, 0; + %delay 2, 0; + %end; + .thread T_1; +# The file index is used to find the file name in the following table. +:file_names 3; + "N/A"; + ""; + "tb_lm_2.v";