FPGA活用回路&サンプル記述集(1) ―― アナログ信号入出力回路
tag: 半導体 電子回路 ディジタル・デザイン
技術解説 2009年2月23日
● 波形再生の周波数を切り替える
波形データの再生周波数は,外部のロータリ・スイッチの設定により,FPGAの動作クロックを分周して生成します.この設定周波数で波形データを1回再生し,その後は繰り返し再生する設定となっています.
今回は16段階の切り替え(0~15)に対応してFPGAの動作クロックを分周し,40kHz~10Hz(FPGAクロックが8.192MHzの場合)の再生周期に切り替え可能にしています.
再生データのROMからの読み出しは,再生周期が2kHz以下の場合は4096個を順番に読み出し再生します.再生周期が2kHzを超える場合には4096個のデータを間引いて読み,周期内に収まるようにしています表2-2,図2-3.
ROMデータ | 2kHz以下の場合 | 4kHzの場合 |
0 : 32767 | 0 : 32767 | 0 : 32767 |
1 : 32817 | 1 : 32817 | -(使わない) |
2 : 32868 | 2 : 32868 | 2 : 32968 |
3 : 32918 | 3 : 32918 | -(使わない) |
4 : 32968 | 4 : 32968 | 4 : 32968 |
5 : 33018 | 5 : 33018 | -(使わない) |
6 : 33069 | 6 : 33069 | 6 : 33069 |
7 : 33119 | 7 : 33119 | -(使わない) |
8 : 33169 | 8 : 33169 | 8 : 33169 |
9 : 33219 | 9 : 33219 | -(使わない) |
... | ... | ... |
表2-2 再生周波数によって使用する再生データが違う
4kHz以上の場合は一つ置きに2048個のデータで再生する.
図2-3 ROMに内蔵するデータの再生イメージ
ROM番地:値(10進数).
● データ格納ROM
データ格納用のROMはQuartus IIのライブラリ(Mega Core)を用いて生成しました.ROMのサイズは2048×16ビットで,そのインターフェースとしてアドレス,クロック出力データを持っています.
リスト2-1にD-Aコンバータ制御部分,リスト2-2に周波数設定部分,リスト2-3にROM制御部分のVerilog HDL記述を示します.
module dacntl(ck,res,freq,q,we,sck,adrs,mck);
input ck,res;
input [15:0]freq;
output [15:0]q;
output we, sck, mck;
output [11:0]adrs;
reg [15:0]freq;
reg [7:0]cktmp;
reg [11:0] cnt,wcnt;
reg wck,sck,we;
wire wcntmax;
wire [15:0] q,k1a,k2a;
wire [11:0] k1,k2,adrs ;
wire mck ,cka;
always@(posedge ck)begin ←※5
if(res) cktmp <= 8'b0;
else cktmp <= cktmp + 8'b1;
end
always@(posedge ck)begin
if(res) frq <= 16'b0;
else if(cktmp == 8'b0) frq <= freq;
end
assign k1a = (frq >= 16'd2000) ? frq / 16'd2000 : 16'd1; ←※6
assign k1 = k1a[11:0];
assign k2a = (frq <= 16'd2000) ? 16'd2000 / frq : 16'd0;
assign k2 = k2a[11:0];
assign wcntmax = (k2 > 1) ? wcnt == k2 - 12'b1 : 1'd0; ←※7↓
always@(posedge ck)begin
if(res) wcnt <= 12'b0;
else if(wcntmax) wcnt <= 12'b0;
else wcnt <= wcnt + 12'b1;
end
always@(posedge ck)begin
if(res) wck <= 1'b0;
else if(wcntmax) wck <= 1'b1;
else wck <= 1'b0;
end ※7↑
assign cka = (k2 > 12'd1) ? wck : ck ; ←※8
always@(posedge cka)begin
if(res) sck <= 1'b0;
else sck <= ~sck;
end
always@(negedge cka)begin
if(res) we <= 1'b0;
else if(we) we <= 1'b0;
else if(~sck) we <= 1'b1;
end
always@(posedge sck or posedge res)begin ←※9
if(res) cnt <= 12'b0;
else cnt <= cnt + k1;
end
assign adrs = cnt[11:0];// * 12'd4;//16kHz
assign mck = sck & ~cka;
memif wfm1(mck,res,adrs,q); ←ROMブロック
endmodule
リスト2-1 D-Aコンバータ制御部のVerilog HDL記述
注5;周波数の更新タイミング設定(16クロック・サイクルに1回)
注6;設定周波数によって,ROMデータの読み出しを切り替え.2kHz以下の場合には,k1(ROMアドレスの移動ステップ)を'1'にして全データを利用.2kHz以上の場合には「周波数/2kHz」でアドレスの移動ステップ(間引き)を設定.
注7;再生周波数が2kHzより遅い場合は,D-Aコンバータのデータの更新を周波数に合わせる.そのため,更新用クロック(WCK)を生成
注8;D-Aコンバータの更新クロックを切り替え
注9;ROMの読み出しアドレスを生成
//frq set
module frq_set(dsw,frq);
input [3:0]dsw;
output [15:0]frq;// 1 - 64,000[Hz]
reg [15:0] freq;
always @(dsw) begin
case(dsw)
4'h0 : freq <= 16'd10; ←※10
4'h1 : freq <= 16'd50;
4'h2 : freq <= 16'd100;
4'h3 : freq <= 16'd200;
4'h4 : freq <= 16'd500;
4'h5 : freq <= 16'd1000;
4'h6 : freq <= 16'd2000;
4'h7 : freq <= 16'd4000;
4'h8 : freq <= 16'd8000;
4'h9 : freq <= 16'd10000;
4'ha : freq <= 16'd12000;
4'hb : freq <= 16'd14000;
4'hc : freq <= 16'd16000;
4'hd : freq <= 16'd20000;
4'he : freq <= 16'd30000;
default : freq <= 16'd40000;
endcase
end
assign frq = freq;
endmodule
リスト2-2 周波数設定部のVerilog HDL記述
注10;ロータリ・スイッチの値によって信号周波数を設定 0=1Hzから15=64kHzまで
module memif(ck,res,adrs,q);
input ck;
input res;
input [11:0] adrs;
output [15:0] q;
wire [10:0] rom_adrs,address;
wire pn,inclock;
wire [15:0] qa,rom_q;
reg [15:0] q;
always @(negedge ck) begin
if(res) q <= 16'b0; ←読み出しデータ
else q <= qa;
end
assign pn = adrs[11];
assign qa = pn ? ~rom_q : rom_q; ←※11
assign address = adrs[10:0];
sin_tbl rom_if(address,ck,rom_q); ←実際のFPGA内ROM
endmodule
リスト2-3 ROM制御部のVerilog HDL記述
今回の回路例ではFPGA内のメモリに波形データを格納する形式としました.また,sin波の再生だけに限定して実際の1/2のデータでの構成としています.このROMをRAMとして外部からの書き換えに対応すれば,任意の波形をリアルタイムに更新,再生できます.
tag: FPGA