2009年11月9日月曜日

トランジスタの規格

トランジスタ回路の基本設計法

ICが全盛の時代ですが、トランジスタもちょっとしたドライブなど使われる
場合もまだ多く残っています。 われわれアマチュア工作でも簡単な回路
で増幅やドライブ回路が構成できるので、まだまだ現役で使うことが多く
あります。
ここでは、難しい論理的な話は抜きにして、動作させるために必要なことを
説明します。


【トランジスタの規格】

規格表の見方は別ページにありますのでそちらを参考にして頂くとして、
規格で大切なポイントは下記4点となります。

(1) 何ボルトまで使えるか
  コレクタ・エミッタ間最大定格電圧(Vceo)で見ます。
  実際には、これの1/2以下の電圧で使うようにします。
(2)何アンペアまで流せるか
  これは2つの観点から考えます。
  まず コレクタ最大定格電流(Ic) は絶対超えられない値です。
  これも実際の使用では。1/2以下で使います。
  もう一つは、最大全損失(Pt)で何ワットまで使えるかということです。
  これの考え方は、 使う電圧×流す電流 で考え、やはり1/2以下で
  使うようにします。
  しかし、この全損失は放熱板の有無と、周囲温度で極端に変わるので、
  グラフで確認して使います。
(3)何倍の増幅が出来るか
  直流電流増幅率(hfe)で単純に入力電流が何倍になって出力されるかが
  分かりますが、非常にMinとMaxの差が大きいので、Minで考えて
  おく必要があります。
(4)どれくらいの周波数まで増幅できるか
  これには、利得帯域幅積(ft)で判定しますが、その判定は、下記のように
  します。
    使用可能な周波数 = 利得帯域幅積(ft) ÷ 直流電流増幅率(hfe)

2009年5月9日土曜日

Prism Video Converter

AVIファイルをダウンロードして、再生!って、思ったけど再生ソフトは?ん~
さらにDVDに焼こうと思っても、所有のDVDAutherでは、「なんとかXpressでMPEG-1/2とかに、変換してねぇ~それからっ」と言われて相手にされません。
で、ググるとPrism Video Converterをみっけ!
なかなかよろしい~、AVIの再生はモチロン!mpgやらwmvやらなんにでも変換できそう、ほんとにフリーソフトなのかなぁ

2009年4月22日水曜日

sSMTPとProcmailでメール転送

nbsmtpにSMTP AUTHをしゃべらせて利用してきたけど。。forwardingが必要になったので、fetchmail+procmail+nbsmtp
で、メールリレーをやろうと設定したけど、うまく動かんのぉ
どうもnbsmtpにはrecipientの引数が無く、メール本文の内容から、
TO:、CC:、BCC:
なんかを見分けて勝手に送ってしまう仕様になっている。ん~ん便利だけど。

※ちょっと解説アリ
sendmailなどがメールを送信する際にメール本文にあるTO:、CC:、BCC:とかは参照されない。つまりTO:、CC:、BCC:はsendmailにとって本来は不要な記述らしい。で、MUA(Netscapeとかねぇ)が、ユーザーの支持に従ってsendmailに引数(recipient)をくっつけて起動しメールを相手先に送りつけている。nbsmtpはMUAのやっていることを肩代わりする機能をもってるってことらいし。
※解説終り

でprocmailからnbsmtpを呼び出す際に、
nbsmtp 相手先アドレス
ってな形になってnbsmtpがエラーを吐いてしまう。
(エラーを出して終了して良かったぁ。もし引数を無視して送信動作をすると、メール本文にはTO:、CC:、BCC:などが沢山書いてあるのでメールループが発生してしまうところだった。怖え~:-)

ssmtpは、.tarをsourceforgeからGet。
./configure --prefix=どっか
make
make install
だけ。どっか/etc/ssmtp/ssmtp.confを
#
# /etc/ssmtp.conf -- a config file for sSMTP sendmail.
#
# The person who gets all mail for userids < 1000
# Make this empty to disable rewriting.
root=postmaster
# The place where the mail goes. The actual machine name is required
# no MX records are consulted. Commonly mailhosts are named mail.domain.com
# The example will fit if you are in domain.com and you mailhub is so named.
# mailhub=mail
mailhub= SMTPサーバアドレス
# Where will the mail seem to come from?
#rewriteDomain=renesas.com
# The full hostname
hostname= 自分のドメイン名
FromLineOverride=YES

AuthUser= SMTPサーバのID
AuthPass= SMTPサーバのパスワード
AuthMethod=CRAM-MD5

ってな感じ。ちなみに、FromLineOverride=YESは、メール転送する際にメール本文のFromアドレスを書き換えないって設定。意味的にYESでは逆っぽいけど、デフォルトのNOだとFrom行が書き換えられてしまう。

.procmailrcは、
SENDMAIL=どっか/bin/ssmtp
SENDMAILFLAG=""
:0 c :
* ! 自分に届くようなMLを指定
! kenji.ogura.st@hitachi.com

ってな感じ。転送しなくても自分に届くようなメーリングリストがアドレスに含まれている場合は転送しない。

2009年3月20日金曜日

2アマ

モールスの学習、だいぶ疲れてきた。
大してやっていないのかもしれないが、仕事の合間に携帯で聞いているけれど、スピードについてゆけない。実感として、耳で聞いてすぐに文字が浮かんでこな~い!
聞く

もう一度頭の中で聞いた音を繰り返す

文字が浮かんでくる

どうしても、もう一度聞いた音を思い出している間に、次の音が聞こえてきて、グチャグチャになっちゃう。合調法にもどすか?いやいや、だめだめ。やっぱり音から直接文字にしないと。この先きっとスピードが上がってゆかないと思う。文字の名前を覚えるっと概念は解るけど、どうしても、聞いた音を頭の中で繰り返さないと文字が浮かんでこない。頭の中で繰り返すってことは、やはり、短点と長点に分解しているような感じだぁ~。分解して視覚的に、・-でAみたいに変換している感じで~す。

2アマではなく、まずは3アマで免許取って、実践で鍛えるって戦法もありかなぁ~

2009年3月2日月曜日

2アマ

合調法(ご~ちょ~ほう)
最初、読めなかった。語呂合わせの正式名称らしい。使わないよねぇこんな言葉、めったにぃ~。。まあまずは語呂合わせでモールス符号を覚えよう~っと思ったが、どうも速度が足らん、てか、5WPM(5WordPerMinutes、試験の早さ)ぐらいならなんとか追いつきそうだけど、それ以上は無理でしょ。一旦語呂合わせをやり始めると、早いモールスに、早い語呂合わせが必要になって、どっかで限界がきそう~ってのは判る。このことを真剣に述べているHPも多々あります。
で、どうせぃ~っていうかといえば、音→文字 で変換せぃっとある。ん~?
トツー → A
みたいにせいとっ。こりゃ難しいぃ。トツー→エアー→ア→A てなかんじが語呂合わせなんだけど、→エアー→アの部分を使うなと、かつ、音を直接文字にせよとなっ。こうなると、A-Zまで文字を見ながら、A-Zのトンツーを聞いて、トンツー→文字(視覚)で覚えるのかなぁ?これだと、聴覚→視覚、つまり、音→文字イメージ の変換になるようなぁ~
文字そのものってのが難しい。人間、頭で文字をイメージするのが普通なので、視覚も使うよなぁ。
トツーツート→P
で頭の中で"P"を思い浮かべるのが音響法の正しい練習なのでしょうか?"P"を紙に書くのでしょうか、それとも、紙に書いてある"P"を指差す?"P"を"ピー"と口に出してみる?
どれでも、語呂合わせをしなければ音響法なのかなっ?
無線電信の巧みと技
↑ここにこうある、
「これから私達がやろうとしていることは文字の名前を変えることです。例えば、Yという字の代りに、ツートツーツーという音になるのです。」
ほぉ~、トツー→Aの"A"は"エー"ではなくて"トツー"である、つまり"A"は"トツー"と読む。
この方針で進めてみましょ。

2009年2月27日金曜日

2アマ

突如、2アマにトライ。
全ての始まりは、超再生式ラジオの回路図面からはじまった。
超再生、再生、ストレート、発振器
などブレッドボードで試してみたけど、結局、高周波回路やらトランジスタ回路やらの性質がわからないと、、と思うが、いろんな本からは正確なことがわからん。で、辿り着いたのがアマチュア無線の教科書。インピーダンス・マッチングの意味がまるで理解できないことからも、本を買ってみた~。けど良くわからん。1アマの本、無線数学・電機数学の本まで来て、なんとなくは複素インピーダンスを理解し始め、2アマにトライかぁ?

鬼門はモールス受信

ん~つらい

エア・・・
エイ・・・
ターマー・・・
ターニー・・・

の4種類で聞き取って、脳内高速アルファベット変換に挑戦中。

2008年7月1日火曜日

Win2K リモートで使用する

VPNで会社のPCに接続できるようになりました。
で、会社のPCの電源管理をLAN経由で。。。

会社のPCにはMagicPacketからの目覚め機能だけでなく、

Wake Up On Direct Packet

なる機能が。

コンピュータの管理→ネットワークアダプタ→Intel(R) 82566DM Gigabit Network Connection

からプロパティで見たら出てました、以下説明文、

「パケットがアダプタに直接送信されたとき、このデバイスによりコンピュータをスタンバイまたはハイバーネーションからウェークアップ出来るようにします。 たとえば、コンピュータに保存されたファイルにリモート アクセスするように試行すると、ウェークアップします。」

MagicPacket以外のパケットを受信した場合でもWakeupしそう。。。
さっそく機能オン!試してみました。

まずは会社PCをハイバネーションへ入れ。
ノートPCからVPN経由で、ping!

なんと、会社のPCは無事目覚めましたぁ~

これであとは、
コントロールパネル→電源オプションのプロパティ→電源設定
→システムスタンバイ 10分後
→システム休止状態  2時間後
→詳細設定→コンピュータの電源ボタンを押したとき 休止状態
とか適当に休止かスタンバイに入るようにしておく。

とっ自宅でノートPCからVPNに入って、
会社のPCにpingするとお目覚め!
ほっとくと休止!

って具合。めでたい

2008年5月12日月曜日

GTKWave 3.0.0

ここがGTKWaveの本家らしいぃ。知らなかったのですが、すでに3.0.0がありますし、WindowsでもLinuxでも動作しました。
Linuxなら、これ
Windowsなら、こここれと、これの2ファイルを同一ディレクトリに展開すると動きますねぇ。
なんと3.0.0はカラー~
当たり前な気もしますが古いGTKWaveの白黒画面を見慣れていると、カラーなんで売り物?みたいな気分になります。
便利便利。

