lp6m’s blog

いろいろかきます

Verilogのテストベンチ(bdfファイルとかRAMとかの話)

大学の学生実験でFPGAボード上で簡単なCPUを作っている(easyではない).

使っているツールはALTERA社のQuartusというツール.これでANDとかORとかDフリップフロップとかをぽちぽちして回路を作る.

ぽちぽちの回路はBlock Diagramというらしい〜

Quartusにはmodelsimというシミュレータもあるけど、とりあえず今回はicarus-verilog http://iverilog.icarus.com/を用いてテストをしてみました.

QuartusはWindowsLinuxにはあるのにMacにはなくて悲しい.

Verilog HDLでつくったモジュールとBlock Diagramでつくったモジュールが混在した回路でも問題なくテストできました.

適当に回路を作る

3進カウンタをつくりました.ぽちぽち.
f:id:lp6m:20160704042511p:plain
次にこれを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

icarus-verilogのインストール

Macだと

brew install icarus-verilog 

でおわり.

テストを書く.

テストについては「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を使ったりします.
f:id:lp6m:20160704101153p:plain
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;
	}
}

反省

Cはもっとはやくふるいで解けることに気がつくべきだった.まあ全然練習してないので雑魚なのは当然.
コンテストに出るたびにやっときゃよかったとか行ってるので少しくらいがんばってみるかなあという感じ.
今日は平安神宮に行った.精進しろと言われた.
f:id:lp6m:20160626150841j:plain


あとは全然関係ないのだけど前日まで追われていた実験でCっぽいSmallCのコンパイラを作ったのは面白かった.
文系の父親が大学生のときくらいにかいていたZ80アセンブラのコードを印刷したノートが家にあって、実験のことについてたくさん話せただろうなあとかおもってすこし寂しかった.

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を使って何か作りたくなりました。
バーサライタというものが面白そうなので、作ってみることにしました。

バーサライタとは

バーサライタ、といってもピンと来ないかもしれませんが画像をみたらわかるかもしれません。
f:id:lp6m:20151222032139j:plain:w300
f:id:lp6m:20151222032146p:plain:w300

光が動いても、人間の目は残像としてそこに光があったかのように認識します。これを利用して、空間上に文字や絵を映し出す装置のことです。海外ではPOV(Persistent Of Vision)と呼ばれたりします。
LED部分がモーターで回転するものがオーソドックスですが、回転ではなく反復するものや、手で光源をもって振り回すことで残像を作り出すものもあります。

制作

電子工作の知識がほとんどないので、インターネットで情報を集めます。LED制御にはArduinoを使います。Arduinoめちゃくちゃ便利です。
色々な情報が手に入りました。

とりあえず部品を買ってきて、組み立てます。
ユニバーサル基板に、電池BoxとLEDとArduinoを乗せて、配線するだけです。電池boxの固定や、基盤とモーターとの固定に必要なネジ・ナットも購入します。穴あけには電動ドリルを利用します。
モーターは強力なほうがいいとおもったので、マブチモーターRS-380PHを使いました。モーターの固定にはパイプのL字固定具を使用しました。

モーターと基盤を接続する部分の部品選びにかなり時間がかかりました。大阪のデンデンタウンを歩き回っていました。
f:id:lp6m:20151222032400j:plain:w300

※1点固定だと重心がぶれて軸がぶれまくるので、2点以上で固定すべきかもしれません。

またモーターが必要とする電圧が高かったので電池駆動は諦め、ACアダプタを買おうとしたのですが、今後も工作をするのに必要だろうと思い電源装置を購入しました。高かった・・
f:id:lp6m:20151222033816j:plain:w300
めんどくさい配線作業を終えると、完成です。あとはプログラムを書きます
LED5個の縦バージョンも作成しました。
f:id:lp6m:20151222034647j:plain:w300

制御プログラム

Arduinoを使用したことある人はわかるとおもうのですが、Arduinoではloop()という関数が一定時間ごとに呼び出されます。
このloop()が呼び出される間隔がバーサライタでのLEDの表示切り替え間隔より大幅に遅く、悩まされました。

完成!!

https://twitter.com/lp6m/status/678990382756040704
https://twitter.com/lp6m/status/678955161817972736
いい感じです。撮影するときはシャッタースピードを遅くしたほうがいいです。このためにわざわざ

ProShot

ProShot

  • Rise Up Games
  • 写真/ビデオ
  • ¥730
このアプリを買いました。

本当はしたかったこと

もともとはフルカラーバーサライタで絵を表示するぞ!と思ってAdafruitのフルカラーLEDスティックhttp://akizukidenshi.com/catalog/g/gM-08435/を使おうとしていました。
しかし回転させると・・
f:id:lp6m:20151222034243j:plain:w300
外側のLEDが内側のLEDの色の変化より遅れています。1本の信号線で複数のLEDをコントロールできるからなのか、応答速度が遅いようです。バーサライタ向きではないですね。
結局いろいろ試行錯誤したのですが、結局今回は赤色LEDでのバーサライタのみにしました。
絵を表示するときは、LEDが1周する間に1枚の絵の分光らせないといけないので、回転速度なども検出しないといけません。このために赤外線センサのRPR-220などを利用するとよいです。

感想

電子工作も工作も、知識がないのにするのは大変ですが、完成したときはとても楽しいです。
ぜひみなさんも作ってみてください!!
f:id:lp6m:20151222035905j:plain:w300(試行錯誤途中の写真。上手くやればAdafruitのスティックでもフルカラーバーサライタ作れるかもしれない)
あしたはtaiseiさんの「Unreal Engine 4を触る」です。楽しみですね!

CODE THANKS FESTIVAL 2015に参加しました

去年

lp6m.hatenablog.com

”””来年は普通に予選突破できるレベルまで上げたい”””なんて言ってたのに結局何もしなかった・・・のでまたTHANKSに出た。(出れるだけありがたい)

出発〜開会式

行きは飛行機に乗った。離陸直前に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
帰りは新幹線 帰る時間おそくてつらかった。

いやなんていうか来年は決勝でるって決めたんだし出るぞ。ちゃんと毎日練習するんやで。

追記

CはFAでした。ありがたい。

UnityのShaderLabでわからないこと

分からないことのメモなので、解決策があれば教えてほしいです。

半透明だけど輪郭は色が濃くなるようなシェーダを書いた。

球体のオブジェクトに割り当ててみた。
Sceneビューでは見えるんだけど、Gameビューでは見えない。
他のマテリアルを割り当てるとGameビューで見えるのに、自分でかいたシェーダを使ったマテリアルだと、Gameビューでなにも表示されない。
f:id:lp6m:20150926160602p:plain

なんでこんなことになるんでしょうか・・・・誰かおしえてください。 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...を選ぶ.
f:id:lp6m:20150804131530p:plain
②OptionタブのUse Custom Working Directoryをオンにして、読み込みたいテキストファイルがあるディレクトリを選択.
f:id:lp6m:20150804131535p:plain
動きました。

終わり。

英語で調べたらすぐでてくるんだけど。これの通りです。
stackoverflow.com