« 2013年10月 | トップページ | 2013年12月 »

2013.11.27

A-D/D-A変換ICの実用技術: 高性能を引き出す回路の作り方と実装方法 を買ってみた

アマゾンでたまたま「A-D/D-A変換ICの実用技術: 高性能を引き出す回路の作り方と実装方法」という本を見つけました。

http://www.amazon.co.jp/dp/4789842894/

Addabook


アナログデバイセス著で、あの黒田徹さんが翻訳されています。

これは世界的名著に違いないと確信し、速攻でお急ぎ便で注文しました。この本を買って、まえがきを読んで初めてCQ出版のトラ技編集部の編であることに気が付きました。今月初めに出た新刊だったようですね。

まだ第1章の最初の部分だけを読んだだけですが、すばらしい知識とノウハウが詰まっていることに気が付くまでに時間は要しませんでした。

第1章はADCをドライブするためのOPアンプの話からはじまっていますが、ADCがサンプリングするときに過渡電流を生じさせることとそれが及ぼす影響、完全なレールツーレールのOPアンプなど存在しないことなど、1年半かけて経験して頭の中にぼやっと入っていたことがしっかりと明文化されていました。

次に第4章をざっと読んでみたところ、OPアンプのゲインを決める抵抗が自己発熱によってゲインが変わってくること、そして16bitADCではその自己発熱でゲインに温度特性が生じ、誤差を生じることなど、いままでの実験でも経験してきたことです。

16bit ADCでは、1個800円もするLinear Technology製のマッチングのとれた抵抗を使うというのは、やはり正しい選択だったようです。

この本を読むとアナログ回路とADCの原理と本質を理解することができ、よりよい回路設計のための手助けになります。確かにこの本で出てくるOPアンプやADコンバータはAnalog Devicesの製品ばかりですが、決して自社製品の宣伝のための提灯記事を集めたものではありません。この本で書かれていることはTIやLTのOPアンプやADCを使った場合でもまったく同じように応用できます。この本の著者には正しい技術を広く普及させたいという使命すら感じます。これが洋書の素晴らしさで、私も含め日本の筆者諸兄も見習わなければならない点だと思います。

大変すばらしい本なのですが、A4版で640ページもあるので全部読むには相当の時間がかかりそうです。本当はこの本を全部読んでからADCボードを設計したかったのですが、その時間はなさそうですので、ボードを試作してみてから再び振り返って読んでみたいと思います。

| | コメント (0)

2013.11.26

ZYNQのPLからPSへ大規模DMA

PLからPSへ大きなサイズのDMAができるようにしました。

AXIバスは最大で256ビートのバースト転送(32bit幅なら1024バイト)ができます。AXIのマスターとなる回路をユーザロジックに作り、ZYNQのPSにAXIでパケットを送ればメインメモリに書き込まれます。

しかし、AXIバスは最大256ビートまでなので、より長いサイズのDMAを行いたい場合は、このバースト転送を細切れにして発行するしかありません。

そこで、そういうステートマシンを作りました。

Axi_master_3

上の図は64ビートのバーストライトを4回繰り返しています。書き込んでいるデータは乱数(XorShift)です。

実際に67108864ビート(256MByte)のDMAを行ってみて、その時の端子の状態をMITOUJTAGのバウンダリスキャンで見てみたところ、約0.77秒の間、DDR3 SDRAMの端子が激しく動いていました。

256Mバイトを0.77秒で書くわけなので348MByte/secということになります。

Axi_master_4

たしか、ZYNQのメモリは32bit幅で、周波数は1066MHzくらいだったと思うので、メモリ帯域幅は4Gバイト/秒はあるはずです。

したがって、AXIのマスターポートから100MHzのバスクロックでデータを入れても10%も使っていない計算になります。まだまだ余裕ですね。

Axi_master_5

| | コメント (4)

2013.11.24

ZYNQでFPGA(PL)からARM(PS)のDDR3メモリへDMA転送

タイトルの通りです。

ZYNQでFPGA(PL)からARM(PS)のDDR3メモリへDMA転送することができるようになりました。

いま、ある種の計測器を作っています。FPGAに入ってきた計測データがBRAMに溜まっていきます。ある程度溜まったらそれを一気にPSのDDR3メモリに吐き出すようにしたいのですが、CPUの動作を介さずにハードウェア的にメモリ転送を自動的に実行したいと思います。

いわばDMAのような感じですが、AXIのバスの動作を使ってバスに自動的にやらせたいわけです。

ZYNQのAXIのポートには、①32bGP AXI Master Ports 2個, ②32bGP AXI Slave Ports 2個, ③High Performance 32b/64b Slave Ports 4個, ④64b AXI ACP Slave Port、のようにいくつかあります。

FPGA(PL)から、PSのDDR3メモリにアクセスするにはHigh Performance Slave Portsがよさそうです。

考えている構成は次のようになります。

Axi_master_1

32bGP AXI Master Ports(CPUがマスタで、コントローラはスレーブ)を通じて、転送先のメモリアドレスや長さなどの条件を設定し、計測データをHigh Performance 32b/64b Slave Ports(コントローラがマスタで、DDR3メモリがスレーブ)に入れるというわけです。

つまり、AXIマスタを作らなければなりません。実際にやってみて、MITOUJTAGのBLOGANA(簡易FPGA内蔵ロジアナ。ChipScopeみたいなもの)機能を使って波形を見てみました。

Axi_master_2

要するに、

  1. 書き込み先のアドレスをAWADDRに出力し
  2. 書き込みたいビート数(ワード数)をAWLENに出力する。AWLENの値は書き込みたい長さ-1である。(つまり16ワード書き込みたいならば0x0fを与える)
  3. AWREADYが'1'であるならばスレーブがアドレス受け入れ可能なので、AWVALIDを'1'にアサートする
  4. WREADYが'1'であるならばスレーブがデータ受け入れ可能なので、WVALIDを'1'にアサートするとともに、WDATAに32bitのデータを与える。そのときWSTRBには"1111"を与えると全バイトが書き込まれる。マスクしたい場合は当該バイトを0にする。
  5. 最後の1ワードを書き込むときには、WLASTを'1'にする。
  6. しばらくしてBVALID='1',BRESP="00"を確認したら終了

です。

さて、各種の信号に何を与えればよいかは、XILINXのAXIガイド(UG761)を読んでも正直言ってよくわかりません。ARM社からダウンロードできるIHI0022E_amba_axi_and_ace_protocol_spec.pdfという文章を読まなければ、結局のところわかりません。

ARM社の文章を読んでわかったことは、次のとおりです。

  • AWSIZEは、1ワードのサイズです。000は8bit、001は16bit、010は32bit、011は64bit、100は128bitです。AXIのポートを32bitで使っているので、ここでは axim_AWSIZE_i <= "010"; としておきます。
  • AWBURSTはバースト時のアドレスの変化方法を指定します。"00"だとFIXEDといってアドレスがインクリメントしないモード、"01"はINCRといってアドレスが1つずつ増えていくモード、"10"はWRAPといって、よくわかりません(笑)。
    "01"のINCRにすればよいでしょう。
  • AWCACHEは"0011"; にします。この意味は「Normal Non-cacheable Bufferable」だそうです。
  • AWPROTは保護モードだそうですが、"000"で良いようです。

また、DDR3メモリに書き込むだけであれば、リード動作は不要なのでリード系の入力新語うにはすべて0を与えておきます。、

  ARADDR   <= (others => '0');
  ARLEN    <= (others => '0');
  ARSIZE   <= (others => '0');
  ARBURST  <= (others => '0');
  ARCACHE  <= (others => '0');
  ARPROT   <= (others => '0');
  ARVALID  <= '0';
  RREADY   <= '0';

これでAXI Masterの信号がすべて片付きました。

私の作ったコントローラは、C言語から、

  volatile unsigned long *tmp = (volatile unsigned long *)(XPAR_AXI_EXT_SLAVE_CONN_0_S_AXI_RNG00_BASEADDR);
  regbase[16] = (unsigned long)dmabuf; // 格納先のメモリアドレス
  regbase[17] = len; // ワード単位
  regbase[18] = 1; // DMAライト開始

とすればDMAが発行されるようになっています。

さて、ZYNQのややこしいところはキャッシュの存在です。DMAで転送されたデータのCPUから読み出すには、Xil_DCacheInvalidateRangeという関数を使って、キャッシュの中のデータが古いからDRAMから読み直すようにという指示を与えなければなりません。そうしないと、せっかくDMAで更新されたデータではなく古いキャッシュの内容が読み出されてしまいます。

  int len = 16;
  Xil_DCacheInvalidateRange(dmabuf,len*sizeof(int));
  for(i=0;i<len;i++)
  {
    printf("data(%d) = %08lx\r\n",i,dmabuf[i]);
  }

これでOKです。

忘れないように今日作ったソースを書いておきます。

signal axim_ARESETN_o      : std_logic;
signal axim_AWADDR_i       : std_logic_vector(31 downto 0);
signal axim_AWLEN_i        : std_logic_vector(7 downto 0);
signal axim_AWSIZE_i       : std_logic_vector(2 downto 0);
signal axim_AWBURST_i      : std_logic_vector(1 downto 0);
signal axim_AWCACHE_i      : std_logic_vector(3 downto 0);
signal axim_AWPROT_i       : std_logic_vector(2 downto 0);
signal axim_AWVALID_i      : std_logic;
signal axim_AWREADY_o      : std_logic;
signal axim_WDATA_i        : std_logic_vector(31 downto 0);
signal axim_WSTRB_i        : std_logic_vector(3 downto 0);
signal axim_WLAST_i        : std_logic;
signal axim_WVALID_i       : std_logic;
signal axim_WREADY_o       : std_logic;
signal axim_BRESP_o        : std_logic_vector(1 downto 0);
signal axim_BVALID_o       : std_logic;
signal axim_BREADY_i       : std_logic;
signal axim_ARADDR_i       : std_logic_vector(31 downto 0);
signal axim_ARLEN_i        : std_logic_vector(7 downto 0);
signal axim_ARSIZE_i       : std_logic_vector(2 downto 0);
signal axim_ARBURST_i      : std_logic_vector(1 downto 0);
signal axim_ARCACHE_i      : std_logic_vector(3 downto 0);
signal axim_ARPROT_i       : std_logic_vector(2 downto 0);
signal axim_ARVALID_i      : std_logic;
signal axim_ARREADY_o      : std_logic;
signal axim_RDATA_o        : std_logic_vector(31 downto 0);
signal axim_RRESP_o        : std_logic_vector(1 downto 0);
signal axim_RLAST_o        : std_logic;
signal axim_RVALID_o       : std_logic;
signal axim_RREADY_i       : std_logic;
signal axim_remain         : std_logic_vector(7 downto 0);
signal axim_state          : std_logic_vector(1 downto 0);
・・・
  axi_ext_master_conn_0_S_AXI_AWADDR_pin  => axim_AWADDR_i,
  axi_ext_master_conn_0_S_AXI_AWLEN_pin   => axim_AWLEN_i,
  axi_ext_master_conn_0_S_AXI_AWSIZE_pin  => axim_AWSIZE_i,
  axi_ext_master_conn_0_S_AXI_AWBURST_pin => axim_AWBURST_i,
  axi_ext_master_conn_0_S_AXI_AWCACHE_pin => axim_AWCACHE_i,
  axi_ext_master_conn_0_S_AXI_AWPROT_pin  => axim_AWPROT_i,
  axi_ext_master_conn_0_S_AXI_AWVALID_pin => axim_AWVALID_i,
  axi_ext_master_conn_0_S_AXI_AWREADY_pin => axim_AWREADY_o,
  axi_ext_master_conn_0_S_AXI_WDATA_pin   => axim_WDATA_i,
  axi_ext_master_conn_0_S_AXI_WSTRB_pin   => axim_WSTRB_i,
  axi_ext_master_conn_0_S_AXI_WLAST_pin   => axim_WLAST_i,
  axi_ext_master_conn_0_S_AXI_WVALID_pin  => axim_WVALID_i,
  axi_ext_master_conn_0_S_AXI_WREADY_pin  => axim_WREADY_o,
  axi_ext_master_conn_0_S_AXI_BRESP_pin   => axim_BRESP_o,
  axi_ext_master_conn_0_S_AXI_BVALID_pin  => axim_BVALID_o,
  axi_ext_master_conn_0_S_AXI_BREADY_pin  => axim_BREADY_i,
  axi_ext_master_conn_0_S_AXI_ARADDR_pin  => axim_ARADDR_i,
  axi_ext_master_conn_0_S_AXI_ARLEN_pin   => axim_ARLEN_i,
  axi_ext_master_conn_0_S_AXI_ARSIZE_pin  => axim_ARSIZE_i,
  axi_ext_master_conn_0_S_AXI_ARBURST_pin => axim_ARBURST_i,
  axi_ext_master_conn_0_S_AXI_ARCACHE_pin => axim_ARCACHE_i,
  axi_ext_master_conn_0_S_AXI_ARPROT_pin  => axim_ARPROT_i,
  axi_ext_master_conn_0_S_AXI_ARVALID_pin => axim_ARVALID_i,
  axi_ext_master_conn_0_S_AXI_ARREADY_pin => axim_ARREADY_o,
  axi_ext_master_conn_0_S_AXI_RDATA_pin   => axim_RDATA_o,
  axi_ext_master_conn_0_S_AXI_RRESP_pin   => axim_RRESP_o,
  axi_ext_master_conn_0_S_AXI_RLAST_pin   => axim_RLAST_o,
  axi_ext_master_conn_0_S_AXI_RVALID_pin  => axim_RVALID_o,
  axi_ext_master_conn_0_S_AXI_RREADY_pin  => axim_RREADY_i
