オリジナルCPU「DL166」のレジスタをLEDドットマトリックスで見える化するオリジナルCPUでバイナリコード入門(6)(2/3 ページ)

» 2023年07月18日 07時00分 公開
[今岡通博MONOist]

LEDドットマトリクスの表示方法

 11〜14行目に当たるリスト2は、LEDドットマトリクスで8個のレジスタの表示とTang Nano搭載のLEDにc_flagの値を表示するためのコードです。

11:    wire [2:0]i=counter[15:13];
12:    assign col ={4'b0000,regs[i]};
13:    assign row ={i!=7,i!=6,i!=5,i!=4,i!=3,i!=2,i!=1,i!=0};
14:    assign leds={5'b11111,!c_flag};
リスト2 LEDドットマトリクスとTang Nano搭載のLEDで表示を行うためのコード

 11行目でcounterの13〜15ビット目の3ビット分をiというシンボルで参照できるように設定しています。12行目は、col、LEDドットマトリックスでいうと8ビット長の横のラインを表します。上位4ビットを0とし、下位4ビットはr0〜r7までのレジスタの値を代入しています。13行目でiが0〜7までカウントアップを繰り返す中、それぞれのレジスタを表示する順番が来たらそのビットを1から0にします。すると、rowはカソードに接続されていますので、col側との電位差が生じそのドットのLEDが点灯するという仕掛けです。

 ただこの書き方はポータビリティーの点で問題を起こす可能性があります。この記述でうまくいかない場合は「i!=7」のところを「(i==7)?0:1」としてください。

 14行目は、Tang Nano搭載の6個並んだオレンジのLEDの最下位にオーバーフローを示すc_flagの値を反映するようにしています。ちなみに上位5ビットまでは消灯するように設定しています。リスト2は4行と短いコードですが、密度の高い仕事をさせています。

CPUの動作の記述

 行番号の順番でいくと説明が前後しますが、30〜49行目に当たるリスト3ではCPUに関わる動作を記述しています。

 30行目でdoutにメモリからフェッチしてきた命令セットをセットします。regs[7]は現在のプログラムカウンターの値が定義されています。31行目ではcounter[23]の値の立ち上がりまたはrstの立ち下がりで32行以下のブロックが実行されます。32行目でrstの値が0、すなわちリセットのタクトスイッチが押された状態であればレジスタ群とキャリーフラグを0にします。そうでなければ34〜48行目のコードを実行します。

 34行目では、外部入力である4ビットのスイッチの値をregs[5]に格納します。今回は未接続なので全て1がregs[5]に格納されます。34〜48行目は命令セットのデコードと実行を行っています。これらの説明は連載第2回記事で説明しているのでここでは省きます。39行目は、クロック(clk)の立ち上がりでcounterのカウントアップを行っています。

30: assign dout = ram[regs[7]];    
31:	always @(posedge counter[23]  or negedge rst)
32:	  if(rst==0) {regs[0],regs[1],regs[2],regs[3],regs[4],regs[6],regs[7],c_flag}=0;
33:	  else begin
34:	   regs[5]=btn;
35: /*MOV*/     if (0==(dout&192)) regs[(dout&56)>>3]=regs[dout&7]; 
36: /*ADD*/     if (64==(dout&248)) begin if (regs[0]+regs[dout&7]>15) c_flag=1;regs[0]=regs[dout&7]+regs[0];end
37: /*OR*/      if (72==(dout&248)) regs[0]=regs[0]|regs[dout&7];
38: /*AND*/     if (80==(dout&248)) regs[0]=regs[0]&regs[dout&7];
39: /*XOR*/     if (88==(dout&248)) regs[0]=regs[0]^regs[dout&7];
40: /*NOT*/     if (104==(dout&248)) regs[dout&7]=~regs[dout&7];
41: /*RLOTATE*/ if (112==(dout&248)) regs[dout&7]=((regs[dout&7])>>1)|((regs[dout&7]&1) << 3);
42: /*LLOTATE*/ if (120==(dout&248)) regs[dout&7]=((regs[dout&7])<<1)|((regs[dout&7]&8) >> 3);
43: /*INC*/     if (96==(dout&248)) begin if (regs[dout&7]+1>15) c_flag=1;regs[dout&7]=regs[dout&7]+1;end
44: /*JMP*/     if (144==(dout&240)) regs[7]=dout&15;
45: /*MVI*/     if (160==(dout&240)) regs[0]=dout&15;
46: /*JNC*/     if (128==(dout&240)) begin regs[7]=((c_flag)?regs[7]+1:dout&15);c_flag=0;end
47: /*PC++*/    if ((144!=(dout&240)&&(128!=(dout&240)))) regs[7]=regs[7]+1;	
48:    end
49:    always @(posedge clk) counter <= counter + 1;
リスト3 CPUの動作に関わるコード

Copyright © ITmedia, Inc. All Rights Reserved.