2008年4月21日月曜日

ゼロディレイ・シミュレーション

これ、FFのRTLから波形を見たところ。RTLはこんな感じです。
module ff;

reg clk,D,R;
initial begin
$dumpfile("ff.vcd");$dumpvars(0,ff);
clk=0;D=0;
#3; D=1;
#2; D=0;
#10 $finish;
end
always #1 clk=~clk;

always @(posedge clk)
R <= D;
endmodule
クロックの立ち上がりのとき、データ(D)の値は`1`と表示されてます。実回路ではディレイが乗って、クロックの立ち上がりではまだD=`0`で、ホールド時間後にD=`1`に変化するはずですが、波形上はこのホールド時間が見えてきません。実負荷シミュレーションなら遅れがでますね。
波形表示ツールはCadenceのSimvisionなのですが、フリーのGTKWaveでも同じように表示されます(当たり前ですが)。しかし私、これ見難い。常にディレイはあるものとして回路を考えていますから、クロックの立ち上がりで即座に値が変化する、って感覚になかなか慣れません。

2008年4月15日火曜日

I2C

ここがI2Cに関する詳しい。

2008年4月13日日曜日

RS232Cコネクタのオス/メス

RS232Cコネクタのオス/メス
電子回路の豆知識にストレートケーブルとクロスケーブルのなぞについて解説がありますし、ググれば沢山出てきます、結局は皆さん苦労しているのでしょうねぇ。LANケーブルについても同じような状況にあるようですね。

2008年3月7日金曜日

PIC 互換マイコン verilogソース

ここにはPICマイコンの互換と称してVerilogソースを作成し、公開している方がいます。

1999/CQ トランジスタ技術で公開されたものらしいぃ 知りませんでした。
(CQ出版社からはすでにサーバが閉鎖されているようです、Googleキャッシュからは辿れますね)

.zipを解凍して見てみると、まあ実に可愛らしいcpuです。
「PIC16C57互換です」
とマニュアルにもありますが、ダウンロードしたファイル名は`risc8.zip`とあり、8bit RISCであることが判ります。

risc8.jpegにブロック図があります。



また、ここには、フリーのVerlog用コードカバレージ・ツールが公開されています。IcarusVerilogといい、フリーのVerilog関連ツールってあるのねぇ

RTLソースを眺めてみると、本当に単相設計になってます。PICの教科書的な電気工作の本には、PICの内部動作の説明として、システムクロックを4回に分けて使っている様子が書かれていますが、どちらが本当の内部動作なのか、はたまた、どちらの表現も本当のことを示しているのか、私には判断が付きません。

それにしても、CPUのソースコードを眺めるのは楽しいものですねぇ。自分が考えるCPUと、他人が考え出すCPUはとっても似ていて、「人は違うようで似通ったことを考えるもんだぁ」と改めえ、感慨深くなるのです。

2008年2月27日水曜日

3state HDL

module top;

initial begin
$dumpfile("a.vcd");
$dumpvars(0,top);
en=1;
repeat (10) #10 en=~en;
end
assign bd=(~en)? 3'b111 : 3'bzzz;

reg en;
wire [2:0] bd;

a a(en, bd);
endmodule

module a(en,bd);
input en;
inout [2:0] bd;
reg [2:0] r,s;
always @ (en)
if(en)
r=3'b101;
else
s=bd;
assign bd=(en)?r:1'bz;
endmodule

2008年2月26日火曜日

TD4.v 3段パイプランのブロック図





これらがブロック図と波形になります。特に3段パイプラインは難しいなぁって感じですが、一番難しいのは本当に正しい3段パイプ動作をしているのか、つまりは検証の網羅性を立証することではないでしょうか。
今回設計してみたTD4の3段パイプライン版は一応それらしく動いています。が、本当の意味でBUGが無い、なんて決して口に出しては言えません。(かつて技術者の後輩が「自分のプログラムにはBUGがありません」と言い切ったことがありましたが、「BUGの無いプログラムであることを証明できますか?」と聞き返したくなったのを覚えています)

検証技術はソフトウェアに比較して並列動作である分高度なものが要求されますよね。なのでソフトウェア以上にコードを良く見る、つまりはコードインスペクションが大切であると思います。また、デザインレビューが重要で、他人の目を通して自分の設計を見ることが非常に役に立ちます。これも、ひとえに、「BUGが無いことを立証することが出来ない」ことに寄ります。

TD4.v CPUの創り方 3段パイプライン版

module rom(oen, rom_address, rom_data);

/*
instruction decode
0000_0000 : add r0,r1
0001_0000 : add r1,r0
0010_.... : add r0,#i
0011_.... : add r1,#i
0100_0000 : move r0,r1
0101_0000 : move r1,r0
0110_.... : move r0,#i
0111_.... : move r1,#i
1000_.... : jmp #i
1100_.... : jnz #i

ld(on)
0001 : r0
0010 : r1
0100 : r2
1000 : r3(PC)
*/
input oen;
input [3:0] rom_address;
output [7:0] rom_data;

wire [3:0] rom_address;
reg [7:0] rom_data;

