Verilogのテストベンチ(bdfファイルとかRAMとかの話)
大学の学生実験でFPGAボード上で簡単なCPUを作っている(easyではない).
使っているツールはALTERA社のQuartusというツール.これでANDとかORとかDフリップフロップとかをぽちぽちして回路を作る.
ぽちぽちの回路はBlock Diagramというらしい〜
Quartusにはmodelsimというシミュレータもあるけど、とりあえず今回はicarus-verilog http://iverilog.icarus.com/を用いてテストをしてみました.
QuartusはWindowsとLinuxにはあるのにMacにはなくて悲しい.
Verilog HDLでつくったモジュールとBlock Diagramでつくったモジュールが混在した回路でも問題なくテストできました.
適当に回路を作る
3進カウンタをつくりました.ぽちぽち.
次にこれをVerilog HDLに書き出します.
メニューから File -> Create/Update -> Create HDL Design from Current File ... を選択してVerilog HDLを選んで,保存.
複数のモジュールを使用している際はすべてのモジュールをそれぞれ書き出します.
もちろんもともとVerilog HDLでモジュールをつくっている場合はそのままでOK.
書き出されたファイルは以下のようなものです.
// Copyright (C) 1991-2015 Altera Corporation. All rights reserved. // Your use of Altera Corporation's design tools, logic functions // and other software and tools, and its AMPP partner logic // functions, and any output files from any of the foregoing // (including device programming or simulation files), and any // associated documentation or information are expressly subject // to the terms and conditions of the Altera Program License // Subscription Agreement, the Altera Quartus Prime License Agreement, // the Altera MegaCore Function License Agreement, or other // applicable license agreement, including, without limitation, // that your use is for the sole purpose of programming logic // devices manufactured by Altera and sold by Altera or its // authorized distributors. Please refer to the applicable // agreement for further details. // PROGRAM "Quartus Prime" // VERSION "Version 15.1.1 Build 189 12/02/2015 SJ Lite Edition" // CREATED "Mon Jul 04 04:11:37 2016" module counter( clear, clock, Q1, Q2 ); input wire clear; input wire clock; output wire Q1; output wire Q2; wire SYNTHESIZED_WIRE_0; wire SYNTHESIZED_WIRE_3; reg SYNTHESIZED_WIRE_4; reg DFF_inst1; assign Q1 = SYNTHESIZED_WIRE_4; assign Q2 = DFF_inst1; assign SYNTHESIZED_WIRE_3 = 1; always@(posedge clock or negedge clear or negedge SYNTHESIZED_WIRE_3) begin if (!clear) begin SYNTHESIZED_WIRE_4 <= 0; end else if (!SYNTHESIZED_WIRE_3) begin SYNTHESIZED_WIRE_4 <= 1; end else begin SYNTHESIZED_WIRE_4 <= SYNTHESIZED_WIRE_0; end end always@(posedge clock or negedge clear or negedge SYNTHESIZED_WIRE_3) begin if (!clear) begin DFF_inst1 <= 0; end else if (!SYNTHESIZED_WIRE_3) begin DFF_inst1 <= 1; end else begin DFF_inst1 <= SYNTHESIZED_WIRE_4; end end assign SYNTHESIZED_WIRE_0 = ~(SYNTHESIZED_WIRE_4 | DFF_inst1); endmodule
テストを書く.
テストについては「Verilog testbench」とかでしらべたら山のようにでてくるのでググる.
とりあえず上の回路に対応するベンチを書いてみました.
//counter_test.v module counter_test; //テストベンチの入力はreg //テストベンチの出力はwire //複数行にかいてもいい.バスのときはreg[15:0] Q;とか. reg clear, clock; wire q2,q1; parameter STEP = 100; //常に実行される always begin clear = 1'b1; #(STEP/2) clock = !clock; end //最初に一度だけ実行される initial begin clear = 1'b0; clock = 1'b1; //monitorは引き数の値が1つでも変わった時に値を表示するように設定する.(alwaysにはかかないものらしい) $monitor("Counter: %b%b", q2, q1); #1000 $finish; //1000STEPで停止 end //インスタンスの作成(回路の呼び出し)counter_instance はなんでもいい //counter の部分は呼び出したいモジュールのVerilogファイルの1行目にあるモジュール名を入れる. //引数はVerilogファイルの冒頭にあるinputの/outputにある順番にかく. counter counterinstance(clear,clock,q1,q2); endmodule
コンパイル
使用したモジュールすべてのVerilogファイルと、テストベンチのファイルをすべてまとめてコンパイルします.
iverilog -o counter counter.v counter_test.v
たくさんある場合は
iverilog -o simple2 simple2.v ./lib/phase/*.v ./lib/selector/*.v ./lib/other/*.v ./lib/component/*.v ./lib/calc/*.v ./lib/cable/*.v ./lib/7SEG/*.v dummy_ram.v simple2_test.v
こんなかんじ.
- oの後に指定したファイル名でコンパイルされたファイルが出力されます.
vvp counter
または
./counter
と入力すればシミュレーションがはじまります.
Counter: 00 Counter: 01 Counter: 10 Counter: 00 Counter: 01 Counter: 10 Counter: 00 Counter: 01 Counter: 10 Counter: 00 Counter: 01
無事にシミュレーションできました.
ハマった点としては,ぽちぽちでカウンタを作る際に、DFFのpresetを1にしておけば,DFFの出力の初期値は0だと思っていたのですが、出力されたVerilogのコードを読んだところ,初期値については何もかかれておらず,テストするとxx(値不定)となってしまいました.
そのため上のテストベンチではinitialブロック内でclear = 0として一度クリアしています.
Verilog、入門のページみながら適当にかいたりしているけど難しい・・・・・・・・・・・・・・
RAMについて
CPUをつくる実験ではRAMを使ったりします.
RAMはQuartus上ではVerilogに変換できないので,自分でダミーのVerilogファイルを書きます.
module ram( input [15:0] data, input wren, input wire [11:0] address, input clock, output reg [15:0] q ); //16bit幅 4096word (* ram_style = "BLOCK" *) reg [15:0] bram[0:4095]; initial begin bram[12'd0] = 16'b1000000000000001; bram[12'd1] = 16'b1000000100000011; bram[12'd2] = 16'b1100100000000000; bram[12'd3] = 16'b1100000011010000; bram[12'd4] = 16'b1000000100000101; bram[12'd5] = 16'b1100100000000000; bram[12'd6] = 16'b1100000011010000; end always @(posedge clock) begin if(wren) bram[address] <= data; else q <= bram[address]; end endmodule
こんなかんじでダミーのRAMをつくればOK.(説明が雑)
wrenが1のときにclockがはいったらdataの内容をbram[address]に書き込んで,wrenが0のときはbram[address]の内容をqに入れて出力というのをかいただけ.
とりあえずこれでデバッグできるようになったので嬉しいです〜〜〜
ぽちぽちのときは値不定なんてほとんどないと思うんだけどVerilogでかくとif文の条件分岐とかが足りてないと値不定になってしまってなるほどなあというかんじ.
ここ間違ってるとか表記おかしいとかあったら教えてください.
ICPC2016国内予選に参加しました
今年も参加しました.情報学科3人で.
2年前: 126位 LP6m メモ ICPC予選に参加してきました
1年前: 90位 ICPC2015国内予選に参加しました - lp6m’s blog
今年: 67位 3完
去年は「来年は4完するぞ」とか言ってたのにできなかった.
去年終わってから競プロの勉強をぜんぜんしてこなかったし,前日までHardware and Software Laboratory Project 3B (Software Part) に追われていたのが完全に悪い.それでもとりあえずいま自分ができる実力を発揮しようということで頑張った.
A問題 4分
2重forループ回しただけ.
チーム全員で問題を読んだ.自分は後ろでコードを眺めて指示したりした.2分でかいて4分でACしたっぽい.
ちなみにこの時点では15位でイエーイとか言ってた.
int main(){ while(1){ int n; cin >> n; if(n == 0) break; ll int a[1001]; for(int i = 0; i < n; i++){ cin >> a[i]; } long long int res = 1000000000; for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ if(i == j) continue; res = min(res, abs(a[i] - a[j])); } } cout << res << endl; } }
B問題 24分
自分はCを読んでいたので問題を見ていない.ちょっとだけハマったらしいけど焦ってたからだと思う.
int main(){ while(1){ int n; cin >> n; if(n == 0) break; map<char, int> m; for(int i = 0; i < 26; i++){ m[i + 'A'] = 0; } char tmp[101]; for(int i = 0; i < n; i++){ cin >> tmp[i]; } for(int i = 0; i < n; i++){ char c = tmp[i]; m[c]++; vector<pair<int, char> > result(26); for(int i = 0; i < 26; i++){ result.push_back(make_pair(m['A' + i], 'A' + i)); } sort(result.begin(), result.end()); reverse(result.begin(), result.end()); int sub = result[0].first - result[1].first; if(sub > n - i - 1){ cout << result[0].second << " " << i + 1 << endl; break; } if(i == n - 1) cout << "TIE" << endl; } } }
C問題 70分
自分はCをずっと眺めていたのにふるいすれば終わりに気がつかなかった。言われて実装したらなんかなかなか処理が終わらない.ぼくが無駄な処理してるところに気がついて直してAC
int oksize = 7400000; int main(){ int n,m; bool ok[oksize]; while(1){ cin >> m >> n; if(n == 0 && m == 0) break; REP(i,oksize) ok[i] = true; REP(i,m) ok[i] = false; int cnt = 0; int tmp = m; REP(j,n){ for(int i = 0; i * tmp < oksize; i++){ if(i*tmp < m) continue; ok[i*tmp] = false; } FOR(i,tmp,oksize){ if(ok[i]){ tmp = i; break; } } } cout << tmp << endl; } }
D問題 提出できず
C問題をACしてとりあえず去年と同じなのでホッとした.D問題を読んだ.ダルマのどこを崩すかって枝分かれしていくわけだからdfsを思いついたので一番競プロをまじめにやってるチームメイトに書いてもらった.サンプルが通ったので入力データをダウンロードして実行したが全然終わらない.とりあえずメモ化できるのでメモ化してみたんだけど、全然早くならなかった.
結局そのまま試合終了まで考えてもどうにもならなくて終わってしまった.
以下、遅いコード
int n; int ans = 0; map<vector<int> , int> m; int solve(vector<int> v){ // cout << v.size() << endl; if(m.find(v) != m.end()) return m[v]; m[v] = n - (int)v.size(); for(int i = 0; i < ((int)v.size() - 1); i++){ //cout << "jhe" << v.size() <<" " << i << endl; if(abs(v[i] - v[i + 1]) <= 1){ vector<int> newv = v; newv.erase(newv.begin() + i); newv.erase(newv.begin() + i); m[v] = max(solve(newv), m[v]); } } return m[v]; } int main(){ while(1){ cin >> n; if(n == 0) break; vector<int> w; for(int i = 0; i < n; i++){ int tmp; cin >> tmp; w.push_back(tmp); } ans = 0; m.clear(); cout << solve(w) << endl; } }
Schemeのメモ
Schemeのリストの操作
> (list 1 2) (1 2);普通にリスト > `(1 2) (1 2);これもリスト > (define a 1) > (define b 2) > (list a b 3) (1 2 3);aとbは中身が展開される > `(a b 3) (a b 3);aとbは中身が展開されない > `(,a ,b 3) (1 2 3);aとbの中身が展開された どうやら`を利用したリストの中では変数の前にカンマをいれると中身が展開されるみたい > (list (list 1 2) 3 4) ((1 2) 3 4);リストの中にリストがあるやつ > `(`(1 2) 3 4) (`(1 2) 3 4);なんで(1 2)の前に`があるのか謎い > (equal? (list (list 1 2) 3 4) `(`(1 2) 3 4)) #f;上の二つは違うらしい・・・・・・・? > `(,@(list 1 2) 3 4) (1 2 3 4);,@をつかうと直後のリストのカッコが外れる > `(,@`(1 2) 3 4) (1 2 3 4);同様 > `(,@`(,a ,b) 3 4) (1 2 3 4);合わせ技
バーサライタを作った
この記事はKMC Advent Calendar 2015 - Adventar22日目の記事です。
昨日はastatineさんのboost::property_treeでした。
kmc.hatenablog.jp
はじめに
KMCID:lp6mです。今年部費を払って以来一度もKMC部室に行ったことのない幽霊部員です。。
クリスマスといえばイルミネーションなので、LEDを使って何か作りたくなりました。
バーサライタというものが面白そうなので、作ってみることにしました。
バーサライタとは
バーサライタ、といってもピンと来ないかもしれませんが画像をみたらわかるかもしれません。
光が動いても、人間の目は残像としてそこに光があったかのように認識します。これを利用して、空間上に文字や絵を映し出す装置のことです。海外ではPOV(Persistent Of Vision)と呼ばれたりします。
LED部分がモーターで回転するものがオーソドックスですが、回転ではなく反復するものや、手で光源をもって振り回すことで残像を作り出すものもあります。
制作
電子工作の知識がほとんどないので、インターネットで情報を集めます。LED制御にはArduinoを使います。Arduinoめちゃくちゃ便利です。
色々な情報が手に入りました。
とりあえず部品を買ってきて、組み立てます。
ユニバーサル基板に、電池BoxとLEDとArduinoを乗せて、配線するだけです。電池boxの固定や、基盤とモーターとの固定に必要なネジ・ナットも購入します。穴あけには電動ドリルを利用します。
モーターは強力なほうがいいとおもったので、マブチモーターRS-380PHを使いました。モーターの固定にはパイプのL字固定具を使用しました。
モーターと基盤を接続する部分の部品選びにかなり時間がかかりました。大阪のデンデンタウンを歩き回っていました。
- RS-380PHの軸(2.3mm)から3mmに変換するアダプタ デジットBlog:レインボープロダクツ メカトロパーツの新製品が登場!
- 3mm軸ジョイント レインボープロダクツ アルミダブルストッパー内径3mm
- 3mmネジつきシャフト
- 3mm 3mm軸アダプタ
※1点固定だと重心がぶれて軸がぶれまくるので、2点以上で固定すべきかもしれません。
またモーターが必要とする電圧が高かったので電池駆動は諦め、ACアダプタを買おうとしたのですが、今後も工作をするのに必要だろうと思い電源装置を購入しました。高かった・・
めんどくさい配線作業を終えると、完成です。あとはプログラムを書きます
LED5個の縦バージョンも作成しました。
制御プログラム
Arduinoを使用したことある人はわかるとおもうのですが、Arduinoではloop()という関数が一定時間ごとに呼び出されます。
このloop()が呼び出される間隔がバーサライタでのLEDの表示切り替え間隔より大幅に遅く、悩まされました。
完成!!
https://twitter.com/lp6m/status/678990382756040704
https://twitter.com/lp6m/status/678955161817972736
いい感じです。撮影するときはシャッタースピードを遅くしたほうがいいです。このためにわざわざ
本当はしたかったこと
もともとはフルカラーバーサライタで絵を表示するぞ!と思ってAdafruitのフルカラーLEDスティックhttp://akizukidenshi.com/catalog/g/gM-08435/を使おうとしていました。
しかし回転させると・・
外側のLEDが内側のLEDの色の変化より遅れています。1本の信号線で複数のLEDをコントロールできるからなのか、応答速度が遅いようです。バーサライタ向きではないですね。
結局いろいろ試行錯誤したのですが、結局今回は赤色LEDでのバーサライタのみにしました。
絵を表示するときは、LEDが1周する間に1枚の絵の分光らせないといけないので、回転速度なども検出しないといけません。このために赤外線センサのRPR-220などを利用するとよいです。
感想
電子工作も工作も、知識がないのにするのは大変ですが、完成したときはとても楽しいです。
ぜひみなさんも作ってみてください!!
(試行錯誤途中の写真。上手くやればAdafruitのスティックでもフルカラーバーサライタ作れるかもしれない)
あしたはtaiseiさんの「Unreal Engine 4を触る」です。楽しみですね!
CODE THANKS FESTIVAL 2015に参加しました
出発〜開会式
行きは飛行機に乗った。離陸直前にAOJの1126http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1126を通した。
https://twitter.com/lp6m/status/672910101120880640
https://twitter.com/lp6m/status/672938739413286912
羽田からバスにのってなんとかテレコムセンターについた。
去年と同じ場所だったので迷わなかった。テレコムセンター駅で外でつったっていたのは@kenkooooさんだったみたい。すごい人外に立たせるのか。
参加賞のCODE THANKS FESTIVAL Tシャツをもらった。
弁当、位置的に焼肉弁当を手に入れられなかったつらい。去年は近かったから焼肉弁当手に入れた。
開会式、ちょくだいさんの走り方がかわいかった。
コンテスト
去年はFirst ACにアマゾンギフト券があったのでC問題あたりでFirst ACできるだろうと思ってCからといた。
C 02:04 日本語が一番簡単なのがこの問題. なんとかboundとかいうvectorの便利なやつしらないのでちゃんと復習しようとおもった
A 06:09 なにをあせってたのかすごく時間かかってる・・・?もっとはやく解けただろって感じ
B 17:57 なんかこれも謎かった(結構時間潰してる人多いみたい)簡単なのになんかダメダメ
E 46:27 そもそもTに含まれるアルファベット全部がSに含まれてないとダメ,
あとはTに含まれる文字列以外をSから全部除去した文字列にTが部分文字列として含まれてなかったらダメ,でいけると気づいた(気づくのおっそ まあ自分で気付けたからいいか)string.findみたいなのはなんか覚えてた。
D 57:37 これはまあ10分程度でかけたし特に詰まったりしなかったのでよしとする
去年は5完で42分なのでちょっとおそいかんじ。
H を触る。累積和をとればはやいぞ!とおもって累積和のとりかたは知ってたから実装する。めっちゃ汚いけどサンプルあったし提出してみたらACしてて何個かTLE 提出したのはこれ(コンテストから数日しないとURLみれなさそう)http://code-thanks-festival-2015.contest.atcoder.jp/submissions/587635
https://twitter.com/lp6m/status/673014031096025090
https://twitter.com/lp6m/status/673014419673055232
うーんうーんと言ってる間にコンテスト終了
Hはしゃくとりでオーダー落とすんかなとおもって解説前につぶやいやらkenkooooさんにふぁぼられた。解説でもしゃくとりって言ってた。
部分点ほしかったかなあ。。
https://twitter.com/lp6m/status/673019270352142336
そのあとは解説聞いて、懇親会とかでわいわいしてた。みんなフレンドリーで優しかった。
スタンプ全部あつめたのうれしい
https://twitter.com/lp6m/status/673176055545397248
帰りは新幹線 帰る時間おそくてつらかった。
いやなんていうか来年は決勝でるって決めたんだし出るぞ。ちゃんと毎日練習するんやで。
UnityのShaderLabでわからないこと
分からないことのメモなので、解決策があれば教えてほしいです。
半透明だけど輪郭は色が濃くなるようなシェーダを書いた。
球体のオブジェクトに割り当ててみた。
Sceneビューでは見えるんだけど、Gameビューでは見えない。
他のマテリアルを割り当てるとGameビューで見えるのに、自分でかいたシェーダを使ったマテリアルだと、Gameビューでなにも表示されない。
なんでこんなことになるんでしょうか・・・・誰かおしえてください。 Twitter:@lp6mまで。
Xcodeでテキストファイルを読み込めないときの解決策
全然たいしたことじゃないのにこれで結構時間くうことあるのと、日本語でググってもなかなかヒットしなかったのでメモ。
XcodeでCとかC++を書いていて、コードが間違っているわけではないのに、ファイルを読み込めないときがある。
FILE *fp; char *filename = "load.txt"; if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "%sのオープンに失敗しました.\n", filename); exit(EXIT_FAILURE); }else{ printf("成功!!\n"); }
解決策
①Product->Scheme->Edit Scheme...を選ぶ.
②OptionタブのUse Custom Working Directoryをオンにして、読み込みたいテキストファイルがあるディレクトリを選択.
動きました。
終わり。
英語で調べたらすぐでてくるんだけど。これの通りです。
stackoverflow.com