2012年05月23日

MPSSEめも

いままで作ってきた コードは、Synchronous BitBang(以下 SYNCBB) Mode を使っている。FT2232H でも FT232H でも SYNCBB は持っているので、コードはそのまま使えるのだ。

遅いという問題はあるが、実用上さほど問題になることはないと思っている 。FT2232H とか使ったら それなりに高速になる。ただ、UM232H とか安価な モジュールも出てきたし MPSSE を使ってみたいような気もしている。MPSSE は、JTAG ケーブルで良く使われているが、実際どういう機能なのか知りたくも思っていた。まずは、どのように使うものなのか調べていこう。

初期化:

    SYNCBB も MPSSE も FT_SetBitMode() を使ってモード設定する。だから、FT_SetBitMode() するまでの手順は、どちらも共通なのだ。

    FT_SetBitMode() で MPSSE モードにした後は、送受信するデータの意味が SYNCBB とは違う。

  • AN108: Command Processor for MPSSE and MCU Host Bus Emulation Modes

    このドキュメントがその詳細。初期化に必要そうなコマンドをちょっと抜粋しておこう。

  • GPIO の設定と読み出し (初期値の設定)
    MPSSI で使う TCK/TDI/TDO/TMS を含めて ADBUS/ACBUS (BDBUS/BCBUS) の設定と読みだしが出来る。


    Set Data bits LowByte 0x80 Value Direction
    Set Data bits HighByte 0x82 Value Direction
    Read Data bits LowByte 0x81
    Read Data bits HighByte 0x83

    LowByte は、ADBUS の Bit番号に対応し、HighByte は ACBUS の Bit番号に対応する。
    また、ADBUS の bit0 - bit3 は、 デバイスにかかわらず TCK/TDI/TDO/TMS が割り当てられる。Direction は 各bit の値が、1 で出力 0 で入力。

      ここで注意点がある。RS232C のモードだと TXD/RXD/RTS/CTS に割り当てられている。bit2 TDO はデバイスからの出力 だが、RS232C でも RTS でホストからの出力でぶつかるのだ。

      なので、一般的には シリアルに割り当てないように EEPROM の設定が必要になる。

  • クロックレートの設定
    FT_SetBaudRate とは別に クロックレートの設定をしなければならない。

    Clock 30MHz 0x8A
    Clock 6MHz 0x8B (default)
    Set TCK/SK divisor 0x86 ValueL ValueH

    0x8A/0x8B は、FT2232D にはない モードで ベースクロック値を変更する。0x86 の Value はこのクロックに対して分周する値(-1)。bit clock を 1 MHz に設定したければ、5 を設定する。30 MHz にした場合は、29。

    この説明は、正確ではないがだいたいこんなもの。

    GPIOの設定 の周期が、この設定で変わるのかどうかは不明。

  • ループバックの設定
    デバッグの初期にしか必要ないと思えるのだが、TDI と TDO を内部でつなげるモード。

    Loopback Enable 0x84
    Loopback Disable 0x85

    ひょっとしたら 初期化で Disable にしないといけないかも。

  • 2232D にない機能
    2232D にない機能は、無視してよいかと思ったのだが、気になるものがあるので、追記


    Enable 3 Phase Data Clocking 0x8C
    Disable 3 Phase Data Clocking 0x8D

    他にもあるが、とりあえず。

データの入出力

    データの出力方法に様々なパターンがあるのだが、JTAG で使いそうなものだけピックアップ。

    Clock Data Bytes Out on +ve clock edge LSB First (no read)
    0x18 LengthL LengthH byte1 .... ByteN
    Clock Data Bytes In on -ve clock edge LBS FIrst (no write)
    0x2C LengthL LengthH
    Clock Data Bytes In and Out (Out +ve / In -ve)
    0x3C LengthL LengthH byte1 .... ByteN

    Clock Data Bits Out on +ve clock edge LSB First (no read)
    0x1A Length byte1
    Clock Data Bits In on -ve clock edge LBS FIrst (no write)
    0x2E Length
    Clock Data Bits In and Out (Out +ve / In -ve)
    0x3E Length byte1

    -ve clock edge とは TCKの 立下り(↓)だと思えるが、説明はないようだ。8bit 単位でない操作は、bit mode を使う。それぞれの mode は、Out/In を行うかどうかで 3 通りがある。 byte mode に設定できる Lehgth は 1 〜 65535。bit mode は、1 〜 7 。

    基本はこの 6 種類で済むはずだが ... ルールがあるのでそれについて

    bit0 : -ve CLK on write
    bit1 : 0 byte mode / 1 bit mode
    bit2 : -ve CLK on read
    bit3 : 0 MSB First / 1 LSB first
    bit4 : DO write TDI
    bit5 : DO read TDO
    bit6 : DO write TMS
    bit7 : 0

    ピックアップした 6 つは、

    0 x x x 1 1 x 0

    のパターンが基本。ただし no read の場合は、bit2 は 0/1 どちらでも良いのかも知れない。 あと 出力は TMS 入力は TDO というパターンがある。TDI/TMS とも write に設定するとどうなるのか? ... 説明は見つけられていない。

rtavr_tools とのマッピング

    rtavr_tools での CABLE ドライバのインターフェイスは、次のように決めている。

    open
    close
    delay bitclock ベースの遅延
    put_tdi_bits TDI ストリームの出力 , Read あり/なし
    put_tms_tdi_bits TDI+TMS ストリームの出力 , Read あり/なし
    setup_port TCK/TDI/TMS の値を設定。
    setup_gpio INIT/PROG/M1/M2 と名付けた GPIO の状態設定
    get_gpio      INIT/PROG/M1/M2 と名付けた GPIO の状態取得
    set_bitclock bitclock の設定

  • put_tdi_bits

    上に書いてないが、最後のビットだけ TMS を H にするオプションがあり、JTAG では良く使われる。

    コマンドの組立てを考えると...

    MPSSE_PUT_BYTES (MPSSE_PUT_GET_BYTES read あり)
    :
    MPSSE_PUT_BITS (MPSSE_PUT_GET_BITS read あり)
    (TMS_HIGH オプションの場合 の追加)
    MPSSE_SET_LOW
    MPSSE_PUT_BITS (MPSSE_PUT_GET_BITS read あり)
    MPSSE_SET_LOW

    こんな感じになる。ただし、bit 数によっては、MPSSE_PUT_BYTES / MPSSE_PUT_BITS のどちらかがない場合がある。read なしの場合は、単に一気に 送れば良いのであまり問題でないのだが ...

    read ありでは、read データを解析しないといけない。MPSSE_GET_PUT_BYTES / MPSSE_GET_PUT_BITS がどういう組み合わせになっていようが、綺麗なビットマップになる。TMS_HIGH オプションがあると 1 bit 分のデータがそれにくっつく。... これぐらいだったら、BitBang 用として作ったものをベースに改造すればいけそうだ。

  • put_tms_tdi_bits

    これは、JTAG の ステートを変更する 時に使っている。操作するビット数はあまり多くない(最大 10bit)が、jtag の API がステート + TDI ストリーム という構造なので、put_tdi_bits と同じような頻度で使われることになる。

    もともとの仕様は、read あり になっているのだが ... どう実装するのが良いのだろう?

    (bit 数分のくり返し)
    MPSSE_SET_LOW (TMS が 変化する場合のみ)
    MPSSE_PUT_GET_BITS (1bit 分)
    MPSSE_SET_LOW (TMS を最後の状態に戻す)


    read の結果には MPSSE_SET_LOW は関係せず、1 バイト 1bit と決まるから、解析は難しくない。

    これで一応仕様を満たすことにするが ... 実は read ありは使っていない。read が入らなければ、write が連続で出ることになり、レイテンシは無視できる。BitBang だと write した分は、かならず read が入る。たぶんこの理由で、MPSSE の方が速くなりそう。

      ところで、JTAG の ステート変更では、TMS のみを TCK で出力するパターンを使う。そうであれば、TMS を変化させる コマンドを使った方が効率が良い。

      ただ、API まで変えるつもりはないので、TDI が全部 0 のとき TMS を変化させるコードにする .. とか最適化のひとつと考えておく。

  • delay
    クロックを発行しつつ delay する というコード。MPSSE_GET_BITS を必要クロック分発行すれば良さそう。ただし、実装する必要はなくオプション。

    実装されていなければ、put_tdi_bits で代替する。

  • setup_port / setup_gpio / get_gpio

    BitBang 用のコードをベースにすることで、簡単につくれる。

    ちなみに、INIT/PROG/M1/M2 は、Xilinx の信号線をベースに決めている。どのように操作するかは、

    (cbl->setup_gpio)(cbl, CABLE_GPIO_PROG, -1);
    (cbl->setup_gpio)(cbl, CABLE_GPIO_M2, 1);
    (cbl->setup_gpio)(cbl, CABLE_GPIO_M1, 0);
    (cbl->setup_gpio)(cbl, CABLE_GPIO_PROG, 0);
    (cbl->setup_gpio)(cbl, CABLE_GPIO_PROG, -1);
    (cbl->setup_port)(cbl, 1, 0, 0); // TMS = 1, TDI = 0, TCK = 0;

    こんな風に固定にしている。-1 は HI-Z (入力) 、あと config ファイルでの割り当てがなければなにもしない。それに加えて論理を逆にする config の設定がある。

(おまけ)I2C の考察

    I2C のコードはますます作る気はないが、メモ。

    MPSSE_SET_LOW/MPSSE_SET_HIGH は、アトミックに 方向を切り替えられる。だから L または HI-Z (入力) という操作は簡単にできる。読み込みの MPSSE_GET_LOW/MPSSE_GET_HIGH も期待通り同期してくれるだろうから、似非 I2C マスターのコードは簡単そうだ。

    似非 と書いたのは、ちゃんと作ると SCL を H にしたい場合は H になったことを確認しないといけないから。読み込みの結果によってループするようなコードにすると、USB は極端に遅くなる。だから、応答性能 の保証がないデバイス相手だと、ちょっと面倒なことになりそう。

    対策としては、遅くなるのを覚悟で、H になったことを確認する (1)。このパターンだと すごく遅くなるだけでなく、AVR USI を使うときに AVR も止まるという弊害がある。

    もうひとつは、delay をちゃんと計算する(2) 。AVR USI 相手 だと、割り込みが起きる フレームの最初のところだけ遅くして、あとは 普通にするとか。たぶん このやりかたが適切だろう。
posted by すz at 21:45| Comment(0) | TrackBack(0) | artemis

2012年05月19日

昇圧 DC-DC コンバータ覚書

前の記事に関係あるが、ステッピングモータ SPG20-1362を使うなら、15V 近い電源が必要になる。これをどうしたら良いかちょっと考察。

MC34063A

    汎用の DC-DC コンバータだと MC34063A がある。これは、昇圧にも使うことが出来て 5V → 12V なんかでも使える。あまり凝らないのなら、これで作るのも良いだろう。

    以前に書いたのだが、この MC34063A の派生版のような IC で M5291FP というのがある。日本語の PDF もあって、細かい説明が書かれていて参考になる。ググるキーワードは、RJJ03D0805 。現在も ルネサスのサイト から ダウンロードできる。

    4.8V (NiMH x4) を入力として 13V 0.5A を作りたいとして、ちょっと検討してみよう。

    まず 部品として、
  • 表面実装用(SMD) インダクタ (27uH , 3.1A) 4個 100円 
  • 表面実装用ショットキーバリアダイオード SS2040FL (40V , 2A) 20個 300円
    を使うことにする。

      Ton/Toff = ( Vout + Vf - Vin ) / ( Vin - Vsat )
       Vf は、ダイオードの 順方向電圧
      Vsat は、トランジスタの飽和電圧

    こういう式がある。Vin から上げたい電圧:Vin が Ton:Toff になるということか。

    ダイオードの 順方向電圧 は電流を流せば増える。0.5 V と見積もっておく。Vsat は、M5291FP のデータシートでは、外付け Tr を使わないなら 0.6V だそうだ。あと電流検出抵抗 Rsc の分がある これは Vin から 0.3V 引いておくことにしよう。

      Ton/Toff = ( 13 + 0.6 - 4.5 ) / ( 4.5 - 0.5 )
      = 2.275

    結果はこうなった。Ton は結構長い。

      Ipk = 2 x Iout x (1 + Ton/Toff)

    次にこういう式がある。電流は 線形で増えていくから ピークは平均の 2 倍。で、平均電流と出力電流の関係は、Iout x (1 + Ton/Toff) 。Toff の時間に 線形に減っていく電流の面積。こういうこと?

      Ipk = 2 x 0.5 + (1 + 2.275)
      = 3.275 (A)

    13V で 0.5A 流したいなら Ipk は 3.275 になる。インダクタの定格をちょっとオーバするが気にしない。

      Lmin = (Vin - Vsat)/Ipk * Ton
      1/Ton = (Vin - Vsat)/Ipk / Lmin
      Ton = Lmin * Ipk / (Vin - Vsat)

    Ipk はこの式で使い、Ton(MAX) を出す。

      Ton = 27u * 3.275 / ( 4.5 - 0.6)
      = 22.7 (us)
      Toff = 22.7 /2.275
      = 10.0 (us)

    計算した Ton + Toff から周波数を計算すると 30.6 kHz になった。

    これで良いの? という気がするのだが ... 5V → 12V 1A の回路例で 10uH なのに 50kHZ に周波数を設定している。0.5A なら 20uH で50kHZ 前後のはずだから だいたい合っているような ...

    効率はどうなるのだろう?

      出力は、13V x 0.5A
      入力は、Vin (4.8V) x ( 0.5A + 1/2 Ipk x Ton/(Ton + Toff) )
      で計算してみた。0.5A 足しているのは、昇圧は Vin に 上乗せするような計算になっていたから。理由ははっきりわからないが、こうしとかないと辻褄が合わなさそう。

      計算すると 82% ... 理論値みたいなものだし、実際はそんなはずはないか ...

    ところで、Ipk と 定格の関係。ダイオードなんかは、定格は平均電流。ダイオードの定格は 2.0A だが、大丈夫なんだろう。インダクタは、10% インダクタンスが減るときの 電流値で、実はもうすこし流せるようだ。これも問題ない。問題は、MC34063A自体。1.5A と書いてはあるのだが、ピークなのか平均なのか?

    ピークなら Ipk = 3.275 (A) だから全然ダメ。だが平均は、

      1/2 Ipk x Ton/(Ton + Toff)
       = 1.14 (A)

    だからいけることになる。

    どっちだろうか? それはやってみれば分かる。ただ、やってみるには、Rsc として 0.1 Ωが必要。... これの入手に難がある。

  • コスモ電子: 酸化金属皮膜抵抗 1W

    とかあるところにはあるようだ。

  • MCR25JZHFLR100 0.1Ω 3225
  • MCR50JZHFLR100 0.1Ω 5125

    デジキーならこのあたり。

    MC34063A の互換品には、NJM2360ADがある。 あと、100均の シガープラグ の 5V アダプタでも使われているのは有名。

    発振周波数設定用のコンデンサの値

      Ct (pF) = 40 x Ton (us)

    だそうだ。1000p ぐらい。


Tiny13A

    上の計算で、周波数や Duty比は分かった。なら Tiny13A とかの PWM でも良さそうなものだ。ADC があるから 電圧を測定できる。出力電圧を上回ったら スイッチングをやめれば良い。

    追加部品は、Nch MOSFET。

  • シングルNchチップMOSFET FD6612A (30V , 8.4A) 10個 200円 売り切れ
  • シングルNchチップMOSFET FD5680 (60V , 8A) 5 個 200円
  • DMS3016SSS SO-8 シングル(デジキー)
  • DMG3420U SOT-23 (デジキー)
  • DMG3415U SOT-23 (デジキー)
  • IRLML6246 SOT-23 (デジキー)

    沢山書いたが、FD6612A,FD5680 は VGS が高く 4.8V をそのまま AVR の電源にしないといけないという制限になる。 DMS3016SSS はデジキーで買えるものだが、置き換えが可能。はなからデジキーから買うつもりなら SOT-23 の DMG3420U も良いかも。

    ... というわけで、Nch の MOSFET の選択もなかなか面倒。

Tiny85/Tiny45

    Tiny85/Tiny45 だと もっと高度なことが出来る。やってみたいのは、コンパレータを使った電流モード制御の追加。

    電流測定用 抵抗として 0.1Ωを用意して、Nch MOSFET と GNDの間に入れる。あと、比較用に 0.3V を 分圧して作る。分圧の元は VCC (4.8V) でも良い。

    制御は、3A 流れることがあれば、Ton を短くする。毎周期 3A 流れた時点で Off にするというのは 厳しいので、3A 以上流れないように Ton を調整するわけだ。

    ピンアサイン案:

    ~RESET 1 8 VCC
    ADC3 2 7 ADC1 (SCK) voltage
    L 電流検出 ADC2 3 6 PWM (MISO)
    GND 4 5 (0.3V)基準電圧 (MOSI)

    #5 は、AIN0 だが、AREF でもある。こちらに 基準となる電圧を入れたほうが融通が利きそうだ。AIN1 は、ADC0-3 と置き換えることができる。Tiny85/Tiny45 は、差動入力 ADC2-ADC3 が使えるので、応用の可能性を考慮して、電流検出は #3 ADC2 にする。
posted by すz at 02:31| Comment(0) | TrackBack(0) | 日記

倒立振子ロボットめも

メモたんく』の ぱんと氏 のところで倒立振子ロボットを作っているのを見つけた。興味深いのでメモしておこう。

オリジナルは、『からくり小僧』の iCHIRO 氏の LIBRA-ZERO/ONE 。こちらの記事も合わせて見ている。

モーター + 車輪:

    まず、モーターは、ギア付きの ステッピングモータ SPG20-1362。 (ぱんと氏は) これに、タミヤの 楽しい工作シリーズ No.96 オフロードタイヤセット を直接付けている。

      記事をみていると、 オフロードタイヤセットの(ホイールではなくて)タイヤが外れる? -- みたいなことが書いてあった。iCHIRO 氏は 同じシリーズの ナロータイヤセットを使っている。ただ、ちゃんとセットアップできれば オフロードタイヤセットの方が良いようなことも書いてあった。

      ... なかなか タイヤの選択も難しいらしい。

    いままでにも、倒立振子ロボットに興味を持ったことはあるのだが、駆動部のトルクと速度をどうするのが良いのか分からなかったので、パスしていた。なるほど、SPG20-1362 が具合が良いのか。-- この組み合わせで 倒立振子ロボットとして実績があるというのは 心強い。

モータ用電源

    モータの駆動電圧は 15V 近いようだ。オリジナルの LIBRA-ZERO/ONE では PIC の PWM で 昇圧 DC-DC コンバータを自作している。

    キーになる要素をメモすると ..

    表面実装用(SMD) インダクタ (27uH, 3.1A) を使用し、PWM周波数は、200KHz位。出力電圧14.4Vで 電流0.4A (5.76Wの出力) 。入力は約4.8Vで2.0A (約60%位の効率)

    この DC-DC コンバータは I2C デバイスとして実装されているとのこと。

その他の部品

    (ぱんと氏は) センサに、小型圧電振動ジャイロモジュールを使っている。

      iCHIRO氏も 使っているのは ジャイロセンサ 秋月の旧製品? 。それはともかく、ジャイロセンサは、角加速度を検出するものではなく、角速度。ふうむ Gセンサは使わないものなのか。

    モータドライバは、何だろう? ユニポーラ型だそうだから、表面実装用トランジスタアレイTD62083AFNG とかで十分? 8ch だから これで 2 個のモータを制御できるし。

モーターを回すだけでも 電源の問題もあるし、なかなかに手応えがありそうだ。その上で 倒立振子 としての制御 、さらに 自由に動かすための制御 がある。

駆動系を作るのは比較的簡単そうで、動かすのに頭を使う。なかなか良さそうなテーマだ。 実際に動かすのも狭い場所で楽しめそうだし、その面でも良い。

部品についても、良い物が結構安く手に入るようになってきた。良い時代になったものだ。

その他のメモ