always @ (rom_address) begin
if (oen) begin
casez(rom_address)
4'h0: rom_data=8'b0110_0001; /* move r0,#0001 */
4'h1: rom_data=8'b0010_0010; /* add r0,#0010 */
4'h2: rom_data=8'b0111_0000; /* move r1,#0000 */
4'h3: rom_data=8'b1100_1111; /* jnz #1111 */
4'h4: rom_data=8'b1000_0001; /* jmp #0001 */
default:
rom_data=8'b0000_0000;
endcase
end else begin
rom_data=8'bxxxx_xxxx;
end
end

endmodule

module dec (
ck,
reset,
i_code,
imidiate,
co,
fetch_en,
ld,
ld_na,
on,
im,
oz,
oi
);
input ck, reset;
input [3:0] i_code, imidiate;
input co;
output fetch_en;
output [3:0] ld, ld_na, on, im;
output oz;
output oi;

reg [3:0] ld_c, on_c;
reg oz_c, oi_c, en_c;
reg [3:0] ld, ld_na, on, im;
reg oz, oi;
reg en, en_na;

always @ (i_code or co or en) begin
if (en) begin
casez (i_code)
4'b0000: begin /* add r0,r1 */ ld_c=4'b0001; on_c=4'b0010; oz_c=0; oi_c=0; en_c=1; end
4'b0001: begin /* add r1,r0 */ ld_c=4'b0010; on_c=4'b0001; oz_c=0; oi_c=0; en_c=1; end
4'b0010: begin /* add r0,#i */ ld_c=4'b0001; on_c=4'b0001; oz_c=0; oi_c=1; en_c=1; end
4'b0011: begin /* add r1,#i */ ld_c=4'b0010; on_c=4'b0010; oz_c=0; oi_c=1; en_c=1; end
4'b0100: begin /* move r0,r1 */ ld_c=4'b0001; on_c=4'b0010; oz_c=0; oi_c=0; en_c=1; end
4'b0101: begin /* move r1,r0 */ ld_c=4'b0010; on_c=4'b0001; oz_c=0; oi_c=0; en_c=1; end
4'b0110: begin /* move r0,#i */ ld_c=4'b0001; on_c=4'b0001; oz_c=0; oi_c=1; en_c=1; end
4'b0111: begin /* move r1,#i */ ld_c=4'b0010; on_c=4'b0010; oz_c=0; oi_c=1; en_c=1; end
4'b1000: begin /* jmp #i */ ld_c=4'b1000; on_c=4'bxxxx; oz_c=1; oi_c=1; en_c=0; end
4'b1100: begin /* jnz #i */
if (co) begin
ld_c=4'b1000; on_c=4'bxxxx; oz_c=1; oi_c=1; en_c=0;
end else begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
end
default: begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
endcase
end else begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
end

always @ (posedge ck or posedge reset) begin
if (reset) begin
ld<=4'b0001; on<=4'b0001; oz<=1; oi<=0; /* add r0,#0 as NOP */
im<=4'b0000;
en<=1;
end else begin
ld<=ld_c; on<=on_c; oz<=oz_c; oi<=oi_c;
im<=imidiate;
en<=en_c;
end
end

always @ (posedge ck) begin
en_na<=en;
end

assign fetch_en=en & en_na;

always @ (posedge ck or posedge reset) begin
if (reset) begin
ld_na<=4'b0000;
end else begin
ld_na<=ld;
end
end

endmodule

module registor (
ck,
reset,
r_bus,
r0_ld, r1_ld, r2_ld, r3_ld,
r0_ld_na, r1_ld_na, r2_ld_na, r3_ld_na,
r0_on, r1_on, r2_on, r3_on,
ra,
rb,
ia
);

input ck, reset;
input r0_ld, r1_ld, r2_ld, r3_ld;
input r0_ld_na, r1_ld_na, r2_ld_na, r3_ld_na;
input r0_on, r1_on, r2_on, r3_on;
input [3:0] r_bus;
output [3:0] ra, rb, ia;
reg [3:0] r0, r1, r2,r3;
wire [3:0] r0_bypass, r1_bypass, r2_bypass, r3_bypass;

always @ (posedge ck) begin
if (reset) begin
r0<=4'h0;
r1<=4'h0;
r2<=4'h0;
r3<=4'h0;
end else begin
if (r0_ld_na) r0<=r_bus;
if (r1_ld_na) r1<=r_bus;
if (r2_ld_na) r2<=r_bus;
if (r3_ld_na) r3<=r_bus; else r3<=r3+1;
end
end

assign r0_bypass = (r0_ld_na==1) ? r_bus : r0;
assign r1_bypass = (r1_ld_na==1) ? r_bus : r1;
assign r2_bypass = (r2_ld_na==1) ? r_bus : r2;
assign r3_bypass = (r3_ld_na==1) ? r_bus : r3;

assign ra =
(r0_on==1) ? r0_bypass :
(r1_on==1) ? r1_bypass :
(r2_on==1) ? r2_bypass :
(r3_on==1) ? r3_bypass : 4'bxxxx ;

assign rb =
(r0_ld==1) ? r0 :
(r1_ld==1) ? r1 :
(r2_ld==1) ? r2 :
(r3_ld==1) ? r3 : 4'bxxxx ;

assign ia = r3;

endmodule

module alu (ck, reset, a, b, im, oz, oi, q_na, of, co);
input ck, reset;
input [3:0] a, b, im;
input oz, oi;
output [3:0] q_na;
output of, co;

wire [3:0] q;
reg [3:0] q_na;

assign {of,q} =
(oi == 1 && oz == 1)? im :
(oi == 1)? a + im :
(oz == 1)? a :
a + b ;
assign co=| {of,q} ;

always @ (posedge ck or posedge reset) begin
if (reset) begin
q_na<=4'b0000;
end else begin
q_na<=q;
end
end

endmodule

module cpu(ck, reset) ;
input ck, reset;

wire fetch_en;
wire [3:0] rom_address;
wire [7:0] rom_data;
wire [3:0] ld_na, ld, on;
wire oz, oi;

wire [3:0] r_bus;
wire [3:0] ra, rb;
wire [3:0] im;
wire rc;
wire co;

rom rom ( .oen(fetch_en), .rom_address(rom_address), .rom_data(rom_data));

dec DEC (
.ck(ck),
.reset(reset),
.i_code(rom_data[7:4]),
.imidiate(rom_data[3:0]),
.co(co),

.fetch_en(fetch_en),
.ld(ld),
.ld_na(ld_na),
.on(on),
.im(im),
.oz(oz),
.oi(oi)
);

registor REG_ (
.ck(ck),
.reset(reset),
.r_bus(r_bus),
.r0_ld(ld[0]),
.r1_ld(ld[1]),
.r2_ld(ld[2]),
.r3_ld(ld[3]),
.r0_ld_na(ld_na[0]),
.r1_ld_na(ld_na[1]),
.r2_ld_na(ld_na[2]),
.r3_ld_na(ld_na[3]),
.r0_on(on[0]),
.r1_on(on[1]),
.r2_on(on[2]),
.r3_on(on[3]),
.ra(ra),
.rb(rb),
.ia(rom_address)
);

alu ALU (
.ck(ck),
.reset(reset),
.a(ra),
.b(rb),
.im(im),
.oz(oz),
.oi(oi),
.q_na(r_bus),
.co(co)
);

endmodule

2008年2月22日金曜日

TD4.v CPUの創り方 2段パイプライン版

module rom(oen, rom_address, rom_data);

/*
instruction decode
0000_0000 : add r0,r1
0001_0000 : add r1,r0
0010_.... : add r0,#i
0011_.... : add r1,#i
0100_0000 : move r0,r1
0101_0000 : move r1,r0
0110_.... : move r0,#i
0111_.... : move r1,#i
1000_.... : jmp #i
1100_.... : jnz #i

ld(on)
0001 : r0
0010 : r1
0100 : r2
1000 : r3(PC)
*/
input oen;
input [3:0] rom_address;
output [7:0] rom_data;

wire [3:0] rom_address;
reg [7:0] rom_data;

always @ (rom_address) begin
if (oen) begin
casez(rom_address)
4'h0: rom_data=8'b0110_0001; /* move r0,#0001 */
4'h1: rom_data=8'b0010_0010; /* add r0,#0010 */
4'h2: rom_data=8'b0111_0000; /* move r1,#0000 */
4'h3: rom_data=8'b1100_0001; /* jnz #0001 */
4'h4: rom_data=8'b1000_0001; /* jmp #0001 */
default:
rom_data=8'b0000_0000;
endcase
end else begin
rom_data=8'bxxxx_xxxx;
end
end

endmodule

module dec (
ck,
reset,
i_code,
imidiate,
co,
fetch_en,
ld,
on,
im,
oz,
oi
);
input ck, reset;
input [3:0] i_code, imidiate;
input co;
output fetch_en;
output [3:0] ld, on, im;
output oz;
output oi;

reg [3:0] ld_c, on_c;
reg oz_c, oi_c, en_c;
reg [3:0] ld, on, im;
reg oz, oi;
reg en;

always @ (i_code or co or en) begin
if (en) begin
casez (i_code)
4'b0000: begin /* add r0,r1 */ ld_c=4'b0001; on_c=4'b0010; oz_c=0; oi_c=0; en_c=1; end
4'b0001: begin /* add r1,r0 */ ld_c=4'b0010; on_c=4'b0001; oz_c=0; oi_c=0; en_c=1; end
4'b0010: begin /* add r0,#i */ ld_c=4'b0001; on_c=4'b0001; oz_c=0; oi_c=1; en_c=1; end
4'b0011: begin /* add r1,#i */ ld_c=4'b0010; on_c=4'b0010; oz_c=0; oi_c=1; en_c=1; end
4'b0100: begin /* move r0,r1 */ ld_c=4'b0001; on_c=4'b0010; oz_c=0; oi_c=0; en_c=1; end
4'b0101: begin /* move r1,r0 */ ld_c=4'b0010; on_c=4'b0001; oz_c=0; oi_c=0; en_c=1; end
4'b0110: begin /* move r0,#i */ ld_c=4'b0001; on_c=4'b0001; oz_c=0; oi_c=1; en_c=1; end
4'b0111: begin /* move r1,#i */ ld_c=4'b0010; on_c=4'b0010; oz_c=0; oi_c=1; en_c=1; end
4'b1000: begin /* jmp #i */ ld_c=4'b1000; on_c=4'bxxxx; oz_c=1; oi_c=1; en_c=0; end
4'b1100: begin /* jnz #i */
if (co) begin
ld_c=4'b1000; on_c=4'bxxxx; oz_c=1; oi_c=1; en_c=0;
end else begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
end
default: begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
endcase
end else begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
end