・・・
 process(plclk) begin
  if(plclk'event and plclk = '1') then
   if(axis_reset = '0') then
    axim_WVALID_i <= '0';
    axim_AWVALID_i      <= '0';
   else
    if(axis_wren(16) = '1') then
     axim_AWADDR_i <= axis_wdata;
    end if;
    if(axis_wren(17) = '1') then
     axim_AWLEN_i <= axis_wdata(7 downto 0) - 1;
     axim_remain  <= axis_wdata(7 downto 0) - 1;
    end if;
    axim_AWSIZE_i <= "010"; -- 32bit?
    axim_AWBURST_i <= "01"; -- increment
    axim_AWCACHE_i <= "0011"; -- Normal Non-cacheable Bufferable
    axim_AWPROT_i  <= "000";

    case axim_state is
     when "00" =>
      axim_WVALID_i <= '0';
      axim_AWVALID_i <= '0';
      axim_WSTRB_i <= "0000";
      axim_WLAST_i <= '0';
      axim_BREADY_i <= '1';
      if(axis_wren(18) = '1') then
       axim_WDATA_i <= axis_wdata;
       axim_state <= "01";
      end if;
     when "01" =>
      axim_AWVALID_i <= '1';
      if(axim_AWREADY_o = '1') then
       axim_state <= "10";
      end if;
     when "10" =>
      axim_AWVALID_i <= '0';
      if(axim_WREADY_o = '1') then
       axim_remain <= axim_remain - 1;
       axim_WSTRB_i <= "1111";
       axim_WVALID_i <= '1';
       axim_WDATA_i <= axim_WDATA_i + 1;
      else
       axim_WVALID_i <= '0';
      end if;
      if(axim_remain = 0) then
       axim_WLAST_i <= '1';
       axim_state <= "11";
      end if;
     when others =>
      axim_WVALID_i <= '0';
      axim_WSTRB_i <= "0000";
      axim_WLAST_i <= '0';
      axim_state <= "00";
   end case;
  end if;
 end if;
end process;

axim_ARADDR_i   <= (others => '0');
axim_ARLEN_i    <= (others => '0');
axim_ARSIZE_i   <= (others => '0');
axim_ARBURST_i  <= (others => '0');
axim_ARCACHE_i  <= (others => '0');
axim_ARPROT_i   <= (others => '0');
axim_ARVALID_i  <= '0';
axim_RREADY_i   <= '0';

| | コメント (3)

2013.11.22

ET2013へのご来場ありがとうございました

皆様、ET2013のXILINXブースの中のPALTEKブースの中の特電スペースにご来場いただきまして、誠にありがとうございました。

Et2013_1

こんな感じで、約50cmの幅で何とか展示していました。FULL HDの液晶ディスプレイにきれいな色のグラデーションと、帯状の文字が表示されています。この画像信号をArtix-7ボードで作り出すというデモでした。

出展1日目は、グラデーションだけが出ていて何のデモかわからなかったので、2日目の明け方に、『これはARTIX-7ボードのデモです。ZYNQじゃなくて生のARTIXです。』のような説明文が画面に出るように改良してきました。

それから、1日目は社名サイン(特殊電子回路という社名の看板)も出せなかったので、液晶ディスプレイの画面上に画像として社名を出すようにしました。

Et2013_2

画像は口ほどにものをいうんです。

さすがにXILINXブースだったので、すごくたくさんのお客様がいらっしゃいました。特電の製品を使用しているよと言ってくださる方もいっぱいいらっしゃって、とてもうれしかったです。

意外と特電のA/Dボードが期待されていたので、やる気が出てきました。

100人以上のお客様とお話した気がします。

元気をいっぱいもらったので、明日から再びZYNQとかAXIバスとかを触り始めます。

| | コメント (0)

2013.11.21

特殊電子回路はXILINXの中でET2013に出展しています

特殊電子回路はET2013に出展しています。

XILINXさん(F-37)の中のパルテックさんの中で「ボードメーカー」としてひっそりと、出展しています。

Et2013

幅50cmにも満たないスペースですが、元気にArtix-7ボードを展示しています。

上の写真は展示会1日目の写真です。2日目はもう少しバージョンアップしていたのですが、朝からずーっとお客様がいらっしゃっていたので、写真を撮るチャンスがありませんでした。明日の朝こそはバージョンアップした展示スペースの写真を撮りたいと思います。

今回の出展物はArtix-7ボードなのですが、「A/D変換ボード」の件でお越しいただく方がたくさんいらっしゃいました。明日は、開発中のボードをこっそりと持っていこうと思います。

ご覧のとおり弊社ブースは基本的に軒下を借りている身分なので、余分なスペースがありません。っていうか、1日目の後半からこの液晶ディスプレイも全部見られないほど狭くなってしまいました。とても「A/D変換ボードを出せるスペースをください」とは言い出せる雰囲気ではないので、カバンの中にしまっておきます。「A/D変換ボードは?」とお尋ねいただいた方にだけお見せすることにします。

| | コメント (0)

2013.11.18

特電総合カタログを作成

明後日から始まるET2013に向けて、製品総合カタログを作り直しています。

今回もIllustratorと格闘しました。

2013

トンボがないとかフチなし印刷のはみだし量とか、わけのわからないことばかりで大変でした。3回くらい入稿してようやく印刷屋さんのデータチェックに通ったようです。色とかの話になると、もうお手上げです。CMY混色の黒とか、見つける術がありません。

正直なところ、Illustratorのファイルをaiにするかpdfにするかでどういう違いがあるのかもよくわからないし。私のDTPの知識は、PDFXってなんだ?っていうレベルです。

今回のカタログは12ページフルカラー。135kgコート紙。このカタログを作るのに丸3日もかかってしまいました。19日の0:00に入稿、19日の18:00出荷、19日夜の納品、20日に会場に手持ち、というぎりぎりのスケジュール進行です。

そのため、特急印刷なので値段も高めです。

来年からは製品もどんどん増えていくし、16ページ~20ページくらいにしたいので、もっとスケジュールは厳しくなりそうです。IllustratorとDTPに詳しい専属スタッフを入れるか、完全に外注するしかなさそうです。

| | コメント (0)

2013.11.15

A/D D/A変換ボードを設計。そのための電源で苦労した。

さまざまな受託案件でA/D + FPGA + D/A + モータドライバ、みたいなのを作ってきました。特電が長年あたため続けてきた「究極のA/D D/A変換ボード」をついに作ることを決意しました。

ざっくりいうと、性能は、

  • ADCが18bit 2Mサンプル/秒
  • DACが16bit 1Mサンプル/秒

で、ノイズが限界まで小さいこと、です。

Tkdn_adc

計測したデータはFPGAボードを通じてメモリに蓄えてUSBから読み出したり、SDカードに書き込んだりできるようにする予定です。

18bitのA/Dの性能を出すため、高価な部品を惜しげもなく投入します。

まず、初段のオペアンプはOPA211AIDRを使います。1.1nV/√Hzと、OPアンプの中でも超低ノイズのランクです。このOPA211AIDRは単なるボルテージフォロアとして使っているので、不要ならばバイパスできるようになっています。

そして、そのあと、完全差動OPアンプで差動信号に変換します。ここでも1.9nV/√Hzクラスの業界最高レベルの低ノイズ品を使います。

完全差動OPアンプは4本の抵抗でゲインを決めますが、この比が崩れるとコモンモードノイズがシングルエンドになって見えるようになってしまいます。そのため、マッチングのとれた集合抵抗を使います。たかが抵抗に1個800円もします。

AD変換器のVREFには専用の高精度リファレンスを使います。これも高い。

そして、A/D変換器とFPGAとの間にはアイソレータを使って電気的に絶縁しています。電源も絶縁型のプラスマイナス電源を作ります。

ここでは、3.3Vまたは5Vから±の絶縁型電源を作るのですが、市販の電源モジュールはいずれもリップルが40mVくらいあります。電源に40mVの変動があってもADCの変換結果には影響を与えないかもしれませんが、あらかじめ削減しておきたいものです。

そこで前から目をつけていたのが、Linear Technology社のLT3439です。

http://www.linear-tech.co.jp/product/LT3439

普通のスイッチング電源は、コイルに流した電流をFETでバチバチとON/OFFするときの逆起電力を使って昇圧したり負の電圧を作ったりします。そのため、リップルも大きいしノイズもまき散らします。

それに対してLT3439は手加減をしながらプッシュプルのコイルに交流を流します。スルーレートコントロール型と書かれていますが、つまり商用AC電源のような電流変化の交流を作ってくれるのでしょう。

そしてトランスを使って昇圧し、ブリッジダイオードで整流するというわけです。従来のDC/DCと違って、AC/DCインバータのような感じの電源回路になります。

データシートによれば、後ろにLDOを入れなくてもリップルが0.2mVppに抑えられています。

Lt3439_sch

(データシートより引用)

 

LT3439の欠点は2つあって、出力電圧をコントロールできないことと、トランスの入手が難しいことです。

出力電圧はコイルの巻き数比と入力電圧で決まるので、フィードバックをかけるわけでもなく、完全な無制御です。そのため、後ろにLDOを入れて定電圧を作ります。

それから、LT3439のデータシートにはCOILTRONICS社のCTX02-16030やCOILTRONICS CTX02-16076といったトランスを使った参考回路が示されています。しかし、これは容易に入手できるものではありません。

データシートを読みながら、どういう特性のトランスが必要なのかを計算してみると、3.3V→±5Vの場合は巻き数比が1:2くらいで、5V→±5Vの場合は巻き数比が1:1.6くらいが適当でした。100mA~500mAくらいの電流を取り出したい場合、トランスの一次側のインダクタンスは300uH~800uHくらいが最適です。

このような仕様を満たすトランスをDigikeyの「SMSP(スイッチング電源用)トランス」のカテゴリの中から探すと絶望します。インダクタンスが小さかったり、電流を取り出せなかったり、条件にあうものが1つもありません。

インダクタンスが小さくてもリップルが大きくなるだけだと思うのですが、やはり冒険はしたくないもの。

・・・

このトランスの入手ができないので特注しかないかなーと半ば諦めていたのですが、なんと!Digikeyの「特殊トランス」というカテゴリの中でLT3439にぴったりのトランスを見つけました!

http://www.digikey.jp/product-search/ja?lang=ja&site=jp&KeyWords=78253%2F55MC&x=0&y=0

ありがとう村田製作所。78253シリーズという3.3V→5V昇圧あるいは5V→5Vのトランスがあるのです。しかも1個から変える!


(データシートより引用)

何やらMAX253用のトランスということで「特殊トランス」に分類されていたのですが、MAX253とLT3439は同じような機能のSW電源ICなのです。インダクタンスも数百uHあるし、きっと使えるはずです。

このトランスが本当に使えれば特注の必要はありません。もっともっとLT3439が使いやすくなるでしょう。この村田製作所のトランスを使ってLT3439の実験をすることにします。

Lownoise_smpw

来週早々には基板の出図をしようと思います。来週後半には結果が出るでしょう。

| | コメント (0)

2013.11.13

EXPARTAN-6Tを2枚挿しする実験

特電のSpartan-6LXT PCI Expressボードをたくさんお買いあげいただいたお客様から、「2枚(以上)を同時に使えるようにしてほしい」と、嬉しい(!?)ご依頼がありました。

そこで、2枚以上のPCIeボードを扱えるようにDLLを改良しました。

特電PCI ExpressドライバではIoCreateSymbolicLinkを使ってシンボリックリンクを作るのではなく、GUIDを使って識別できるようにしています。

ドライバのAddDeviceの最後のほうで

DEFINE_GUID(TKDNPCIE_GUID, 
0xee30eddb, 0xeb46, 0x4df5, 0x91, 0xa7, 0x64, 0x5d, 0x60, 0xd7, 0x7e, 0x9d);
・・
・・
・・
status = IoRegisterDeviceInterface(pdo, &TKDNPCIE_GUID, NULL, &dx->ifSymLinkName);

とやって、TKDNPCIE_GUIDを使ってデバイスを登録しています。

こうすると、ユーザプログラム(DLLを含む)からは、

HANDLE  hTP = GetDeviceViaInterface((LPGUID)&TKDNPCIE_GUID,0);

とやって、このドライバへのハンドルを得ることができます。

※古いやり方ではAddDeviceの中で、IoCreateSymbolicLink( &win32DeviceName, &DeviceNameUnicode );という関数を使ってL"\\DosDevices\\Tkpe0"みたいな名前を登録して、ユーザモードからはCreateFileで\\.\Tkpe0を開くようにしてドライバを開いていた。
このやり方では、1つのドライバに対して複数のデバイス(カード2枚刺しや、USB2本刺し)を行うときには、末尾の数字を変えていくことで複数のドライバを管理していた。

さて、2個目のPCI Expressカードを開くときにはどうしたらいいでしょう?答えはとても簡単。

HANDLE  hTP = GetDeviceViaInterface((LPGUID)&TKDNPCIE_GUID,1);

でよいのです。

これで複数のデバイスがあっても個別にハンドルを得ることができて、個々に操作できそうです。

Exsp6_2devices


とりあえず2つのEXPARTANを開いてみて、バス番号、デバイス番号、ファンクション番号をそれぞれ調べてみたところ、3-0-0と4-0-0になっていたので大丈夫でしょう。

割り込みレベルと割り込みベクタも別々のが与えられていて、もしかしたら割り込みやDMAまで簡単にできるかも、と期待できそうです。

明後日にはメモリリードやライトの試験をしてみたいと思います。

 

 

| | コメント (0)

2013.11.12

祝!ET2013にArtix-7評価ボードを出展します 祝 ☆彡

皆様、突然の報告で驚かせてしまい申し訳ございません。

特殊電子回路は、突如ET2013に出展することになりました。

場所は、ななななんと! XILINXさんのブースの中です。
私も驚きです!!

ザイリンクス(ブース番号F-37)の中で、代理店パルテックさんの中の、孫ブースとして出展します。

特電の幅は50cmくらいとのことですが、その中でArtix-7ボードのデモをさせていただけることになりました。

いままで、XI○INXさんはARMを内蔵したZYNQばかり力をいれて、素のFPGAだけのArtix-7はほとんど顧みてくれませんでした。しかも、XI○INXに認定された純正ボードは、
拡張コネクタがFMCメザニンコネクタのものばかり・・

『わずか数台の試作でメザニンを使う基板を起こしたくないよ』

というのが、多くの研究開発者の方々の本音ではないでしょうか。

そんな状況だからこそ、特電から力強い反撃をします。
産業用・物理計測用の試作に最適なArtix-7ボードで皆様をお待ちしております。

Et2013_2

【 ET 2013 特殊電子回路 出展概要 】
名称 : Embedded Technology 2013/組込み総合技術展
会期 : 2013年11月20日(水)~22日(金) 10:00~17:00
会場 : パシフィコ横浜
場所 : F-37 ザイリンクスブース内のパルテックブース内

出展内容:
 ① Artix-7評価ボードの展示と楽しめるデモアプリ

開催まであと1週間となりましたが、
遊んで楽しめる面白いデモアプリを開発していきたいと思います。

開発の状況は逐一ブログに書いていこうと思いますので、
ブログ「なひたふJTAG日記」をたまにごらんいただければ幸いです。

これからも特殊電子回路をどうぞよろしくお願いします。

| | コメント (0)

2013.11.10

高精度ADC回路の設計

特電Spartan-6ボードや、Artix-7ボードの拡張基板とするべく、ADCボードを設計しています。

ADCボードは、中速・高精度のものと、高速・中精度の2種類作る予定です。

中速高精度というのは2Mサンプルで18bi程度、高速中精度というのは200MHzサンプルで12bit程度を考えています。様々なセンサなどを使った計測には2Mサンプルで18bi程度で充分だし、放射線の計測には200MHzくらいのものがほしいということで、2種類作ることにします。

で、まずは18bitのものを作ろうとしているのですが、このクラスになると熱雑音とかアンプの雑音とかを真面目に考えなければならなくなります。

1kΩの抵抗の両端に生じる熱雑音は4nV/√Hzですから、1MHzの帯域を持たせるとなると音電圧は4μVになります。ADCを18bit精度として、ADCのフルスケールを3.3Vとすると、1LSBは12μVとなります。

もしプリアンプにゲインを持たせようと思って、抵抗で10kΩを使おうものならば熱雑音は約3倍になるわけなので、ADCの1LSBに匹敵する大きさになります。

このクラスのADCになると、アナログ入力端子が差動型になっています。シングルエンドで入ってきた信号を完全差動アンプを使って差動信号に変換します。

差動信号に変換するときに、もう1個の入力は通常は0Vにますが、ここに電圧を加えるとオフセットをキャンセルすることができます。

Lt6362

つまり、増幅と、オフセットのキャンセルが1個のアンプでできてしまうのが、完全差動アンプの魅力でもあります。

そして、完全差動アンプの出力には抵抗とコンデンサをつなぎます。このコンデンサが結構重要です。ADCはサンプリングするときに内部のコンデンサが電荷を引き抜くので、そのときに大量の電流を流す必要があるためです。その電流の元となる電荷をためておくためにコンデンサが必要です。

そして、次のサンプリングに備えて、このコンデンサにはすばやく電荷を補充しなければなりません。

低ノイズの完全作動アンプを探してみると、Linear TechnologyではLT6362(3.9nV/√Hz, 電源電圧±2.5Vまで、34MHzで-3dBダウン、消費電流1mA)なんていうのがあります。

Texas Instrumentsでは、THS4130(1.3nV/√Hz, 電源電圧±15Vまで、150MHzで-3dBダウン、消費電流16mA)が良い感じです。

LT6362とTHS4130のどちらが良いかは一概には決められないのですが、幸いなことにピン互換なので、両方作って試してみることにします。

それから、完全差動アンプに使う4個の抵抗も、値が正確にそろっていなければなりません。4個の抵抗の値のバランスが崩れると、コモンモードノイズがシングルエンドのノイズとして出てきてしまって、ノイズが増えます。

通常のディジタル回路のプルアップに使うような集合抵抗は、それぞれの抵抗の値のばらつきに規定はない(バラの抵抗を4個使うのと同じ?)ので、使えません。

このような用途に最適なのが、マッチングが保障された集合抵抗。たとえば、Linear TechnologyがLT5400というのを出しています。

http://www.digikey.jp/product-detail/ja/LT5400BCMS8E-4%23PBF/LT5400BCMS8E-4%23PBF-ND/

相対誤差が0.025%なので完全差動アンプの帰還抵抗に最適です。なんと1個800円もします。

まとめると、

  • 1kΩの抵抗からは4nV/√Hzの熱雑音が発生する。1MHz帯域の場合20bitADCの1LSBに匹敵する。このあたりが物理的限界。
  • ADCの入力に使うOPアンプも、そのくらいのノイズレベルのものを使うべし。
  • 完全差動OPアンプの帰還抵抗のマッチングは重要。精度のそろった抵抗は高い。

このような部品を使って、ADCボードを作って、今週中には動作試験をしたいと思っています。

| | コメント (2)

2013.11.09

伊勢神宮に行ってまいりました

朝4時に起きて、4時50分に家を出て、品川6時発の新幹線に乗って伊勢神宮に行ってまいりました。

JR東海ツアーズの「日帰り1dayお伊勢さん みえ利用 スタンダードプラン」なのですが、朝6時に品川を出るのぞみ99号に乗る、というところが最大の特徴です。

6時に品川に着くためには総武線も始発に乗らなければならないという難関はあるのですが、このプランは激安で、しかも2000円相当のクーポン券や1000円相当のバス券が付いてくるなど極めてお得なプランなのです。クーポンを使うと「おかげ横丁」で大きな海老が2本もついてくる豪華な海老フライ定食+漁師汁が食べられます。これが楽しみで毎年行っているようなものです。

で、伊勢に着いて驚いたのは、伊勢市駅(外宮前)の参道が賑やかになっていること!

新しいお店、食べるところや土産物屋がたくさん立ち並んですごく賑やかになっていました。1年でこんなにも変わるものなのですね。

外宮も驚くほど人が多い! 快速みえ はそれほど混んでいなかったのに、いったいどこから人が来るのでしょう。

正宮に参拝するのに十分以上かかりそうなくらい並んでいました。外宮では正式参拝して神楽を申し込みましたら、木の箱に入ったお札やら鰹節やらいろいろいただきました。

そしておかげ横丁に移動して昼食。混んでいるかなと思って早めにいったのですが、いつものお店はあまり混んでいなくてよかった。おいしい海老と漁師汁をいただきました。

そのあと急いで内宮に参拝。やはりすごい人の数。ぐるっと歩いて1時間くらいで抜けてきました。

新しい社も見れたし、おいしいものも食べられたし、良い旅行でした。

| | コメント (0)

2013.11.06

MITOUJTAGを使って基板の異常をわずか3分で発見!

あるお客様から、究極のRX62NボードのSDRAMテストでエラーが発生するというメールをいただきました。

実装上の不具合かもしれないと思い、さっそく送り返してもらいました。

実装の不具合を調べるにはJTAGバウンダリスキャンが最適です。JTAGバウンダリスキャンを簡単に行う日本製のツールでMITOUJTAG(みとうジェイタグ)というのがあります。

ここでは、MITOUJTAGを使って戻ってきたRX62Nボードを検査することにしました。

究極のRX62NボードにはオンボードのUSB-JTAGが乗っていますので、USB-JTAG用のポートにUSBケーブルを挿すだけで、すぐにJTAGが使えるようになります。

Rx_jtag_con_2

そして、MITOUJTAGを起動して、自動認識ボタンを押すと・・

Rx_mitoujtag_1_2

このようにRX62マイコンが検出されました。

同じIDCODEを持ついくつかのデバイスの中から、RX62NのBGA176ピンを選ぶと、

Rx_mitoujtag_2_2

このように、CPUの1個1個の端子の状態(H/L、入力/出力)がパソコンの画面上で可視化されます。

ここまでで約1分経過です。とても簡単です。

そうしたら、MITOUJTAGのメインメニューの中から[ツール]→[基板検査]を選びます。

Rx_mitoujtag_3

こんな表の画面が開きます。

Rx_mitoujtag_4_2 

とりあえずスタートボタンを押します。

・・

すると、CPUの端子の一本一本をバウンダリスキャンでH→Z→L→Zと動かして、その端子がオープンなのか、プルアップ/ダウンされているのか、どこかの端子とショートしているのか、を調べてくれるのです。

スタートボタンを押してから1分くらい経つと、すべての端子を検査し終わります。

Rx_short_2

この結果をみると、PD4_D4という端子(PORTD.4またはデータバス4)と、PD5_D5という端子(PORTD.5またはデータバス5)がショートしていることがわかります。

基板上のどの端子とどの端子がくっついているか、ということが一瞬でわかるのです。

ここまでで2分経過です。

そして、基板上のPD4とPD5の周辺をみてみると・・・

あっ!チップ抵抗がブリッジしている!

Short_d4_d5_2

あっという間に、異常を発見できました。

おそらくお客様がピンヘッダをはんだ付けしたにブリッジしたものと思われます。

このように、MITOUJTAGを使ったら、本当にわずか3分で基板の異常を発見できました。

基板のネットリストも回路図も、BSDLファイルも何も必要ありません。

JTAGをつないで、認識させて、自動検査ボタンを押すだけでボード上のショートを発見できるのです。

思い起こせば、MITOUJTAG(みとうジェイタグ)は今年で10周年なのです。

いままでありがとう、そしてこれからもMITOUJTAGをよろしく。

今後も益々発展させていきたいと思います。

| | コメント (0)

2013.11.05

Spartan-6の4倍速コンフィグがうまくいかない

Spartan-6のコンフィギュレーションをSPI ROMのQuadモードでやろうとしているのですが、なかなかうまくいきません。

WinbondのW25Q32BVだとうまくいくけど、W25Q32FVだとうまくいきません。

W25q64

うーん。

コマンドセットは一緒のはずなのに、何が違うんだろう・・・

FPGAから1個ずつコマンドを与えて挙動を見るしかないでしょうかね。

| | コメント (0)

RXduinoのイーサネットライブラリを更新しました

RXduinoのネットワークまわりを少し修正し、ネットワークサンプルアプリを更新しました。

主な更新点は、

  • TCPの受信バッファのサイズを変更できるようにしました。
  • 全体的に動作の安定化

です。もうtketh_process()を繰り返し呼び出す必要はありません。

void tketh_tcp_set_rbuf_length(unsigned short len);

という関数を追加しました。この関数を呼び出すと、TCPの受信バッファのサイズを変更できます。

デフォルトの受信バッファのサイズは128バイトです。内蔵メモリを使う組み込みマイコンだからと思って小さくしていたのですが、受信バッファが小さいとTCPは遅くなってしまうので、このサイズを変更できるようにしたというわけです。

たとえば、

tketh_tcp_set_rbuf_length(1024);

とやると、受信バッファのサイズが1024バイトになり、1回のパケットで1024バイトのデータを受け取れるようになります。TCPの転送速度は、(ペイロードサイズ÷パケット往復時間)でだいたい決まるので、受信バッファのサイズが大きいほうが効率よく転送できるわけです。

なお、このサイズを大きくすると、ローカルサーバのような遅延が少ないサーバから受信するときにデータが化けてしまうという現象が発生します。また、2048以上に設定しても効果はないようですし、メモリを消費します。

やはり、1024くらいが妥当なのではないかと思います。

また、サンプルプログラムも大幅に更新しました。

Rxduino_net1


このサンプルプログラムでは次のようなコマンドが使えます。

help                 Show this message.
reg                  Register dump.
dhcp                 Set IP, GW and DNS by dhcp.
nslookup             Resolve name.
arp -a               Show arp table.
ipconfig             Show IP configuration
ipconfig addr        Set IP address
telnet {addr} [port] Connect server with TCP
whois {hostname}     Whois
rtc                  Show RTC time
ntp {server}         Get NTP time and set RTC
gateway              Set default gateway address
ping target          Ping the specified target.
link                 Retry link-up and negotiation.
dump [off|on|full]   On/Off received packet dump.
nslookup [hostname]  nslookup.
hostname [newname]   change or show my hostname.
macaccr [newaddr]    change or show my macaddr.
nameserver [ipaddr]  change or show nameserver.
netstat              show tcp status.
rbuf [len]           Set receive buffer length.
reboot               reboot system with firmware.

ためしに、特電サーバのHTTPのポートにTELNETしてトップページをとってきたところのスクリーンショットを載せます。

Rxduino_net2

TCP/IPの受信側はだいぶん安定して動くようになってきました。

残る問題は

  • 再送
  • 通信速度が極端に遅くなって回復しないことがある(おそらく、RX62/63のイーサハードウェアにある受信ディスクリプタが壊れた場合に生じる)
  • TCP受信バッファのサイズを大きくしたときに、遅延の少ないサーバからの受信ができない。

です。

今回の更新されたライブラリは、RXduinoのバージョン1.08をベースに作っていますので、まず各種ライブラリを1.08にアップデートしてから適用してください。

ダウンロードは以下のリンクから無償で行えます。

GR-SAKURA用のライブラリと、サンプルアプリ

 「ethersample-gr-20131105.zip」をダウンロード

究極のRX62Nボード、RaXino、RaXino-i用のライブラリと、サンプルアプリ

 「ethersample-src-20131105.zip」をダウンロード (ソース付)

どなた様も、RXduinoのイーサネットをお楽しみください。

| | コメント (0)

2013.11.04

MFT2013に行ってきました

MFT2013に行ってきました。

科学未来館とTIME24と、2つのビルに分かれていてしかも結構遠いので迷いました。

ざーっと全部みてきました。

心に残った展示は、

  • 1階 食パンに焦げ目をつける機械
  • 1階 宇宙エレベータ
  • 1階 巨大水晶発振器 ※音が聞こえる!
  • 7階 人力の3D映画 ※まったく想像できなかった
  • 7階 戦闘能力測定装置
  • 7階 東京動脈(3次元の線路図) ※栗山さんが私のことを知っていてくれたのはうれしかった
  • 7階 ローラースケートで走ると床がに文字が光るもの
  • 7階 自転車の車輪に映像を出すもの
  • TIME24 マイクロマウス

特に7階の展示が濃かったです。人力の3D映画は感動! 立体物の影が立体に見える不思議。

FPGAを使った展示が少ないようで、DE0でフラクタルを描くくらいしか見つけられませんでした。それから、3Dプリンタというのが昨今話題のようですが、世に出た瞬間からすでにコモディティ化しているので、作っているほうは大変だろうなと思います。

正直、自分ももう少し頑張らなければなと思いました。来年はアート作品を作って出たいです。

| | コメント (0)

« 2013年10月 | トップページ | 2013年12月 »