SPG20-1362

    今は、SPG20-1332 と 2 種類がある。以前は SPG20-332 というのが売られていたのだが、性能が上がってコンパクトになったのが、SPG20-1332 。1332 は、1 ステップ 0.75°で遅い。1362 は、1 ステップ 1°で若干高速で こちらの方が 倒立振子 として向いているそうだ。

      (参考) からくり小僧:ステッピングモータ(SPG20-1362)を使ってみた

      これを見ると、高速回転ではトルクが低下していく。グラフを見ると 600 pps ぐらいで半分。とりあえず 限界を 720 pps と仮定すると 2 回転/秒 (= 0.083sec/60°)。55mm のタイヤなら 35cm /sec 。このときの トルクは 25 mN・m ぐらい ... 1N・m = 10.2 kg・cm だそうだから 0.25 kg・cm ?

      無理やりサーボモータで使われる単位にしてみたが ... 速度はサーボモータ並みだけれども トルクは(小型のものと比べても)はるかに(一桁) 小さい感じ。

    データシートを見ると 2W と書いてある。抵抗は 68Ω。電流を流しつづけたときに 14.4 ^2 / 68 = 3.0W だから こんなもの? 電流的には 14.4 / 68 = 210mA (最大) 。0.4 A 流せれば 2 個駆動できる。

DC-DC コンバータ

    AVRで再実装するとして、PWM は 8MHz が使えるから オリジナルと同じ条件。200kHz だと 40 ステップ。ステッピングモータの駆動専用だから、スイッチングの ON/OFF 制御だけでも良さそうな。

    Nch MOSFET は、平均 2A は 流せないといけないが、どういうのが良いのだろう?

    20V耐圧の SOT-23 品を使うとか ... デジキーになってしまうが、DMG3420U,DMG3415U , IRLML6246 とか。-- Pch版が 秋月にあるもの を選んでみた。
    これらだと、AVR を 3.3V で使うことにしてもちゃんとスイッチングできる。秋月にあるのは、VGS が高いので、4.8V のバッテリーをそのまま電源しないといけない。

    あるいは、秋月で手に入る SO-8 パッケージ シングルの FD5680 (60V , 8A) を取り敢えず使うことにしておいて、デジキーで 手に入る DMS3016SSS に置き換え可能にするとか。

    それはともかく、モータ専用で凝らないなら Tiny13A 程度でも作れそう。

タイヤ

    楽しい工作シリーズだと、

      No.96 オフロードタイヤセット
      No.145 ナロータイヤセット
      No.111 スポーツタイヤ
      No.193 スリムタイヤセット
      No.194 ピンスパイクタイヤセット

    と各種ある。直径 55mm 前後 が安心だが、もうすこし小径でも良いらしい 。他のメーカだと MYU-004 あたりが使えるかも知れない。

(不完全)パーツリスト

SPG20 モーターの代替

    SPG20-1362 のようなギア付きのステッピングモータは、入手が難しい。秋月で安く手に入るから良いが、いずれは在庫がなくなるだろう。手に入らないようになるとすれば .. どうするのが良いのだろう?

    だいたいの性能は、最大 2 回転/秒(120RPM) で トルクは 0.25 kg・cm 程度。( 静止トルクはこの 4 倍ぐらい)。120RPM ぐらいまでで これ以上のトルクがあるものを探せば良い。

    ダブルギヤボックス

      4つのギア比を設定できる。その中に 114.7:1 のギア比があり 115 RPM / 0.8 kg・cm だそうだ。

      車軸の位置は 2 通りあるが、114.7:1 のとき 車軸の位置は外側になるので、問題なさそう。

    ツインモータギアボックス

      227 RPM / 0.42 kg・cm 。少々早く トルクが少ない。

      車軸の位置が良さそう。

    このあたりの ギアボックスが 速度・トルクの面で使えそう。これが使える以上他のものを探す必要はないぐらいに思える。モータは最大 3V 。逆回転が必要なので、フルブリッジ(モータドライバ)も必要。

    問題は回転速度検出だが、中間のギアが露出しているのだから、ストライプ状に塗って、反射型フォトリフレクタ を使えば良さそうな気がする。ただしノウハウがないので どうやるのが適切なのかは分からない。

    あと、DC モータなので、(電圧ではなく)電流をモニタしていれば、回転数は分かるのではないか? 10000 RPM というと 166 Hz 。この値か その 2倍の周波数で 電流が変化するに違いない。

    モータドライバは、秋月で扱っている BD6211F-E2 が良さそう。正転・逆転 ができて、PWM での 速度制御もできるようだ。ボリュームを使った 電圧での回転制御すら可能で なかなか興味深い。

    (参考) モーター性能比較表

      上記のギアボックスは、FA-130 モータを使用している。このモータは ミニ四駆でも使われているので、高性能モータが いろいろ存在する。モータ置き換えも考慮に入れた方が良さそう。

ステッピングモータ制御覚書

    Wikipedia にも 項目があり 制御の仕方の説明がある。

    回し方の基本方式は、一相励磁 と 二相励磁。二相励磁は、2 個のコイルに同時に電流を流すやりかたで、トルクが強いらしい。なら基本はこれ?

      一-二相励磁 というのもある。二相励磁のタイミングを変えて 一相励磁の状態が間にある感じ? なめらかになるだけで、トルクは変わらない?

    回し方の原理は簡単だが、負荷が大きすぎたり、パルス周波数が高すぎると脱調する。脱調しないように制御することが重要。

    負荷が小さければ、電圧は高くなくて良いはず。5V でも 制御の実験はできるかも知れない。DC-DC コンバータ自体が怪しげなら、5V でとりあえず制御の基本コードを作るという方針でも良いかもしれない。

    さて、脱調しないようにするには、回転のスタートとストップで 加速度が一定になるような 制御が必要。ものには慣性があるから 当然だ。また、どこまでも速度を上げられるわけではないから、ある速度に達したら その速度を維持する。

    基本はこういうことだが、倒立振子だから扱うものは基本的に加速度。定めた加速度を発生させるような 機能になっていないといけなさそう。

    それを守った上で、目標の速度にしたりすれば良い? あとは移動距離。方向転換とかは、移動距離をベースにした制御?
posted by すz at 00:06| Comment(0) | TrackBack(0) | 日記

2012年05月14日

ACT8796

興味深い電源IC を見つけたのでメモ。

    Android Tablet に使われている電源用IC として Active-Semi の IC がある。

    ここ を見ると各プロセッサー向けにカスタマイズした電源ICを提供しているようだ。

    所有している Tablet の Novo7 Paladin は、JZ4770 という MIPS の チップを採用しているが、それ用の ACT8600 というチップを使っている。これの データシートがダウンロードできるので見てみた。

    なんと 1つの昇圧 DC-DC コンバータ(OTG 用 5Vに使う)、3つの降圧DC-DC コンバータ(3.3V , core電圧 , DRAM 電源?)、5 つの LDO(レギュレータ) を持っていてさらに バッテリー(1セル)の充電まで出来る。すべての電源をこれだけで管理できて、結構すごいと思ったのだが、Tablet の中に入っているもので、電子工作には無関係。単独で入手もできそうにない。

    では、入手可能で データシートも入手できるものはないかと探したら、1つ見つかった。それが ACT8796 。パッケージは、QFN24 (0.75mmピッチ) で 敷居は高いものの電子工作で一応使える範疇。

    チップ自体は、taobao で入手できる。値段はいろいろあって どれが妥当なのか 判別しがたいが 10個 42元(600円ぐらい?)のところ がある。

    さて、このチップの機能は 3 つの降圧DC-DC コンバータと 3つの LDO 。そして、(LDO も含め)それぞれの出力を、I2C で設定できるようだ。AVR と組み合わせて 実験用の 電源にするとか ... バッテリー駆動の なにかを作るときの電源にするとか ... なにか有用な使い方があるかも。

PowTech PT1502

    ついでに電源用 IC PT1502 のメモ

    これも taobao で購入可能 + データシートあり。

    こちらは、バッテリー充電 機能に加えて 降圧 DC-DC コンバータ + LDO 2 つ。I2Cなどはない。充電関係では、AC アダプタ , USB を区別できる。あと Power-on 回路。AVR とかをバッテリーで 制御するには便利かも。 降圧 DC-DC コンバータ は 1.2V とか core 電圧向きで、ARM とか FPGA/CPLD でも使えそう。

    降圧 DC-DC コンバータの電圧は、FB の分圧抵抗で決める。LDO1 は 3.0V 固定。LDO2 は、(ピン設定で) 2.5/2.8/3.0/3.3V から選べる 。

      PowTech PTxx を買うなら、taobao の この店が 良さそう。PT1502 だけでなく、1セル充電IC(PT6181) , LED 向け昇圧IC(PT4181) , 降圧 DC-DC(PT1281 等) を扱っている。ただ、値段が 安すぎで 不安 -- なにか誤解しているかも。

posted by すz at 23:26| Comment(0) | TrackBack(0) | 日記

2012年03月23日

LPCインターフェイスめも

Lattice のリファレンスデザインのなかに

があるのを見つけた。そういえば、自作FPGA ボード を相互に接続するのに I/O が 7本 + 1(入力専用)しかなく、これで実装できるインターフェイスを探したときに LPC を知ったのだった。

    簡単に説明すると、最低 LRESET, LCLK, LFRAME , LAD[3:0] の 7 本の線で接続できる バス規格。周波数は、33 MHz 。

LPC は Intel が提唱した規格で PC の SUPER I/O 用に実際に使われていた。SUPER I/O というのは、所謂レガシーインターフェイスをまとめたもので、今でもデジキーで入手できるチップがある。

もの自体には興味がないが、データシートは実装を実際にどういう風にするのかという参考になる。

    ちょっと見てみたところ、LDRQ , SERIRQ といった DMA や割り込み要求の線がある。実際には 7 本では済まないわけだが、イベントを通知する線は まぁ必要だろう。

    SUPER I/O のデバイスは、シリアル/パラレル/ゲームポート/MIDI/FDC など。あと ハードウェアモニタ関連で、ファンとか 電圧監視用 ADC とか GPIO とか。

    そういえば、PC の bios の FLASH にも使われていた。LPC を初めて知ったのは、これかも知れない。

    こっちのデータシートは、どういう風にアクセスするのか詳細が書いてある。

LPC の詳細

    さて、RD1049 をひもといて見る。ドキュメントは RD1049 自体のもの以外に LPC の仕様書が入っている。規模は、MachXO2 で HOST 用が 84 LUT , デバイス用が 73 LUT 。

    どうも、アドレス 16bit / データ 8bit の ISA バスのような 仕様で使っているようだ。

    次に 仕様書をちょっと見てみた。

    16bit の I/O アドレス以外に 32bit のメモリアドレスが定義されていて、いろいろな転送モードがある。どうも ISA バスの機能を包含することが(もともとの規格では)重要らしい。

      Host Initlated Memory Read
      Host Initlated Firmware Memory Read
      Host Initlated I/O Read

      Host Initlated Memory Write
      Host Initlated Firmware Memory Write
      Host Initlated I/O Write

      Peripheral Initlated Memory Read
      Peripheral Initlated I/O Read (8bit , 16bit, 32bit)

      Peripheral Initlated Memory Write
      Peripheral Initlated I/O Write (8bit , 16bit, 32bit)

      DMA Read (8bit , 16bit, 32bit)
      DMA Write (8bit , 16bit, 32bit)

    RD1049 がサポートしているのは、Host Initlated I/O Read/Write のみのようだ。どんなアクセスをするのか、DMA も加えて表にしてみた。

      START CYCTYPE+DIR ADDR TAR SYNC DATA TAR total
      Host Initlated I/O Read H1 H1 H4 H2 P1 P2 P2 13
      CHANNEL+SIZE
      DMA Write Cycle (8bit) H1 H1 H2 H2 P1 P2 P2 11
      DMA Write Cycle (16bit) H1 H1 H2 H2 P2 P4 P2 14
      DMA Write Cycle (32bit) H1 H1 H2 H2 P4 P8 P2 20

      START CYCTYPE+DIR ADDR DATA TAR SYNC TAR total
      Host Initlated I/O Write H1 H1 H4 H2 H2 P1 P2 13
      CHANNEL+SIZE
      DMA Read Cycle (8bit) H1 H1 H2 H2 H2 P1 P2 11
      DMA Read Cycle (16bit) H1 H1 H2 H4 H4 P2 P4 18
      DMA Read Cycle (32bit) H1 H1 H2 H8 H8 P4 P8 32

    必ずホストが、転送を開始する DMAも同じで、デバイス側の要求が受け付けられたら HOST が転送をスタートさせる。

    H1 というのは、Host 側が 1 回(4bit の)転送を行うという意味。P2 は デバイス側は 2 回。
    DMA では ADDR の代わりに CHANNEL と SIZE が送られる。あと LFRAME は、START の 1 クロックだけ L になる。

    33 MHz 4bit だから 16.5 MB/sec の帯域だが、転送にはこのシーケンスが必要なので、実際の帯域は随分落ちる。Host Initlated I/O Read/Write では 13 クロックで 1 バイトだから 2.56 MB/sec 。

    ちょっと思ったより帯域が少ないのでがっかりだが ... 仕様など知ったことではないというスタンスでプロトコルを 再定義すれば 512B のバースト転送とかで、16 MB/sec ぐらいにはなるかも知れない。

      よく分かって書いているわけではないが、DMA の TAR を 2 クロックに限定して DMA のサイズを 再定義してやるとか。ついでに書くと DDR も CHANNEL か SIZE で指定できるようにしたりして。

      追記: DMA の TAR のクロック数は、上記の表の通りである必要はない。TAR の後に来るのは、SYNC か START で DATA 待ちみたいな感じ。


    以下 START 等の意味。(関係なさそうなものは省略しているので注意)

    START

      0000 Start
      1111 Stop/Abort

      普通 0000 でスタートする。スタートは LFRAME が L になる。Stop/Abort は、wait のタイムアウト時に使う。

    CYCTYPE + DIR

      000x I/O Read
      001x I/O Write
      100x DMA Read
      101x DMA Write

      x は 0 にせよということだが、読む方はきにしない?

    SIZE

      xx00 (0) 8bit
      xx01 (1) 16bit
      xx11 (3) 32bit

      2 のべき乗ルールなら良かったのだが、N+1 になっているようだ。

    SYNC

      0000 Ready
      0101 Short Wait
      0110 Long Wait
      1001 Ready More
      1010 Error

      Short Wait/Long Wait で 所謂 Wait が挿入できるようだ。Short /Long で Timeout のパラメータを変えるものらしい。Short は 数クロック / Long でも 1 マイクロ秒 (30 クロック)程度。

      Timeout したときに HOST は、LFRAME を L にするのだが、数クロック後に 1111(START:abort) を送出して H に戻す。LFRAME=L と同時に 1111 を送出すると信号がぶつかるからダメ。

    TAR (Turn Around)

      1111 zzzz ...

      LAD も weak pull-up だそうだ。最初だけ 1111 にせよということらしい。

    CHANNEL

      なんでも良いかと思ったらルールがあった。0-3 が 8bit で 5-7 が 16 bit 4 が バスマスタ用って書いてある。あと bit3 は、TC(Terminal Count) で 1 だと 最後の転送であることを指示する。

      そして、LDRQ もルールがあった。LCLK に同期したシリアルで、

      LCLK ____ ____ ____ ____ ____ ____
      _____| |____| |____| |____| |____| |____| |____

      LDRQ __________ _________
      |_________| bit2 | bit1 | bit0 |

      こんな風に送るものらしい。

      書き忘れたが、他のデータも negedge LCLK でデータ送出、posedge LCLK で受け取り。

      ちなみに、SERIRQ (Serialized IRQ) というのも プロトコルがあり、LDRQ より複雑そう。
      ( LPC の仕様書には詳細は記述されてない。PCI の仕様書で定義されているらしい。)

おわりに

    なかなか難しいものようだ。だが完全オリジナルよりは、LPC ベースに検討した方が良さそう。

    やりたいことは、もともと 7bit + 入力 1 での デバイスの拡張なのだ。DMA の使い方を変更・拡張して、自分の目的にあったものを作ってみたい。

    あと、lattice のリファレンスデザインは、 lattice のデバイスにインプリメントする場合に限り自由なのであって、本当に自由にしたければ自分で作らないといけない。あくまで参考として使うようにしないと。

おまけ

    RD1049 レベルのものを書いてみた。

  • lpc_master.v
  • lpc_slave.v

    本当は、Host-Peripheral の関係だが、なんとなく master-slave というネーミングにした。あと用語で LAD とすべきところを LDA にしてしまった。(未修正) 。まぁプロトタイプというか書いてみただけだから ... 。もちろん動く保証もない。

    基本的に posedge で state を変更し 入力処理をして、negedge では、state に応じた出力処理になるよにしている。規模は master が 80 LUT , slave が 65 LUT 。RD1049 と似た様なもの。

    これを元にどう膨らませようか思案中。

    まず slave 側。I/O 空間にレジスタをマッピングして定義したデバイスを動作させるようにして、512B ぐらいのバッファを DMA の手順でバースト転送できるようにしたい。あと、クロックは、LCLK をマスタークロックとして全部同期させる。

    slave 側のデバイスとして SDカードをサポートするのをまず想定している。それ以外に複数の slave で共通のデバイスをもたせたりもしたい。なかなかに難しそうな...

    master 側は、LCLK を マスタークロック にしないで ハンドシェークさせるつもり。master 側が数分の1 のクロックで動作しても問題ないようにしたいが、master 側 の方が速かったりするケースにも対応したいような... これもやっぱり難しそう。

追記: OpenCores の LPC モジュール

  • wb_lpc -- Wishbone LPC Host and Peripheral Bridge

    というのがあった。Features を見てみると DMA や firmware アクセス , Serialized IRQ など フルスペックのように見える。

    DMA の DIR (Read/Write の方向) をどう設計すべきか、参考になるかと期待したのだが ... よくわからなかった。より上位で決めるような設計のようだ。

    serirq については、少し分かった。

      START FRAME -- IRQ0 FRAME ... IRQN FRAME -- STOP FRAME --

      START FRAME 0 ... 0 1 1 (6 - 12 clocks)
      P/H H
      IRQN FRAME 0/1 1 1 (3 clocks)
      P
      STOP FRAME 1 0 0 1 1 (5 clocks)
      H H
      IRQ : IRQ0 ... IRQ15 IOCHECK ( INTA INTB INTC INTD .. )

    最初は、Peripheral が 0 にする場合もあれば Host が 0 にする場合もある。続く 3-7 clock Host が 0 にする。0 の期間は、4,6,8 clock だそうだ。どちらも出力しなくても 1 になるから オープンドレイン?

    ちなみに、信号は、posedge で出力、negedge で取り込み。

    次に 3 clock (S - R - T)づつの FRAME が続く。 IRQ15 までの 16 個かと思ったが、未定義を含めて 17個 - 32個分ある。(数は設定で決まる。)

