半導体設計について何も知らない素人が1ヶ月で8bitCPUをテープアウトした話

この記事は HDL Advent Calendar 2021 25日目の記事です。 すいません、11日ほど遅れての投稿です。

この記事では、以下のツイートに至るまでの裏話について話させていただきます。 HDLに関係があるかというとかなーり微妙ですが、許していただきたいです🙏

導入

さて、皆さんCPU自作していますか? 最近もまた、緑の本が出版されるなどして、CPUづくりが盛り上がっているようで、嬉しい限りです。

ご存知のようにCPU自作にもいろんな流派がありまして、オレオレISAの変わったCPUを作ったり、性能を求めてスーパースカラー化したり、自作CPUの上で動かすソフトウェアに凝ったり、電子部品を使って手ではんだ付けをすることによって作ったりと様々です。

上記で挙げた例では、FPGAボードを使ったり、シミュレータで動かしたり、基板に実装したりするわけですが、これらは実際に市販されているCPUとは異なり、実際の半導体のレイアウトになっているわけではありません。現実のCPU製作では、この半導体のレイアウトにも膨大なコストがかかっているはずで、せっかくCPUを作るのであればぜひその大変さを味わってみたいと思うのが人情です。

しかし、半導体のレイアウトをするツール類というのは一般にクローズドで、入手できたとしても莫大な金額がかかります。うーん困った困った...

そんな所にピエロくんがいい情報を持ってきてくれました。

vlsi.jp

オレオレLSIを焼きたいですよね? 焼きましょう。 Skywater社がPDKを公開し、OSSなGDSIIコンパイラであるOpenLANEも生まれました。そしてGoogleの出資によってEfablessが無料でLSIを作らせてくれるプログラム、Open MPW Shuttle Programをスタートしました。 今こそオレオレLSIを焼くチャンスです。あなたの作りたいチップをGoogleの金で作りましょう!

はい、なんとツールが公開されていて、しかも製造もタダでやってくれるらしいじゃないですか!これをやらない訳はありません。しかし、次回の締切まで約1ヶ月...どうなっちゃうの私達!

何はともあれ、手を動かしてみよう!そういう感じで始まりました。*1

Jacaranda-8について

さて、今回テープアウトしたのは1年ほど前にピエロと一緒に作ったオレオレ8bitアーキテクチャ「Jacaranda-8」の「charlatan」という実装です。このアーキテクチャは命令長もバス幅も8bitでとても窮屈ながらも、割り込みにも対応しておりUARTもあるので、意外と楽しいものになっております。簡易的なラベルに対応したアセンブラもあります。詳細はこちらをご覧ください。

LSI設計の流れ

さて、ここに書くことは我々も最近になって理解したことで、つまりこのプロジェクトを進行するに当たっては全然知らなかったことです。

LSIの設計は、LSIの大規模化に伴って自動化が進んでおり、今回のプロセスであるsky130を使った設計についても、OpenLANEというツールが対応しているので、基本的にはVerilogのコードと要求するLSIのスペックを記述したconfigファイルを用意することで行うことが出来ます。

しかし、LSIのレイアウトを実際に描いていく配置配線という作業は本質的に組み合わせ最適化問題で、configをうまく調整したり、Verilogコードの最適化を行ったりしてうまく解けるように試行錯誤する必要があり、ここが肝心で大変な作業という認識です。

OpenLANEについて

OpenLANEはOpenROADという所が作っているLSI設計の自動化ツールで、OpenROADやyosysやmagicといったOSSのツールを組み合わせて構成されています。 f:id:yuhki0223:20211221212225p:plain OpenLANEの中では、LSIレイアウトの生成に必要な各工程が自動化されており、中間ファイルを生成しては次のツールに渡して、というのを繰り返すことでGDSというレイアウトの図形データを作ります。 上の図はその工程の流れを示しています。

論理合成からタイミング解析、テスト、配置配線、最適化などを行います。

Caravelについて

今回のOpenMPW Shuttleでは、Caravelというハーネスが用意されています。Caravelは、RISC-VのマネジメントSoCやGDSの配置などを含むもので、我々のモジュールはこのマネジメントSoCを通して信号を入出力することができます(もちろん生のピンにつなげることも出来ます)。またEfablessがこのCaravelを使ってcaravel_user_projectというレポジトリを公開しており、これを自分の環境に持ってきて、caravel_user_project_wrapperに自分のモジュールをインスタンス化することによってGDSの生成はもちろん、マネジメントSoCを含むシミュレーション等ができるようになっています。

実際の作業の概要

序盤

まずはこれをダウンロードしてJacaranda-8のHDLを配置しました。そのままのconfigでビルドしてみたところうまく行ったかのように見えたのですが、GDSビューワーで確認してみると何も生成されてないやんけとなりました。しばらく色々と調べてみると、yosysの最適化で自分たちのHDLがばっさり無視されてしまっていることが分かりました。

トップモジュールの入出力の記述が良くないようだったので、これらを改善することで解決しました。

中盤

上記が解決すると、今度はビルドが通らなくなりました。現状デフォルトのconfigになっているので、生成するGDSの面積や実装密度などを調整しないとダメなようです。Jacaranda-8はメモリの記述を含んだモジュールのため、回路が複雑化し、大変苦労しました。本来であれば、メモリだけ外部のメガセルを使えると良かったのですが、あまり知識がなかったので結局手を出すことが出来ませんでした。1-2週間、ピエロと共に1回8時間以上かかるビルドをひたすら回し続けました。時にはメモリが足らなくなり、swapを大量に切ることもしばしば。また、efablessのサイトでprecheckというテストを通すことができるのですが、用意されているvmのコンピュータのメモリが16GBで、足りなくなってしまい、急遽メモリを増やしていただくなどの対応をしていただきました。色々試した結果、なんとかビルドには成功することが出来ました。

終盤

さて、最後の仕上げとしてefablessのサイトでtapeoutという最終テストに通します。ここでは、precheckより厳しく製造時のルールに違反していないか、ちゃんと動作するのかなどを見られているようです。

HDLに同期リセットと非同期リセットが混在しているのを発見し、改善しました。 お行儀の良いHDL記述について全く知見がなかったので、もしかするとまだまだ改善する余地があるのかもしれません。

終盤は、特にタイミング解析での違反を解決する作業でした。他のプロジェクトのコンフィグを見様見真似で取り入れたりしました。

締め切りの前日からは、Efablessのメンバーの人がDMでつきっきりで対応してくれるなど、かなり有り難かったです。

まとめ

ざっくりとではありますが素人がテープアウトするまでの様子を書かせていただきました。今まで全く知らなかったLSI製造の一端を知れた気がして楽しかったです。それにしても分からないことが依然として多すぎるので今後勉強していきたいです。

*1:実は、二人でLSIを作ろうと決めたのはちょうど二人で遠くまで出掛けていたタイミングで、空港でOpenLANEをインストールしてあれこれ作業したのを今でも覚えています

山登り2021

この記事は東京高専プロコンゼミ① Advent Calendar 2021 15日目の記事です。

今年は色々な山に登りました。この記事では今年登った山のハイライトを紹介をします。

雲取山 1/5-1/6

行程

詳細

雲取山は、東京都最高峰として有名な山です。標高2017m。今回冬季テント泊は初めての経験となりました。 冬季のテント泊となると、荷物の体積・重量が夏季と比べて大きくなるため、辛かったです。冬用シュラフと大容量ザック、軽アイゼンなどを揃えて臨みました。

鴨沢バス停からの道中、他の登山客はいないようでした。冬季の平日なので、当然かも知れません。野生の猿が登山道の近くに群れていて、癒やされました。暖冬で熊が冬眠しないこともあると聞いたことがあったので、少し怖かったです。

