Created
April 14, 2021 19:05
-
-
Save yuichiro-shibata/86bf9fe63d5ef16992cf8467c437c593 to your computer and use it in GitHub Desktop.
ACRi ブログ「DA コンバータがなくてもできる FPGA ピアノ (1)」のコード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`default_nettype none | |
module pulse_sound | |
#( | |
parameter real CLK_FREQ = 100e6, // クロック周波数 (Hz) | |
parameter int COUNT_WIDTH = 32 // カウンタビット幅 | |
) | |
( | |
input wire clk, | |
input wire [3:0] btn_in, | |
output logic led_out, | |
output logic pulse_out | |
); | |
// カウンタ増分値の設定: 500 Hz, 1 KHz, 2 KHz, 4 KHz | |
localparam bit [COUNT_WIDTH-1:0] INCS[4] = '{ | |
freq2inc(500), freq2inc(1000), freq2inc(2000), freq2inc(4000) | |
}; | |
logic [COUNT_WIDTH-1:0] count = '0; | |
always @(posedge clk) begin | |
if (btn_in == '0) | |
count <= '0; // どのボタンも押されていなければカウンタをクリア | |
else begin | |
for (int i = 0; i < 4; i++) begin | |
if (btn_in[i]) begin | |
count <= count + INCS[i]; // 押されたボタンに対応する増分値を加える | |
break; | |
end | |
end | |
end | |
end | |
assign pulse_out = count[COUNT_WIDTH-1]; | |
assign led_out = count[COUNT_WIDTH-1]; | |
// 周波数からカウンタの増分値を計算する関数 | |
function bit [COUNT_WIDTH-1:0] freq2inc(real freq); | |
return ((2.0 ** COUNT_WIDTH) / CLK_FREQ * freq); | |
endfunction | |
endmodule | |
`default_nettype wire |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`default_nettype none | |
module pulse_sound_artytop | |
( | |
input wire clk, | |
input wire [3:0] btn_in, | |
output logic led_out, | |
output logic pulse_out | |
); | |
localparam real CLK_FREQ = 100e6; // クロック周波数: 100MHz | |
logic [3:0] btn_sync; // 同期化されたボタン入力 | |
for (genvar i = 0; i < 4; i++) begin | |
// シクロナイザつきデバウンサ | |
sync_and_debounce | |
#( | |
.CLK_FREQ(CLK_FREQ), | |
.STABLE_TIME(1e-3) // 安定判定時間: 1 ms | |
) | |
sync_and_debounce_inst | |
( | |
.clk(clk), | |
.din(btn_in[i]), | |
.dout(btn_sync[i]) | |
); | |
end | |
// パルス波発生回路 | |
pulse_sound | |
#( | |
.CLK_FREQ(CLK_FREQ), | |
.COUNT_WIDTH(32) | |
) | |
pulse_sound_inst | |
( | |
.clk(clk), | |
.btn_in(btn_sync), | |
.led_out(led_out), | |
.pulse_out(pulse_out) | |
); | |
endmodule | |
`default_nettype wire |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Clock signal | |
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clk }]; | |
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports { clk }]; | |
## LED | |
set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { led_out }]; | |
## Buttons | |
set_property -dict { PACKAGE_PIN D9 IOSTANDARD LVCMOS33 } [get_ports { btn_in[0] }]; | |
set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn_in[1] }]; | |
set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn_in[2] }]; | |
set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn_in[3] }]; | |
## Pmod Header JA | |
set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { pulse_out }]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`default_nettype none | |
`timescale 1ns/1ps | |
module sim_pulse_sound_artytop; | |
localparam real CLOCK_PERIOD_NS = 10; | |
localparam int N = 500000; | |
logic clk, pulse_out, led_out; | |
logic [3:0] btn_in; | |
pulse_sound_artytop pulse_sound_artytop_inst | |
( | |
.clk(clk), | |
.btn_in(btn_in), | |
.led_out(led_out), | |
.pulse_out(pulse_out) | |
); | |
initial begin | |
clk = 1'b0; | |
forever begin | |
#(CLOCK_PERIOD_NS / 2.0) | |
clk = 1'b1; | |
#(CLOCK_PERIOD_NS / 2.0) | |
clk = 1'b0; | |
end | |
end | |
initial begin | |
btn_in = 4'b0000; | |
#(CLOCK_PERIOD_NS * N) | |
btn_in = 4'b0001; | |
#(CLOCK_PERIOD_NS * N) | |
btn_in = 4'b0010; | |
#(CLOCK_PERIOD_NS * N) | |
btn_in = 4'b0100; | |
#(CLOCK_PERIOD_NS * N) | |
btn_in = 4'b1000; | |
#(CLOCK_PERIOD_NS * N) | |
btn_in = 4'b0000; | |
#(CLOCK_PERIOD_NS * N) | |
btn_in = 4'b0001; | |
#(CLOCK_PERIOD_NS * 100) | |
btn_in = 4'b0000; | |
#(CLOCK_PERIOD_NS * 200) | |
btn_in = 4'b0001; | |
#(CLOCK_PERIOD_NS * N) | |
$finish; | |
end | |
endmodule | |
`default_nettype wire |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`default_nettype none | |
module sync_and_debounce | |
#( | |
parameter real CLK_FREQ = 100e6, // クロック周波数 (Hz) | |
parameter real STABLE_TIME = 1e-3 // 安定したと判定するまでの時間 (秒) | |
) | |
( | |
input wire clk, | |
input wire din, | |
output logic dout = 1'b0 | |
); | |
// 2段のシフトレジスタによるシンクロナイザ | |
logic din_meta = 1'b0, din_sync = 1'b0; | |
always @(posedge clk) begin | |
din_meta <= din; // メタステーブルの危険あり | |
din_sync <= din_meta; // 同期化された入力信号 | |
end | |
// デバウンス用カウンタのビット幅と最大値 | |
localparam int COUNT_WIDTH = $clog2(int'(STABLE_TIME * CLK_FREQ)); | |
localparam bit [COUNT_WIDTH-1:0] MAX_COUNT = STABLE_TIME * CLK_FREQ - 1; | |
// カウンタ | |
logic [COUNT_WIDTH-1:0] count = '0; | |
always @(posedge clk) begin | |
if (din_sync != dout) begin // 入力と出力が異なるならカウンタを進める | |
if (count == MAX_COUNT) | |
count <= '0; | |
else | |
count <= count + 1'b1; | |
end | |
else // 入力と出力が同じならカウンタをクリア | |
count <= '0; | |
end | |
// 出力レジスタ | |
always @(posedge clk) begin | |
// カウンタが最大値まで達したら入力の変化を出力に伝える | |
if (din_sync != dout && count == MAX_COUNT) | |
dout <= din_sync; | |
end | |
endmodule | |
`default_nettype wire |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment