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