登山道には岩場など特に難所はありませんでした。若干積雪があり、試しの意味もあって軽アイゼンを装着したりもしましたが、雪があまり深くなかったので、歩きにくかったです。

f:id:yuhki0223:20211215003324p:plain いい天気だった七ツ石山

f:id:yuhki0223:20211215003418p:plain 雲取山頂付近から登山道を振り返る

テントは、雲取山荘のテント場に貼りました。1人500円で、1Lの水がついてきた記憶です。 コーラは確か400円だったかな。気温が低く、常に冷たいコーラを飲めて最高でした。 f:id:yuhki0223:20211215003736p:plain

テントを張って、1時間ほど仮眠。めちゃくちゃ寒い。 日が沈んで、星空が見えるようになったので、撮影会をしました。

f:id:yuhki0223:20211215003924p:plain

20時で-10℃だったので、深夜はもっと冷え込んだんじゃないだろうか...

f:id:yuhki0223:20211215004039p:plain f:id:yuhki0223:20211215004112p:plain

寒いのでちゃんと寝れるか不安でしたが、持ってきた服を全部着て寝袋を完全に閉じることで乗り切りました。両足先がとても冷えるのでカイロは絶対に必要です。

翌朝。日の出前から行動開始です。実は天の川がチラッと見えるんじゃないかと期待して早起きしたのですが、流石に厳しかったです。

f:id:yuhki0223:20211215004536p:plain f:id:yuhki0223:20211215004604p:plain 鹿に遭遇。全然警戒されてない。

三峯神社の近くまで降りると、人も多くなってきてなんとなく安心しました。

西武秩父駅でわらじかつを食べて帰宅。

二子山 8/22

行程

尾登山口→股峠→東岳→股峠→西岳→股峠→倉尾登山口

詳細

前から気になっていた二子山に登りました。二子山は、岩場の続く登山道として有名です。標高1166m(西)。

f:id:yuhki0223:20211215005948p:plain 入口から物々しい看板です。

f:id:yuhki0223:20211215010113p:plain 東岳から望む西岳。

f:id:yuhki0223:20211215010224p:plain f:id:yuhki0223:20211215010937p:plain

こういう感じの登山が続きます。

f:id:yuhki0223:20211215010718p:plain 西岳山頂。険しくてカメラをザックにしまってしまったので、あまり写真がありません。 行程自体は短く、お昼頃には下山できました。下山中、ロッククライミングをしている人たちを見かけてスゲーとなりました。

岩場の練習にオススメの山です。高度感があり、踏み外すとちゃんと死ねるので結構怖いです。落石対策にヘルメットは必要でしょう。

後立山連峰(爺ヶ岳鹿島槍ヶ岳五竜岳) 9/26-9/28

行程

詳細

北アルプスでのテント泊をしてみたかったので、定番(?)の八峰キレット縦走路へ。鹿島槍ヶ岳五竜岳日本百名山です。主要標高は、爺ヶ岳2670m(中)。鹿島槍ヶ岳2889m(南)。五竜岳2814m。

今年一番の過酷登山となりました。テントを担いでの2泊3日行程は初めてです。 夏なので荷物も冬ほど重くならないだろうと高を括っていましたが、食事が重く、冬とそんなに変わらない重さでした。 f:id:yuhki0223:20211215103701p:plain f:id:yuhki0223:20211215103724p:plain

1日目の天気は雨。気温も低く、かなり悪かったです。2日目以降の行程は、重い荷物を背負っての岩場となるため、足元が濡れていたら引き返すつもりでしたが、天気予報によれば曇りのようだったので、1日目の幕営地まで行ってみることにしました。

f:id:yuhki0223:20211215104029p:plain f:id:yuhki0223:20211215104116p:plain

歩いて4.5時間ほど、種池山荘に到着です。 f:id:yuhki0223:20211215104219p:plain f:id:yuhki0223:20211215104314p:plain 運のいいことに、雨が止みました。種池山荘はピザなどの販売が有名のようですが、この日は雨だからか登山客も全然おらず、販売もしていないようでした。