always @ (posedge ck or posedge reset) begin
if (reset) begin
ld<=4'b0001; on<=4'b0001; oz<=1; oi<=0; /* add r0,#0 as NOP */
im<=4'b0000;
en<=1;
end else begin
ld<=ld_c; on<=on_c; oz<=oz_c; oi<=oi_c;
im<=imidiate;
en<=en_c;
end
end
assign fetch_en=en;

endmodule

module registor (
ck,reset,r_bus,
r0_ld, r1_ld, r2_ld, r3_ld,
r0_on, r1_on, r2_on, r3_on,
ra,
rb,
ia
);

input ck, reset;
input r0_ld, r1_ld, r2_ld, r3_ld;
input r0_on, r1_on, r2_on, r3_on;
input [3:0] r_bus;
output [3:0] ra, rb, ia;
reg [3:0] r0, r1, r2,r3;

always @ (posedge ck) begin
if (reset) begin
r0<=4'h0;
r1<=4'h0;
r2<=4'h0;
r3<=4'h0;
end else begin
if (r0_ld) r0<=r_bus;
if (r1_ld) r1<=r_bus;
if (r2_ld) r2<=r_bus;
if (r3_ld) r3<=r_bus; else r3=r3+1;
end
end

assign ra =
(r0_on==1) ? r0 :
(r1_on==1) ? r1 :
(r2_on==1) ? r2 :
(r3_on==1) ? r3 : 4'bxxxx ;

assign rb =
(r0_ld==1) ? r0 :
(r1_ld==1) ? r1 :
(r2_ld==1) ? r2 :
(r3_ld==1) ? r3 : 4'bxxxx ;

assign ia = r3;

endmodule

module alu (a, b, im, oz, oi, q, of, co);
input [3:0] a, b, im;
input oz, oi;
output [3:0] q;
output of, co;
assign {of,q} =
(oi == 1 && oz == 1)? im :
(oi == 1)? a + im :
(oz == 1)? a :
a + b ;
assign co=| {of,q} ;
endmodule

module cpu(ck, reset) ;
input ck, reset;

wire fetch_en;
wire [3:0] rom_address;
wire [7:0] rom_data;
wire [3:0] ld, on;
wire oz, oi;

wire [3:0] r_bus;
wire [3:0] ra, rb;
wire [3:0] im;
wire rc;
wire co;

rom rom ( .oen(fetch_en), .rom_address(rom_address), .rom_data(rom_data));

dec DEC (
.ck(ck),
.reset(reset),
.i_code(rom_data[7:4]),
.imidiate(rom_data[3:0]),
.co(co),

.fetch_en(fetch_en),
.ld(ld),
.on(on),
.im(im),
.oz(oz),
.oi(oi)
);

registor REG_ (
.ck(ck),
.reset(reset),
.r_bus(r_bus),
.r0_ld(ld[0]),
.r1_ld(ld[1]),
.r2_ld(ld[2]),
.r3_ld(ld[3]),
.r0_on(on[0]),
.r1_on(on[1]),
.r2_on(on[2]),
.r3_on(on[3]),
.ra(ra),
.rb(rb),
.ia(rom_address)
);

alu ALU (.a(ra), .b(rb), .im(im), .oz(oz), .oi(oi), .q(r_bus), .co(co));

endmodule

2008年2月19日火曜日

TD4.v CPUの創り方

module top;

reg ck, reset;

initial begin

$dumpfile("cpu.vcd");
$dumpvars(0,CPU);

#0 ck=0;
#0 reset=1;

#100 ck=~ck;
#100 ck=~ck;

#0 reset=0;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

$finish;

end

cpu CPU (.ck(ck), .reset(reset));

initial $monitor ("ck:rs = %b:%b", ck, reset);
endmodule

module rom(rom_address, rom_data);

/*
instruction decode
0000_0000 : add r0,r1
0001_0000 : add r1,r0
0010_.... : add r0,#i
0011_.... : add r1,#i
0100_0000 : move r0,r1
0101_0000 : move r1,r0
0110_.... : move r0,#i
0111_.... : move r1,#i
1000_.... : jmp #i
1100_.... : jnz #i

ld(on)
0001 : r0
0010 : r1
0100 : r2
1000 : r3(PC)
*/
input [3:0] rom_address;
output [7:0] rom_data;

wire [3:0] rom_address;
reg [7:0] rom_data;

always @ (rom_address) begin
casez(rom_address)
4'h0: rom_data=8'b0110_0001; /* move r0,#0001 */
4'h1: rom_data=8'b0010_0010; /* add r0,#0010 */
4'h2: rom_data=8'b0111_0000; /* move r1,#0000 */
4'h3: rom_data=8'b1100_0001; /* jnz #0001 */
4'h4: rom_data=8'b1000_0001; /* jmp #0001 */
default:
rom_data=8'bxxxx_xxxx;
endcase
/*$display("%h:%h",rom_address,rom_data);*/
end

endmodule

module dec (
i_code,
co,
ld,
on,
oz,
oi
);
input [3:0] i_code;
input co;
output [3:0] ld;
output [3:0] on;
output oz;
output oi;

