Sim's blog

電子工作はじめてみました

ICFPプログラミングコンテスト2009

2009-06-27 15:05:09 | ICFPプログラミングコンテスト
ICFPプログラミングコンテストが始まっています。

今年は、宇宙船を操縦して4つのミッションをクリアする課題です。去年は惑星探査車の操縦でした。
去年は環境(live CD)が配布されて、その環境で動かしていました。今年は仮想マシン上で動かすので、仮想マシンの作成から始めないといけません。
仮想マシンを作るところから始めるのは2006年, 2007年もそうでした。2007年のように仮想マシンを作ること自体が難しくて入り口にすらたどり着けないということはなく、今年の仮想マシンはかなりシンプルです。
仮想マシンのレジスタはPCと比較結果を入れるstatusの2つだけです。アキュムレータもないので、演算結果は全てメモリに格納します。また、PCを操作する命令もないので、ストレートに実行されるだけになります。0番地から開始して最終番地まで実行して、おしまいです。ハーバードアーキテクチャなので、プログラムとデータは別の空間です(さらにはI/O空間も別です)。つまり自己書き換えコードも存在しません。メモリ空間は14ビットなので16kバイトです。

宇宙船の操作は、以下を繰り返します。
(1) プログラムとメモリの初期値を読み込む
(2) 入力ポートにデータを設定する
(3) 仮想マシンを動かす
(4) 出力を読み取る
(5) (2)に戻る

仮想マシンの仕様やミッションについては開催ホームページからpdfをダウンロードできます。宇宙船(仮想マシン上のプログラム自体)は、メールアドレスを登録するとTeam Pageからダウンロードできるようになります。今、見てみたら仕様書がV1.6になっています。

参加者のすることは、宇宙船を制御するプログラムを書くことです。うまく制御すると点数が高く(低く?)なるようで、点数を競います。
主催者に提出するのは、制御プログラムそのものではなく、どのタイミングでどんな入力を与えたかを示すバイナリファイルです。これなら、どんな言語を使っても平気です。去年の実行ファイルの提出よりはスマートです。なんか2007年と2008年のいいところを合わせた感じになっています。宇宙船の仕様というか動作を知るために仮想マシン上のコードを読まないといけないのも2007年と似ています。

というわけで、概要はなんとなく分かったので、仮想マシンのコードでも書いてみようと思います。逆アセンブラも必要そうです。


6/29 追記 結局、コンパイラを書いちゃいました。って、肝心の問題の方はほとんどやっていません。物理というか数学というか、むずかしいです。最初っから、式で考えるのは諦めて、数字を変えながら、グルグル回すプログラムを作ってたりします。課題1の4つのコースはなんとかできました。そもそもブレーキを踏むと、なんで楕円な軌道になるのかさっぱりです。
上で宇宙船と言っているのは、全て衛星(satellite)の間違いです。英語もさっぱりだあ。
一応、全員のランキングが見えるんですが、下の方に載ってます。同じ数字がいっぱい並んでいるのは、たぶん式で解いた人達なんでしょう。これから課題2を考えてみようと思います。課題1は軌道に乗せればおしまいだったけど、課題2は別な衛星の1k以内に近づかないといけません。さてさて、どうすればいいのやら。今日というか、明日の夜中の3時までになんとかなるんでしょうか。

6/30 追記
今日の夜中の3時に無事終了したみたいです。結局、寝ちゃって課題2はしませんでした。今公開されているランキングは終了4時間前のものみたいです。その段階では249位でした。最終結果はICFPという国際会議で発表されます。

今更ながら、wikiのHohmann transfer orbitの記事を見ました。計算式が載っていて、試しに代入してみるとぴったりではありませんが、それっぽい数値が出てきます。うーん、計算式なしでやってたなんて、かなりの時間の無駄でした。出てくるのは最初の加速と2番目の加速と、あとは2番目に加速するまでの時間の3つです。この3つを力任せで探索してました。そのせいか計算式で計算するより、少しだけ点数がよくなっています。これは当たり判定が1kmあるので、当たり判定のあるあたりだけコースに入っていて、その先は知らないみたいなコース選びだったということだと思います。
物理関連だということで、おもいっきりやる気をなくしてましたが、wikiをちゃんと読めば普通に計算できたんですね。しくしく。

上でコンパイラと書きましたが、正確にはCへのトランスレータです。代入文くらいしかないので、ひたすら対応するCのコードに変換しているだけです。

課題2は既に別の軌道にいる人工衛星とランデブーする問題です。同じ軌道に入るのは課題1と同じです。回転速度は半径だけの関数なので、もう一つの人工衛星も同じ速度で回っています。なので、軌道に入っただけだと、速度が同じ同士でいつまでたっても追いつくことはありません。ちゃんとは解いていませんが、最初に時間あわせのための待ちを設けて、必要なだけ待ってから軌道移動すればぴったりの座標にいけるはずだと思います。課題3は相手が円でなく楕円の軌道になっています。これも時間合わせと、さらには2番目の加速で同じ楕円軌道になるようにしてやらないといけないはずです。たぶん楕円の一番底でランデブーします。課題2と違うのは、ランデブーするタイミングも合わせてやらないといけないことだと思います。ってか、そこまで分かっていて、なぜ手が動かないのか不思議です。課題4は問題すら見てません。

課題1の軌道変更の様子です。

グラフはエクセルで書きました。プログラムはx, y座標をprintfするので、ファイルにリダイレクトして、エクセルシートにコピペしています。xとyの間をTABにすると直接別の列になってくれるので、即時にグラフも更新されます。って、原始的ですね。

主催者から、各データがダウンロードできるようになっていますが、パスが間違っていて、ダウンロードできません。URLからbinaries/を削ってやるとダウンロードできるようになります。

とりあえず色々と楽しませていただきました。主催者のみなさまありがとうございます。参加者の皆様ごくろうさまでした。

FPGA将棋を作っている人がいます

2009-06-26 20:15:31 | FPGA
A級リーグ指し手1号」さんでは、FPGA将棋を作っておられます。ソースも公開されています。
うはー、すごいー。

コンピュータ将棋のことは、よく分からないので、ぐぐってみました。コンピュータ将棋協会blogさんの記事が参考になりました。
コンピュータ将棋専用機がやってくる
GPW-08イブニングセッション講演の動画: FPGA将棋

コンピュータ将棋の王座決定戦みたいな大会が毎年開催されているんだそうです。数年前に開発されたボナンザという将棋ソフトのせいで、このところ飛躍的にコンピュータ将棋は強くなっていて、それというのも学習を使っているところがポイントらしいです。そういえば2001年宇宙の旅のHALも学習でかしこくしていました。

ボナンザの話が知りたくて「ボナンザVS勝負脳―最強将棋ソフトは人間を超えるか」という本を買ってきて読みました。色々とすごいです。って、話題が数年遅れてますね><。でも、つい最近まで知りませんでした。

マイコンボード付き書籍2冊

2009-06-26 20:02:53 | その他のマイコン
CQ出版のページの近刊予告を見ているとマイコンボード付きの書籍が2冊出るみたいです。
dsPIC基板で始めるディジタル信号処理
dsPIC基板というと、トラ技2007年8月号の付録だった基板でしょうか?確かマルツで販売していました。

USBマイコンでパソコンI/O![78K0基板付き]
こちらは、2008年8月号の付録基板みたいです。目次にトラ技BIOSの文字が見えます。

diceをverilogに書き換えてみました

2009-06-22 21:43:31 | FPGA
diceを動かしてみましたの続きになります。

やっぱり、7セグLEDの方が雰囲気が出るということで、比叡につないでみました。

Spartan-3スタータキットにあわせて、アノードコモンの7セグLEDにしています。
電流制限抵抗は510Ωなので1セグメントあたり3mAくらい流れている計算になります。
ちゃんとデータシート見てないけど、このくらいならたぶん平気かな。
比叡の回路図を見ると電流制限抵抗が120Ωでした。

というわけで、オリジナルのVHDLソースをなるべくそのままVerilogに書き直してみました。(<が全角になっています)
// dice_top.vhd
module dice_top (reset_sw, clk, roll, an_n, a_n, b_n, c_n, d_n, e_n, f_n, g_n, dp_n);
    input reset_sw;
    input clk;
    input roll;
    output [3:0] an_n;
    output a_n;
    output b_n;
    output c_n;
    output d_n;
    output e_n;
    output f_n;
    output g_n;
    output dp_n;

    wire roll_sig;
    wire roll_ena;
    wire [2:0] binary;

    assign an_n = 4'b1110;
    assign dp_n = 1'b1;

    reject_chatter inst_reject_chatter (
        .reset_sw(reset_sw),
        .clk(clk),
        .roll(roll),
        .roll_sig(roll_sig),
        .roll_ena(roll_ena)
    );

    dice_state_machine inst_dice_sm (
        .reset_sw(reset_sw),
        .clk(clk),
        .roll(roll_sig),
        .roll_ena(roll_ena),
        .spots(binary)
    );

    seven_seg_dec inst_seven_seg_dec (
        .binary(binary),
        .a_n(a_n),
        .b_n(b_n),
        .c_n(c_n),
        .d_n(d_n),
        .e_n(e_n),
        .f_n(f_n),
        .g_n(g_n)
    );

endmodule

// reject_chatter.vhd
module reject_chatter (reset_sw, clk, roll, roll_sig, roll_ena);
    input reset_sw;
    input clk;
    input roll;
    output roll_sig;
    output reg roll_ena;

//  parameter frequency_KHz = 1;
    parameter frequency_KHz = 50000;
    parameter divided_200Hz = frequency_KHz * 5;

    reg [17:0] sw_cnt;
    reg [1:0] roll_cnt;
    reg roll_node;

    // 200Hz, 5ms
    always @(posedge clk or negedge reset_sw)
        if(reset_sw == 1'b0)
            sw_cnt <= 0;
        else if(sw_cnt == (divided_200Hz - 1))
            sw_cnt <= 0;
        else
            sw_cnt <= sw_cnt + 1;

    always @(posedge clk or negedge reset_sw)
        if(reset_sw == 1'b0)
            roll_node <= 1'b1;
        else if(sw_cnt == (divided_200Hz - 1))
            roll_node <= roll;

    assign roll_sig = roll_node;

    // 50Hz, 20ms
    always @(posedge clk or negedge reset_sw)
        if(reset_sw == 1'b0) begin
            roll_cnt <= 2'b00;
            roll_ena <= 1'b0;
            end
        else if(sw_cnt == (divided_200Hz - 1))
            if(roll_cnt == 2'b11) begin
                roll_cnt <= 2'b00;
                roll_ena <= 1'b1;
                end
            else begin
                roll_cnt <= roll_cnt + 1;
                roll_ena <= 1'b0;
                end
        else
            roll_ena <= 1'b0;

endmodule

// dice_state_machine.vhd
module dice_state_machine (reset_sw, clk, roll, roll_ena, spots);
    input reset_sw;
    input clk;
    input roll;
    input roll_ena;
    output reg [2:0] spots;

    parameter [2:0]
        st_one = 3'h1, st_two = 3'h2, st_three = 3'h3,
        st_four = 3'h4, st_five = 3'h5, st_six = 3'h6;

    reg [2:0] current_state, next_state;

    always @(posedge clk or negedge reset_sw)
        if(reset_sw == 1'b0)
            current_state <= st_one;
        else
            current_state <= next_state;

    always @(current_state, roll, roll_ena)
        case(current_state)
        st_one : begin
            spots = 3'b001;
            if(roll == 1'b1 & roll_ena == 1'b1)
                next_state = st_two;
            else
                next_state = st_one;
            end
        st_two : begin
            spots = 3'b010;
            if(roll == 1'b1 & roll_ena == 1'b1)
                next_state = st_three;
            else
                next_state = st_two;
            end
        st_three : begin
            spots = 3'b011;
            if(roll == 1'b1 & roll_ena == 1'b1)
                next_state = st_four;
            else
                next_state = st_three;
            end
        st_four : begin
            spots = 3'b100;
            if(roll == 1'b1 & roll_ena == 1'b1)
                next_state = st_five;
            else
                next_state = st_four;
            end
        st_five : begin
            spots = 3'b101;
            if(roll == 1'b1 & roll_ena == 1'b1)
                next_state = st_six;
            else
                next_state = st_five;
            end
        st_six : begin
            spots = 3'b110;
            if(roll == 1'b1 & roll_ena == 1'b1)
                next_state = st_one;
            else
                next_state = st_six;
            end
        default : begin
            spots = 3'b001;
            next_state = st_one;
            end
        endcase

endmodule

// seven_seg_dec.vhd
module seven_seg_dec (binary, a_n, b_n, c_n, d_n, e_n, f_n, g_n);
    input [2:0] binary;
    output reg a_n;
    output reg b_n;
    output reg c_n;
    output reg d_n;
    output reg e_n;
    output reg f_n;
    output reg g_n;

    always @(binary)
        case(binary)
        3'b001: begin // 1
            a_n = 1'b1; b_n = 1'b0; c_n = 1'b0; d_n = 1'b1; e_n = 1'b1; f_n = 1'b1; g_n = 1'b1; end
        3'b010: begin // 2
            a_n = 1'b0; b_n = 1'b0; c_n = 1'b1; d_n = 1'b0; e_n = 1'b0; f_n = 1'b1; g_n = 1'b0; end
        3'b011: begin // 3
            a_n = 1'b0; b_n = 1'b0; c_n = 1'b0; d_n = 1'b0; e_n = 1'b1; f_n = 1'b1; g_n = 1'b0; end
        3'b100: begin // 4
            a_n = 1'b1; b_n = 1'b0; c_n = 1'b0; d_n = 1'b1; e_n = 1'b1; f_n = 1'b0; g_n = 1'b0; end
        3'b101: begin // 5
            a_n = 1'b0; b_n = 1'b1; c_n = 1'b0; d_n = 1'b0; e_n = 1'b1; f_n = 1'b0; g_n = 1'b0; end
        3'b110: begin // 6
            a_n = 1'b0; b_n = 1'b1; c_n = 1'b0; d_n = 1'b0; e_n = 1'b0; f_n = 1'b0; g_n = 1'b0; end
        default : begin
            a_n = 1'b1; b_n = 1'b0; c_n = 1'b0; d_n = 1'b1; e_n = 1'b1; f_n = 1'b1; g_n = 1'b1; end
        endcase

endmodule

Verilogにはtypeがないのでparameterでごまかしています。
オリジナルと違うのは比叡に合わせてリセットをアクティブローにしているところと、roll_nodeの初期値を1にしたことです。roll_nodeは0のとき、キーが押されていることになるのですが、リセットを押した直後は一瞬だけキーを押したことになるので、リセットのときの初期値を1'b1、つまりキーは押されていない状態にしました。
VHDLはなんでもsignalでいいみたいなんですが、Verilogは状況に応じてwireとregを使い分けないといけないのが面倒です。
VHDLの方は35スライスでしたが、Verilogだと32スライスと3スライス減りました。理由は分かりません。

いい勉強をさせていただきました。

diceを動かしてみました

2009-06-17 19:54:27 | FPGA
トラ技2009年6月号の別冊付録「再確認 電子機器の開発ツール」にFPGAの部屋のmarseeさんが、FPGAの開発方法の解説記事を書かれています。そこで使われていたのがdiceというサイコロのサンプルです。VHDLのソースは、FPGAの部屋さんの「ISE11.1iのチュートリアル1(導入編)」という記事に貼り付けてあります。先日買ったLatticeXP2基板「比叡」で動かしてみました。
徒然日記さんがAlteraで動かしているので、Xilinx、Altera、Latticeと3社のFPGAで動作が確認されたことになります。


オリジナルのソースはSpartan-3スタータキット用です。違うところは、比叡には7セグLEDがないので普通のLEDにしてしまったところと、リセットの極性が逆(比叡はアクティブロー)なところ、クロックが比叡は32.768MHz(SP3の方は50MHz)なところです。

使用スライス数は35でした。


VHDLのprocess文を使って非同期リセットを記述するには以下のように書きます。
process(clk, reset) begin
  if(reset = '1') then
    リセット時の動作
  elsif(clk'event and clk = '1') then
    クロック立ち上がり時の動作
  end if;
end process

この例ではresetが1のときにリセット時動作をするのでアクティブハイです。比叡で動作させるには0のときに動作させたいのでifの判定をreset='0'に書き換えることになります。

ちなみにverilogで同じことをalways文を使って書くと次のようになります。
always @(posedge clk or posedge reset)
  if(reset)
    リセット時の動作
  else
    クロック立ち上がり時の動作

ついでに、VHDLの同期リセットです。
process(clk) begin
  if(clk'event and clk = '1') then
    if(reset = '1') then
      リセット時の動作
    else
      クロック立ち上がり時の動作
    end if;
  end if;
end process;

resetのif文がclkのif文の内部に入っているのでクロックに同期しています。またprocessのセンシティビティリストがclkのみになっています。このあたりは、慣用句というか、形で覚えておくとよさそうです。

verilogの同期リセットは次のようになります。
always @(posedge clk)
  if(reset)
    リセット時の動作
  else
    クロック立ち上がり時の動作

verilogでは、センシティビティリストが変わるだけです(posedge resetがなくなります)。

と、ここで気づいたのですが、diceのソースでは以下のような記述になっています。
process(clk) begin
  if(reset = '1') then
    リセット時の動作
  elsif(clk'event and clk = '1') then
    クロック立ち上がり時の動作
  end if;
end process;

私の知っている同期リセットとも非同期リセットとも違います。どのような動作をするんでしょうか?

まだVHDLは、よく分かりません。

6/20 追記 diceのソースの件は、センシティビティリストの書き忘れだったそうです。弘法も筆の誤りといったところでしょうか。marseeさんのフォローの記事「ISE11.1iのチュートリアル1(導入編)の訂正」、徒然日記さんのフォローの記事「非同期リセットと同期リセット」が出ています。ISE、Quartus、ispLEVER、どのツールもwarningは出ていた模様です。合成ツールはたいてい山のようにwarningを吐き出してくれるので、warningに不感症になりやすいです。あまりに多すぎて見る気になれなくなっちゃいます。これはこれで役に立たないというか、重要なwarningを見落とす原因になります。このあたりは何とかしてもらいたいものです。


LatticeXP2のFPGAボード買っちゃいました

2009-06-10 00:31:19 | FPGA
今年のESECで見かけた富士エレクトロニクスさんのLatticeXP2トレーニングボード比叡を買っちゃいました。


お気に入りな点は、コンフィグ回路内蔵なのでUSB接続するだけで、FPGAに書き込めるところと、USB給電で動作しちゃう点です。自由に使えるI/Oが多いのもポイント高いです。

裏面にはSRAMを増設できるパターンが用意されています。型番はCY62148EV30LLとコンパチなSRAMを使えるみたいです(digikey品番428-2076-ND)。

とりあえず気をつけないといけないのが、拡張ポートに出ている電源が全て5Vな点です。I/Oは3.3V固定なので、どうせなら3.3Vも出してほしかったところです。

電源LEDとかステータス関係のLEDが全くありません。コスト削減といったところでしょうか。設定用のジャンパーも一切ありません。外部電源とUSB電源の切り替えはチップ抵抗の張替えになります。また、内蔵フラッシュか外部フラッシュかの切り替えもチップ抵抗を貼ることになります。

載っているFPGAは結構でかいです。Latticeは型番がルックアップテーブル(LUT)の数を表しています。LFXP2-17Eの「17」が17k個、LUTが載っていることを表しています。DD誌の付録のはLFXP2-5Eなので5k個LUTが載っています。

DD誌のLatticeXP2基板と並べてみました。

DD誌基板の長辺と比叡の短辺がちょうど同じ長さです。面積で2倍ちょいくらいになります。

Latticeのダウンロードケーブルの信号を眺めてみました

2009-06-08 22:44:19 | FPGA
Latticeのダウンロードケーブル動きましたの続きになります。

前回の記事で色々とコメントをいただき、実際にどうなっているのか(プルアップの影響とか、信号波形とか)を見たいと思いました。

結論から言うと、Thinkpad T42のプリンタポートは3.3Vみたいで、レベル変換は起こっていませんでした。Latticeのコンフィグ用の信号も3.3Vです。ちなみにXilinxのSpartan-3E付録基板では2.5Vでした。

測定したのはプリンタポートの3ピン(ch1)と、対応するTCK(ch2)です。TCKはFPGA基板の直前、プリンタポートも直後です。入力側のプルアップ抵抗は、はずしています。

まずはプリンタポートの出力波形(ch1)です。

縦軸は1divが2Vなのでだいたい3.3Vくらいです。横軸は1div 2.5usです。

次はFPGA基板に伝わっているTCK(ch2)の信号です。

スケールは上と一緒です。リンギングが上より目立ちます。

ch1(赤)とch2(黄)を重ねてみました。

微妙にレベルシフトされてます。GNDが少し浮いているのが気になります。

拡大してみました。

横軸は1div 25nsです。100倍くらい拡大したことになります。入力(赤)より出力(黄)の方が鋭く立ち上がっていることが分かります。このあたりは、74LCX244を入れた効果です。

さらに拡大してみました。

横軸は1div 10nsです。このオシロ(PDS5022S)は100Mサンプル/秒なので、一見なめらかに見えていますが、補間しているので、あまり当てにならないはずの画像です。ちなみに5nsまで拡大できることになっていますが、それって2div 1ポイントってことになるんでしょうか。

というわけで、プルアップで悩んだりしていましたが、今回に限っていうとなくても平気だったみたいです。特にFPGA基板側にプルアップ抵抗とプルダウン抵抗があります。

TCKの速度は180kbpsくらいみたいでした。3.3V系だと適当に抵抗を挟むだけで、バッファICなしでも、ダウンロードできるかもしれません。

Latticeのダウンロードケーブル動きました

2009-06-02 22:45:29 | FPGA
Latticeのダウンロードケーブル作成?の続きになります。

Latticeの書き込みツールispVM Systemでも動作することを確認しました。最初、ドライバがはいっていなかったらしく、変なエラーが出ていましたが、メニューのispTools → Install/Uninstall LSC USB/Parallel Port Driverを選んでインストールしなおしたところ、うまく動くようになりました。
これで、ispLEVERを使って*.jedファイルを作って、ispVMでFPGAに書き込むことができるようになりました。

昨日作った回路の回路図です(クリックすると拡大します)。


部品は、100Ω抵抗×8、10kΩ×3、0.1uF積層セラミックコンデンサ、74LCX244です。後は変換基板やコネクタ類です。

74LCX244の入力側を、一応プルアップしたつもりですが、3.3Vでいいんでしょうか?5Vが電源に流れ込んじゃう?このあたりがよく分かってないところが一番の弱点です。

ちなみに、ほとんど同じ回路でザイリンクスのダウンロードケーブルも作れちゃいます。スイッチで切りかえれるようにするのもありです。

ザイリンクスのケーブルのときの接続
・パラレルポートの13ピン <---> 74LCX244の9ピン(2Y1)
・パラレルポートの8ピン-11ピン-12ピンを接続

Latticeのケーブルのときの接続
・パラレルポートの10ピン <---> 74LCX244の9ピン(2Y1)
・パラレルポートの8ピン-12ピン-13ピンを接続

ブレッドボードでスカスカに作って動くくらいなので、かなり動作は安定していると思います。
電源はケーブル側から供給していますが、FPGAボード側からもらってもいいです。
DD誌の回路図との違いです。

・ispEN、RESET、JTAGという3本の線を省略しています。
・DD誌の回路図では、74LCX244でなく74VHC244になっています。
・DD誌の回路図では、入力側のダンピング抵抗がありません。
・DD誌の回路図では、出力側はローパスフィルターになっています。
・DD誌の回路図では、パラレルポートの15ピンにVccをつなげています。
・DD誌の回路図では、TDOもプルアップしています。

DD誌の回路図は雰囲気的にSPI接続のフラッシュROMにも書き込める回路になっているように思えます。

74LCX244は8個もバッファがついているのに4個しか使っていません。74LCX125とかでもよさそうです。

Latticeのダウンロードケーブル作成?

2009-06-01 23:48:02 | FPGA
ディジタル・デザイン・テクノロジ(DD)の創刊号にはLatticeXP2のFPGAボードが付録でついてきました。

なひたふさんのツールを使えばザイリンクスケーブルでも書き込みができるのですが、Lattice互換のダウンロードケーブルも作ってみたくなりました。

いつものようにブレッドボードです。


バッファICは74LCX244です。ダイセンの変換基板にはんだづけしてあります。

昔ザイリンクス用に作ったダウンロードケーブルからはずしてきました。

LatticeXP2基板のCN3にJTAGの線をつないでいます。


こちらはパラレルポートへつないでいます。

このケーブルはHuMANDATAさんのアルテラ用ダウンロードケーブルについてきたパラレルポート用のケーブルです。たしかフラットケーブル単体でも販売していたはずです。MIL26ピンとDIP25ピンがつながっていて、この手の工作には便利なアイテムです。

とりあえずは、MITOUJTAGで動作確認です。

Lattice用のケーブルの設定にして、IDCODEの読み出しや、LEDチカチカの様子が画面で見れました。古いバージョンですが、ケーブルの動作確認には役に立ちます。

さてさて、なんとか動いているようです。

次はLatticeのツールを使って書き込みができるかどうかを調べます。
回路図はDD誌に載っていたのをかなり簡略化しています。どうせ4本つなげば動くんでしょ?くらいのノリです。Latticeのツールで駄目なら、ちょっとずつDD誌の回路図に近づけていくつもりです。
というわけで続きます。