昼飯を食べて、歩くこと40分。今日初めての頂上に到着です。 f:id:yuhki0223:20211215104614p:plain

ここから先の登山道は、尾根道で、北アルプス〜という感じの風景です。 f:id:yuhki0223:20211215104731p:plain f:id:yuhki0223:20211215104759p:plain

歩を進めること1時間弱。冷池山荘が見えてきました。 f:id:yuhki0223:20211215104954p:plain f:id:yuhki0223:20211215104923p:plain 晴れ間も見えてきて、最高です。これはテントを濡らさずに済むかもしれないと期待。

f:id:yuhki0223:20211215105101p:plain なんとか日没前に到着。テント場は山小屋から10分くらい登ったところにあります。 f:id:yuhki0223:20211215105203p:plain

翌朝。2日目の行程は12時間を超える見込みだったので、日の出前から出発です。 f:id:yuhki0223:20211215105502p:plain f:id:yuhki0223:20211215105657p:plain 天気がいい!雲海を望みながら鹿島槍ヶ岳を目指します。

f:id:yuhki0223:20211215105710p:plain

f:id:yuhki0223:20211215105748p:plain ご来光もばっちり見えました。

f:id:yuhki0223:20211215105858p:plain

景色に癒やされながら進むこと1時間弱、鹿島槍ヶ岳に到着です。

f:id:yuhki0223:20211215110051p:plain これから進む道も見えてきました。

鹿島槍ヶ岳から先五竜岳までかなり険しく、落ちたら死ぬな〜という緊張感が続きます。 f:id:yuhki0223:20211215110605p:plain 来た道を振り返ります。画像右の頂上が鹿島槍ヶ岳f:id:yuhki0223:20211215110625p:plain こっちは一眼レフで撮影。持ってきたレンズの画角的に鹿島槍ヶ岳が入りませんでしたが、十分距離感を感じていただけるのではないでしょうか。

軽く死ねますね〜と思いながら慎重に進み、八峰キレットに到着。 f:id:yuhki0223:20211215111204p:plain f:id:yuhki0223:20211215111303p:plain

ここから先も、更に険しさが増して急峻な地形が続きます。 f:id:yuhki0223:20211215111406p:plain f:id:yuhki0223:20211215111939p:plain

荷物が重く、バランスを取るのが難しいため通過に時間がかかります。 途中雷鳥に出会ったりしながら、山頂はまだかまだかと登ること5.5時間。五竜岳に到着です。

f:id:yuhki0223:20211215112113p:plain

写真がないのですが、五竜岳から幕営地の五竜山荘も見えました。まだかなり距離がある様子。 結局1時間ほど歩いて到着しました。テント場の料金を払うと共に、コーラを買います。

f:id:yuhki0223:20211215112356p:plain

(写真を取り忘れていた事に気づいて夜撮ったので暗いです)

テントなどの写真は疲れ果てていて撮っていない様子。下山したら肉を食おう!などと言っていると、隣のテントの方が豚の焼肉を差し入れてくださいました。本当にありがたい。

3日目もご来光が見えました。 f:id:yuhki0223:20211215112911p:plain f:id:yuhki0223:20211215112943p:plain

遠見尾根を進みます。途中まちが見えて綺麗でした。 f:id:yuhki0223:20211215113104p:plain

下りておよそ4時間。アルプス平駅に到着。コーラを飲んで登山終了です。 f:id:yuhki0223:20211215113233p:plain

夕食はちゃんと肉にありつきました。たまらん。 f:id:yuhki0223:20211215113339p:plain

総評

さて、写真を中心に今年登った山を紹介して参りました。来年も山頂で飲む美味しいコーラを求めていろんな山に登っていきたいです。

UEFI ELFローダーを作る 前編(Zigの紹介)

これは東京高専プロコンゼミ① Advent Calendar 2020 22日目の記事です。

導入

自作OSを始めるためには、はじめに一山超えなければなりません。 その山とはブートローダーです。legacy BIOSであっても、UEFIであってもまずはじめに書くのは自分のOSをロードするためのブートローダーなのです。

このブートローダー、OSを作りたいと意気込んでいる人にとってはちょっと厄介です。なぜなら、ブートローダーはOSほど魅力的なものではなく*1、その割にAPIについて調べたり思いの外手間がかかるからです。 そしてUEFIでのブートローダーの書き方について、UEFIアプリを書いたことがない人でも分かるように説明されている記事があまりないようでした。

そこでこの記事ではUEFIでELFファイルをロードするブートローダーの書き方について見ていこうと思います。時間がなかったので、記事を前後編に分けて前編である今回は、Zigの紹介パートとします。

今回、ブートローダーを作るにあたっては、C言語ではなくZigという言語を用いました。この言語は、C言語を置き換えることを目的とした言語であり、C言語と比べて安全なプログラムが書けるようにデザインされています。システムプログラミングや組み込みプログラミングで嬉しい機能も標準で組み込まれています。

ziglangについて

ziglangは、シンプルで安全なプログラミング言語で現在活発に開発されています。システム開発や組み込み開発向けのライブラリや機能も充実しており、UEFI APIにも対応しています*2

ziglang.org

なぜziglangを使うのか

ziglangは、C言語の置き換えとして使うことを推奨しています。このことは、zigコンパイラがCコンパイラを含んでいることからもわかります。C言語は、とても危険な言語です。例えば、以下のコードには潜在的なバグが幾つか有りますが気づけますでしょうか。

gist.github.com

yuki/Akagi :) ./a.out
please input number: -9
zsh: segmentation fault (core dumped)  ./a.out

ひとつは、よくあるバグなので見つけやすいでしょう。そうです、scanfの引数に変数のポインタではなく、変数そのものを渡してしまっているため、不正なアドレス参照が起きてセグメンテーション違反となりました。直したコードが以下です。しかし、まだバグがあります。確認してみましょう。

gist.github.com

yuki/Akagi :) ./a.out
please input number: -9
v: -9, data: 65535

dataの値が変わってしまいました。理由はわかりますでしょうか。フォーマット指定子がdなのにshortのポインタを渡してしまっていますね。結果、buffer over runが起きてスタック上の隣の変数まで書き込んでしまうことになります。このバグは、gccでwarningを表示するようにすれば検出することができますし、考えればわかることですが、そもそもこんなコードを意図して書いていたら相当ヤバイと思うので、どうせならコンパイルエラーにしてほしいと思うのです。

yuki/Akagi :) gcc -Wall test.c
test.c: In function ‘main’:
test.c:10:13: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘short int *’ [-Wformat=]
   10 |     scanf("%d", &v);
      |            ~^   ~~
      |             |   |
      |             |   short int *
      |             int *
      |            %hd

以上のコードと同じ入出力を行うプログラムをzigで書くと以下のようになります。

gist.github.com

いくつか特徴をピックアップしてみましょう。

pub fn main() anyerror!void {
    const stdin = std.io.getStdIn();
    var v: u16 = undefined;
    const data: usize = 80;

zigでは、変数の宣言時には初期値を設定することが強制されています。これにより、初期値の設定し忘れによるバグを埋め込む余地がありません。また、次に詳しく述べますが標準入出力関数として特別なものは用意されておらず、標準入出力は単なるファイルとして扱います。std.io.getStdIn()で標準入力ファイルを取得できます。特に初期値がない場合には、undefinedで初期化することができます。undefinedで初期化した変数に何も代入しないまま使用するとそれはバグとなります。zigでは、debugモードにおいてundefinedで初期化すると0xaaが書き込まれるようになっています。これにより、早期にバグを検出することができます。

    std.debug.warn("please input number: ", .{});
    v = read_num(u16, &stdin);
    std.debug.warn("v: {}, data: {}\n", .{ v, data });
}

先程少し書きましたが、zigでは標準入出力を特別に抽象化していません。標準入出力は、zigの標準ライブラリにあるAPIを使ってユーザーの責任において行う必要があります。今回はお試しコードなので出力はstd.debug.warn関数を用いました。これは、debugモードにおいてのみ有効なものです。入力はデバッグモードだけで使えるようなものもないのでお試しであっても自分で書かなくてはなりません。

fn read_num(comptime T: type, stdin: *const std.fs.File) T {
    var buf: [64]u8 = undefined;
    const len = stdin.read(&buf) catch |err| {
        std.debug.warn("Error while reading number: {}\n", .{err});
        std.os.exit(1);
    };
    if (len == buf.len) {
        std.debug.warn("Input is too big!\n", .{});
        std.os.exit(1);
    }
    const line = std.mem.trimRight(u8, buf[0..len], "\r\n");
    const val = std.fmt.parseInt(T, line, 10) catch |err| {
        std.debug.warn("Error while parsing number: {}\n", .{err});
        std.os.exit(1);
    };
    return val;
}
fn read_num(comptime T: type, stdin: *const std.fs.File) T {

関数宣言です。comptimeを使ってジェネリックプログラミングができます。

var buf: [64]u8 = undefined;

zigの配列型は、要素数ごとに固有の型になっています。つまり、[64]u8のbufと[128]u8のbufは別物です。もし、配列外参照をコンパイル時に検出した場合にはコンパイルエラーとしてくれます。さらに、コンパイル時に検出できなかった配列外参照についてもデバッグモードの強力なランタイムにより検出することができます。このランタイムは、@panic関数を自分で実装しさえすればベアメタルにおいても使用することができます。

./main.zig:5:8: error: index 65 outside array of size 64
    buf[65] = 'a';
index out of bounds
/home/yuki/workspace/tmp/zig-test/src/main.zig:33:9: 0x22cdea in main (zig-test)
    hoge[v] = 'a';
pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
    @setCold(true);
    EFI.puts("PANIC: ");
    EFI.puts(msg);
    EFI.puts("\r\n");
    while (true) {}
}
    const len = stdin.read(&buf) catch |err| {
        std.debug.warn("Error while reading number: {}\n", .{err});
        std.os.exit(1);
    };
    if (len == buf.len) {
        std.debug.warn("Input is too big!\n", .{});
        std.os.exit(1);
    }

read関数では、bufferの大きさを超える入力を受けないようになっています(先述のように、配列型はその要素数を持つので、buf.lenによってbufのサイズを得ることができます)。

    const line = std.mem.trimRight(u8, buf[0..len], "\r\n");
    const val = std.fmt.parseInt(T, line, 10) catch |err| {
        std.debug.warn("Error while parsing number: {}\n", .{err});
        std.os.exit(1);
    };

あとは、入力を整数にパースします。これは標準ライブラリで行うことができます。

さて、長くなってしまいましたが一通りZigの紹介をしてきました。Zigはシンプルでありながら、とても強力にプログラマーのサポートをしてくれる言語です。ドキュメントが不十分なので、今の所自分で標準ライブラリを見に行って仕様を調べたりする必要がありますが、discordで質問をすると開発者のみなさんがすぐに回答してくれます。今後の推移に期待しましょう。

では、次回は実際にローダーについて解説します。

*1:諸説あります...

*2:全部実装されているわけではありませんが、ブートローダーに必要な部分は一通り私が書いておきました

CPU自作のためのコミュニティを設立した

あけましておめでとうございます。新年はいかがお過ごしでしょうか。 私は元旦に初日の出をみたりとか、年賀状の作成に追われる年末を過ごしたりするわけでもなく例年より素っ気ない新年を迎えています。