reg [3:0] ld, on;
reg oz, oi;
always @ (i_code) begin
casez (i_code)
4'b0000: begin /* add r0,r1 */ ld=4'b0001; on=4'b0010; oz=0; oi=0; end
4'b0001: begin /* add r1,r0 */ ld=4'b0010; on=4'b0001; oz=0; oi=0; end
4'b0010: begin /* add r0,#i */ ld=4'b0001; on=4'b0001; oz=0; oi=1; end
4'b0011: begin /* add r1,#i */ ld=4'b0010; on=4'b0010; oz=0; oi=1; end
4'b0100: begin /* move r0,r1 */ ld=4'b0001; on=4'b0010; oz=0; oi=0; end
4'b0101: begin /* move r1,r0 */ ld=4'b0010; on=4'b0001; oz=0; oi=0; end
4'b0110: begin /* move r0,#i */ ld=4'b0001; on=4'b0001; oz=0; oi=1; end
4'b0111: begin /* move r1,#i */ ld=4'b0010; on=4'b0010; oz=0; oi=1; end
4'b1000: begin /* jmp #i */ ld=4'b1000; on=4'bxxxx; oz=1; oi=1; end
4'b1100: begin /* jnz #i */
if (co) begin
ld=4'b1000; on=4'bxxxx; oz=1; oi=1;
end else begin
ld=4'b0001; on=4'b0001; oz=1; oi=0; /* add r0,#0 as NOP */
end
end
default: begin
ld=4'bxxxx;
on=4'bxxxx;
oz=1'bx;
oi=1'bx;
end
endcase
end
endmodule

module registor (
ck,reset,r_bus,
r0_ld, r1_ld, r2_ld, r3_ld,
r0_on, r1_on, r2_on, r3_on,
co,
ra,
rb,
rc,
ia
);

input ck, reset;
input r0_ld, r1_ld, r2_ld, r3_ld;
input r0_on, r1_on, r2_on, r3_on;
input [3:0] r_bus;
input co;
output [3:0] ra, rb, ia;
output rc;
reg [3:0] r0, r1, r2,r3;
reg carry;

always @ (posedge ck) begin
#1;
if (reset) begin
r0=4'h0;
r1=4'h0;
r2=4'h0;
r3=4'h0;
carry=0;
end else begin
if (r0_ld) r0=r_bus;
if (r1_ld) r1=r_bus;
if (r2_ld) r2=r_bus;
if (r3_ld) r3=r_bus; else r3=r3+1;
carry=co;
end
$display("r0 = %h r1 = %h r2 = %h r3 = %h", r0,r1,r2,r3);
end

assign ra =
(r0_on==1) ? r0 :
(r1_on==1) ? r1 :
(r2_on==1) ? r2 :
(r3_on==1) ? r3 : 4'bxxxx ;

assign rb =
(r0_ld==1) ? r0 :
(r1_ld==1) ? r1 :
(r2_ld==1) ? r2 :
(r3_ld==1) ? r3 : 4'bxxxx ;

assign rc = carry;

assign ia = r3;

endmodule

module alu (a, b, im, oz, oi, q, of, co);
input [3:0] a, b, im;
input oz, oi;
output [3:0] q;
output of, co;
assign {of,q} =
(oi == 1 && oz == 1)? im :
(oi == 1)? a + im :
a + b ;
assign co=| {of,q} ;
endmodule

module cpu(ck, reset) ;
input ck, reset;

wire [3:0] rom_address;
wire [7:0] rom_data;
wire [3:0] ld, on;
wire oz, oi;

wire [3:0] r_bus;
wire [3:0] ra, rb;
wire rc;
wire co;

rom rom (.rom_address(rom_address), .rom_data(rom_data));

dec DEC (.i_code(rom_data[7:4]), .co(rc), .ld(ld), .on(on), .oz(oz), .oi(oi));

registor REG_ ( .ck(ck), .reset(reset), .r_bus(r_bus), .r0_ld(ld[0]), .r1_ld(ld[1]), .r2_ld(ld[2]), .r3_ld(ld[3]), .r0_on(on[0]), .r1_on(on[1]), .r2_on(on[2]), .r3_on(on[3]), .co(co), .ra(ra), .rb(rb), .rc(rc), .ia(rom_address));

alu ALU (.a(ra), .b(rb), .im(rom_data[3:0]), .oz(oz), .oi(oi), .q(r_bus), .co(co));

endmodule

2008年2月14日木曜日

startx/startxwin.bat/startwin.sh

この3つのスクリプトって、

startx :xinitを呼び出してXを起動(shellスクリプト)
startxwin.bat:XWinを呼び出してXを起動(.batファイル)
startxwin.sh :XWinを呼び出してXを起動(shellスクリプト)

がそれぞれの違いになります。
なのでぇ、cmdからはstartxwin.bat、bashからはstartx/startwin.sh、でCygwin Xを起動することになります。
っつと、もっとも大きな違いはと、xinitを使わないと$HOME/.xinitrcが読まれません。

当たり前なんですが、忘れがちです・・・

CygwinX.bat(startwin.bat日本語編)

@echo off
set DISPLAY=127.0.0.1:0.0
set CYGWIN_ROOT=\cygwin
set PATH=.;%CYGWIN_ROOT%\bin;%CYGWIN_ROOT%\usr\X11R6\bin;%PATH%