ちょっとコードを書いてみた。

    module serirq_slave (
    input LCLK
    , input LRESET
    , inout SERIRQ

    , input [7:0] irq_req
    );

    reg [3:0] state;
    reg [1:0] sub_state; // S R T
    reg serirq_out;

    assign SERIRQ = serirq_out ? 1'b0 : 1'bz;

    always @(negedge LCLK)
    begin
    if (sub_state == 2'b01)
    begin
    if ((state == 4'h1) & (irq_req[0])) serirq_out <= 1'b1;
    else if ((state == 4'h2) & (irq_req[1])) serirq_out <= 1'b1;
    else if ((state == 4'h3) & (irq_req[2])) serirq_out <= 1'b1;
    else if ((state == 4'h4) & (irq_req[3])) serirq_out <= 1'b1;
    else if ((state == 4'h4) & (irq_req[3])) serirq_out <= 1'b1;
    else if ((state == 4'h5) & (irq_req[4])) serirq_out <= 1'b1;
    else if ((state == 4'h6) & (irq_req[5])) serirq_out <= 1'b1;
    else if ((state == 4'h7) & (irq_req[6])) serirq_out <= 1'b1;
    else if ((state == 4'h8) & (irq_req[7])) serirq_out <= 1'b1;
    else serirq_out <= 1'b0;
    end
    else if (sub_state == 2'b00)
    begin
    serirq_out <= irq_req[0] | irq_req[1] | irq_req[2] | irq_req[3]
    | irq_req[4] | irq_req[5] | irq_req[6] | irq_req[7]
    ;
    end
    else serirq_out <= 1'b0;
    end // always

    always @(posedge LCLK)
    begin
    if (LRESET)
    begin
    state <= 4'h0;
    sub_state <= 2'b00;
    end
    else if ((sub_state == 2'b00) & ~SERIRQ)
    begin
    state <= 4'h0;
    sub_state <= 2'b01;
    end
    else if (sub_state == 2'b00)
    begin
    state <= 4'h0;
    sub_state <= 2'b00;
    end
    else if ( (sub_state == 2'b01) & (state == 4'h0) & SERIRQ)
    begin
    state <= 4'h0;
    sub_state <= 2'b10;
    end
    else if ( (sub_state == 2'b01) & (state == 4'h0))
    begin
    state <= 4'h0;
    sub_state <= 2'b01;
    end
    else if ( (sub_state == 2'b11) & ~SERIRQ )
    begin
    state <= 4'h0;
    sub_state <= 2'b00;
    end
    else
    begin
    sub_state <= sub_state + 2'b01;
    end
    end // always
    endmodule


    簡単に説明すると、posedge LCLK で ステート制御。ステートは 3 の倍数で進むので 2 つに分けている。スタートビット検出をきっかけに進む。( 最初のスタートビットは、slave 側が作っている。)

    ストップビットは、2bit 目の 0 を検出したところで IDLE に戻る。

    sub_state は、0 → 1 → 2 → 3 → 1 → 2 → 3 と進む。0 になるのは IDLE だけ。

    master も状態制御は、同じようなもの。スタートストップビットの送出と irq_req が取り込みに変わる。

    冗長な書き方だが、14 スライス/27 LUT 。

LPC マザー

    LPC HOST をいくつか接続できるものを作ってみたい。

    HOST 毎に制御するデバイスが GPIO , SDIO , シリアル とか。共有するデバイスが LCD とか キーボードとか。

    あと入れたいのが、HOST 間通信。4 つ HOST が付けられるとしたら 12 個の FIFO でも実装可能か。
    共有を考えなければ簡単?

    ただ、そんなものを作るぐらいなら、SDIO という気も。

    ちょっとググってみると Posedge SDIO device controller (pdf) なんてものが見つかった。

    SD bus を AHB Bus に変換する IP。チップだと思ったら違った。

    中華Android / 中華PMP に使われている CPU(SoC) は、超低価格なのだが PCI みたいな バスは持っていない。最も高速なインターフェイスが USB device (640Mbps) で次が SDIO (〜 80Mbps x 4 とか) というパターンも多い。これになにかデバイスを付けようとすれば、SDIO のデバイスコントローラが欲しくなるのだった。

      S-ATA が付いているものもある。(Allwinner A10) 。Ethernet は一般的だが 100Mbps で上記より遅い。

    で、公開されている SDIO Simplifyed Specification を見てみた。

       I/O の方式は、SPI , 4bit-SD 以外に 1bit-SD がある。(これはメモリカードも同じ)

       割り込み(IRQ) は、DAT[1] を使うが 4bit-SD では、特定のタイミングでのみ有効(optional) 。詳細は削られている。

       DAT[2] にも Read Wait という機能が割り当てられている(optional)

       I/O 電圧変更は、SPI でも可能なようだ。

      SDIO は、基本的に CMD52(IO_RW_DIRECT), CMD53(IO_RW_EXTENDED) を使う。CMD52 は、レジスタアクセス+I/O 制御。CMD53 が I/O (サイズは 1-512B)

      レジスタ の仕様で 0-FF は、OCCR(Card Common Control Register) といって、いろいろ決まりごとがある。
      256B 単位で Function 1-7 の FBR(Function Basic information Registers) が続く。

      Function の定義には、USB の標準クラスのようなものがある。UART , BlueTooth Type A, BlueTooth Type B, カメラ, GPS, WLAN , SDIO-ATA など。

      CMD52,CMD53 以外で発行されうるコマンドは、

      CMD0 Pin1=High (CS=Low : SPI)
      CMD8
      CMD5 Arg=0 Get IO OCR
      CMD5 Arg=WV
      ACMD41 Arg=00 Get memory OCR (CMD58 : SPI)
      CMD3 (SD only)

      初期化シーケンスから拾ってきただけなので、詳細は知らない。ACMD41 はエラー(OCR invalid)になる。
posted by すz at 22:33| Comment(1) | TrackBack(0) | MachXO2

2012年03月10日

MachXO2コンフィグめも

MachXO2のコンフィグについてのメモ。

rtavr_tools で持っている FPGA の コンフィグが出来るようにしようと思っている。MachXO と LatticeXP2 は、一応書いてみたもの(ただし不動)があるが、MachXO2 は、ほぼこれから。

MachXO2 と MachXO , LatticeXP2 の違い

    MachXO , LatticeXP2 は、RAM にコンフィグするデータがそのまま FLASH に格納されている。ちょっと手続きとか コマンドとかが違うものの、RAM へのアクセスと FLASH へのアクセスを統合できる。jed データを元に RAM に書くこともできる。

    MachXO2 はというと FLASH のデータは圧縮されている。そのデータを FPGA 内部の伸張エンジンで RAM に展開している。伸張アルゴリズムは不明なので、自作の rtavr_tools では、jed は、FLASH のみが対象。

      ... と思ったが、実をいうと RAM への アクセスコードは、MachXO/LatticeXP2 とよく似ていて統合可能で、そういう風にコードは作っていた。

    ついでに書いておくと Xilinx は、FLASH がなく RAM に書くデータだけがある。このデータは SPI FLASH に書くデータと 同じ(bit のオーダーは違う) で、SPI FLASH に対応したとしても 1 種類の内部データで扱える。

    構想では、扱うデータはこんな分類になると思う

    internal FLASH RAM SPI FLASH file format
    Xilinx FPGA x O O bit,mcs
    MachXO,XP2 O O ? jed
    MachXO2 O x ? jed
    MachXO2(RAM) x O ? ? (サポートしない)

    O は作ろうと思っているもの。? は未定だが、やるとしても後回し。

MachXO2 のデータ と FLASH の 読み書き

    MachXO2 のデータには、以下の種類があり、それぞれ別の手続きになる。( () 内は、1200 のサイズ )

    • CFG データ (128bit x 2175 )
    • UFM データ (128bit x 512 )
    • USERCODE ( 32bit)
    • FEATURE (64bit)
    • FEABITS (16bit)

    FLASH は、128bit の column と 2688 の row からなっていて、USERCODE , FEATURE , FEBITS は 最後の row に入っている。UFM は、ユーザ回路で使えるが、CFG データがはみ出す場合がある。また、ブロック RAM の初期データも UFM に圧縮されない形で入っている。

  • CFG データ (128bit x 2175 )

    XO2_INIT_ADDRESS(0x46)
    SDR(0x04);
    idle(10ms)

    # 1 column 分
    XO2_PROG_INCR_NV(0x70)      XO2_READ_INCR_NV(0x73)
    SDR(128 bit)           idle( 1ms)
    idle( 0ms)  SDR(128 bit)           
    idle( 1ms)
    # check busy (10)
    XO2_CHECK_BUSY(0xF0)
    for (i=0; i&ft;10; i++)
    idle(1ms)
    if (SDR (1bit 0) == 0 ) break;


    read の場合、最初の row だけ XO2_INIT_ADDRES を発行し、SDR していく。PROGRAM の場合は、row 毎に XO2_INIT_ADDRES し、SDR 後 CHECK_BUSYする。
    コマンドは、SIR(8bit) コマンドの値は、MachXO2 独自のものがほとんど。

  • UFM データ (128bit x 512 )

    XO2_INIT_ADDR_UFM(0x47)
    idle(10ms)

    UFM の場合、最初の指定のみが変わる。PROG/READ の方法は同じ。

  • USERCODE ( 32bit)

    XO2_USERCODE(0xC0) XO2_USERCODE(0xC0)
    SDR (32bit) SDR (32bit)
    XO2_PROGRAM_USERCODE(0xC2)
    idle(10ms)

    # check status bit
    XO2_READ_STATUS(0x3C)
    idle(1ms)
    SDR (32bit) & 0x00003000 == 0


  • FEATURE (64bit)

    XO2_INIT_ADDRESS(0x46) XO2_READ_FEATURE (0xE7)
    SDR(0x02) idle(1ms)
    idle(10ms) SDR (64bit)

    XO2_PROG_FEATURE( 0xE4)
    SDR (64bit)

    # check busy (略)

  • FEABITS (16bit)

    XO2_PROG_FEABITS(0xF8) XO2_READ_FEABITS(0xFB)
    SDR (16bit) idle(1ms)
    idle(0ms) SDR (16bit)

    # check busy (略)


    これらを実行する前後で、初期化と後処理が必要。あと erase の手続きがある。


    # check IDCODE

     XO2_IDCODE(0xE0)
    SDR(32bbit) == 0x012B2043 (1200の場合)

    # Program Bscan register
    PRELAD(0x1C)
    SDR(208 bit: all 1 , 1200の場合)

    # enable flash
    XO2_ISC_ENABLE(0xC6)
    SDR(0x08)
    idle(10ms)

    (ここまで共通)
    --- erase ----

    # check status bit

    --- program/read

    (Write のみ , erase で実行しないこと)
    # Program DONE bit

    XO2_PROGRAM_DONE(0x5E)
    idle(0ms)
    # check busy (略)

    (ここから program/read 共通)
    # Exit the programming mode
    BYPASS(0xFF)
    XO2_ISC_DISABLE(0x26)
    idle(1000ms)

    BYPASS(0xFF)
    idle(0ms)

    erase 手続き

    XO2_ISC_ENABLE(0xC6)
    SDR(0x00)
    idle(10ms)

    XO2_ISC_ERASE(0x0E)
    SDR(0x01)
    idle(1000ms)

    BYPASS(0xFF)

    XO2_ISC_ENABLE(0xC6)
    SDR(0x08)
    idle(10ms)

    XO2_ISC_ERASE(0x0E)
    SDR(0x0E)

    # check busy (350)


    ちなみに、XP2 や MachXO も似ていると言えば似ている。ただ、共通化できるほどは似ていない。FLASH への書き込みでは UFM はないし、RAM と同じ column , row で書き込むのも違う点。

rtavr_tools への実装

    rtavr_tools の内部データは、ただの配列になっている。なので、次の順で格納するようにした。

    CFG 128bit x 2175 = 34800 bytes
    UFM 128bit x 512 = 8192 bytes
    FEATURE 64bit 8 bytes
    FEABITS 16bit 2 bytes
    USERCODE 32bit 4 bytes
    合計 43006 bytes

    デバイスによって CFG,UFM の row が変わるが これは 別にデータベースを持っている。Preload での bit 数も データベースに持つ。

      LCMXO2_1200.tgt_type = lscc
      LCMXO2_1200.device_type = 0x12B2
      LCMXO2_1200.address_size = 333
      LCMXO2_1200.data_width = 1080
      LCMXO2_1200.boundary_width = 208
      LCMXO2_1200.flash_col = 128
      LCMXO2_1200.flash_cfm_row = 2175
      LCMXO2_1200.flash_ufm_row = 512

      こんな形式で config ファイルを作っている。address_size , data_width は RAM の column , row。
      address_size, data_width, boundary_width は、BSDL ファイルに記載がある。
      flash_col, flash_cfm_row, flash_ufm_row は、SVF ファイルを生成すると分かる。( 他の記載は 信用できない。)

    作るべきプリミティブは、erase_flash_xo2 , write_flash_xo2 , read_flash_xo2 。サブルーチンとして xo2_check_busy(ループ数) と xo2_read_status() を作る。

    あと、FEABITS の jed ファイル読み込みが未対応。

rtavr_tools-0.8

  • rtavr_tools-0.8.tar.gz

    とりあえず、最新版。

    これは、MachXO2 用の コンフィグのコードを入れた版。デバッグ中のもの。

    FLASH への書き込みは、

      cmd> fl xxxx.jed
      cmd> w flash

    FLASH からの読み込みは、

      cmd> tl flash

    とかで出来ることを期待したのだが、全然ダメ。読み込みすらちゃんと動かない。

    RAM への読み書きは、以前に作ったコードが大分対応していたので、作ってみた。

      cmd> tl ram

    とすることで、なにやら読める。

      cmd> w ram

    で書き戻す操作になるのだが、ERASE はできるが、書き込みでエラーして ERASE された状態になる。
    ただし、電源を入れなおすことで、元に戻る。

      cmd> w flash

    FLASH についての ERASE も動くようだ。

RAM への コンフィグについてのメモ

    うまく動かないのであれこれ調べていたら、直接は関係ないことがいろいろ分かってきたのでメモしておく。

    SRAM Fast Program というのがあって、

    XO2_BITSTREAM_BURST(0x7A)

    というコマンドで書き込んでいる。このコマンドでは、どうも 圧縮 bit ファイル と 非圧縮 bit ファイル のデータの 2 種類を流し込めるようなのだ。たぶん、FLASH からのパスを利用しているのだろう。

    実際の bit ファイルとどういう関係にあるか調べてみた。
    非圧縮 bit ファイル のデータは、47371 バイトで、 XO2_BITSTREAM_BURST で送りこむデータは、47739 バイト。差分の 368 バイト分の 0xff を先行して 送り 非圧縮 bit ファイル のデータ を送っている。

    ついでに SRAMのデータ 44959 バイト(1080x333/8) と 非圧縮 bit ファイル のデータ の関係も調べてみた。


    0000: ff ff bd cd ff ff dc 00 00 00 ff ff ff ff ff ff
    0010: ff ff 62 00 00 00 41 07 80 b2 00

    非圧縮 bit ファイル は、このような 0x1A(26) バイトが先行して格納され、SRAMのデータ が続く。 残り は、2386 バイトだが、

    2e ce ff ff ff ff ff ff ff ff 43

    こういうデータで始まっている。ブロック RAM に 2KB の初期値を入れたので、2386 バイトのうち 2KB ? (2K x 9bit ?) 分の値もそのなかに含まれているはず。

    圧縮 bit ファイル のデータは、10170 バイト だった。XO2_BITSTREAM_BURST で書き込むデータは、84152 bit(10519 バイト) 349 バイトの差があるが、これも同様で、差分は、0xff が頭につく。

    0000: ff ff bd cd ff ff dc 00 00 00 47 00 00 00 80 d4
    0010: 04 c2 40 00 00 00 50 0a 0c c0 12 14 90 ff 44 00
    |
               :
    2790: fd fb f7 ef df bf 7f ff fe fd fb f7 ef df bf 7f
    27a0: ff fe fd fb f7 ef df bf 7f ff 44 00 00 00 02 00
    27b0: 00 00 7a 00 00 00 ff ff ff ff

    圧縮 bit ファイルはこんな風なデータ。非圧縮同様 0x1A バイトがヘッダなのかも知れない。

    さて、jed ファイルと 圧縮 bit ファイルは 同じなのか? というのが気になったので見てみると... 似ている感じだが、厳密には だいぶ違う。

    0000: ff ff bd cd ff ff dc 00 00 00 40 00 00 00 50 0a
    0010: 0c c0 12 14 90 ff 62 00 00 00 1d 07 80 b2 00 00
    :
    2790: fb f7 ef df bf 7f ff fe fd fb f7 ef df bf 7f ff
    27a0: 44 00 00 00 02 00 00 00 7a 00 00 00 ff ff ff ff

    そもそもヘッダーがちょっと違う。だが、最後は 同じっぽい。もっとも 非圧縮 bit ファイルも同様。

    最後の部分の最初だが、

    jed ファイル:
    1e60: 39 39 00 a4 c3 e7 e4 00 00 00 e9 ee
    1e70: ff ff ff ff ff ff ff ff 43 01 00 00 4a 2a 0c 8c
    1e80: 67 90 44 00 00 00 03 00 00 00 ff ff ff ff 6f 00
    圧縮 bit ファイル:
    1e50: 39 39 00 a4 c3 e7 e4 00 00 00 c8 cc ff ff ff ff
    1e60: ff ff ff ff 43 01 00 00 4a 2a 0c 8c 67 90 44 00

    こんな風にずれている。"e9 ee" と "c8 cc" は、たぶん CRC かチェックサム。ずれるルールは分からないが、ff が挿入されている感じ。

    ところで、圧縮 bit ファイルを生成するのは、意外にも簡単だった。制約ファイルに

    SYSCONFIG GENERATE_BITSTREAM=ENABLE ;

    この行を入れておけば良い。

    ... なんだか、XO2_BITSTREAM_BURST だけが動けば良いような気がしてきた。FPGA を汚さずにコンフィグできるし、ブロックRAM もちゃんと初期化できる(はず) 。しかも 圧縮したデータを一気に書くから高速にできる。SPI-FLASH への書き込みでは、それようの回路をコンフィグしないといけないのだが、実装の目処も立つ。

    bit ファイルの生成が面倒だと思っていたが、簡単ということも分かった。


    XO2_BITSTREAM_BURST

      これが動いた。圧縮 bit ファイル, 非圧縮 bit ファイル ともに OK 。それどころか、jed を読み込んだ内部形式のデータまで OK だった。

      重要なのは、最初に十分な数の 0xff を送ること と 正しいデータを続けて送ることのようだ。後にごみがあっても問題ない。verify はできないが、失敗すると初期化状態のままになる。


        cmd> fl test_hdl.bit
        Lattice Semiconductor Corporation Bitstream
        Version: Diamond_1.4_Production (87)
        Bitstream Status: Final Version 1.80
        Design name: MachXO2_Breakout_test_hdl_xo2.ncd
        Architecture: xo2c00
        Part: LCMXO2-1200ZE-1TQFP144
        Date: Thu Mar 15 23:49:02 2012
        Rows: 333
        Cols: 1080
        Bits: 359640
        Readback: Off
        Security: Off
        Bitstream CRC: 0xA2F6
        memory loaded size = 10170
        cmd> w ram
        Programming :################################################## 1.151 sec
        program success

      書き込みはわずか 1.151 秒。しかも ERASE の待ちが そのうちの 1 秒。

      bit ファイル のフォーマット

        ちょっと説明しておく。

        0xff 0x00 で始まり ストリング 0x00 がいくつか続く。最後に 0xff が来てここまでがヘッダ。その後は バイナリでデータが続くのだが、バイト内の ビットが反転 している。(bit0 ⇔ bit7)。

        もともと、Xilinx 用の bit ファイル の読み込みを作っていたのだが、自動判別して読み込むようにした。内部データは、ビットの反転を元に戻したもので、そのまま XO2_BITSTREAM_BURST(0x7A) にかけられる。


      書き込みは格段に早いが、RAM にしか書かないので、使用目的は主にテスト。複数の config を切り替えて動作を確認するとか...。あとは、仮の回路を組み付けるときに使う。ツールでは、SPI ライタのサポートで使うつもり。

      FLASH への書き込みは、コードは出来たものの全然だめなまま。目的は達したので、当面寝かせるかも。

    rtavr_tools-0.9

    • rtavr_tools-0.9

      最新版を置いておく。

      あと SPI FLASH への書き込みコードを作れば、コードだけは予定していたものをだいたい作ったことになる。自作 Xilinx ボード用のコードは形だけは入っている。

      次は、rtavr のデバッグに進もう。

    rtavr_tools-0.10

    • rtavr_tools-0.10

      最新版を置いておく。

      rtavr のデバッグを少し始めているのだが、なかなか。1回合成するのに、2 時間ぐらいかかるし。

      ちょっと息抜きに、SPI FLASH への書き込みコードを作ってみた。もとは、ATUSB162 で Mass Storage Class を作ったときのコードだが、移植というより書き直しになったので、ちょっとデバッグが必要そう。

      あと、SPI 用の HDL も作っておいた。手順的には、これをまず SRAM に書き込んで 仮コンフィグし、mcs ファイルを読み込んでSPI FLASH に書き込む。ただしオフセット 0 から書き込んでいるので、mcs ファイルによっては、アドレスがずれる。

      ちょっと MCS ファイルの調査:

      UFW で bit ファイルを MCS に 変換できる。0x000000 と 0x010000 という アドレスが表示されている。XO2 や XP2 は、0x010000 から ロードするので、0x010000 に Insert するようだ。

      *** dump ***
      0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
      *
      10000: aa 76 96 6e a6 4e ce 86 36 04 62 96 36 a6 04 ea
      10010: 4e 96 2e a6 4e 04 6a 4c 74 2c 1c 50 22 86 2e a6
      10020: 5c 04 2a 16 ae 04 0c cc f4 4c 4c f4 8c 4c 04 8c
      10030: 0c 5c ac 2c 5c ac ec 04 50 ff ff ff ff ff ff ff
      10040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
      *
      10150: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff bd
      10160: cd ff ff dc 00 00 00 47 00 00 00 80 d4 04 c2 40
      10170: 00 00 00 50 0a 0c c0 12 14 90 ff 44 00 00 00 02
      10180: 00 00 00 ff ff ff ff 62 00 00 00 1d 07 80 b2 00
      10190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

      できたファイルを 見てみるとこんな感じ。10150 からお馴染みの パターンが入っている。... jed ファイルと全く同じような ...

      その上は何かというと テキストなのだった。bit の MSB/LSB を反転すると ...

      Universal File Writer V2.48
      Date: Thu 03/22/12 5:54:57

      こんなようなデータが入っている。ごみはスキップして、ビットストリームだけ取り込んでくれるようだ。

      ところで.... 論理合成する時間が MachXO2 だけ圧倒的に長いことに気がついた。1200 だとぎりぎりなので遅いのかと思っていたのでは、そうではない。XO や XP2 は結構速い。

      ここまで MachXO2 でやったが、rtavr のデバッグの最初は、MachXO breakout を試してみようかと思っている。ただ、結構忘れてしまっている。

        rtavr_tool -p LCMXO2280

      rtavr_tool では、こんな風にチップ名を指定するようにしている。さて、XO の場合は、どこまで出来ていたのだっけか。

      まず、基本的な話から思い出す。

        XO は、flash と ram の構造が一致する。圧縮もない。さらに flash に書くデータと ram に書くデータは同じ。jed ファイルのデータと flash のデータも一致する。ただし、ram から読み込んだデータは、書き込んだデータとは一致しない。svf ファイルを見ても違うデータでベリファイしている。

      で、動作を確認したところ..

      • flash の erase は大丈夫。
      • flash の書き込みも 基本 OK なのだが、USERCODE が何故か一致しない。先頭が 0x00 になっってしまう。そのために config をエラーにしてしまっていた。USERCODE が不一致でも成功扱いにすることで、一応は flash に config できるようだ。
      • flash の read も OK 。正しいデータと jedから読み込んだ内部データは一致した。
      • ram への書き込みは、正しいかチェックできない。コンフィグした回路が動かないことから失敗しているようだ。

      まぁ、こんなところ。flash への操作はひと通り可能にしたので使えないことはない。

      これで、少しやるきが出た。まずは、MachXO2 と同じレベルまでもっていこう。
posted by すz at 12:47| Comment(0) | TrackBack(0) | MachXO2

2012年03月09日

MachXO2のJTAG通信

MachXO2 , MachXO ともに JTAG を通して SPI (のような方法)で通信できることになっている。MachXO2 breakout ボードでは、MPSSE で JTAG と接続されているから、理想的には、30Mbps までの速度での通信が可能。シリアルのように 外付けクロックにも依存しないからお手軽でもある。

  • LatticeXP2のFPGA回路内部へJTAGで通信する

    これは、XP2 に付いての記事だが、MachXO2もほぼ同じらしい。XP2 では、JTAGE を使うが、MachXO2 では、JTAGF , MachXO では、JTAGD を使う。

    /c/lscc/diamond/1.4/cae_library/synthesis/verilog/machxo2.v

    このあたりを見ると、インターフェイスがわかる。HOST 側での使い方はまったく同じ。

というわけで、通信しようとしているのだが、なかなか思うようにいっていない。何が間違いなのか分からなかったのだが ...どうも根本的なミスをしていたらしい。

    そもそも SPI は、双方の出力は同じタイミングで切り替わる。JTAG 経由の場合もそれは同じ。だから、8bit 目の SCK の立ち上がりで、入力処理をしたら、SCK が立ち下がるまでに次の出力処理も完了させなければならない。
    (補足: 普通に作ると出力が先行する。8 bit のデータを受け取る前に、出力を確定させないといけないが、そうはしたくないのが前提としてある。)

    だいたいが、そういう処理にしていなかった。だが、次の条件があり、なかなか面倒なのだ。

    上の記事には、SCK と MOSI は同時に変化するから、SCK の立ち上がりをトリガーにする 『@(posedge SCK)』 と MOSIは読み込めない。ようなことが書いてある。

で、困ったわけだが ... もっと高い周波数の CLK で 駆動して SCK MOSI ともにデータとして扱うことにした。(SCK はエッジを検出して処理)。もともと ISP として使いたいので、CLK が別にあるのが前提になるから、こうした方が都合がよい。

SCK と MOSI は同時に変化するので、SCK は、CLK でサンプリングして遅延させるようにする。具体的には、top モジュールで次のようにする。

    always @(posedge CLK)
    begin
    r_jtck_prev <= JTCK_IN;
    if (r_jtck_prev == JTCK_IN)
    r_jtck <= r_jtck_prev;
    end
    wire JTCK1 = r_jtck;
    wire JTDI = JTDI_IN;

JTCK_IN だけ ひとまず CLK で同期する。2 クロック連続で同じ値ならという論理なので、これだけで遅延されている。次に下位モジュールで、半クロックずらして処理をする。

    always @(negedge CLK)
    begin
    r_sck <= SCK;
    if (CS)
    :
    else if (~r_sck & SCK) // posedge SCK : INPUT
    begin
    入力処理
    :
    end
    end

これで、JTDI_IN の値は読めるはず。さて、SCK の立ち上がりですべてを行わないといけない 。これは次のようにした。

    else if (~r_sck & SCK) // posedge SCK : INPUT
    begin
    req_shift <= 1'b1;
    入力処理
    end
    else if (req_shift) // next
    begin
    req_shift <= 1'b0;
    :
    出力処理
    end

CLK を複数クロック使って 処理するわけだ。通信速度は、CLK の 1/10 以下でないとダメそうだが、CLKは普通 10 MHz 以上で、1Mbps 程度ならいける。
 
CLK
___ ___ ___ ___ ___ ___ ___ ___ ___
__| |___| |___| |___| |___| |___| |___| |___| |___| |___|

: : :
SCK : : :
_______________________________ ___
_____| |________________________________|


r_valid : : :
_________________________________________________________________
_________| |
: : :
r_req : : :
_______
_________| |_________________________________________________________
@ SPI_DATA_I input

これは、8bit 目を受け取ったときのタイミング。出力処理を他のモジュールで行うなら、CLK の立下りで 行うのが良さそう。

    always @(negedge CLK)
    begin
    if (SPI_DATA_REQ)
    r_data <= SPI_DATA;
    end
    assign SPI_DATA_I = r_data;

こんな風にして、エコーするだけのものは、動いた。(ラッチは必要なく、入出力をつないでも動く。)

実際の応用回路として、ISP を作ろうとしているのだが、こちらは、うまく動いてくれない。

SCK
___ ___ ___ ___ ___ ___ ___ ___
__| |___| |___| |___| |___| |___| |___| |___| |.....
: :
CS _______
|_____________________________________________________.....
: :
data
<bit7 ><bit6 ><bit5 ><bit4 ><bit3 ><bit2 > .....


随分長い間悩んでいたのだが、CS が L になってから 余計な 1bit があるのが原因だった。エコーするだけのものは ずれても問題ないのだが、通信できていると思い込んでいたのが敗因。


CLK
___ ___ ___ ___ ___ ___ ___ ___
__| |___| |___| |___| |___ .... __| |___| |___| |___| |___|

SPI_DATA_REQ
_______ _______
_________| |______________________ .... ___| |__________

r_req
_______ _______
_____________| |__________________ .... ______| |______

(a) (b) (c) (d)

コマンド データ

ISP のモジュールを設計しているのだが、こんな風に 2 バイト のデータ (コマンド , データ) 組みにしようとしている。処理のタイミングは それぞれ 2 つ作る。

(a) , (c) で 出力をラッチすると SPI_DATA_REQ の立下りで受け取られて 次の フェーズで HOST に出力される。(a), (b) で入力データを受け取ることが出来るが、(a) で解析してすぐに次のデータを決めるのは、タイミング的に厳しい。あらかじめ決めておいたデータを送ることにしよう。

といっても、アドレスが決まるのは、(c) でデータを受け取った後。演算する場合もあるので、(d) になる。

    ここで ISP の仕様を書いておく。

    // SSTPR 0110 100a PR[a] ( PR[0] : low byte of PR )
    // XXXX XXXX XXXX XXXX ( PR[1] : high byte of PR )
    //
    // SLD 0010 0I00 XXXX XXXX ( if I == 1 , PR = PR +1 )
    // XXXX XXXX load_data
    //
    // SST 0110 0I00 store_data ( if I == 1 , PR = PR +1 )
    // XXXX XXXX XXXX XXXX

    まぁたいしたことはない。ポインタをセットする命令と、ロード・ストアがあるのみ。


always @(posedge CLK)
begin
if (CS)
:
else
begin
r_req <= SPI_DATA_REQ;
(a) if (SPI_DATA_REQ & ~SPI_COUNT[0])
begin
r_data_out <= ISP_LOAD_DATA;
end
(b) if (r_req & ~SPI_COUNT[0])
begin
r_pr_inc <= f_pr_inc;
r_sstpr_hi <= f_sstpr_hi;
r_sstpr_lo <= f_sstpr_lo;
r_store <= f_store;
end
(c) if (SPI_DATA_REQ & SPI_COUNT[0])
begin
r_data_out[0] <= r_pr_inc;
r_data_out[1] <= r_load;
r_data_out[2] <= r_store;
r_data_out[3] <= 1'b1;
r_data_out[7:4] <= SPI_DATA[7:4];
end
(d) if (r_req & SPI_COUNT[0])
begin
if (r_pr_inc) r_pr <= r_pr + 1;
else if (r_sstpr_hi) r_pr[15:8] <= ISP_STORE_DATA;
else if (r_sstpr_lo) r_pr[7:0] <= ISP_STORE_DATA;
end
end

コードの一部を紹介するとこんな風になった。

ちなみに、コードで ISP_STORE_DATA となっているのは、SPI からの入力データで、ISP_LOAD_DATAは、メモリからの読み出しデータ。

f_pr_inc などは、デコードの結果。

HOST 側のコード

    HOST 側のコードは、随分前から用意してある。(rtavr_tools-0.x.tar.gz)。ちょっと解説。

    もともとは、Xilinx の自作ボード用として作っていたものだが、MachXO/MachXO2 にも一部対応。ISP を使ってプログラムメモリを書き換えるのと config の 両方の機能を想定している。

    MachXO2 は、FT2232H なので MPSSE が使えるのだが、FT232R でも使えるように Bitbang モードを使っている。

    使い方なのだが、少々くせがある。

    target_load タイプ [サイズ]

    これで、バッファに タイプで指定したものから読み込む。

    fpga_ram fpga_flash spi_flash rtavr_isp

    タイプには、以上のものを指定できるが、コードが出来ているのは、rtavr_isp のみ。

    erase タイプ
    program タイプ
    verify タイプ

    書き戻したり、ベリファイする場合は、こういう風に指定する。

    ファイルから読み込む場合は、次のコマンド。

    file_load [ファイルタイプ] file
    filetype: bit jed mcs mem

    MachXO2 に関係するのは、jed と mem 。isp の場合は、mem を使う。jed をコンフィグするコードも用意してあるが、未テスト。... というか未完成。

    mcs も読み込めはするが、SPI FLASH に書き込むには、先に専用の config を書きこまないとだめで、コードは全然。構想では、RAM のみ config して ... みたいなことを考えていたのだが ... MachXO2 では RAM 用のデータを用意するのが面倒そう。

    ちなみに、Xilinx も JTAG を通して通信することが可能。Xilinx 用のコードも入れてはあるのだが、実際に動かすのは随分先の話になりそう。

    他に テスト用のコードも入れてあって

    spi_test
    isp_test

    のコマンドがある。ついでなので、API に付いてもちょっと紹介。

    isp_test(TARGET tgt, CABLE cbl) {

    uint32_t s,r;

    jtag_reset(cbl);
    (tgt->sel_chan)(tgt, cbl, ISP_CHAN);

    s = (TPI_SETPR_LO << 8);
    jtag_SDR32R(cbl, s, 16, JTAG_RECV|JTAG_CONT, &r);
    :

    こんな感じで使えるようになっている。jtag_SDR32R が MSB first の SPI 通信で 32bit までを指定できる。JTAG_CONT は、最後に TMS を H にしないオプションで SPI 通信では必須。

    JTAG_RECVを指定しないと、戻り値不要。書き方も変わりバッファリングされる。

    tgt, cbl の初期化は、ちょっと面倒なので割愛。

rtavr_tools 最新版

  • rtavr_tools-0.7.tar.gz

    上記の内容に対応するコードを rtavr_tools 最新版として置いておく。


    rtavr_tools-0.7/
    /src -- HOST 側プログラム (MinGW , Linux 用)
    /rtavr_tools.exe -- プログラム 実行形式 (CUI)
    /test_hdl/ -- HDL ソース (tool_test.v , jtag_spi.v , isp.v)
    /out/test_hdl_xo2.jed -- MachXO2 breakout ボード用 (CLK 10 MHz)


    さて、これでようやく、ISP のベースが出来た。これがないと rtavr のデバッグが出来るような気がしなかった。ぼちぼち rtavr も実機でのデバッグを進めていこうと思う。

    あと、この ISP は、内部のメモリ(と アドレス可能なデータ)を読み書きするものでもある。調停がまだ出来ていないが、ロジアナとかフレームバッファの通信に応用できるはず。これをベースにしてなにか作ってみたい。

    fpga flash への 操作も できたほうが便利そうな気も。 開発のフェーズによっては、いちいち Diamond で書くのも面倒だろうし。プログラムとハードウェア(HDL) を入れ替えてデバッグしたりするとき なんかは役に立ちそう。ちなみに、fpga flash への 操作は、SVF を作って解析して作る。根気はいるが難しいことではない。気が向いたときでもやっておこう。

タイミング変更

    せっかく動かせたのだが、JTAG 通信の都合に合わせていったので、タイミングはやはり標準的なものではなくなっている。いずれは、rtavr の SPI モジュールに接続したりもしたいので、これでは困るのだ。それで、大胆な変更をあえて行うことにした。

    変更するのは以下のところ。

    • CS の遅延

      CS と通信開始までの 1 クロック(SCK) の空白は 困るので、CS を遅延させることにした。

    • 入力/出力のタイミング

      ISP 向けのコードを作って 入力 した後に 出力を確定できるという特徴は利用しなかった。タイミングが厳しくなるのが嫌なのが、その理由。そうであれば、出力先行で 普通のタイミングにした方が良い。それに合わせて SCK も反転させる。

    • SPI_DATA_VALID の有効化

      いままで SPI_DATA_REQ だけで制御してきたが、タイミングが全く変わるので SPI_DATA_VALID も 使うようにする。


    変更後 タイミング

    ___ __________________ _____
    SCK |___________________| |_________________|

    SPI_DATA_VALID: ____________________________________
    _______________________| |____

    SPI_DATA_REQ:
    _ _
    ___| |______________________________________________________| |__

    コードも随分変わったが、すんなり動かせた。今後は新方法に全面置き換え。以前のコードについて せっかく説明も書いたのだが、rtavr_tools-0.7 のみのコードになる(予定)。

付録: 外部 SPIデバイスとの通信

    `define TARGET_MachXO2
    //`define TARGET_MachXO
    //`define TARGET_LatticeXP2

    module spi_lattice (
    // JTAG
    input TOP_TDI
    , input TOP_TCK
    , input TOP_TMS
    , output TOP_TDO
    // EXTERNAL SPI PORT
    , output CS
    , output SCK
    , output SI
    , input SO
    );

    `ifdef TARGET_MachXO
    `define JTAG_BSCAN JTAGD
    OSCC osc_internal (.OSC(CLK)); // 18 MHz - 26 MHz
    `elsif TARGET_MachXO2
    `define JTAG_BSCAN JTAGF
    OSCH #(.NOM_FREQ("24.18")) osc_internal
    (.OSC(CLK), .STDBY(1'b0));
    `elsif TARGET_LatticeXP2
    `define JTAG_BSCAN JTAGE
    OSCE #(.NOM_FREQ("20.0")) osc_internal
    (.OSC(CLK));
    `endif

    `JTAG_BSCAN bscan (
    .JSHIFT(BSCAN_SHIFT)
    // .JRSTN(BSCAN_RESET) // H : in TestLogicReset State
    // , .JUPDATE(BSCAN_UPDATE)

    , .TDI(TOP_TDI)
    , .TCK(TOP_TCK)
    , .TMS(TOP_TMS)
    , .TDO(TOP_TDO)

    , .JTDI(JTDI_IN)
    , .JTCK(JTCK_IN) // negedge capt, posedge shift

    // signals for IPA
    , .JRTI1(JRTI1)
    , .JCE1(SEL1)
    , .JTDO1(JTDO1)

    // signals for IPB
    , .JRTI2(JRTI2)
    , .JCE2(SEL2)
    , .JTDO2(JTDO2)
    );

    reg r_jtck;
    reg r_jtck_prev;
    reg r_cs1;
    reg r_cs1_prev;
    reg r_cs2;
    reg r_cs2_prev;

    always @(posedge CLK)
    begin
    r_jtck_prev <= JTCK_IN;
    if (r_jtck_prev == JTCK_IN)
    r_jtck <= ~r_jtck_prev;
    if (r_jtck_prev & r_jtck & (r_jtck_prev == JTCK_IN)) // negedge JTCK
    begin
    r_cs1_prev <= ~(SEL1 & BSCAN_SHIFT);
    r_cs1 <= r_cs1_prev;
    r_cs2_prev <= ~(SEL2 & BSCAN_SHIFT);
    r_cs2 <= r_cs2_prev;
    end
    end
    wire JTCK1 = r_jtck;
    wire JTCK2 = r_jtck;
    wire JTDI = JTDI_IN;
    wire CS1 = r_cs1;
    wire CS2 = r_cs2;

    assign CS = CS1;
    assign SCK = JTCK1;
    assign SI = JTDI;
    assign JTDO1 = SO;

    endmodule

    たぶん、このコードで XO/XO2/XP2 で JTAG を通じて SPI デバイスと通信できる。XO2 で確認済みのコードをベースにしているのでたぶん大丈夫だろう。

    ちなみに、XP2 / XO2 だと SPI FLASH からのブートが可能。接続した SPI FLASH にプログラムするためには、こういったものを 一時的に config する必要がある。(バウンダリスキャンでも良いが遅い)

    XilinX も似た様なことは可能だが、内蔵クロックを使えないので、内蔵クロックを使わない やりかたに変更しないといけない。
posted by すz at 00:24| Comment(0) | TrackBack(0) | MachXO2

2012年02月23日

Lattice Diamond メモ

MachXO2 の論理合成をするには、Lattice Diamond というツールを使う。

使いこなしているとは到底言えないレベルだが、使い方とか分かったことを忘れないようにメモしていこうと思う。

テーマの選択

    ついでなので、どうやって 使うかを順に説明しておこうかと思う。サンプルとして何を作るかについては、乗算回路にしようと思う。32bit の CPU も作ってみたいのだが、乗算器のない MachXO2 でどれぐらいの規模になるのか見ておきたいのが理由。ちなみに MachXO2 は、LUT4 の代わりに 2b x 2b 乗算器にできる。単純な LUT4 よりは規模を縮小できそうな機能がある。

プロジエクトの生成

    "Start Page" という タブに Open とか New があるので、New をクリック。
    ダイアログが現れるので、例えば

      Project:
      Name: diamond_test1
      Location: D:/diamond/diamond_test1
      Implementation:
      Name: xo2
      Location: D:/diamond/diamond_test1/xo2

    と入力してみる。Next の ソースの追加はスキップ して "Select Device" で LCMXO2-7000ZE-1FTG256C になるように入力する。そうすると 左側の "File List" は次のようになる。

      実際に動かす場合、MachXO2 Breaout ボードなら、LCMX2-1200ZE-1TG144C を選ぶのだが、今回は、入出力を全部ポート に割り当てると 必要ポートが多すぎで Map できないケースが出る。動かすつもりもないので、大きな規模のものに変更。

      ちなみに、後で変更できるので、間違っても気にしなくて良い。



    この時点で作成されたファイルは、diamond_test1 をカレントディレクトリとして

      xo2/diamond_test1_xo2_summary.html
      diamond_test1.lpf
      diamond_test1.ldf
      Strategy1.sty
      diamond_test1.pty


ソースコードの追加

    "Input Files" を右クリックして、ソースコードを追加していく。新規ファイルは New を選ぶ。のでトップレベルから。

      module mult_test (
      input [31:0] DataA
      , input [31:0] DataB
      , input Clock, ClkEn, Aclr
      , output [63:0] Result
      );

      wire [63:0] Result;

      `define USE_PMI
      `ifdef USE_PMI
      pmi_mult #(.pmi_additional_pipeline(0)
      , .pmi_dataa_width(32)
      , .pmi_datab_width(32)
      ) MU (.DataA(DataA[31:0])
      , .DataB(DataB[31:0])
      , .Clock(1'b0)
      , .ClkEn(1'b1)
      , .Aclr(1'b0)
      , .Result(Result[63:0])
      );
      `else
      assign Result = DataA * DataB;
      `endif
      endmodule

    この内容を mult_test_pmi.v で生成すると、"Input Files" に xo2/source/mult_test_pmi.v が追加される。

    さて、pmi というのは、Parameterized Module Instantiation の略で、プリミティブのようなもの。ただし、定義したファイルを 追加しないといけない。

    Diamond をインストールするディレクトリは、lscc/diamond/1.4 のような階層になっているが、そこから pmi_mult.v を検索すると ...

    ./examples/MachXOBoard-SWDemo/Demo_MachXO2_Control_SoC/LatticeMico8_v3_1_Verilog/models/pmi/pmi_mult.v
    ./ispfpga/verilog/data/pmi/pmi_mult.v
    ./cae_library/simulation/verilog/pmi/pmi_mult.v

    の 3 つが見つかる。ispfpga と cae_library/simulation の 2 つは同じもので最新版。examples/MachXOBoard-SWDemo/Demo_MachXO2_Control_SoC に Mico8 が付属するのだが、最新版ではなく、pmi_mult.v も少し古い。(Mico8 自体を最新版にしても pmi は古い)

    ispfpga のやつを Add することにしよう。"Exsiting File" で 追加するのだが、"Copy file to ..." のチェックボックスにチェックする。

論理合成

    `define USE_PMI をコメントにして合成してみる。

    "Process" のタブを選んで実行していくと次のような画面になる。
    (実際に動かす場合は、JEDEC file にチェックして作成する。その後は、Tools の Programmer で)



    出来たところで、Map の Design Summary を見てみると次のようになった。

    Design Summary
    Number of registers: 0
    PFU registers: 0
    PIO registers: 0
    Number of SLICEs: 581 out of 3432 (17%)
    SLICEs(logic/ROM): 581 out of 858 (68%)
    SLICEs(logic/ROM/RAM): 0 out of 2574 (0%)
    As RAM: 0 out of 2574 (0%)
    As Logic/ROM: 0 out of 2574 (0%)
    Number of logic LUT4s: 36
    Number of distributed RAM: 0 (0 LUT4s)
    Number of ripple logic: 563 (1126 LUT4s)
    Number of shift registers: 0
    Total number of LUT4s: 1162
    Number of PIO sites used: 128 out of 207 (62%)

    581 スライスも使っている。1200ZE なら全部で 640 スライスしかないから、これでは使い物にならない。

    次に `define USE_PMI を有効にして再度 合成してみる。

    Design Summary
    Number of registers: 0
    PFU registers: 0
    PIO registers: 0
    Number of SLICEs: 64 out of 3432 (2%)
    SLICEs(logic/ROM): 64 out of 858 (7%)
    SLICEs(logic/ROM/RAM): 0 out of 2574 (0%)
    As RAM: 0 out of 2574 (0%)
    As Logic/ROM: 0 out of 2574 (0%)
    Number of logic LUT4s: 64
    Number of distributed RAM: 0 (0 LUT4s)
    Number of ripple logic: 0 (0 LUT4s)
    Number of shift registers: 0
    Total number of LUT4s: 64
    Number of PIO sites used: 64 out of 207 (31%)

    64 スライスと規模が小さいのだが、PIO を 64 しか使っていない。どうも 16bit 乗算までで .pmi_dataX_width になにを書いても良いというわけではないようだ。失敗。

    失敗はしたが、16bit 乗算はどうも 64 LUT らしい。2b x 2b が 1LUT なら 4b x 4b が 4LUT 、8b x 8b が 16LUT となって 16b x 16b は 64LUT 。そうであれば、うまく作れれば 32b x 32b は 256 LUT 。ただし今のところうまく作れない。

    実際にうまく作れたとしても、1 クロックで 32bit 乗算をするのが現実的なのかどうか... やはり 乗算器がある FPGA に乗り換えるのが現実的に思える。MachXO2 で、なんとかするとしても テストぐらいにしておいた方が無難そうだ。

      MachXO2 Breakout ボードは気軽に使えて便利なのだ。使えるものなら使いたい。TQFP 144 の 1200ZE と 7000ZE ならピンコンパチだと思うので、載せ替えが可能なはず。載せ替え出来れば 回路的には余裕。ただ性能が出せないので、テストぐらいしか使えないと思う。テストなら無理して 最適化する必要もないし、すなおなコードで十分。

    大体分かったので、今回はこれぐらいにしておこう。

プロジェクトのtarball

    ところで、一旦 合成すると非常に多数のファイルが作成される。Make clean 相当のことをして 再現するのに最低限のファイルのみにして tarball にしたいのだが、どうしたら良いのだろう?
    一応 *.* xo2/source xo2/*.html でファイルを指定すると ...

      Strategy1.sty
      diamond_test1.ldf
      diamond_test1.lpf
      diamond_test1.pty
      xo2/source/
      xo2/source/mult_test_pmi.v
      xo2/source/pmi_mult.v
      xo2/diamond_test1_xo2_mrp.html
      xo2/diamond_test1_xo2_pad.html
      xo2/diamond_test1_xo2_par.html
      xo2/diamond_test1_xo2_summary.html
      xo2/diamond_test1_xo2_synplify.html

    これを違うディレクトリにもっていって Project を Open することは出来た。

    ただし、Input Files は、再指定しないといけない。( xo2/source にあるファイルを全指定するので、楽ではある)。あと、html ファイルは、summary 以外 report では、見ることができない。ブラウザなどで見ないといけないのだが、最後の状態が残っているので セーブする意味はあるだろう。

      追記:
      reportview.xml も 作成されていたので、これも セーブ。あと xo2/*.prf (Preference File) もセーブすれば良いみたい。


    ところで、Implementation とは何だろう? プロジェクトに対して右クリックで "New Implementation" を Add できるから 、いくつもの バージョンを持てるようだ。ただ、lpf とかは共有しているから 『同じハードウェアに対するもの』 というのが前提らしい。

    さらに言うと、同じトップディレクトリに 多数のプロジェクトを置いたらどうなるのだろう?

    Strategy1.sty は共有されるが、一応は置くことができる。Implementation を同じにしても プロジェクト名+Implementation で主なファイルが作られているから 整合性は問題なさそう。

    こういうことを前提にして、どうプロジェクトを組み立てたら良いか考えてみよう。

プロジェクトの構成

    いま、MachXO Breakout ボード と MachXO2 Breakout の 2 つのボードを持っている。それぞれに対して、rtavr の バリエーションがいくつか考えられる。(ただし ソースコードは共有)。また、全然違うソースのテスト用コードがある。

    ひとつの Top ディレクトリに 構成していくとするならどうしたら良いか。今の案を書いてみる。

    • まず、Top に rtavr と rtavr_tools のソースコードを展開する。いくつかの例外を除いて、この ソースコードを Copy せずに 使うことにする。

    • 例外とは、Include するファイル。rtavr だと rtavr_defs.v , rtavr_common.v , rom_data.mem の 3 つ。これらは、Implementation/source にコピーして使う。

        注意) Include するパスは、ソースを Add する前に 定義しておかないと面倒なことになる。Implementation名の Properties で 指定しておく。

        あと、ソースと同じディレクトリにあるファイルの方が優先されるので、都合が悪い場合は、ソースの方もコピー指定が必要。

    • プロジェクト名は、ボード名を元にしたものにする。この先に Implementation をぶらさげる。( Implementation はボード名が違えば 別名になるようにする。)

    とりあえず ...

    (Project) (Implementation)
    MachXO2_Breakout --- rtavr_isp_xo2
    +- test_hdl_xo2

    MachXO_Breakout --- rtavr_isp_xo
    +- test_hdl_xo

    こういう風に構成できるようにしてみよう。



    お、なんかできた。Implementation は、いずれか1つを Active にして使うようだ。

    ソース(rtavr-0.9.5.tar.gz , rtavr_tools-0.6.tar.gz) を除いて tarball にしてみたところ 4MB になった。これを違うマシンの パスが違うディレクトリに作成しなおしても 大丈夫のようだ。

    ただ、調子に乗って Implementation を作ってしまうと tarball が どんどん大きくなってしまう。

      プロジェクト名.*
      reportview.xml
      Strategy1.sty
      インプリテーション名/*.prf
      インプリテーション名/*.html
      インプリテーション名/source

    だけをセーブすると 100KB 程度と随分小さくなった。再ビルドも出来るみたいだし、プロジェクトのバックアップは これのみにしよう。

  • rtavr_diamond-sample.zip (2012/2/25 更新)

    プロジェクトのサンプルを ここに置いておく。(動かすためのものではなく、論理合成の確認用として) 今の最新版の rtavr と rtavr_tools も入れてある。

Warningのチェック

    例えば rtavr_isp_xo2 を合成すると Synthesis Design だけでも 相当な Waring が出る。これをチェックすることにした。

    まず、連鎖的に Waring になるものがある。とりあえずそれを除いて整理してみる。

      s/".*\\rtavr-0.9.5\\/"/
      /enable tied to GND/d
      /Undriven input .*, tying to 0/d
      /Found undriven nets .*, mapper will optimize them/d

    こんな sed スクリプトで、何種類かのものを削除。あとファイルのパスが長すぎるので 相対パスに変換。


      @W: MT420 |Found inferred clock xo2_isp|CLK0_OUT_inferred_clock with period 1000.00ns. Please declare a user-defined clock on object "n:CLK0_OUT"


    クロックの定義が必要らしい。JTM08_007(Spreadsheet ViewでのConstraint設定),JTM08_010(タイミング制約および検証に関する注意事項) を読んでも正直良く分からない。

      とりあえず、PLL 出力で位相差がある場合は、ちゃんと計算してくれることは分かった。ただ、この Warning が出るということは、周波数は計算してくれないようだ。全部に 同じ周波数を設定してやれば良いのだろうか?

      さて、CLK0_OUT_inferred_clock とは何だろう? コード上は、CLK0_OUTで 余計なサフィックスは付いていない。しかも、"n:CLK0_OUT" という別の名前が出ている。これで随分混乱している。

      いろいろやってみると、Spreadsheet View を使うと設定したものを 制約ファイル(lpf) に書いてくれる。あと、Synplity Pro と LSE では、設定が違うようだ。

      ちなみに、Spreadsheet View は、Translate Design が終わらないと設定変更できない。また、制約ファイル(lpf)は、 # でコメントを書けるようだ。

    なにをやっても埒があかない。ひょっとして、制約は基本 LSE 用であって、Synplity Pro 向けでは制限があるのかも。

      追記: JTM08_005(SynthesisのStrategy設定と制約記述) の 30p あたりから説明があった。少し分かってきているが、当面 LSE を使うつもり。

    クロックに関係する他の Warning で要チェックなもの。

      @W: MT462 :"soc\rtavr_rom_4p.v":110:16:110:67|Net RTAVR.ROM.CLK_B appears to be an unidentified clock source. Assuming default frequency.
      @W: MT462 :"soc\rtavr_rom_4p.v":156:18:156:31|Net RTAVR.ROM.CLK_L appears to be an unidentified clock source. Assuming default frequency.
      @W: MT462 :"soc\rtavr_sram.v":80:20:80:57|Net RTAVR.RAM.CLK_90_270 appears to be an unidentified clock source. Assuming default frequency.

    これらは、特殊なことをしているので、クロックとして認識されてしまう。READ と WRITE でタイミングを変えたり、 1クロックに 2 回アクセスしていたりする。

      @W: CG532 :"isp_sample\isp.v":215:4:215:10|Initial statement will only initialize memories through the usage of $readmemh and $readmemb. Everything else is ignored
      @W: CG532 :"soc\rtavr_rom_4p.v":283:2:283:8|Initial statement will only initialize memories through the usage of $readmemh and $readmemb. Everything else is ignored

    rom では、$readmemh 使っているのだが、まだ出る。rom_data.mem のサイズが違うのかとも思ったが合っていた。要調査。

    isp では、initial 文を register の初期値に使っていた。

    reg r_cs = 1'b0;

    の記述方法で書き換えると消えはする。

      @W: FX474 |User specified initial value found in some of the sequential elements in the design. Applying an initial value to a register may not deliver the best synthesis results. For example, registers with initial values may be preserved and retiming/pipelining may not be performed. To improve synthesis results you may want to remove the register initialization from the RTL code

    この諭すような、Waring は何なのだろう? とりあえずパス。

    これでもまだ多数の Warining が残る。だが、かなりの部分は規模を減らすオプションの結果。

      `define IOR_SPHBITS 2 // SPH bits 1-8 (-15 slices)

    例えば、スタックポインタの上位ビットを定数化するオプションを入れると ...

      @W: CL189 :"soc\rtavr_ior_ps.v":403:4:403:9|Register bit r_sph[2] is always 0, o
      ptimizing ...
      @W: CL189 :"soc\rtavr_ior_ps.v":403:4:403:9|Register bit r_sph[3] is always 0, o
      ptimizing ...
      @W: CL189 :"soc\rtavr_ior_ps.v":403:4:403:9|Register bit r_sph[4] is always 0, o
      ptimizing ...
      @W: CL189 :"soc\rtavr_ior_ps.v":403:4:403:9|Register bit r_sph[5] is always 0, o
      ptimizing ...
      @W: CL189 :"soc\rtavr_ior_ps.v":403:4:403:9|Register bit r_sph[6] is always 0, o
      ptimizing ...
      @W: CL189 :"soc\rtavr_ior_ps.v":403:4:403:9|Register bit r_sph[7] is always 0, o
      ptimizing ...
      @W: CL279 :"soc\rtavr_ior_ps.v":403:4:403:9|Pruning register bits 7 to 2 of r_sp
      h[7:0]
      @W: CL246 :"soc\rtavr_ior_ps.v":56:18:56:22|Input port bits 15 to 10 of SP_IN[15
      :0] are unused

    これだけの Warning になるのだ。この手のものは、フル機能にすることでのみ Waring が消える。

    面倒だが、上の sed スクリプトを増強して、分かっているものを消していくのも手か。


      s/".*\\rtavr-0.9.5\\/"/
      /enable tied to GND/d
      /Undriven input .*, tying to 0/d
      /Found undriven nets .*, mapper will optimize them/d
      /rtavr_ior_ps.*Pruning .* r_sph/d
      /rtavr_ior_ps.*Register bit r_sph.[0-7]. is always 0, optimizing/d
      /rtavr_ior_ps.*Input port bits [0-9]* to [0-9]* of SP_IN.[0-9:]*. are unused/d
      /rtavr_ior_usart.*Pruning bit [0-9]* of rx_ps.* -- not in use/d
      /rtavr_ior_usart.*Pruning bit [0-9]* of tx_ps.* -- not in use/d
      /rtavr_ior_usart.*Pruning bits [0-9]* to .* rx_data.* -- not in use/d
      /rtavr_ior_usart.*Pruning bit [0-9]* of tx_data.* -- not in use/d
      /rtavr_ior_usart.*Pruning register bit 1 of r_count_max_x/d
      /rtavr_ior_usart.*Pruning register rx_parity/d
      /rtavr_ior_usart.*Register bit UPE is always ., optimizing/d
      /rtavr_ior_usart.*Register bit r_count_max_x.1. is always ., optimizing/d
      /rtavr_ior_usart.*Removing register 'RXB8' because/d
      /rtavr_ior_usart.*Removing register 'TXB8' because/d
      /rtavr_ior_usart.*Input WE_ubrrl is unused/d
      /rtavr_ior_usart.*Input WE_ucsrc is unused/d
      /rtavr_ior_usart.*Input WE_ubrrh is unused/d
      /rtavr_ior_usart.*Input XCK_IN is unused/d
      /rtavr_ior_usart.*Input XCK_DDR is unused/d
      /rtavr_ior_timer0.*Pruning register bit.* of r_prescaler/d
      /rtavr_ior_timer0.*Input WE_ocr0b is unused/d
      /rtavr_ior_timer0.*Input WE_ocr0a is unused/d
      /rtavr_ior_timer0.*Input WE_tccr0a is unused/d
      /rtavr_ior_port.*Input WE_pin is unused/d
      /rtavr_ior_port.*Input DI_pin is unused/d
      /rtavr_ior_spi.*Input SS_DDR is unused/d
      /rtavr_ior_spi.*Input MISO_IN is unused/d
      /rtavr_ior_spi.*Pruning register r_count_en/d
      /rtavr_ior_spi.*Pruning register r_ps/d
      /rtavr_ior_spi.*Input WE_spsr is unused/d
      /rtavr_rom_4p.*Pruning bit.* of r_addrb/d
      /rtavr_rom_4p.*Input port bit.* of ADDRA.* is unused/d
      /rtavr_rom_4p.*Input port bit.* of ADDRB.* is unused/d
      /rtavr_rom_4p.*Input OEA is unused/d
      /rtavr_s1_decode.*Pruning register r_wdr/d
      /rtavr_sram.*Pruning bit.* of r_addrb/d
      /rtavr_sram.*Input port bit.* of ADDRB/d


    十分ではないが、だいぶ見やすくなった。

      @W: CL157 :"soc\rtavr_ior_ms.v":71:18:71:20|*Output DDR has undriven bits -- simulation mismatch possible.
      @W: CL157 :"soc\rtavr_ior_ms.v":72:18:72:21|*Output PORT has undriven bits -- simulation mismatch possible.
      @W: CL246 :"soc\rtavr_ior_ms.v":73:18:73:20|Input port bits 15 to 0 of PIN[23:0] are unused
      @W: CL118 :"soc\rtavr_rom_4p.v":163:1:163:2|Latch generated from always block for signal r_doa[15:0]; possible missing assignment in an if or case statement.

    残ったのには、こんなものがある。チェックしていかないと。

    上 3 行の port 関係だが、

    // external I/O
    , output [23:0] DDR
    , output [23:0] PORT
    , input [23:0] PIN

    パラメータにこういう定義をしておいて、PORTC/PORTB/PORTA に割り当てている。PORTB/PORTA を有効にしていないので、ビット 15 - 0 が未定義のまま。上位レイヤーも 未定義な bit は使わない。

    これでも良いかということにしたのだが、論理合成では問題ないものの、Active-HDL でまずいかも ... ということか。
    下のやつは、これ。

    `ifdef ROM_USE_LATCH
    `ifdef SYS_DRIVEN_CLK4PH
    wire CLK_L = CLK_180 | OEB;
    `else
    wire CLK_L = CLK | OEB;
    `endif

    always @(ROM_DO_AB or CLK_L)
    begin
    if(~CLK_L) r_doa <= ROM_DO_AB;
    end
    assign DOA = r_doa;
    `else

    ROM_USE_LATCH というローカル define を有効にしていて、正に ラッチを作ろうとしている。遅延の最適化がそうした理由だった。まぁ目的どおりだから良いのかな?

LSEに切り替え

    デフォルトが Synplify Pro だったので、そちらがお薦めなのかと思って使っていたが、残念なことに良くわからない。 Tools に Synplify Pro for lattice なんてのがあって、これを立ち上げると、Diamond と同じような window が出てくる。Synplify Pro 専用の制約ファイル(sdc)なんてのもあるようだし、上記の "n:CLK0_OUT" とかは、その制約ファイルで使うものらしい。

    お気軽に使うのなら、LSE の方が良さそうに思えてきたので、合成ツールを 切り替えることにした。


      Preference Summary

      FREQUENCY NET "CLK_INT" 2.080000 MHz (0 errors)
      FREQUENCY NET "CLK_IN0" 24.000000 MHz (0 errors)

      FREQUENCY NET "CLK0_OUT" 33.000000 MHz (4096 errors)
      4096 items scored, 4096 timing errors detected.
      Warning: 12.772MHz is the maximum frequency for this preference.

      FREQUENCY NET "CLK90_OUT" 33.000000 MHz (1024 errors)
      2395 items scored, 1024 timing errors detected.
      Warning: 14.775MHz is the maximum frequency for this preference.

      FREQUENCY NET "CLK180_OUT" 33.000000 MHz (1726 errors)
      4096 items scored, 1726 timing errors detected.
      Warning: 15.232MHz is the maximum frequency for this preference.

      FREQUENCY NET "CLK270_OUT" 33.000000 MHz (737 errors)
      4096 items scored, 737 timing errors detected.
      Warning: 19.077MHz is the maximum frequency for this preference.

      FREQUENCY PORT "EXTOSC" 24.000000 MHz (0 errors)
      Report: 150.150MHz is the maximum frequency for this preference.

      PERIOD PORT "TOP_TCK" 0.100000 nS (1 errors)
      0 items scored, 1 timing error detected.

    LSE を使ったらクロックの設定が認識された。33 MHz にしてみたが、それは無理そうだということも分かった。まぁ HE と中身が同じなら 4 グレードレベル程度まではオーバクロック出来そうな気もするが。

    ちなみに Strategies を Space に変更した上で、GPR_16 を有効にして スペースを稼ぐ設定にしたから最遅
    という条件。

      "CLK0_OUT": 18.491MHz is the maximum frequency

      4 グレードの HC でやってみたらこうなった。ざっと 1.5 倍か。

      strategies を Strategy1 に戻し、GPR_16 も無効にすると 20 MHz ぐらい。

      FREQUENCY NET "CLK0_OUT" 22.000000 MHz (0 errors)
      Report: 25.938MHz is the maximum frequency for this preference.

      FREQUENCY NET "CLK90_OUT" 22.000000 MHz (0 errors)
      Report: 28.073MHz is the maximum frequency for this preference.

      REQUENCY NET "CLK180_OUT" 22.000000 MHz (0 errors)
      Report: 32.356MHz is the maximum frequency for this preference.

      FREQUENCY NET "CLK270_OUT" 22.000000 MHz (0 errors)
      Report: 29.255MHz is the maximum frequency for this preference.

      さらに、22 MHz で制約を変更すると 25.9 MHz 。

rtavr_diamond-sample.zip(2012/2/25 更新) を試す

    大分脱線してしまったが、すぐ試せるものをリリースできるかどうかは、重要だ。それにクロックも。どれぐらいで動くものなのか知らないと動かすのが難しい。

    さて、上記のものを展開して、MachxO2_Breakout.ldf を open すると test_hdl_xo2 がターゲットの インプリメンテーションになっている。

    project の JEDEC File にチェックを付け、ダブルクリックをすると ... なにやら出来上がる。

    で、programmer で書き込みしようとすると、xcf ファイルがないと言われてエラーになる。この場合は、Scan 実行すると xcf ファイルが生成されて オペレーションが出来るようになる。(Check XCF File だったかも)

    動かしてみると ... LED0/1 と LED 2-5 が 1 秒毎ぐらいで点滅し、LED 2-5 の点滅が遅れて ずれるために光が流れるような動きをする。これが予定通りの動き。

    warning について

    沢山 warning が出るのだが、

      OSCH 'osc_internal' has mismatching FREQUENCY preference value of 2.08 MHz and NOM_FREQ value of 24.18 MHz.

    まず気になるのはこれ。24.18 MHz だと 1 秒ぐらいの点滅間隔なので、コードに書いた NOM_FREQ が有効のようだ。

    2.08 MHz というのは、デフォルトで勝手に設定される。Spread sheet View の Timing Preferences で NET "CLK" を modify するか、制約ファイル(lsf)に

    FREQUENCY NET "CLK" 24.180000 MHz ;

    を追加するかすれば、直るはず。


      ERROR - <E0055> Port 'TXD' is unconnected.
      ERROR - <E0055> Port 'RXD' is unconnected.

    なんてエラーが出る場合がある。これは、rtavr と同じ制約ファイルを使っているため。# でコメントすれば一応は出なくなる。ただ、インプリメンテーションを変更する毎にいちいち編集はしてられない。

    さて、

      WARNING - trce: Output clock frequency on pin CLKOP of pll is 12.0 MHz, whichwith divider 16, requires internal VCO frequency to be 192.0 MHz ( 12.0 MHz x 16), outside VCO valid range [400, 800] MHz.

    この手の warning がやたら出てうるさい。


      FREQUENCY NET "CLK" 24.180000 MHz ;
      FREQUENCY NET "CLK_IN0" 24.000000 MHz ;
      FREQUENCY NET "CLK0_OUT" 24.000000 MHz ;
      FREQUENCY NET "CLK90_OUT" 24.000000 MHz ;
      FREQUENCY NET "CLK180_OUT" 24.000000 MHz ;
      FREQUENCY NET "CLK270_OUT" 24.000000 MHz ;
      FREQUENCY PORT "EXTOSC" 24.000000 MHz ;
      FREQUENCY PORT "TOP_TCK" 0.100000 MHz ;

    まずは、制約ファイル。一応近い値にしてやる。これだけだと 400 MHz 以下なので、too_test.v の

    , .CLKOP_DIV(32)
    , .CLKOS_DIV(32)
    , .CLKOS2_DIV(32)
    , .CLKOS3_DIV(32)

    CLKOP_DIV 等の値を全部 2 倍の 32 にすると 見事消えてくれる。

    これで、Warning は随分見やすくなる。

      WARNING - synthesis: logical net 'TXD' has no load
      WARNING - synthesis: input pad net 'TXD' has no legal load
      :
      WARNING - map: input pad net 'TXD' has no legal load
      WARNING - map: input pad net 'RTS' has no legal load
      WARNING - map: input pad net 'DTR' has no legal load
      WARNING - map: input pad net 'RXD' has no legal load
      WARNING - map: input pad net 'CTS' has no legal load
      WARNING - map: IO buffer missing for top level port TXD...logic will be discarde
      d.
      :

    これは、top モジュールの引数に書いてあるのに使っていないため。エラーになることはないので無視。

      WARNING - synthesis: logical net 'clk_count1_113_add_4_1/CI' has no driver
      WARNING - synthesis: logical net 'clk_count1_113_add_4_1/S0' has no load
      WARNING - synthesis: logical net 'clk_count2_114_add_4_25/CO' has no load

    これは、加算器のキャリー関係。明示的に記述もしてないし、勝手に作られて、勝手に消される。これも無視。/CI /CO /S0 /S1 あたりが対象。

    こうやって直していくのは良いのだが ... インプリメンテーションを変更した時どうするのが良いのだろう?

    lpf ファイルは、複数持てる。で、インプリメンテーション同様に 1 つをアクティブにするという使いかたをする。よく分からなかったのだが、JTM08_002(プロジェクト管理) 29p あたりに書いてあった。

付録

    どこでどんなファイルを使っているか、抜けはあると思うがまとめてみた。

    synpwrap: Synthesize Design (Synplify Pro)
    MachXO2_Breakout_test_hdl_xo2_synplify.tcl
    MachXO2_Breakout_test_hdl_xo2.srf
    synlog/MachXO2_Breakout_test_hdl_xo2_premap.srr
    synlog/MachXO2_Breakout_test_hdl_xo2_fpga_mapper.srr
    MachXO2_Breakout_test_hdl_xo2.srm

    edif2ngd:
    MachXO2_Breakout_test_hdl_xo2.edi
    MachXO2_Breakout_test_hdl_xo2.ngo

    ngdbuild:
    MachXO2_Breakout_test_hdl_xo2.ngo
    MachXO2_Breakout_test_hdl_xo2.ngd

    synthesis: Sythesize Design (LSE)
    MachXO2_Breakout_test_hdl_xo2_lattice.synproj
    MachXO2_Breakout_test_hdl_xo2.ngd

    map: Map Design
    MachXO2_Breakout_test_hdl_xo2.ngd
    MachXO2_Breakout_test_hdl_xo2_map.ncd
    MachXO2_Breakout_test_hdl_xo2.prf
    MachXO2_Breakout_test_hdl_xo2.mrp

    mpartrce:
    MachXO2_Breakout_test_hdl_xo2.p2t
    MachXO2_Breakout_test_hdl_xo2.p3t

    MachXO2_Breakout_test_hdl_xo2.pt
    MachXO2_Breakout_test_hdl_xo2_map.ncd
    MachXO2_Breakout_test_hdl_xo2.ncd

    par: Place & Route Design
    MachXO2_Breakout_test_hdl_xo2.p2t
    MachXO2_Breakout_test_hdl_xo2_map.ncd
    MachXO2_Breakout_test_hdl_xo2.dir
    MachXO2_Breakout_test_hdl_xo2.prf

    # Dumping design to file MachXO2_Breakout_test_hdl_xo2.dir/5_1.ncd.

    trce: Place & Route Trace
    MachXO2_Breakout_test_hdl_xo2.pt
    MachXO2_Breakout_test_hdl_xo2.twr
    MachXO2_Breakout_test_hdl_xo2.ncd
    MachXO2_Breakout_test_hdl_xo2.prf

    iotiming: I/O Timing Analysis
    MachXO2_Breakout_test_hdl_xo2.ncd
    MachXO2_Breakout_test_hdl_xo2.prf

    bitgen: Export Files (JEDEC File)
    MachXO2_Breakout_test_hdl_xo2.t2b
    MachXO2_Breakout_test_hdl_xo2.ncd
    MachXO2_Breakout_test_hdl_xo2.prf (Preference File)
    MachXO2_Breakout_test_hdl_xo2.jed

参考資料

  • Lattice Diamond 1.3 マニュアル

    JTM08_001 インストールとライセンス設定
    JTM08_002 プロジェクト管理
    JTM08_003 GUIのカスタマイズと環境設定
    JTM08_004 デザインフローとRun Mangerによる並列処理
    JTM08_005 SynthesisのStrategy設定と制約記述
    JTM08_006 Translate DesignのStrategy設定と注意点
    JTM08_007 Spreadsheet ViewでのConstraint設定
    JTM08_008 Package Viewによるピンアサイン
    JTM08_010 タイミング制約および検証に関する注意事項
    JTM01_009 SSO Analyzerユーザーマニュアル
    JTM08_012 Map DesignのStrategy設定と注意事項
    JTM08_015 Map Traceとシミュレーション
    JTM08_013 Place & Route DesignのStrategy設定と注意事項
    JTM08_016 Place & Route TraceとI/O Timing Analysis
    JTM05_001 Power Calculatorユーザマニュアル
    JTM08_018 シミュレーション・ユーザガイド
    JTM08_014 書き込みデータ生成


  • file:///C:/lscc/diamond/1.4/docs/webhelp/eng/start_page.htm オフラインドキュメント(1.4)
posted by すz at 23:48| Comment(0) | TrackBack(0) | MachXO2

2012年02月22日

MachXO2のクロック

MachXO2 Breakout ボードを使ってみて覚えたことをメモしておこうと思う。

内蔵オシレータ

    MachXO2 は、MachXO と同じくオシレータを内蔵している。MachXO2 から良くなったのは、周波数を設定できること と 精度が規定されたこと。

    MachXO は、18 〜 26 MHz と なっているだけで とりあえずクロックが使えれば良いという用途でしか使えなかった。

    MachXO2 では、133 MHz を 1 , 1.5 , 2, 2.5 ... 62 で分周した周波数を出力可能。64 通りの設定がある。精度は±5% で、あまり良いわけではないが、それでも 目安にはなる。

    分周比は、1 〜 16 の範囲では、0.5 刻み。16 〜 32 は 1 刻み、32 〜 62 では 2 刻み。

    OSCH #(.NOM_FREQ("24.18")) osc_internal
    (.OSC(CLK_INT), .STDBY(1'b0));

    こんな風に使う。NOM_FREQ の値は、TN1199 の表に書いてあるものと同じでないといけないことになっているが、本当かどうか 未確認。

PLL

    PLL は、EHXPLLJ というのを使うのだが、

      f = CLKI/CLKI_DIV(1-40) x CLKFB_DIV(1-40) x CLKOP_DIV(1-128:default 8)

    の周波数が VCO の周波数になる。実際に合成して Warning を見ると、VCO 周波数は、400 〜 800 MHz の範囲でないといけないらしい。... が、多分間違いで、データシートを見ると 200 〜 800 MHz の範囲。CLKOP_DIV が 8 なら CLKOP の範囲は、 25MHz 〜 100 MHz ということに。

    CLKOP の出力は

      f = CLKI/CLKI_DIV(1-40) x CLKFB_DIV(1-40)

    だが、CLKOS, CLKOS2, CLKOS3 は、

      f = CLKI/CLKI_DIV(1-40) x CLKFB_DIV(1-40) x CLKOP_DIV(1-128:default 8) / CLKOSn_DIV(1-128:default 8)

    になるようだ。

    あと、これらは、ENCLKOSn を 1 に設定してやらないと出力されない。

    (いろんな使い方をして構わないが) 基本 四相のクロック出力をするときに使う。その場合は、CLKOSn_DIV の値は、CLKOP_DIV に一致させる。

    位相は、CLKOSn_FPHASE パラメータで 0-7 を指定する。45°単位。

    さて、 ちゃんと記述しても Waring が出る。

      WARNING - par: Output clock frequency on pin CLKOP of pll is 100.0 MHz, which with divider 16, requires internal VCO frequency to be 1600.0 MHz ( 100.0 MHz x 16), outside VCO valid range [400, 800] MHz.

    こんなメッセージ。ここの 100.0 MHz は、制約による指定で、

    FREQUENCY NET "NET名" 24.0 MHz

    というのを制約ファイル(.lpf) に記述することで指定する。

    あと、正しいレンジは、200 - 800 MHz のようなので、400 MHz を切る設定をしても良さそうなのだが、Warning を消すのは難しいかも知れない。

    ついでに書いておくと、MachXO や LatticeXP2 も PLL を持っている。MachXO では、EHXPLLC LatticeXP2 では、EHXPLL1 というのを使うらしいのだが、MachXO2 のものほど 高機能ではない。

PLLの動作確認


    OSCH #(.NOM_FREQ("24.18")) osc_internal
    (.OSC(CLK_INT), .STDBY(1'b0));

    DCMA clk_selector (.CLK0(CLK_INT)
    , .CLK1(EXTOSC)
    , .SEL(1'b0) // 0: CLK0 1: CLK1
    , .DCMOUT(CLK_IN0)
    );

    EHXPLLJ #(
    .CLKI_DIV(24)
    , .CLKFB_DIV(24)
    , .CLKOP_DIV(16)
    , .CLKOS_DIV(16)
    , .CLKOS2_DIV(16)
    , .CLKOS3_DIV(16)
    , .CLKOP_FPHASE(0)
    , .CLKOS_FPHASE(2)
    , .CLKOS2_FPHASE(4)
    , .CLKOS3_FPHASE(6)
    ) pll
    (.CLKI(CLK_IN0)
    `ifdef SYS_DRIVEN_CLK4PH
    , .CLKOP(CLK0_OUT)
    , .CLKOS(CLK90_OUT)
    , .CLKOS2(CLK180_OUT)
    , .CLKOS3(CLK270_OUT)
    , .ENCLKOS(1'b1)
    , .ENCLKOS2(1'b1)
    , .ENCLKOS3(1'b1)
    `else
    , .CLKOP(CLK_IN)
    `endif
    );

    完全には正確ではないのだが、こんな感じで使ってみた。

    それぞれのクロックに カウンタを付けて、1 秒程度おきに点滅させてみたところ、おなじ周期で点滅した。ただし、PLLの出力が (CLK_IN0に対して) ずれていく現象になった。

    原因は PLL の ロック が外れまくるため(のはず)。内蔵オシレータを基準クロックに使うのは、さすがに無理があるようだ。ただ、水晶なら問題ないとして、セラミック発振子を使ったり RC 発振だとどうなるのだろう? いずれ実験してみたい。

    ちなみに DCMA (Dynamic Clock Mux) は、おまけ。ドキュメントに書いてあったので使ってみただけ。

PLLの出力周波数の設定

    切りの良い周波数を 出力するのに

      CLKI_DIV : 入力周波数と同じにする。(1-40)
      CLKFB_DIV:出力周波数と同じにする。(1-40)
      CLKOP_DIV: 出力周波数 x CLKOP_DIV が 200 (400?) を超えるように 8/16/32 .. から選ぶ。

    基本の考えかたを、こんな風にしようかと思う。そうするなら、入力周波数は、切りが良ければなんでも良い。ただ応用できる範囲を広げるには、5x4 MHz とか 6x4 MHz とかが良さそうな気がしている。

PLL周波数をユーザ回路で変更

    MachXO2 だとこれが出来る。

    lscc/diamond/1.4/cae_library/synthesis/verilog/machxo2.v に EHXPLLJ に定義がある。インターフェイス仕様は WISHBONE。ドキュメントは、TN1199(J) の付録 D 。

水晶発振器

    MachXO2 Breakout ボードには、5mm x 7mm のオシレータのパターンもある。

    EXTOSC 27 PL9A_PCLKT3_0
    EXTOSC_EN 32 PL10A

    クロック出力だけでなく、Enable ピンにも接続されている。(R54 でジャンパされている)。

    回路図には、CB3LV-3C の 50MHz が記載されているが、消費電流が 40mA と大きく、±50ppm と精度もいまいち。16mA で ±10ppm の ASYMB の方が良いかも。

    秋月だと 『クリスタルオシレーター 40MHz』というのがある。いつなくなるかも分からないが ..

    J4

    (EXTOSC)PL9A 27 (33) (34) 28 PL9B
    GND (35) (36) GND
    (EXTOSC_EN)PL10A 32 (37) (38) 33 PL10B
    PL10C 34 (39) (40) 35 PL10D

    この信号は、20x2 のコネクタにも出ている。場所は、内側の 左(J4) の下。

    ユニバーサル基板を載せるのなら、こちらを使っても同等になる。その場合は、DIP 品(3.3V)が使える。といっても秋月でも 300円

その他の発振回路

    例えば、(EXTOSC)と (EXTOSC_EN) は、GND を挟んで配置されているのだが ... ここに 水晶とか セラミック発振子を付けて発振させられないかと思っている。単なるインバータなら 簡単に実装できるが、なんとかなるものなのか? 入出力にはいろんな設定があるので、設定次第なのかも知れない。

    追記: オシレータが入手できたので、(EXTOSC)と (EXTOSC_EN)を使っての実験はヤメ。

    J2
    (1)(2)
    NC VCCIO0
    PT17D/DONE 109 110 PT17C/INTn
    PT17B 111 112 PT17A
    GND GND
    PT16D 113 114 PT16C
    PT16B 115 117 PT15A
    PT15D/PROGn 119 120 PT15C/JTAGen
    GND GND

    J2 左側の外側上あたり。PT17A と PT16C が良さそうな。

      設定できるのは、プルモード、ヒステリシス、クランプ動作 あと ドライブ強度。これらは、制約ファイル(.lsf) にも記述できるし、プリミティブもあるようだ。

      それに加えて DELAYE とかのプリミティブもある。なにがどう使えるかは良く分からない。

      追記:



      こんな回路で、XIN , XOUT にインバータを入れれば良いらしい。水晶+コンデンサをセラミック発振子に変えても良い。

      村田製作所の FAQ 『発振回路部の各部品の役割について教えてください。』を見ると、R1(1M) は、帰還抵抗で C-MOS ICでは100k〜10MΩ (通常1MΩ) とのこと。『大きすぎると帰還量が減って動作点が不安定になり、小さすぎるとゲインの低下や、電流の増大につながります』と書いてあるから、入れないと発振が不安定になるかも知れない。

      XOUT 側 帰還抵抗 R1 と 水晶(セラミック発振子)の間に抵抗を入れる場合がある。『負荷容量とローパスフィルタを形成し、高域のゲインを低下させることで、高周波の異常発振を抑えられます。』なんて説明があるが、通常不要らしい。もともと数十Ωが入っているようなものだし ... それにドライブ強度の変更で調整できるかも。

      ... というわけで FPGA でも 単なるインバータ + この回路で良さそうだ。(1M は省略しないこと)

      さて、『セラミック発振子 40MHz (YIC社)』というのは、使えるのだろうか? 周波数が高めで AVR とかでは使えないが FPGA なら丁度良いかも知れない。

      最も 『クリスタルオシレーター 40MHz』なんてのもあるのだが ... いつまでもあるとは限らないし、水晶発振子やセラミック発振子の回路も押さえておきたい。

      ちなみに、安い YIC社のやつは、8,12,16,20,25,32,40,48 MHz と各種ある。PLL が使えそうだからなんでも良さそうだが ...

      いつか実験しよう。

      RC発振器(1)



      シュミットトリガ入力 と オープンドレイン出力がある MachXO2 だとこういう回路もあり?
      (シュミットトリガ入力 = HYSTERESIS : LARGE ?)

      R1 = 10k , C1 = 20pF ぐらいで数MHz ?

      原理は、コンデンサに充電されていって 入力の電位が上がってくると 出力が L になって コンデンサが放電される。ただ 0 になる前に Hi-Z に戻る。入力の波形はのこぎり波(に近い三角波)。シュミットトリガ入力 でないと 波高が 0 だから使えない。

      RC発振器(2)



      むしろオープンドレイン出力を使わないこっちのが普通?

      こっちの原理は、入力 L のときは、 充電で H になると反転して 放電。入力の波形は三角波。こっちも、シュミットトリガ入力必須。

      出力強度を変えたり、 HYSTERESIS : SMALL にすると周波数が変わるはず。

      いずれにしてもあまり高い周波数向けではないような.. それに定数が分からない。

    ところで、 PL9A は、PCLKT3_0 というクロック入力用 ピンが割り当てられている。こういったピンは、他にもあって 1200 の LQFP144 は、

    PT12B_PCLKT0_1 128
    PR5C_PCLKT1_0 92
    PB9A_PCLKT2_0 49
    PB11A_PCLKT2_1 55
    PL9A_PCLKT3_0 27
    PL5A_PCLKT3_1 19
    PL3A_PCLKT3_2 5

    という割り当てになっている。

    これらのピンは、外部回路と同期を取るのに重要そうだが、PLL にクロックを供給するだけなら、これを使う必要はないはず。たまたま DCMA を使ってみたが、DCMA は、PLL にクロックを供給できる。DCMA の入力は、general routing が使えるみたいだから、要はなんでも良いみたいだ。

    RC発振器は、単なるインバータで良かったはず。そういえば、フランクリン発振器もそう。

四相クロックについて

    普通 四相クロック が欲しいなら PLL で良いわけだが、内蔵オシレータをクロック元にすると PLLのロックが外れることが頻繁に起きる。通信でこういうことが起きると少々具合がわるい。分周して 四相クロックを作る方法も 検討しておこう。


      reg [3:0] r_clk_0 = 4'b0110;
      reg [3:0] r_clk_90 = 4'b0011;
      reg [3:0] r_clk_180 = 4'b1001;
      reg [3:0] r_clk_270 = 4'b1100;

      always @(posedge CLK_IN0) // CLK4X
      begin
      r_clk_0 <= { r_clk_0[2:0] , r_clk_0[3] };
      r_clk_90 <= { r_clk_90[2:0] , r_clk_90[3] };
      r_clk_180 <= { r_clk_180[2:0] , r_clk_180[3] };
      r_clk_270 <= { r_clk_270[2:0] , r_clk_270[3] };
      end

      wire CLK0_OUT = r_clk_0[3];
      wire CLK90_OUT = r_clk_90[3];
      wire CLK180_OUT = r_clk_180[3];
      wire CLK270_OUT = r_clk_270[3];

    Xilinx だとこんなコードが良さそう。SRL16 を使っていることになるから 4LUT しか消費しないんじゃないかと思う。

    だが、Lattice では、SRL16 相当の機能はないようだ。MachXO2 では、カウンタとか 比較機能を持っているから素直なロジックのコードが良いのかも知れない。

      reg [1:0] r_clk_cnt = 2'b00;
      reg [3:0] r_clk_out = 4'b1100;

      always @(posedge CLK_IN0) // CLK4X
      begin
      r_clk_cnt <= r_clk_cnt + 1;
      r_clk_out[0] <= (r_clk_cnt == 0) | (r_clk_cnt == 1);
      r_clk_out[1] <= (r_clk_cnt == 1) | (r_clk_cnt == 2);
      r_clk_out[2] <= (r_clk_cnt == 2) | (r_clk_cnt == 3);
      r_clk_out[3] <= (r_clk_cnt == 3) | (r_clk_cnt == 0);
      end
      wire CLK0_OUT = r_clk_out[0];
      wire CLK90_OUT = r_clk_out[1];
      wire CLK180_OUT = r_clk_out[2];
      wire CLK270_OUT = r_clk_out[3];

    あと POWER ON RESET 関係。すこし遅延させたい。


      reg [15:0] reset_sft = 16'h0000;
      always @(posedge CLK)
      begin
      reset_sft <= { reset_sft[15-1:0] , 1'b1 };
      end
      wire RESET = reset_sft[15];

    Xilinx だと 16bit まで 1 LUT だから、こんなのもアリだと思うのだが、他は具合がわるい。


      reg [3:0] reset_cnt;
      reg r_reset;
      always @(posedge CLK)
      begin
      if (reset_cnt == 4'b1111)
      r_reset <= 1'b1;
      else
      reset_cnt <= reset_cnt + 1;
      end
      wire RESET = r_reset;

    素直な コードだとこう?

    ところで、MachXO2 だと、シフトを使った コードはどちらも期待どおりにならない。初期値の設定がどうやっても出来ず、最終的に 定数 になるようだ。Synplify Pro も LSEも同じ。

    上記の reset_cnt のコードだと Synplify Pro は定数でないものを合成してくれる。が、LSE はダメ。


      reg [15:0] reset_sft = 16'h0000;
      reg r_reset = 1'b0;
      always @(negedge CLK_IN)
      begin
      if (r_reset != 1'b1)
      begin
      r_reset <= 1'b1;
      reset_sft <= 16'h0000;
      end
      else
      reset_sft <= { reset_sft[14:0] , 1'b1 };
      end
      assign RESET = reset_sft[15];

    このコードだと Synplify Pro は定数でないものを合成してくれる。が、LSE はダメ。
    r_reset を使わずに、( reset_sft != 16'hFFFF) なんて条件を使うと、Synplify Pro でもダメ。

    Warning をしっかり見ないと 期待どおりかどうか分からない。

    WARNING: Register r_reset_11 is stuck at One

    LSE だとこういうエラー に注意。

    ちなみに、こういうコードは、クロックや RESET 自体の生成にしか重要でないように気をつけてはいるのだが...

参考資料
posted by すz at 22:53| Comment(0) | TrackBack(0) | MachXO2

2012年02月07日

MachXO2 1200ZE Breakout ボード

2572円と安価に買える FPGA ボードについて。

    追記: 2012/10/8 なんと秋月で取り扱い開始! 2600 円也

    追記: 2013/4/26 LCMXO2-7000HE-B-EVN にグレードアップ。チップ置換であとは同じ。秋月では 3000 円。

     ユーザーズガイドの回路図すら直してない。VCCIO4,5 が VCCIO3 のままになってる。



簡単な説明

    FPGAは、Lattice 社の MachXO2 1200ZE 。価格は $29.99。発表は 2012/1月

    このボードには、FT2232H が載っていて、非常に安易に使える。USB に接続するだけだ。Lattice 社の合成ツール Diamond でもサポートしていて、ビルドしてから、2オペレーションで書き込みが可能。

      (1) Tools→Programmer を選ぶと ダイアログが出る。
      (2) (一回設定した後は) Download ボタンを押す。

    FPGA に接続されているデバイスは、JTAG と シリアル と LED x 8 。

      5mm x 7mm のオシレータのパターンもある。(スタンバイモードがある) ASYMB 24 MHz あたり を Breakout ボードと同時に買っておくのが良さそう。ただし、300 円ぐらいであまり安くないので、後でマルツで買うのも良いかも。
      ちなみに、回路図に載っているのは、CB3LV-3C の 50MHz。

    製品 URL : MachXO2 1200ZE Breakout Board Evaluation Kit Resources

MachXO 2280 Breakout ボード との違い

    MachXO 2280 Breakout ボード もまた、同価格で安価に入手できる。こちらの方が規模が大きく、使えるピンの数も多い。ただし、EBR RAM は、9kb がたったの 3 つ。MachXO2 1200ZE は、7 つあり プログラムに使えるメモリを 4KB は割り当てられる。

    MachXO2 1200ZE Breakout ボード の方は、FT2232H の機能を流用しやすくなっている。JTAGENB ピンが コネクタに出ているので、Disable すれば JTAG ボードとして流用可能。Serial ( BDBUS0-6) も ジャンパすれば FPGA で使える。

    ちょっと FPGA を試してみるとかといった使い方には向いていそうだ。

      追記:JTAG として使えないようにするには、config で JTAG_PORT を DISABLE に設定する。その場合 JTAGENB ピンが専用ピンになり、H レベルにすることで、JTAG が使えるようになる。

      要するに JTAG 関係のピンを全部 HI-Z にして、 JTAG_PORT を DISABLEにした config データを書き込めば、JTAG を外部回路用に引き出せる。JTAGENB ピンを H レベルにするスイッチを付けて ON にすれば再度JTAG を使用できる。

      (追記2)JTAG コネクタは、Lattice 用 8pin タイプ

      (1) (8)
        3V3 TDO TDI NC NC TMS GND TCK

      こうなっている。 デジタルデザインテクノロジー No.1(ISBN:9784789849401 : ググるとまだ売っている)の XP2 基板 に接続する場合は、(1) を 除いて 接続すれば良さそう。

      追記(注意): 1200ZE は、低消費電力向けチップで、スピードグレードは 、1 。HC あるいは HE が最大周波数 150 MHz のところ ZE は、60 MHz 。趣味の範囲できっちり守るべきかどうかは分からないが、あまり高速で動かすものではないのは確か。

      追記: BDBUS のシリアルを使うには、裏面の R14〜R21 をジャンパするか、そのパターンを使って引き出す。割り当ては、

      R14 BDBUS0 TXD
      R15 BDBUS1 RXD
      R16 BDBUS2 RTS
      R17 BDBUS3 CTS
      R18 BDBUS4 DTR
      R20 BDBUS5 DSR
      R21 BDBUS6 DCD


MachXO2 7000 が購入可能になっている。

    思いのほか安くて驚いた。TQ144 の LCMXO2-7000HE-4TG144C が 1239 円。4000 までは EBR SRAM が少なく面白くないのだが、これは 9kb の EBR SRAM が 26 個付いている。

      Spartan-6 LX9 も 1346 円と同じような価格。こちらは 18kb の ブロック RAM が 32 個。規模も大きいんだろう。そういえば MachXO2 は 乗算器もない。いままで 1200 しかなかったのが、7000 になって喜んでみたが、実は大したことはないのかも。

      ちなみに、MachXO2 1200 は、Spartan-3A 50 より規模が小さい。50A は、704 スライスだが、1200 は、640。50A のブロックRAM は、18kb x 3 で 1200 の 9kb x 7 と同じようなもの。
      MachXO2 7000 は、3442 で 400A の 3584 スライス と同じぐらい。400A のブロックRAM は、18kb x 16 なので、9kb x 26 の 7000 はちょっと少ない。

    TQ144 の 7000ZE とか 7000HE とかを MachXO2 1200ZE Breakout ボード のチップと入れ替えられると便利なような気がするのだが ...

    外すのは、SMD取り外しキット:1575円を使うとして ... さて。

    追記: BSDLファイルを比べてみたが、載せ替え自体は可能なようだ。

      4000/7000 2000 1200
      30 VCCIO3 VCCIO3 VCCIO3
      7 VCCIO4 VCCIO4 VCCIO3
      16 VCCIO5 VCCIO5 VCCIO3

      15 v NC NC
      17 v NC NC
      31 v NC NC
      63 v NC NC
      87 v v NC
      89 v v NC
      103 v NC NC
      129 NC NC NC

      電源,NC の違いは、こう。2000 以上はバンク 4,5 があるが、VCCIO3 が割り当てられている。あと、1200 は、NC が多いため、載せ替えると使えないピンが出てくる。ちなみに信号名の割り当ては違うが、ピン番号で指定するからあまり関係ない。機能のピンの割り当ては同じようだが未検証。JTAG や I2C は同じだったが、他は見てない。

      ところで、HC の BSDL ファイルしかないが、HE,ZE も信号線は同じなんだろう。HC はレギュレータ付きだが、HE,ZE との違いは良く分からない。(レギュレータ用のピンが見つからない。むしろ HE,ZE 用に見える。) まぁ 7000HE,7000ZE の載せ替えは可能そうだ。

      ついでなので、機能のピンの割り当てに付いても調べた。

      4000/7000 2000 1200

      5 PCLKT5_0 PCLKT4_0 PCLKT3_2
      6 PCLKC5_0 PCLKC5_0 PCLKC3_2
      19 PCLKT4_0 PCLKT4_0 PCLKT3_1
      20 PCLKC4_0 PCLKC4_0 PCLKC3_1

      104 R_GPLLC_IN
      105 R_GPLLT_IN
      106 R_GPLLC_FB
      107 R_GPLLT_FB
      111 R_GPLLC_MFGOUT2
      112 R_GPLLT_MFGOUT2

      2000 以上は、バンクの関係でクロック入力の名前が変わった。あと、4000/7000 は PLL が増えた。

      違いは、これだけ。これなら、ターゲットデバイスを変更するだけで 1200 用の コードもそのまま動く。

      追記: HC と HE/ZE の BSDL ファイル がリリースされていたので比較してみた。

      どうも電源ピンの定義は同じようだ。違いは ID 。

      device code 0x012B 2043 -- 1200ZE/HE
      device code 0x012B 3043 -- 2000ZE/HE
      device code 0x012B 4043 -- 4000ZE/HE
      device code 0x012B 5043 -- 7000ZE/HE

      device code 0x012B A043 -- 1200HC
      device code 0x012B B043 -- 2000HC
      device code 0x012B C043 -- 4000HC
      device code 0x012B D043 -- 7000HC

Lattice (MachXO2) がお気に入りの理由

  • 開発ツールが小さい

    小さいといっても Lattice Diamond は、1.7GB もあるのだが ... それでも Xilinx の ISE なんかと比べるとはるかに小さい。使い勝手も良いみたいだし、気に入っている。

  • Digikey で買える

    Digikey で買えないものは候補にならないのだが、幸い購入可能。電子工作レベルで使える TQFP 100 や 144 品の種類も豊富にあるのが良い。

    TQFP 100 だと、2000 まで 、144 では 7000 まで。

  • お手軽

    FLASH を内臓しているし、レギュレータや 内臓クロックもあるので、チップ単体で 動かすことも可能。

    開発ツールもあわせて、総じてお手軽に使えるというのが良い。

    ついでに書いておくと ライセンスキーは、Mac アドレスに対して発行される。この Mac アドレスは、USB Wifi ドングルのものでもよい。要するに インターネットカフェのようなところでも実行が可能なのだ。プログラムも小さめなので、インストール時間は短めで 実際に 利用可能。

      内蔵クロックは、133 MHz を 1 , 1.5 , 2, 2.5 ... 62 で分周した周波数を出力可能。64 通りの設定がある。精度は±5% だそうで、あまりあてにできないが、とりあえずは便利に使える。MachXO も 持っているのだが、周波数は設定できず 20MHz (18 MHz - 26 MHz) 。( MachXO2 で設定できる近い周波数は 19.00 Mhz ?)

        分周比は、1 〜 16 の範囲では、0.5 刻み。16 〜 32 は 1 刻み、32 〜 62 では 2 刻み。

      ちなみに Breakout ボードには、3.3v 5mmx7mm のオシレータも載せられるようになっている。PLL もあるので、周波数を変換することも出来る。

  • 残念な点

    残念な点としては、規模が小さいこと。ブロックメモリも少ない。自作コアだと 1200 でようやく載るレベル。

    内臓の ハードマクロ の I2C /SPI/ TIMER を生かせば、結構規模を節約できそうだが、専用設計になってしまうのでちょっと面白くない。

    ただ、TQFP 144 に限ると規模の大きいものの品種は限られる。Spartan-6 LX9 , Lattice XP2-8 , MachXO2 7000 ぐらいか。それ以下だと XP2-5 , Spartan-3E 250E , MachXO2 4000 。Spartan-6 LX9 使えば良いのだが、xilinx の ISE が嫌なら MachXO2 7000 とかも良いかなという感じ。

  • 参考 文献

自作コアと MachXO2

    以前 AVR互換COREを作成したのだが、MachXO2 でとりあえず 合成できるところまで確認して 凍結していた。

      AVR互換CORE といっても、互換なのは、米粒AVR の ATtiny10 系統。Mega や Tiny 互換ではなく、AT90S の AVR とも互換ではない。

    最後のバージョンは、rtavr-0.9.3.tar.gz

    README を読み返すと

    (4-A) クイックビルド 『WebPACK ISE』

    以下に 3 種類の 標準的な構成を示します。

    (1) rtavr を top-layer にした 最小構成

    configs/50A/rtavr_defs.v と configs/rtavr_common.v , soc/*.v
    および、tests/tbi_001/rom_data.mem を使い 『WebPACK ISE』を使用して
    Implement します。

    この構成は、USART および SPI を含み実用的なものでありながら、
    XC3S50A で Implement 可能なように しています。

    なお、USART , SPI については、レジスタの定数化により機能を縮小
    しています。 使用する機能に適合しない場合は、rtavr_defs.v を
    編集する必要があります。

    と書いてあるが、MachXO2 では、configs/1200HC/rtavr_defs.v を使用することで 一応合成できるようになっている。できるのは 50A と同等の機能なのだが、MachXO2 では、ROM_PSEUDO_DP が define されて DUALPORT の ROM を使わないようにしている。DUAL PORT を使うと ROM データの READ で 8bit の 別ポートを使うが、define すると 16bit の ROM からデータを読み込むようになり、規模が少し増える。

      こうした理由は、Diamond が DUALPORT ROM を推論してくれないため。最新版の 1.4.1 でも試したがだめだった。

    で、できたものは、ちょっとのデバッグで動くような気がしているが、試していない。

    デバッグするためのツールを作成している段階で放置していたのだった。MachXO2 1200ZE Breakout ボード を reference として使うことにして 作成を再開したい。

PORTの実装

    実は、PORT の 入出力の動的変更がうまく行っていない(かも)
    Lattice のリファレンスデザインを見ると

    inout sda_pin;
    wire scl_pin;
    assign sda_pin = sda ? 1'bz : 1'b0;

    こんな感じで記述されていた。データバスも近い記述で 1'bz の部分が出力データで可変になっている。

    現在のコードをこれに準じた記述に変更したほうがよいかも。ただし、プルアップ/プルダウンを 制御するのは無理そう。制御用の線を割り当てて 信号線と 抵抗でつなぐしかないか。

rtavr 更新

  • rtavr-0.9.4.tar.gz
  • rtavr_tools-0.5.tar.gz

    ここで書くべき内容ではないのだが、XO2 Breakout ボードに対応したものを作って更新した。

    ... といっても対応しただけで、内容的には進展なし。

    rtavr の方は、JTAG ポート経由でアクセスできる 2 つのポートがあるのだが、ここに ISP と SPI(SLAVE) を接続。あと USART の TXD/RXD を シリアルに接続。LED の D1/D2 に PORT を接続。

    これが動けば結構すごいと思うのだが、残念ながら規模を見るのが目的のもので、動作は期待できない。

    device utilization summary: XO2
    PIO (prelim) 14/108 12% used
    14/108 12% bonded
    SLICE 590/640 92% used
    OSC 1/1 100% used
    JTAG 1/1 100% used
    EBR 6/7 85% used

    規模的には、Spartan-3A 50A より少し余裕がある感じ。 synplify Pro を使っているのだが、Xilinx の標準ツールより効率が良い?

      上記は、Diamond 1.1 の結果。1.4 だと 612 SLICE (95%) を消費している。

      あと、

    ISP は、attiny10 系のものをベースに簡易化したもので、ROM の読み書きだけができる機能。(ツールは未対応)

    rtavr_tools の方は、JTAG 経由の通信が本当にできるかのテストなど。JEDEC ファイル の書き込みとかベリファイも仕込んであるが、未テスト。MachXO2 はちょっと複雑で 大分デバッグが必要そう。セキュリティ関係の機能もあるので不用意にテストすると 書き込めなくなる恐れがあり、デバッグも慎重にやる必要がある。

      progname : [rtavr_tool.exe]
      cbl_name = mpsse
      cbl_type = ft245r
      port = ft0
      bitclock = 115200.000
      baudrate = 115200
      ispdelay = 0
      rtavr_tool.exe: BitBang OK
      rtavr_tool.exe: drain OK
      open OK
      bitclock = 102400.000
      ft245r: bitclk 102400 -> ft baud 38400
      ft245r: bitclk 102400 -> ft baud 38400
      load_conf LCMXO2_1200
      -- device_type 12b2
      -- sucsess
      -- device_id 012b2043
      cmd> spi_test
      spi_test -- sel_chan test
      spi_test -- spi_echo test1
      30 00 (00)
      31 30 (18)
      32 31 (18)
      33 32 (19)
      34 33 (19)
      5535 3455 (1a2a)
      aa5536 35aa55 (1ad52a)
      37 36 (1b)
      38 37 (1b)
      39 38 (1c)
      ff 39 (1c)
      ff ff (7f)
      spi_test done
      cmd>

    spi_test で 入力データを echo back させるぐらいは出来ている。といっても、rtavr の SPI と同じコードではなく簡易なものでのテスト。すり合わせも出来ていないので、rtavr の方で動くことは期待できない。

    まぁ、いまのところはこんな感じ。

SVF ファイルについて

    忘却が激しいのでメモ。

    SVF ファイルとは、コンフィグする際のシーケンスが記述してあるもので、これを解析してツールの機能を作ろうとしている。

    論理合成して作成されるのは、JEDEC ファイルで、SVF ファイルを作成するには、ispVM を起動する。SVF アイコンで SVF ファイルに変換するのだが、さまざまなオプションがある。Flash に対して Erase/Write/Verify の組み合わせがあるし、background モードというのもある。

    それに加えて SRAM への直接 Write という機能もある。Flash を汚さないし便利そうな気がするのだが、JEDEC ファイル を bit ファイルに変換しないといけない。変換は UFW アイコンで行う。

      ちなみに、Flash のデータは圧縮されている。SRAM へ直接書きこむデータはたぶん圧縮されていない。伸張ロジックを知っていないと JEDEC ファイルを書き込むようには出来ない。

      あと、EBR RAM は SRAM に含まれているのかどうか? EBR RAM は Flash からのロードしかできないような気がするのだがどうなんだろう?

      ちなみに、MachXO や XP2 は、Flash 用と同じデータを SRAM に書き込める。

    注意) 上記は、Diamond 1.1 での話。1.4 を試してみると ... Diamond に ispVM は組み込まれなくなった。ispVM は別のソフトとしてインストールすることができる。Programmer を動かすと xcf ファイルが作成されるようなので、これを ispVM で Open すると上記のオペレーションが出来るようになるようだ。

Lattice Mico8 について

    Lattice だと Mico8 / Mico32 という 2 つの IP プロセッサがある。このうち 8bit の Mico8 は、結構 AVR に近い感じ。驚いたことに gcc も移植されている。

    Mico8 は、レジスタ数 32 のタイプと 16 のタイプがある。16 のタイプは MachXO2 で 262 LUT で組めるそうだ。(32 は 313)

      自作コアの RTAVR は レジスタ数 16 だが configs/core_test で core のみ生成すると 660 LUT 。(GPR_16 というシュリンクオプションなしだと 690)。結構頑張ったつもりなのだが...

      まぁ、Mico8 の方は パイプラインプロセッサでないし、命令も 18 bit 使っていたり、AVR のような 特殊な命令コードないしで、差が出るのは仕方がない。

    ところで、Mico8 のアドレス空間は 8bit しかない。16bit あるいはそれ以上の空間にアクセスするには、Page Pointer というのを使うそうだ。要するにバンク切り替え。

    プログラム空間は、12bit ある。18bit x 4K であり 8KB の AVR Tiny などと同じぐらい。ただし、プログラム空間のメモリをデータとして使うことはできない。

    実をいうと、自作AVRコアは、gcc が使え、FPGA メーカを選ばない (規模が小さい)8bit のプロセッサを目指した。Mico8 で gcc が使えるのを知っていたら、違うものを作っていたかも知れない。まぁ、FPGA メーカが作るコアは、自社のデバイスに最適化するから 他社のデバイスに移植するようなものではない。移植性が特徴として残っているから これで良かったとは思うのだが...

MachXO2 Breakout ボードのピン配置

    J4 J3
    (1)(2) (1)(2)
    3V3 VCCIO3 1V2 VCCIO1
    3V3 NC 1V2 NC
    PL2A 1 2 PL2B (TXD)PR10C 74 73 PR10D(RXD)
    PL2C 3 4 PL2D (CTS)PR10A 76 75 PR10B(RTS)
    PL3A 5 6 PL3B GND GND
    PL3C 9 10 PL3D (DCD)PR9C 78 77 PR9D(DSR)
    GND GND PR9A 82 81 PR9B(DTR)
    PL4A 11 12 PL4B GND GND
    PL4C 13 14 PL4D PR8C 84 83 PR8D
    GND GND PR8A 86 85 PR8B
    PL5A 19 20 PL5B GND GND
    PL5C 21 22 PL5D PR5C 92 91 PR5D
    GND GND PR5A 94 93 PR5B
    PL8A 23 24 PL8B GND GND
    PL8C 25 26 PL8D PR4C 96 95 PR4D
    GND GND (LED D2)PR4A 98 97 PR4B(LED D1)
    (EXTOSC)PL9A 27 28 PL9B GND GND
    GND GND (LED D4)PR3A 100 99 PR3B(LED D3)
    (EXTOSC_EN)PL10A 32 33 PL10B (LED D6)PR2C 105 104 PR2D(LED D5)
    PL10C 34 35 PL10D (LED D8)PR2A 107 106 PR2B(LED D7)

    内側の2 列分の信号配置。

    5cm x 5cm で基板を作れば 使えるかと思ったのだが、コネクタ間の間隔は 5cm を超えていた。あと、内部機能との重複が多い。重複を退けると 37 pin 。SRAM には十分だが、SDR SDRAM 16bit には少し足りない。(1200ZE では、全然高速に動かせないのでオーバースペック)

      追記: 37 pin では、4Mbit (16bit幅) の CY7C1041DV33(10ns) の駆動は無理だった。一応訂正。

      追記: シリアルのピンは、実際には接続されていない。抵抗パターンが 7 つ並んでいる所があるのだが、そこをジャンパする必要がある。


    J2 J5
    (1)(2) (1)(2)
    NC VCCIO0 NC VCCIO2
    PT17D/DONE 109 110 PT17C/INTn +-PB20D 71 69 PB20B-+
    PT17B 111 112 PT17A (R39) +-PB20C 70 68 PB20A-+ (R37)
    GND GND +-PB18D 67 62 PB18B-+
    PT16D 113 114 PT16C (R35) +-PB18C 65 61 PB18A-+ (R33)
    PT16B 115 117 PT15A GND GND
    PT15D/PROGn 119 120 PT15C/JTAGen +-PB15D 60 58 PB15B-+
    GND GND (R31) +-PB15C 59 57 PB15A-+ (R29)
    PT15B 121 122 PT15A GND GND
    (SDA)PT12D 125 126 PT12C(SCL) +-PB11B 56 54 PB11D-+
    PT12B 127 128 PT12A (R41) +-PB11A 55 52 PC11C-+ (R40)
    GND GND GND GND
    PT11D/TMS 130 131 PT11C/TCK +-PB9B 50 48 PB9D-+
    PT11B 132 133 PT11A (R38) +-PB9A 49 47 PB9C-+ (R36)
    PT10D/TDI 136 137 PT10C/TDO GND GND
    GND GND +-PB6D 45 43 PB6B-+
         PT10B 138 139 PT10A (R34) +-PB6C 44 42 PB6A-+ (R32)
    PT9D 140 141 PT9C GND GND
    PT9B 142 143 PT9A +-PB4D 41 39 PB4B-+
    GND GND (R30) +-PB4C 40 38 PB4A-+ (R28)

    外側の2列はこんな感じ。(SDA),(SCL) は、外部抵抗でプルアップされている。こちらは、JTAG 関係を除いて 48 pin 分。

      訂正: 一番右の J5 は、全て差動受信用に 100 Ωのターミネータを入れられる(抵抗は空きパターン)。あるいは、10kΩとか入れて動的プルアップに流用するとかも可能。といっても 小さいのでハンダ付けはなかなか厳しい。

    EXOSC , EXOSC_EN は、5mm x 7mm のオシレータのパターンにつながっている。スタンバイモードがある ASYMB 24 MHz とか CB3LV-3C が digikey で買えるので、Breakout ボードと同時に買っておくのが良さそう。ただし、300 円程する。

    PLL があるので、発振周波数は、割りとなんでも良い。PLL は、EHXPLLJ というのを使うのだが、基本的に

      f = CLKI/CLKI_DIV(1-40) x CLKFB_DIV(1-40) x CLKOP_DIV(1-128:default 8)

    の周波数が VCO の周波数になるようだ。実際に合成して Warning を見ると、VCO 周波数は、400 〜 800 MHz の範囲でないといけないらしい。... が、多分間違いで、データシートを見ると 200 〜 800 MHz の範囲。CLKOP_DIV が 8 なら CLKOP の範囲は、 25MHz 〜 100 MHz ということに。

    CLKOP の出力は

      f = CLKI/CLKI_DIV(1-40) x CLKFB_DIV(1-40)

    だが、CLKOS, CLKOS2, CLKOS3 は、

      f = CLKI/CLKI_DIV(1-40) x CLKFB_DIV(1-40) x CLKOP_DIV(1-128:default 8) / CLKOSn_DIV(1-128:default 8)

    になるみたい。ただし、あくまで基本で、もっと多彩な機能がある。

これで何をしたいのか?

    MachXO2 breakout ボードは、1200ZE で高速でもなく、規模も小さい。自作AVRコアのテストには便利だから、当面その目的で使うつもりなのだが、実用として考えたときにこれで何が出来るのだろう?

    だいたい 100 pin の 1200 は、1 個 630 円ぐらい。( 256 まで規模を落とすと 365 円 まで下がる。) 随分安くなったものだが、AVR と比べると大分高い。32 bit の Coretex-M0 や PIC32 などと比べると価格差が大分小さくなるが、今度は実現できる機能差が大きい。

    ついでに書いておくと 100 pin だと 2000 がある。こちらは少しだけ高くなって 875 円。あと、144 pin だと単価が上がる。1200 で 751 円、2000 で 991 円。

    さて、こういう条件なのだが ...

  • とりあえず、MachXO2 Breakout ボードを使う方向で考えてみる。安く手に入るし、USB インターフェイスが付いているので、ソフトをなんとかすれば、HOST との通信ができる。シリアルだと最大 12Mbaud までだが、MPSSE だと 30Mbps (3.75 MB/sec)。接続されている範囲では、これが最高速度。(実は Fast Serial の方が速くできるかも知れないのだが、あまり使われているようには思えないし、とりあえず無視)

  • 開発専用だと、作ったモジュールの単体テストとかには便利そう。そういえば、FPGA 同士で通信するモジュールを作りたかったのだった。この場合 いったん外に出して外側で接続すれば、単体テストはできそう。

  • 秋月の480x272 LCD とかのインターフェイス。PC から垂れ流した データをそのまま表示してもなんとか見えそう。ただ帯域が少々足りない。キャラクタディスプレーとかだと内蔵 RAM でもいけるから、端末にするのも一興か。

  • ロジアナも工夫次第。圧縮して 内蔵 RAM をバッファにするとかすれば、測定対象次第で結構取り込めるかも。外付け RAM を付ければ良いのだが、ZE で遅いので 苦労しがいがない。内蔵だけで工夫するのが楽しそう。

  • チップ単体で使うにしても HOST との通信はクリアしておきたい。USB だと SPI で扱える MAX3421E とか SL811HSTが有名だが、1000 円ぐらいする。これなら USB が付いた MCU の方が安いと思える価格。作れるものなのかどうか分からないが、複数チャネルが扱える (12Mbps)USB コントローラなんてのが作れると良さそうな気がする。

Mouser で、WLCS-25 (1200ZE) が 出ている

    在庫 0 だが、1個単位で買える。20 個なら単価 400 円。これを使えば 24 pin DIP (とか)の モジュールを作れそう。最も、基板をなんとか出来たときの話。25 pin とは言え 0.4mm ピッチの BGA だから 趣味のレベルでは難しい。BSDLファイルを見ると、JTAG 4 , GND 2 , VCC 2, VCCIO0,VCCIO2 の 10 pin を除く 15 pin が 入出力に使える。JTAGENB もあるし、config 用の PROGRAMN/INITN/DONE もあるから 正確ではない。あと I2C,SPI のハードマクロの PIN も 。

    1.2V レギュレータ 載せた上で 24 pin ナロー DIP のモジュールとか、誰か作らないかなぁ ... と思ってみたり。


    こんなの(8ビット双方向ロジックレベル変換モジュール)があると 嬉しいような ...

      1 2 3 4 5
      A PT17C/INITN PT15D/PROGRAMN PT12D/SDA TCK TDO
      B PT17D/DONE PT15C/JTAGENB PT12C/SC TMS VCC
      C PT16A VCCIO0 GND VCCIO2 TDI
      D VCC PT12A/PCLKT0_1 GND PB6D/SPISO PB6C/MCLK
      E PB20D/SISPI PB20C PB11A/PCLKT2_1 PB9A/PCLKT2_0 PB4C

      とりあえず、ピン配置を作ってみた。(行と列は逆かも) 。外側の 16 ピンだけで なんとかならないかと思ったが無理。やっぱり 4 層基板 + 極小スルーホールでないと。

    ところで、これの最高周波数は 133 MHz になっている。最も遅いのは、1200ZE 100pin C の 104 MHz 。あと スピードクラス 4 の I は、550 MHz 。60 MHz/150 MHz というのは、実用回路の目安?

    追記: Aliexpress の基板作成サービス

      Aliexpress にも 基板作成サービスをしているところがある。

      Loision's PCB factory だと、4 層基板のサービスがある。Min. Hole Size: 0.2mm, Min. Line Width: 4MIL だそうで、 WLCS-25 のモジュール基板を作成できるかも知れない。
      基板さえ作ることが出来れば、ホットプレート・リフローとかの方法でハンダ付けは可能そう。

      ITeadStudio でも 4層基板 を扱っている。5cm x 5cm (10pcs) で $65 。2層 $9.9 なのと比べると大違いだが これでも安いのかも。ただ、ここだと Hole の最小サイズは 0.3mm で 0.4mm ピッチの BGA のパターンは無理。

Synplify Pro と LSE

    論理合成エンジンに Synplify Pro と LSE が選べる。デフォルトは、Synplify Pro だからそのまま使えば良さそうなのだが、ちょっと 気持ちが悪い Warning がある。

      Initial statement will only initialize memories through the usage of $readmemh and $readmemb. Everything else is ignored

    というもので、どうも initail 文は、$readmemh とかを使わないケースでは意味がないらしい。では、初期値は 0 固定なのか? ... というと良く分からない。まぁ、rtavr 本体は、GPR(汎用レジスタ) と RAM データの初期化にしか使っていないので良いのだが、isp.v の状態変数は、initial 文を使っている。初期値は 0 に統一しているので 0 固定なら問題ないのだが、気になる。

    LSE を使ってみると、そういう Warning は出ない。ただ、同じものを合成しても Synplify Pro は、612/640 スライスだったのが、LSE では、617/640 スライスとちょっと増える。Diamond 1.1 を使っていたときは、Synplify Pro は 590/640 スライスで、LSE はさらに規模が小さかった。増えるのはバグ修正が理由だとすれば、Diamond 1.1 は、結構バグがあったのかも。

    ただ、それでも XilinX の Spartan-3A より効率が良く、704 スライスの 50A より回路が入るようだ。

      Number of ripple logic: 81 (162 LUT4s)

    ひょっとすると、リップルモードの言うのが肝なのかも。LUT4 の代わりに、2bit カウンタとか 2bit 加算回路、乗算回路として使えるようになっている。

    GPR_16 というシュリンクオプションなしで合成すると 規模が 30 ほど増えるはず(24 スライス分 分散 RAM に 余計に使用する)なのだが、ためしにやってみたら Synplify Pro で 623/640 , LSE で 639/640 と なんとか収めて来た。ひょっとしたら余分な LUT が最適化(遅延低減)のために使われるのかも知れない。

MachXO2 Breakout ボードと 秋月 C 基板

    MachXO2 Breakout ボードと 秋月 C 基板を現物合わせしてみたところ、長辺 を横にして、外側の 1 列づつ まで覆えた。ただし、短辺のスルーホールは 17穴なので、20x2 コネクタ全部は使えない。 あと、外側だとギリギリなので、13 穴しかない。

    3V3 電源 は、上にしか出ていないので、1 番 PIN まで上に寄せて 装着することになりそう。そうすると使えないピンが出てきて面白くない。ここは、B 基板を使うのが良いのかも知れない。

    あと両脇について。両脇は C 基板がかぶさるので、上方向にピン/フレームを出すのはどうかと思う。横方向外側に出した方が良さそう。

    内側 の方は、フレームで良さそう。ちなみに、2 列のフレームを使っても全部のピンを接続する必要はない。80ピン 全部 接続する と外すのに随分力がいる。適当に間引いた方が良いと思う。

rtavr 更新

  • rtavr-0.9.5.tar.gz
  • rtavr_tools-0.6.tar.gz

    PLL を組み込んで 四相クロック化。rtavr_tools の方も PLL を組み込んだテスト回路にした。

    四相クロック化をすると何故か随分と規模が減った。Synplify Pro で 623/640 だったのが、 572/640 まで減った。これは、GPR_16 というシュリンクオプションなし。

    LSE でも 639/640 だったのが、607/640 に。

    以前は、2 倍クロック + ロジックで生成した 標準クロック。それを元にして、さらにタイミングを作っている。それ以外に シフトレジスタ x 4 を使った擬似四相クロック のモードもある。

    たぶん 四相クロック が一番すなおで、実際のクロックラインが少ないんだろう。... ということで納得しておこう。

追記 dealextreame の基板
posted by すz at 17:54| Comment(0) | TrackBack(0) | MachXO2