さて、本題です。 先日、自作CPU仲間であるCra2yPierr0t氏と自作CPUにおけるI/Oについて考えるため研究会をしました。 その中の会話で、「やっぱり自作CPUもosdev-jpみたいなコミュニティがある嬉しいねー」という話になりタイトルの通り設立する運びとなりました。

twitter.com

そんなわけでその日のうちにslack workspaceを作り、先程宣伝のツイートをしたところ10人以上の方にご参加いただけました!ありがたい。

ところでこういうslack workspaceを作ったはいいものの、みんなが自発的に会話をするようにならなければ意味がありません。 積極的に話題を作ってもらうにはどうしたらいいのでしょう。難しいです。

また、CPU自作もくもく会も計画しています。

参加したい方は以下のリンクから参加できます。

join.slack.com

よろしくおねがいします。

シリアル通信をハードウェアレベルで実装した

これは東京高専プロコンゼミ① Advent Calendar 2019 20日目およびOS-CPU Advent Calendar 2019 20日目の記事です。

遅刻しました、ごめんなさい!! そして予定していたテーマからも変わっています。。。お許しを。

言い訳

もともとこの記事のネタは「EFI ELFローダーを作る」の予定でした。今流行りのzen言語を使って作るぞ〜とウキウキしていたのですが、zen言語(zig言語)でサポートされているUEFI APIに誤りや未実装箇所があることが判明したためまずはそちらを修正・追加することから始めていまして時間がかかってしまっています。 一応進捗として、zig言語にPRを送って見事マージされました。やったね。

シリアル通信とは

シリアル通信とは一本の伝送路で一つずつビットを送ることで行うエレクトリカルコミュニケーションです。 シリアル通信といってもいろいろなものがありますが、私が実装したのはUART(Universal Asynchronous Receiver/Transmitter)です。UART以外には、SPIとかEthernetとかUSB(Universal Serial Bus)などもシリアル通信の一種です。

ここでAとBという2つのコンピュータでUART通信することを考えると、Aの送信ポート(TX)とBの受信用ポート(RX)、Aの受信ポート(RX)とBの送信ポート(TX)の計2本を接続する必要があります(実際にはGNDも接続しますが)。 2本の送受信用ケーブルがあるので全二重通信というように呼びます。

UART通信をする際には以下の項目について通信する2つのコンピュータ間で共通の設定をする必要があります。

  • baud rate
  • stop bit
  • data bit
  • parity
  • hard ware flow control

私は以下のように設定しました。

  • 115200bps
  • 1bit
  • 8bit
  • none
  • none

作り方

ソフトウェアでUARTを使うときには設定用レジスタにパラメータをいれて割り込み設定して〜ってかんじだと思いますがハードウェアでやるにはもうちょっといろいろ考える必要があります。 大変なことの一つとして、UARTはクロックを共有しない非同期通信なので位相のずれを考慮する必要があります(周波数は、事前に合わせてあるものとします)。

ここでは概要だけ説明します。

まず送信側ですが、これはやるだけです。FPGAのクロックをUARTのボーレートに分周してあとはそれに合わせてスタートビットとデータとストップビットを送るだけです。 次に受信側ですが、こちらはUARTのボーレートより何倍か早めの周波数でRXを見てあげて、複数回0がきたらそれをスタートビットと認めあとは読んでいく感じです。

f:id:yuhki0223:20191225001619p:plain 送信の様子

f:id:yuhki0223:20191225001632p:plain 受信の様子

すごく適当ですが、アドベントカレンダーなので許してください。 実装したものをGitHubに公開してあります。興味のある人は読んでみてください。

github.com

プロコンゼミ ネットワーク講習会を開催します!

この記事は東京高専プロコンゼミ① Advent Calendar 2019の2日目の記事です。

今日まで中間試験お疲れ様でした。残り3週間くらい授業を受ければ冬休みになって、もう2020年が訪れます。早いなあ。

記事のタイトルにもあるように来る2019年12月19日、プロコンゼミの成員に向けてネットワーク講習会を開催したいと思っています。 ここでいうネットワークはコンピュータネットワークのことです。