if not exist %CYGWIN_ROOT%\tmp\.X11-unix\X0 goto CLEANUP-FINISH
attrib -s %CYGWIN_ROOT%\tmp\.X11-unix\X0
del %CYGWIN_ROOT%\tmp\.X11-unix\X0

:CLEANUP-FINISH
if exist %CYGWIN_ROOT%\tmp\.X11-unix rmdir %CYGWIN_ROOT%\tmp\.X11-unix

REM =======================================================================
REM (1)ローカルでCygwinを起動する場合の設定です
REM (2)XWinの書式
REM -rootless:デスクトップが透過します
REM (3)ログイン後にxwinclipコマンドでWindows側とコピー&ペースト可能となります
REM =======================================================================
REM start XWin -engine 4 -clipboard -emulate3buttons
start XWin -engine 4 -clipboard -emulate3buttons -rootless
run xmodmap /home/Administrator/.Xmodmap
run wmaker
run xterm

REM =======================================================================
REM (1)ローカルでCygwinを起動する場合の設定です
REM (2)日本語環境が設定されている場合に利用します
REM (3)XWinの書式
REM -rootless:デスクトップが透過します
REM (4)ログイン後にxwinclipコマンドでWindows側とコピー&ペースト可能となります
REM =======================================================================
REM start XWin -engine 4
REM set LANG=ja_JP.EUC
REM set XMODIFIERS='@im=kinput2'
REM run /usr/local/canna/bin/cannaserver
REM run xset fp+ /usr/X11R6/lib/X11/fonts/TT
REM run xmodmap /home/Administrator/.Xmodmap
REM run xrdb -load /home/Administrator/.Xresources
REM run kinput2 -canna -cannafile /home/Administrator/.canna
REM run wmaker

REM =======================================================================
REM (1)Solarisログインサーバへ接続する場合の設定です
REM (2)XWinの書式(ホスト名を使用する場合はhostsへの登録が必要です)
REM -query :ログインサーバのIPアドレス or ホスト名
REM -from :ローカルのIPアドレス or ホスト名
REM -fp :ログインサーバのIPアドレス or ホスト名
REM -fullscreen -depth 8 :8bitカラーで利用する
REM =======================================================================
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lis4 -from 172.16.245.166 -fp tcp/sv_lis4:7100 -fullscreen -depth 8
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lis4 -from 172.16.245.166 -fp tcp/sv_lis4:7100
REM sleep 30
REM xmodmap /home/Administrator/.Xmodmap

REM =======================================================================
REM (1)Linuxログインサーバへ接続する場合の設定です
REM (2)XWinの書式(ホスト名を使用する場合はhostsへの登録が必要です)
REM -query :ログインサーバのIPアドレス or ホスト名
REM -from :ローカルのIPアドレス or ホスト名
REM -fullscreen -depth 8 :8bitカラーで利用する
REM =======================================================================
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lin11 -from 172.16.245.166 -fullscreen -depth 8
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lin11 -from 172.16.245.166
REM sleep 30
REM xmodmap /home/Administrator/.Xmodmap

REM =======================================================================
REM (1)HP-UXログインサーバへ接続する場合の設定です
REM (2)XWinの書式(ホスト名を使用する場合はhostsへの登録が必要です)
REM -query :ログインサーバのIPアドレス or ホスト名
REM -from :ローカルのIPアドレス or ホスト名
REM -fp :ログインサーバのIPアドレス or ホスト名
REM -fullscreen -depth 8 :8bitカラーで利用する
REM =======================================================================
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lih21 -from 172.16.245.166 -fp tcp/sv_lih21:7000 -fullscreen -depth 8
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lih21 -from 172.16.245.166 -fp tcp/sv_lih21:7000
REM sleep 30
REM xmodmap /home/Administrator/.Xmodmap

2008年2月13日水曜日

imeproxy で cygwin日本語入力

WindowsのIMEをproxyしてくれて、cygwinなどからIMEで日本語入力を可能にしてくれるもの、ん~っすばらしいぃ~考え方
ここにプロジェクトがあります。また、ここに解説があります。まだまだβ的ではありますが。

kinput2→canna

がUnix系日本語入力の基本(だった)なのですが、「IMEがある場合(つまりWindowsからLinuxを使用して仕事している場合っね)」辞書サーバが2つあるのも不経済かと思いますよ。なんでLinuxでの日本語入力もIMEで代用出ると経済的。

kinput2→imeproxy→IME

ってパスで日本語変換を達成してしまうようです。
まあ、FrontEndとしてkinput2が必要なことは致し方ない。英語圏の人はFrontEndなんて不要ですから、少なくともkinput2などは必要になってしまいますよねぇ。で、ご一緒に仕事しているメンバの中には、cannaサーバを立ち上げるのが面倒なので、Linux上では日本語一切使用しないって人もいます。昔は自分でcanna立ち上げて利用していたのに、いまや「Windowsでイイじゃん」ってことらしい。それと自分でIMEの辞書を鍛えてたりすると、「WindowsのIMEとcanna、両方を鍛えるのは面倒」となります。一番キツイのは人名シリーズではないでしょうか?。IMEでは出てくるのにcannaではダメっみたいなことが起こるという訳。

で、imeproxyの登場です。Linux上のEmacsからkinput2でWindows上の自分の辞書へアクセスできれば、とってもウレスィイー