FSMDの練習
チャタリング防止回路を題材にFSMD(Finite State Machine with Datapath) な回路の練習。
チャタリング防止回路のASMDのチャート
https://gyazo.com/63a7aa4701472cde57e46c0090f3de96
( Figure 6.6 ASMD chart of a debouncing circuit. )
Chu, Pong P.. FPGA Prototyping by SystemVerilog Examples (p.138). Wiley. Kindle 版.
書いてみて気になった点
outputはdb_level_regとdb_level_nextは宣言せず、直接always_combで代入してるのね
N=22???
チャタリング防止のため、スイッチをONにしてから100MHzのクロックで4194304回(2 ** 22、41943040ナノ秒 = 41943マイクロ秒 = 41ミリ秒 = 0.04秒)カウントしたらdb_levelを1にする
コード
code:debounce.sv
// iverilog -g 2012 -s debounce_testbench debounce.sv debounce_testbench.sv && ./a.out
parameter N = 22
)
(
input logic clk, reset,
input logic sw,
output logic db_level, db_tick
);
typedef enum {zero, wait1, one, wait0} debounce_state;
debounce_state state_reg, state_next;
logic N-1:0 q_reg, q_next; logic db_tick_reg, db_tick_next;
logic db_level_reg, db_level_next;
always_ff @(posedge clk, posedge reset) begin
if (reset)
begin
state_reg <= zero;
q_reg <= 0;
end
else
begin
state_reg <= state_next;
q_reg <= q_next;
end
end
always_comb begin
state_next = state_reg;
q_next = q_reg;
db_tick = 0;
db_level = 0;
case (state_reg)
zero: begin
if (sw)
begin
state_next = wait1;
q_next = {N{1'b1}};
end
end
wait1: begin
if (sw)
begin
q_next = q_reg - 1;
if (q_next == 0) begin
state_next = one;
db_tick = 1;
end
end
else
state_next = zero;
end
one: begin
db_level = 1;
if (~sw) begin
state_next = wait0;
q_next = {N{1'b1}};
end
end
wait0: begin
db_level = 1;
if (~sw)
begin
q_next = q_reg - 1;
if (q_next == 0) begin
state_next = zero;
end
end
else
state_next = one;
end
endcase
end
endmodule
code:debounce_testbench.sv
`timescale 1ns/1ps
module debounce_testbench();
logic clk, reset, sw;
logic db_level, db_tick;
clk,
reset,
sw,
db_level,
db_tick
);
initial begin
$dumpfile("debounce.vcd");
$dumpvars(0, dut);
clk = 0;
sw = 0;
sw = 1;
sw = 0;
sw = 1;
sw = 0;
sw = 1;
sw = 0;
sw = 1;
end
// 5nsごとにclkを反転することで100MHzのクロックを生成
clk <= ~clk;
endmodule
実行結果
いい感じに動いてそうな気がする。
https://gyazo.com/e9b9bd87556d8292d1f2efb0bd416308