例えば、このブログのURLをブラウザに入力すると当然のことながらこのブログが表示されます。コンピュータに普段から触れている皆さんであれば、URLから直接ブログのあるサーバーへアクセスできるわけではなく、ネームサーバーからURLに対応するIPアドレスを取ってきて、そこへアクセスすることでブログのあるサーバーへアクセスできる、ということはなんとなく知っていると思います。しかし、IPアドレスがあったとてIPv4であれば232パターン(約43億)もある膨大なアドレスの中からどうやって(ある程度の速度で)目的のアドレスへたどり着くのでしょう。

講習会では以上の例はもちろん、実際によくみるイーサネットケーブル(ツイストペアケーブルとか呼びます)を作ってみて我々が何気なく使うネットワークも結局は一本一本の導線(光ケーブルを使ったり、電波を使ったりすることもありますが)を通って上流のスイッチやルーターのLEDをピカピカ光らせながら目的地点までたどり着くということを体感してもらったり、ここまで辿り着けるかはわかりませんけれど、ネットワークのトラフィックがどのように捌かれるのかというところまで触れたらいいなあと思ってます。

どうしていきなりこんな講習会をやろうと思ったか、動機はざっと以下の通りです。

  • プロコンで他の講習会も含めて色々開いたら面白そうなので、そのきっかけにしたい
  • 部室で度々起きるネットワークインシデントの重大さを理解してほしい
  • 部室のネットワーク環境を維持できる人材を育成したい
  • ネットワークの面白さを知ってほしい

講習会はとりあえず1回開いてみて、希望があれば続編もやろうと思います。 ネットワークに詳しい人も呼んでます。疑問があるならたくさん質問を投げてみてください。

それでは、乞うご期待!

KLab Expert Campに参加した

夏休みが終わってしまいました。休み明けの学校というのは本当に辛いもので先週はずっと瀕死の状態だったのですが、そろそろ回復してきたのでこの記事を書いています。

KLab Expert Campとは

ラブライブ! スクールアイドルフェスティバルを起動したときに出てくるあのKLabが主催する技術系インターンの特別版です。 今回が初めての開催のようで、「TCP/IPプロトコルスタック自作開発」がテーマでした。 講義ベースでプロトコルスタックの実装に関する知見を深めるコースと実装ベースで発展的なテーマに取り組むコースの2つが用意されていて、自分は後者で参加しました。

やったこと

実は自分は参加初日に実装ベースのコースに配属されていたことを知ったので、当日の思いつきでRIP(Routing Information Protocol)をmicropsの上で実装することにしました。 実はこのKLab Expert Campの前の週に先輩からルーティングのいろはを教えてもらっていたのでその影響がかなりあったと思います。 4日間だけでの突貫実装でしたが、講師陣の方々に質問しまくりながら最終日にはそれっぽいルーティングができるように仕上がりました。

スライドも公開してみたのでよければ見てください。

www.slideshare.net

開発風景

感想とか

先週のセキュリティキャンプに参加したときにも思ったことですが、気軽に質問できる環境っていいなーと思いました。 質問することで、自分がどこまで理解できているのかちゃんと把握できるし、わからないことがわかるし、質問したこと以上の付随知識がもらえることもあるので本当に美味しいです。

あと、4日間本当に集中して取り組むことが出来ました。家の部屋だとこうはいかないのでやっぱり環境って大事だなあと思います。 環境に関して、まずオカムラの椅子が最高でした。そして昼食がとても美味しかったです。さらに、ルーティングプロトコルデバッグ用に対向用のスイッチやルーターも用意してもらえてトリプル役満でした。

懇親会のときにネットワークのアカデミックな話が聞けたのもとても良かったです。

懇親会とお弁当

(奥の方にスイッチが写ってる)

楽しい4日間でした。ありがとうございました。

PS. KLabの読み方は、「クラブ」らしいです(ずっと「ケーラボ」って読んでた...)