AD7928によるA/Dコンバート
DE1-SOCには10ポート/12bitのA/Dコンバータ、AD7928があります。
これをVerilogで制御して、Analog値を取り出してみます。
データシート
http://www.analog.com/static/imported-files/data_sheets/AD7908_7918_7928.pdf
モジュール
下記のVerilogコードをコンパイルすると、上記のようなモジュールが作成されます。
clkiin : ここには1MHzくらいのクロックを入力します。
この値を基準に、AD7928とのシリアル通信を行います。
rstn : 立ち下がりエッジで、モジュールをリセットします。
ad7928_sclk, ad7928_dout, ad7928_din, ad7928_csn: AD7928の各ポートに接続します。
vin0 - vin7 : AD7928の各ADポートの変換された値が出力されます。
Verilog Code
module ad7928(clkin,rstn,ad7928_sclk,ad7928_din,ad7928_csn,ad7928_dout, vin0,vin1,vin2,vin3,vin4,vin5,vin6,vin7);
input clkin, rstn;
output reg ad7928_sclk,ad7928_din,ad7928_csn;
input ad7928_dout;
output reg [11:0] vin0,vin1,vin2,vin3,vin4,vin5,vin6,vin7; // 12bit adc x 8
reg [14:0] ad7928_reg_in;
reg [14:0] ad7928_reg_out;
reg [7:0] clk_cnt;
reg [7:0] seq;
reg [3:0] rout_no, rin_no;
reg [2:0] idx;
reg hl;
always@(negedge clkin or negedge rstn)
begin
if (!rstn) begin
vin0 = 0;
vin1 = 0;
vin2 = 0;
vin3 = 0;
vin4 = 0;
vin5 = 0;
vin6 = 0;
vin7 = 0;
clk_cnt = 0;
idx = 0;
seq = 0;
hl = 0;
ad7928_csn = 1;
ad7928_sclk = 1;
ad7928_din = 1;
ad7928_reg_out = 15'b100_0001_1001_1000;
end
else begin
clk_cnt = clk_cnt + 1;
if (clk_cnt > 49) begin // 20kHz clock
clk_cnt = 0;
case (seq)
0: begin
ad7928_csn = 0;
ad7928_reg_out = 15'b100_0001_1001_1000;
ad7928_reg_out[11:9] = idx;
rout_no = 14;
rin_no = 0;
seq = seq + 1;
end
1: begin
ad7928_din = (ad7928_reg_out >> rout_no) & 1;
rout_no = rout_no - 1;
seq = seq + 1;
end
2: begin
ad7928_sclk = 0;
seq = seq + 1;
end
3: begin
ad7928_sclk = 1;
ad7928_reg_in = (ad7928_reg_in << 1);
ad7928_reg_in = ad7928_reg_in | ad7928_dout;
rin_no = rin_no + 1;
if (rin_no > 14) begin
seq = seq + 1;
end
else begin
seq = 1;
end
end
4: begin
ad7928_sclk = 0;
seq = seq + 1;
end
5: begin
ad7928_sclk = 1;
seq = seq + 1;
end
6: begin
ad7928_csn = 1;
seq = seq + 1;
end
7: begin
case (ad7928_reg_in[14:12])
0: vin0 = ad7928_reg_in[11:0];
1: vin1 = ad7928_reg_in[11:0];
2: vin2 = ad7928_reg_in[11:0];
3: vin3 = ad7928_reg_in[11:0];
4: vin4 = ad7928_reg_in[11:0];
5: vin5 = ad7928_reg_in[11:0];
6: vin6 = ad7928_reg_in[11:0];
7: vin7 = ad7928_reg_in[11:0];
endcase
idx = idx + 1;
seq = 0; // restart
end
endcase // end of case(seq)
end
end
end
endmodule
出力タイミング
下から、ad7928_sclk, ad7928_csn, ad7928_di, ad7928_do