[[MiniCPUとI2Cバスの接続]]

* 概要 [#zaba5b6a]

- OSはプログラムを動かすプログラムであり、プログラムと人間とハードウェアの間のインターフェースです。よく利用されているようなOSを作成するのは大変ですが、miniCPUを操作するための簡単な機能をハードウェアで構成します。
- このOSは、miniCPUの起動と停止, miniCPUの実行速度の変更, miniCPUの入出力及び、インターフェースの接続状況の変更を行います。プログラムは、ram.v に書かれたものに限定します。
-- fpga で、miniCPU と周辺機器の接続を変更したり、miniCPUの実行を自動で行ったり、実行速度を変えたりすることを、fpga  上の基盤のスイッチの切り替えで行う回路を作成します。
-- 一般的なOSはプログラムの入れ替えを行うことができますが(プログラムローダが存在します)、この簡易OSではminiCPUのプログラムは、あらかじめ、ram.v に書かれたプログラムのみ実行することができます。
プログラムの入れ替えは、ISE上でram.v を書き換えて生成された bitファイルのダウンロードによって行います。
- [[MiniCPUとI2Cバスの接続]]を拡張します。[[MiniCPUとI2Cバスの接続]]と同様に、miniCPU をI2Cのmaster device として、I2Cのslave device を miniCPUのプログラムで、自動的に動かします。
- [[MiniCPUとI2Cバスの接続]]を拡張して実現します。[[MiniCPUとI2Cバスの接続]]と同様に、miniCPU をI2Cのmaster device として、I2Cのslave device を miniCPUのプログラムで、自動的に動かします。
- 
動作モードを変更することにより、([[MiniCPUとI2Cバスの接続]]と同様に) I2Cのslave device を手で動かしたり、miniCPUをI2Cと切り離して単独で動かしたり、miniCPU でI2Cの slave device 自動的に動かしたりできる他, miniCPUにクロックを自動的に供給し, 自動的にminiCPUを動かすことができるようにします。このとき、miniCPU のクロックを、ボードのクロックを分周することにより、変化させることができるようにします。
-- 動作モードの変更は、5つのボタンの、左(東)を使って変更します。
* 動作モード別機能 [#vc8cd336]
- 動作モードの変更は、5つのボタンの、右(東)を使って変更します。初期値の動作モードは0です。
** I2Cバスの手動操作(動作モード0) [#w24316c6]
- [[I2Cデバイスを手で動かしてみる]]と同様のことを可能にします。
**  miniCPUの独立実行(手動クロック供給)(動作モード1) [#t251b564]
- miniCPUのクロックを手で供給するときは、中央のボタンを押したり離したりして供給します。
-- Nexys4ボードのクロックは 100MHz です。ボードのクロックは32bitカウンタに供給されます。Nexys4のスライドスイッチの, 右から5つまでを使って分周比を決定します。このスライドスイッチで0-31までの数を表すことができますが、32bitカウンタを、左から数えて、その数が表す桁の値を、分周されたクロックとして、取り出します。 スライドスイッチを右から(1,1,1,1,0)とすると, これは32bit カウンタの, 下から30bit目の値を取り出すことになり, およそ, 10秒に1回クロックを供給することになります。
- miniCPUの run 信号は, 上(北)のボタンを押して供給します。
** miniCPUでI2Cバスを操作(手動クロック供給)(動作モード2) [#ac1ff30b]
- miniCPUでI2Cの slave device を動かしているとき、miniCPUのoutバッファの out[0]で scl を動かし, out[1]で sda を動かします。
- out[2]-out[5]を基板のJCコネクタの3-6に接続しています。
** miniCPU自動クロック供給のときのクロック分周値設定(動作モード3) [#xf310dd0]
- Nexys4ボードのクロックは 100MHz です。ボードのクロックは32bitカウンタに供給されます。Nexys4のスライドスイッチの, 右から5つまでを使って分周比を決定します。このスライドスイッチで0-31までの数を表すことができますが、32bitカウンタを、左から数えて、その数が表す桁の値を、分周されたクロックとして、取り出します。 スライドスイッチを右から(1,1,1,1,0)とすると, これは32bit カウンタの, 下から30bit目の値を取り出すことになり, およそ, 10秒に1回クロックを供給することになります。
** miniCPUの独立実行(自動クロック供給)(動作モード4) [#q9a75d45]
- クロック分周によって分周されたクロックをminiCPUに供給して, 自動的に動かします。
- I2Cとは切り離します。
** miniCPUでI2Cバスを操作(自動クロック供給)(動作モード5) [#gaa319c7]
- クロック分周によって分周されたクロックをminiCPUに供給して, 自動的に動かします。
- cpuStartStopSequence 回路により, 中央ボタン(BCx)を押すだけで, 実行が始まります。
- miniCPUでI2Cの slave device を動かしているとき、miniCPUのoutバッファの out[0]で sda を動かし, out[1]で scl を動かします。
- out[2]-out[5]を基板のJCコネクタの3-6に接続しています。
* 回路の概要 [#oe8fa2dd]
- miniCPU を構成する部品は、[[MiniCPU]]のものをそのまま使います。
- 「[[I2Cデバイスを手で動かしてみる]]」の回路を拡張して、miniCPUと接続します。
- sw[15:0]と up button, left button, center button, right button をチャタリング防止回路に通し、その出力をswx[15:0], BUx, BLx, BCx, BRx とします。
- sclx が1のときは、sclはZ(high impedance), sclxが0のときは sclは0とします。
- sdax が1のときは、sdaはZ(high impedance), sclxが0のときは sclは0とします。
- 動作モードを表すレジスタ, operationMode を使います。operationMode が 0のときは、I2Cを手動で動かすモード, 1のときは miniCPU を独立して動かすモード, 2のときは miniCPUでI2Cを動かすモードとします。
-- 動作モードをカラーLED 1で表示します。
-- 動作モード 0 のときは、miniCPUのクロック(cpuCLK)や run信号線(cpuRun)や入力信号線(cpuIn)を遮断し、7セグメントLEDの左から5桁目と6桁目で data レジスタを表示し、7桁目と8桁目で、swx[7:0] を表示します。led[15:8]はデータレジスタを表示します。led[7:0]はswx[7:0]を表示します。sclxはBCxと接続し, sdaxはswx[0]と接続します。 color LED 2 は、sda と sclの 1,0を表します。
-- 動作モード 1 のときは、BCxを miniCPUのクロックに接続し、BNxをcpuRUNに接続し, data をcpuINの下位8bit に接続します。7セグメントLEDの左から1桁目で cpu の状態を表します。2桁目から4桁目でcpuの実行中のアドレスを表します。5桁目から8桁目で、実行中の命令を表します。 led のはminiCPUの出力(out)を表します。sclx, sdax はa にします。color LED 2 は、sda と sclの 1,0を表します。
-- 動作モード 2 のときは, BCxを miniCPUのクロックに接続し、BNxをcpuRUNに接続し, data をcpuINの下位8bit に接続します。7セグメントLEDの左から1桁目で cpu の状態を表します。2桁目から4桁目でcpuのアドレスバスの値を表します。5桁目から8桁目で、cpuのデータバスの内容を表します。 ledの上位8bit で, data レジスタの内容を表示し, led の下位8bit でminiCPUの出力(out)の下位8bitを表します。scl にcpuの出力の下位から2bit目, out[1], sda に cpu の出力の下位1bit目, out[0] を接続します。はZ にします。color LED 2 は、sda と sclの 1,0を表します。
- 動作モードの表 &br;
|operationMode |機能|Color LED 1|cpuClk|cpuRun|cpuIn|sSegArray|led|sclx, sdax|Color LED 2|start|
|0|I2Cバスの手動操作| {0,0,0} |BCx | 0 | 0| {16{0}, data,swx[7:0]}|{data,swx[7:0]}|BCx,swx[0]|{0,sda,scl}|0|
|1|miniCPUの独立実行(手動クロック供給)|{0,0,1}|BCx|BNx|swx|{{0},cpuCs,pcout,irout}|out|1,1|{0,sda,scl}|0|
|2|miniCPUでI2Cバスを操作(手動クロック供給)|{0,1,0}|BCx|BNx|{8{0},data}|{{0},cpuCs,abus,dbus}|{data,out[7:0]}|out[1],out[0]|{0,sda,scl}|0|
|1|miniCPUの独立実行(手動クロック供給)|{0,0,1}|BCx|BNx|swx|{sSegBufH,sSegBufL}|out|1,1|{0,sda,scl}|0|
|2|miniCPUでI2Cバスを操作(手動クロック供給)|{0,1,0}|BCx|BNx|{8{0},data}|{sSegBufH,sSegBufL}|{data,out[7:0]}|out[1],out[0]|{0,sda,scl}|0|
|3|miniCPU自動クロック供給のときのクロック分周値設定 |{0,1,1}|BCx |0|{8{0},data}|{{0},cpuCs,abus,dbus}|{data,out[7:0]}|out[1],out[0]|{0,sda,scl}|0|
|4|miniCPUの独立実行(自動クロック供給)|{1,0,0}|dclk|ssRun(自動スタート)|swx|{{0},cpuCs,pcout,irout}|out|1,1|{0,sda,scl}|BCx|
|5|miniCPUでI2Cバスを操作(自動クロック供給)|{1,0,1}|dclk|ssRun(自動スタート)|{8{0},data}|{{0},cpuCs,abus,dbus}|{data,out[7:0]}|out[1],out[0]|{0,sda,scl}|BCx|
|4|miniCPUの独立実行(自動クロック供給)|{1,0,0}|dclk|ssRun(自動スタート)|swx|{sSegBufH,sSegBufL}|out|1,1|{0,sda,scl}|BCx|
|5|miniCPUでI2Cバスを操作(自動クロック供給)|{1,0,1}|dclk|ssRun(自動スタート)|{8{0},data}|sSegBufH,sSegBufL}|{data,out[7:0]}|out[1],out[0]|{0,sda,scl}|BCx|

- down button をリセット信号とします。
- sda を led[8] に接続します。scl が 0->1 に変化するたびに、これをシフトして、過去8回のsda の High/Low の遷移を led[15:8] に表示します。 これを実現するために、レジスタ data[7:0] を使っています。
- 1つのポートで入出力を行う為、scl, sda は verilog の inout 型を使います。
** Verilog [#y617cf4a]
- top.v
 module top(sSegAnode, sSegCathode, sw, ledOut, colorLed_1, colorLed_2,
  bu, bd, bl, br, bc, scl, sda, 
  bu, bd, bl, br, bc, scl, sda, jc,
  bclck
     );  
   output [7:0] sSegAnode;
   output [7:0] sSegCathode;
   output [15:0] ledOut;                  // led[8] ... if sda is sending, corresponding to the last sended sda,
                                           else corresponding to the last received sda
   output [15:0] ledOut;                  // led[8] ... if sda is sending, corresponding to the last sended sda, else corresponding to the last received sda
                                       //               it is shifted to left when a positive edge of scl is detected.
 												  //  led[0] corresponding to sw[0]
 												  //  led[1] corresponding to sw[1]
 												  //  led[2] corresponsing to center button, bc.
   output [2:0] colorLed_1;
   output [2:0] colorLed_2;          // color LED 
   output [3:0] jc;
   input [15:0] sw;                    // sw[15:8] ... for setting sda send data, sw[7:0] ... for controlling
                                        //    sw[0] ... if 1 scl is not ready, else scl is ready;
                                       //    sw[0] ... if 1 scl is not ready, else scl is ready;
 												  //    sw[1] ... if 1 sda is receiving(1), else sda is sending(0).
 												  //    sw[2] ... sending sda.
             												  
   input bu, bd, bl, br, bc, bclck;    //  bd corresponding to !reset.
                                       //  bc corresponding to scl.  scl=sw[0]|bc
 												  //  if posedge bl is detected, sw is shown in hex in the 7seg led array.
   
   inout scl, sda;
   reg sclx, sdax;
   reg [3:0] jcx; 
   
   assign scl=(~sclx)?1'b0:1'bz;
   assign sda=(~sdax)?1'b0:1'bz;
   assign jc=jcx;
   
   wire BNx, BWx, BEx, BCx;
   // reset: BSx
   // BWx, BEx ... change operationMode
   // 
   wire [15:0] swx;
   wire reset;
 //  reg sclRw, sdaRw; // write=1, read=0;
   wire cpuClk;
   wire cpuRun;
   reg [7:0] data;
   reg [2:0] operationMode;
   // operationMode: 0 ... manual operation of peripherals
   //                1 ... CPU independent
   //                2 ... CPU, I2C connected
   reg [15:0] ledWire,cpuIn;
   wire [2:0] cpuCs;
   wire [11:0] pcout,abus;
   wire [15:0] irout,qtop,dbus,out;
   reg [31:0] sSegArray;
   reg [15:0] led;
   wire start;
   wire haltIn;  
   wire halt; 
   wire halt;
   wire [15:0] sSegBufL;
   wire [15:0] sSegBufH;
 
   reg [4:0] divide;
   wire dclk;
   
   initial begin
     divide={01101};
   end
   
   assign ledOut=led;
   
   reg [2:0] colorLed_1x;
   wire [2:0] colorLed_2x;
 //  
   assign colorLed_1=colorLed_1x;
   assign colorLed_2=colorLed_2x;
   
   assign reset=~bd;
   
   always @(posedge sclx, negedge reset) begin
     if(!reset) begin
     	 data<=0; 
 	 end
 	 else
     data<={data[6:0],sda};
   end
   
   // for operation mode
   always @(posedge BEx or negedge reset ) begin
      if(!reset) begin 
      if(!reset) begin
 	    operationMode<=3'b000;
 	  end 
 	  end
 	  else
 	  case (operationMode)
 	    3'b000: operationMode<=3'b001;
 		 3'b001: operationMode<=3'b010;
 		 3'b010: operationMode<=3'b011;
 		 3'b011: operationMode<=3'b100;
 		 3'b100: operationMode<=3'b101;
 		 3'b101: operationMode<=3'b110;
 		 3'b110: operationMode<=3'b000;
 		 default 
 		    operationMode<=3'b000;
 		endcase
 	end
 	/*
    always @(posedge BWx or negedge reset ) begin
      if(!reset) begin
 	    operationMode<=0;
 	    operationMode<=0; 
 	  end
 	  else
 	  case (operationMode)
 	    3'b000: operationMode<=3'b110;
 		 3'b001: operationMode<=3'b000;
 		 3'b010: operationMode<=3'b001;
 		 3'b011: operationMode<=3'b010;
 		 3'b100: operationMode<=3'b011;
 		 3'b101: operationMode<=3'b100;
 		 3'b110: operationMode<=3'b101;
 		 default 
 		    operationMode<=3'b000;
 		endcase
 	end
    */    
   /* */  
 //  assign setDivide=(operationMode==3'b011)?BCx:1'b0;
   always @(posedge BCx ) begin
      if(operationMode==3'b011) begin 
      if(operationMode==3'b011) begin
 	     divide<=swx[15:11];		 
      end 		  
   end
   
   assign	colorLed_2x={dclk,scl,sda};
   assign start=(operationMode==3'b100|operationMode==3'b101)?BCx:1'b0;
   assign cpuClk=(operationMode==3'b100|operationMode==3'b101)? dclk:BCx;
   assign cpuRun=(operationMode==3'b100|operationMode==3'b101)? ssRun:BNx;
   assign haltIn=(operationMode==3'b100|operationMode==3'b101)? halt:1'b0; 
 
   assign haltIn=(operationMode==3'b100|operationMode==3'b101)? halt:1'b0;
   assign sSegBufL=BWx?irout:out;
   assign sSegBufH=BWx?{{0},cpuCs,abus}:pcout;
   
 //  always @(operationMode or swx[0] or BCx or data or BNx or cpuCs or out or sda or scl or out[0] or out[1]) begin
 //  always @(posedge BEx or posedge BWx or negedge reset) begin
     always @(operationMode) begin
      case(operationMode)
       3'b000: begin                             // direct i2c operation only
       3'b000: begin                             // direct i2c operation only 
 		     colorLed_1x=3'b000;
 			  cpuIn=0;
 			  sSegArray={{16{0}},data,swx[7:0]};
 			  led[15:8]=data;
             led[7:0]=swx[7:0];
            sclx=BCx; 
            led[7:0]=swx[7:0];
            sclx=BCx;
 			  sdax=swx[0];
 			  jcx=swx[5:2];
 			end
 		3'b001: begin // mini CPU, with manual clock only ... for start ... push BTN, keep, push BTC, release BTN, BTC
 		     colorLed_1x=3'b001; // blue
 			  cpuIn=swx; 
 			  sSegArray={{0},cpuCs,pcout,irout};
 			  led={{0{16}},out};
 			  sSegArray={sSegBufH,sSegBufL};
 			  led=out;
 			  sclx=1'b1;
 			  sdax=1'b1;
 			  jcx={0,0,0,0};
 		   end
 		3'b010: begin // mini CPU, with manual clock, with i2c IO
 		     colorLed_1x=3'b010; //green
 			  cpuIn={{8{0}},data}; 
 			  sSegArray={{0},cpuCs,abus,dbus};
 			  cpuIn={swx[15:8],data}; 
 			  sSegArray={sSegBufH, sSegBufL};
 			  led[15:8]=data;
            led[7:0]=out[7:0];
            sclx=out[1]; 
            sclx=out[1];
 			  sdax=out[0];
 			  jcx=out[5:2];
 		   end
 		3'b011: begin // set clock divider for mini CPU with automatic clock
 		     colorLed_1x=3'b011; // cyan .. aqua
 			  cpuIn=0; 
 			  sSegArray={divide,{13{0}},data,swx[7:0]};
 			  led[15:8]=divide;
            led[7:0]=swx[7:0];
            sclx=1; 
            sclx=1;
 			  sdax=1;
 			  jcx={0,0,0,0};
 		   end
 		3'b100: begin // mini CPU, only, with automatic clock, 
 		     colorLed_1x=3'b100; // red
 			  cpuIn=swx; 
 			  sSegArray={{0},cpuCs,pcout,irout};
 			  led={{0{16}},out};
 			  sSegArray={sSegBufH, sSegBufL};
 			  led=out;
            sclx=1'b1;
 			  sdax=1'b1;
 			  jcx={0,0,0,0};
 		   end
 		3'b101: begin // mini CPU, with automatic clock, with i2c IO
 		     colorLed_1x=3'b101; //  purple
 			  cpuIn={{8{0}},data}; 
 			  sSegArray={{0},cpuCs,abus,dbus};
 			  cpuIn={swx[15:8],data}; 
 			  sSegArray={sSegBufH, sSegBufL};
 			  led[15:8]=data;
            led[7:0]=out[7:0];
           led[7:0]=out[7:0];
            sclx=out[1];
 			  sdax=out[0];
 			  jcx=out[5:2];
 		   end
 		default begin
 		     colorLed_1x=3'b000;
 			  cpuIn=swx; 
 			  sSegArray={{0{16}},data,swx[7:0]};
 			  led[15:8]=data;
            led[7:0]=swx[7:0];
            sclx=BCx;
 			  sdax=swx[0];
 			  jcx=swx[5:2];
 		end
 	  endcase
   end
 
 
   
    
   chattering #(20) chattering0(.clk(bclck), .reset(reset), .in({bu,bl,br,bc,sw}), .out({BNx,  BWx, BEx, BCx,swx}));
   /* for test bench
   assign BNx=bu;
   assign BWx=bl;
   assign BEx=br;
   assign BCx=bc;
   assign swx=sw;
   */
 
   sSegArray sSegArray0(.clk(bclck), .reset(reset), .load(1'b1), .d(sSegArray), .anode(sSegAnode),  .cathode(sSegCathode)); 
  
   sSegArray sSegArray0(.clk(bclck), .reset(reset), .load(1'b1), .d(sSegArray), .anode(sSegAnode), .cathode(sSegCathode));
   
   minicpu minicpu0(.clk(cpuClk), .reset(reset), .run(cpuRun), .in(cpuIn), .cs(cpuCs), .pcout(pcout),
           .irout(irout), .qtop(qtop), .abus(abus), .dbus(dbus), .out(out), .haltx(haltIn));
 			 
   clockDivider clockDivider0(.clk(bclck),.reset(reset), .div(divide), .dclk(dclk));
   cpuStartStopSequence cpuStartStopSequence0(.clk(dclk), .reset(reset), .start(start), .run(ssRun), .halt(halt));
   
 endmodule

- top.xdc (nexys4の基板上の温度計を使う場合で vivado を使う場合)
-- [[top-xdc-for-minicpu-os-i2c-jc]]
- top.ucf (nexys4の基板上の温度計を使う場合で ISEを使う場合)
-- [[top-ucf-for-minicpu-os-i2c-jc]]

- chattering.v
 module chattering(clk, reset, in, out
 );
 parameter N=1;
 input clk, reset;
 input [N-1:0]in; 
 output [N-1:0]out;
 reg [N-1:0]out;
 reg [21:0] count;
 
 always @(posedge clk or negedge reset)
 if(!reset) count <=0; 
 else count <= count +1;
 
 always @(posedge clk)
 if(count==0) out <= in;
 
 endmodule

- sSegArray.v
  module sSegArray(
     clk,reset,load,d, 
 	 anode, cathode
     );
 parameter N=32;
 input clk,reset,load;
 input [N-1:0] d;
 output [7:0] anode;
 output [7:0] cathode;
 reg [7:0] anode;
 reg [7:0] cathode;
 reg [31:0] q;
 
 wire [2:0] selectedSeg;
 wire [7:0] wOneSeg;
 reg segClk;
 
 counter #(8) waitOneSeg(.clk(clk), .reset(reset), .load(1'b0), .inc(1'b1), .d(16'h0000), .q(wOneSeg));
 
 //assign segClk= (wOneSeg==0)? ~segClk: segClk;
 always @(posedge clk, negedge reset) begin
   if(!reset) segClk<=0;
   else
   if (wOneSeg==0) segClk<=~segClk;
 end
 
 counter #(3) selector(.clk(segClk),.reset(reset),.load(1'b0), .inc(1'b1), .d(4'h0), .q(selectedSeg));
 //counter #(3) selector(.clk(clk), .reset(reset), .load(0), .inc(1), .d(4'h0), .q(selectedSeg));
  
 always @(posedge clk, negedge reset)
 begin
   if(!reset) anode=8'hFE;   // note!  anode is connected by pnp transistor.  
   else                      // in order to active one 7seg, low should be setted to the 7seg. 
    case (selectedSeg)
 	   3'b000: anode=8'hFE;
 		3'b001: anode=8'hFD;
 		3'b010: anode=8'hFB;
 		3'b011: anode=8'hF7;
 		3'b100: anode=8'hEF;
 		3'b101: anode=8'hDF;
 		3'b110: anode=8'hBF;
 		3'b111: anode=8'h7F;
 	endcase
 end
 
 reg [3:0] selectedVal;
 
 always @(posedge clk, negedge reset)
 begin
   if(!reset) cathode=8'h03;                   // note! when one segment of the cathode is low,
   else                                        //  and its anode is low, the segment glow.
   case (selectedVal)                         //          ca
     4'b0000: cathode=8'h03;   //8'hfc; 0              ------
     4'b0001: cathode=8'h9f;   //8'h60; 1              /     /
     4'b0010: cathode=8'h25;   //8'hda; 2              /cf   / cb 
 	 4'b0011: cathode=8'h0d;   //8'hf2; 3              /     /
 	 4'b0100: cathode=8'h99;   //8'h66; 4               -----
 	 4'b0101: cathode=8'h49;   //8'hb6; 5              /  cg  /
 	 4'b0110: cathode=8'h41;   //8'hbe; 6              /ce    / cc
 	 4'b0111: cathode=8'h1f;   //8'he0; 7              /      /
 	 4'b1000: cathode=8'h01;   //8'hfe; 8               ------     . ch
 	 4'b1001: cathode=8'h09;   //8'hf6; 9                  cd
 	 4'b1010: cathode=8'h11;   //8'hee; A
 	 4'b1011: cathode=8'hc1;   //8'h3e; B
 	 4'b1100: cathode=8'h63;   //8'h9c; C
 	 4'b1101: cathode=8'h85;   //8'h7c; D
 	 4'b1110: cathode=8'h61;   //8'h9e; E
 	 4'b1111: cathode=8'h71;   //8'h8e; F
 	endcase
 end
 
 always @(posedge clk, negedge reset)
 begin
   if(!reset) selectedVal=q[3:0];
   else
    case (selectedSeg)
 	  3'b000: selectedVal=q[3:0];
 	  3'b001: selectedVal=q[7:4];
 	  3'b010: selectedVal=q[11:8];
 	  3'b011: selectedVal=q[15:12];
 	  3'b100: selectedVal=q[19:16];
 	  3'b101: selectedVal=q[23:20];
 	  3'b110: selectedVal=q[27:24];
 	  3'b111: selectedVal=q[31:28];
 	endcase
 end
 
 always @(posedge clk, negedge reset)
 begin
   if(!reset) q=0;
   else
   if(load) q=d; 
 end
 
 endmodule

- clockDivider.v
 module clockDivider(clk, reset, div, dclk);
 input clk, reset;
 input [4:0] div; 
 output dclk;
 reg dclk;
 reg [31:0] q;
  
 always @(posedge clk or negedge reset) begin
   if(!reset) 
      q <=0;
   else q<=q+1; 
 end
 
 always @(posedge clk) begin
   dclk<=q[div]; 
 end
 endmodule

- cpuStartStopSequence.v
 module cpuStartStopSequence(clk, reset, start, run, halt
 );
 input clk, reset, start;
 reg [3:0] cs; 
 output run;
 reg run;
 output halt;
 reg halt;
 
 always @(posedge clk or negedge reset)
 if(!reset) begin
      cs<= 4'b0000; 
 	  run<=1'b0;
 	  halt<=1'b0;
 	end
 else
 case(cs)
    4'b0000: if(start) begin
 	    cs <= 4'b0001;
 	  end
    4'b0001: if(!start) begin
 	    cs <= 4'b0010;
 		 run <= 1;
 	  end
 	4'b0010: cs <= 4'b0011;	      
    4'b0011: begin
 	    cs <= 4'b0100;
 		 run <=0;
 	  end
    4'b0100: if(start ) begin
 		     cs <= 4'b0101;
 	   end
 	4'b0101: begin
 	    cs <= 4'b0110;
 		 halt <=1'b1;
 	   end
 	4'b0110: cs <= 4'b0111;
 	4'b0111: cs <= 4'b1000;
 	4'b1000: cs <= 4'b1001;
 	4'b1001: begin
 	     cs <= 4'b0000;
 		  halt <=1'b0;
 	   end
 default: cs <= 3'bxxx;
 endcase
 
 endmodule

- defs.v, minicpu.v, state.v, stack.v, alu.v, counter.v は、[[minicpu-v-for-os-i2c-jc]]のものを使ってください。
- 最初の ram.v の例として、[[I2C温度計その3]]を使って見てください。

----
#counter


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS