目次

簡易プロセッサ開発

 MCR_VCでは、マイコン、モータ等の種別は
 問われないので、各種マイコンが使われて
 います。

 マイコンの種別が問題にされないのなら、自作の
 プロセッサを利用し、それをFPGAに封入して利用
 してもよいだろうと考えました。

 仕事関係で入手したCPLD/FPGA基板があったので
 この評価を兼ねた自作プロセッサを開発すると
 目標を立てます。



 MCR_VCのシステムを実現するプロセッサ動作は
 非常に単純で、次のことを繰り返しているだけ。
  1. 路面状況入手
  2. エンコーダから回転数入手
  3. 取得した情報から、モータに与えるDUTY比計算
  4. モータドライバのカウンタに、DUTY比を設定
  5. 1に戻る
 上のシーケンスを電源が切れるまで繰り返せば  MCR_VCマシンは、動きます。  mugen2012マシンでは、簡単なシーケンサを利用して  動かした実績があります。シーケンサの性能を少し  上げて、プロセッサに近いことをさせるとよいかな  と判断しました。  なるべく単純な動作でMCR_VCマシンを動かせるように  シーケンスの各ステートで担当する機能を考えます。  路面状況入手   カメラかカメラ相当デバイスから1次元の   路面センサー情報を入手するのは、専用の   デジタル回路をFPGA内部に入れて対応します。   プロセッサは、専用回路が出力する結果だけを   利用し、専用回路制御に触れないとすると、   1次元の路面センサー情報(8ビット程度)を   入力するだけに機能限定です。  回転数入手   ロータリーエンコーダが出力するパルスを   FPGA内部のカウンタでカウントし、その値   をプロセッサが取得できるようにします。   プロセッサは、カウンタの値だけを利用し   制御等はやらないと判断です。  DUTY比計算   路面センサーと回転数の情報から、モータに   与えるDUTY比を求めるには、内部にROMを用意   し、その値を取出すことで対応します。   細かい計算が必要ならば、専用の計算ブロックを   用意し、そのブロックからの計算結果を利用する   ことに。  ここまでのメモから、プログラミングモデルを決めました。  汎用CPUのプログラミングモデルからは、相当外れていると  思います。専用プロセッサですから、これで充分でしょう。  各レジスタの仕様を決めていきます。  Instruction Pointer   命令コードを記憶しているROMのアドレスを格納します。   12ビットとして、0〜4095のアドレスを指定。  Instruction Register   ROMから取り出した、20ビット命令を格納します。  Working Register   12ビットの作業用レジスタ。   A、Bの2種を用意。  Data Pointer Register   各種データを格納しているSRAMのアドレスを格納。   12ビットとして、0〜4095のアドレスを指定。  Sensor Register   カメラまたはセンサーの8ビットデータを格納   しているレジスタ。  Left Encoder Register   左ロータリーエンコーダのカウント値を格納する12ビットレジスタ。   12ビットカウンタの値を、そのまま反映。  Right Encoder Register   右ロータリーエンコーダのカウント値を格納する12ビットレジスタ。   12ビットカウンタの値を、そのまま反映。  Servo Motor Register   サーボモータの角度を格納する8ビットレジスタ。   角度は0〜180とする。  Left Motor Register   左DCモータの方向とDuty比を格納する9ビットレジスタ。   9ビットのMSBとその下の2ビットで方向を指定し   7ビットにDuty比を指定。   方向は2進数で指定。    00 回転停止    01 右(前)回転    10 左(後)回転    11 回転停止  Right Motor Register   右DCモータの方向とDuty比を格納する10ビットレジスタ。   9ビットのMSBとその下の2ビットで方向を指定し   7ビットにDuty比を指定。   方向は2進数で指定。    00 回転停止    01 右(前)回転    10 左(後)回転    11 回転停止  Flag Status   演算結果のフラグを記憶する2ビットレジスタ。   フラグは、Zero、Negative。  レジスタ仕様を決めたなら、命令コード(ニモニック)を定義します。  命令コードを決めたなら、マイクロプログラムを  考えます。マイクロプログラムは、デジタル回路  を動かすビットの組み合わせになります。  20ビットで、プログラムコードを記述します。  命令は10種類以上ですが、分類すると以下のように  なります。  ニモニックコードを定義します。  LD   データメモリからWorking Registerにデータ転送するので   命令の4ビットを1000、データメモリのアドレスは12ビット   Working Registerは、A(0)かB(1)とします。   アドレスは、即値かData Pointer Register格納値を利用。 LD WA,100 LD WB,200 LD WA,DPR LD WB,DPR  ST   Working Registerからデータメモリにデータ転送するので   命令の4ビットを1001、データメモリのアドレスは12ビット   Working Registerは、A(0)かB(1)とします。   アドレスは、即値かData Pointer Register格納値を利用。 ST WA,100 ST WB,200 ST WA,DPR ST WB,DPR  JNG   Nフラグが1のとき、指定ステップに分岐します。   命令の4ビットを1010、それに続けて4ビットの   フラグ値を入れます。フラグに続き、命令を格納   したアドレスを入れます。   フラグが0でないときは、次のステップに分岐します。  JZE   Zフラグが1のとき、指定ステップに分岐します。   命令の4ビットを1011、それに続けて4ビットの   フラグ値を入れます。フラグに続き、命令を格納   したアドレスを入れます。   フラグが0でないときは、次のステップに分岐します。  JMP   指定ステップに分岐します。   命令の4ビットを1100、続く4ビットを飛ばして   命令を格納したアドレスを入れます。  MOV   レジスタ間のデータ転送をするので、命令の4ビットを0000とし   それに続けて、転送先の指定4ビット、転送元の指定4ビットを   定義します。下の5ビットはDon't careにします。   レジスタに番号をつけておきます。  MVI   レジスタに値を設定するため、命令の4ビット   は0001とし、レジスタは6種類限定です。   レジスタ番号は、MOV命令に利用した値と同じです。   ただし、使えるレジスタは以下です。  EQ   Working Registerと値を比較し、結果をフラグに反映。   命令の4ビットは0010とします。2つあるレジスタの   うち、どちらを利用するのかを1ビット指定、続けて   12ビットの値を指定します。  INC   Working Register、Data Pointerの値を+1する。   命令の4ビットは0011とします。利用レジスタは   次の3本とします。   演算後、フラグを設定します。  DEC   Working Register、Data Pointerの値を+1する。   命令の4ビットは0100とします。利用レジスタは   次の3本とします。   演算後、フラグを設定します。
アセンブラ、シミュレータ作成  ニモニックから16ビットコードを生成し、プロセッサの  動作をシミュレーションします。  アセンブラとシミュレータは、マルチプラットホームを  想定し、スクリプト言語Tcl/Tkで記述します。  過去にTcl/Tkでアセンブラ、シミュレータを作成した  経験と資産を活用します。  PLC用アセンブラ、シミュレータを改造して  開発時間を短縮します。  バッチファイルを作成し、一気にアセンブルする方式でも  よいのですが、GUI操作が簡単と考え、次画面としました。  Tcl/Tkのソースコードは、以下。 #!/usr/local/bin/wish wm title . "My Assemble Simulator" set theFileName "" set fd_in "" set last 0 for {set i 0} {$i < 4096} {incr i} { set memory($i) 0 } set msft 0 set index 0 set pgm(0) "" set pgmcode "" set xsensor 24 set xsensorb "00011000" set xleftrotary 0 set xrightrotary 0 set xservo 150 set xleftmotor 0 set xrightmotor 0 set xwrav 0 set xwrbv 0 set xdprv 0 set xflag "00" ####################################### # define objects ####################################### #----- label ----- label .lblFileNameLabel -text "FileName" label .lblFileName -textvariable theFileName label .lblMemory -text "Memory" label .lblIndex -text "index" label .lblCode -text "code" label .lblIndexV -textvariable index label .lblCodeV -textvariable pgmcode label .lblWorkingRegisterA -text "WRA" label .lblWorkingRegisterB -text "WRB" label .lblDataPointRegister -text "DPR" label .lblSensor -text "Sensor" label .lblLeftRotary -text "Left rotary" label .lblRightRotary -text "Right rotary" label .lblServo -text "Servo" label .lblLeftMotor -text "Left motor" label .lblRightMotor -text "Right motor" label .lblServoV -textvariable xservo label .lblLeftMotorV -textvariable xleftmotor label .lblRightMotorV -textvariable xrightmotor label .lblWorkingRegisterAV -textvariable xwrav label .lblWorkingRegisterBV -textvariable xwrbv label .lblDataPointRegisterV -textvariable xdprv label .lblFlagStatus -text "Flag Status" label .lblFlagStatusV -textvariable xflag #----- list box ----- listbox .lstCode -yscrollcommand ".scbLadderV set" -width 24 listbox .lstMemory -yscrollcommand ".scbMemoryV set" -width 24 #----- scroll bar ----- scrollbar .scbLadderV -orient vertical -command ".lstCode yview" scrollbar .scbMemoryV -orient vertical -command ".lstMemory yview" #----- entry ----- entry .txtSensor -width 10 -textvariable xsensor entry .txtLeftRotary -width 10 -textvariable xleftrotary entry .txtRightRotary -width 10 -textvariable xrightrotary #----- button ----- button .btnExit -text "Exit" -command "exit" button .btnLoad -text "Load" -command { # tk_messageBox -type ok -message "Load" set theFileName [tk_getOpenFile -filetypes {{"text file" {.txt}}}] # clear list box .lstCode delete 0 end # open set fd_in [open $theFileName "r"] # read context set i 0 while { [gets $fd_in sbuf] >= 0 } { # store set pgm($i) $sbuf # convert set pgmx($i) [getCode $pgm($i)] # display set tmp [format "%04d %s <- %s" $i $pgmx($i) $pgm($i)] .lstCode insert end $tmp # increment incr i } set last $i # close close $fd_in ShowMemory 0 # set pgmcode $pgm(0) } button .btnZero -text "Zero" -command { set index 0 set msft 0 set pgmcode $pgm($index) } button .btnStep -text "Step" -command { doScan $index # increment step index incr index # if { $index < $last } { set pgmcode $pgm($index) } if { $index == $last } { set index 0 set msft 0 set pgmcode $pgm($index) } } ####################################### # procedures ####################################### proc doScan {x} { global last pgm pgmx memory index xwrav xwrbv xdprv xflag xsensor global xleftrotary xrightrotary xservo xleftmotor xrightmotor # if { $x < $last } { # show memory ShowMemory 0 # separate code set pgmxx(0) [string index $pgmx($x) 0] set pgmxx(1) [string index $pgmx($x) 1] set pgmxx(2) [string index $pgmx($x) 2] set pgmxx(3) [string index $pgmx($x) 3] set pgmxx(4) [string index $pgmx($x) 4] # get opcode set opcode [getHex $pgmxx(0)] # clear flag set xflag "00" # LD instruction if { $opcode == 8 } { # register set reg [getHex $pgmxx(1)] # address set adr 0 set dv [getHex $pgmxx(2)] ; set value [expr $adr * 16 + $dv] set dv [getHex $pgmxx(3)] ; set value [expr $adr * 16 + $dv] set dv [getHex $pgmxx(4)] ; set value [expr $adr * 16 + $dv] # WA direct if { $reg == 0 } { set xwrav $memory($adr) } # WB direct if { $reg == 1 } { set xwrbv $memory($adr) } # WA indirect if { $reg == 8 } { # tk_messageBox -type ok -message "$memory($xdprv) $xdprv" set xwrav $memory($xdprv) } # WB indirect if { $reg == 9 } { # tk_messageBox -type ok -message "$memory($xdprv) $xdprv" set xwrbv $memory($xdprv) } } # ST instruction if { $opcode == 9 } { # register set reg [getHex $pgmxx(1)] # address set adr 0 set dv [getHex $pgmxx(2)] ; set value [expr $adr * 16 + $dv] set dv [getHex $pgmxx(3)] ; set value [expr $adr * 16 + $dv] set dv [getHex $pgmxx(4)] ; set value [expr $adr * 16 + $dv] # WA direct if { $reg == 0 } { set memory($adr) $xwrav } # WB direct if { $reg == 1 } { set memory($adr) $xwrbv } # WA indirect if { $reg == 8 } { set memory($xdprv) $xwrav } # WB indirect if { $reg == 9 } { set memory($xdprv) $xwrbv } } # JNG instruction if { $opcode == 10 } { # get flag set tflag $xflag set tflag [expr $tflag / 2] # calculate address set adr 0 set dv [getHex $pgmxx(2)] ; set value [expr $adr * 16 + $dv] set dv [getHex $pgmxx(3)] ; set value [expr $adr * 16 + $dv] set dv [getHex $pgmxx(4)] ; set value [expr $adr * 16 + $dv] # negative flag is set if { $tflag > 0 } { set index [expr $adr - 1] } } # JZE instruction if { $opcode == 11 } { # get flag set tflag $xflag set tflag [expr $tflag % 2] # calculate address set adr 0 set dv [getHex $pgmxx(2)] ; set value [expr $adr * 16 + $dv] set dv [getHex $pgmxx(3)] ; set value [expr $adr * 16 + $dv] set dv [getHex $pgmxx(4)] ; set value [expr $adr * 16 + $dv] # negative flag is set if { $tflag > 0 } { set index [expr $adr - 1] } } # JMP instruction if { $opcode == 12 } { # calculate address set adr 0 set dv [getHex $pgmxx(2)] ; set value [expr $adr * 16 + $dv] set dv [getHex $pgmxx(3)] ; set value [expr $adr * 16 + $dv] set dv [getHex $pgmxx(4)] ; set value [expr $adr * 16 + $dv] # set index [expr $adr - 1] } # MOV instruction if { $opcode == 0 } { # destination register set regd [getHex $pgmxx(1)] # source register set regs [getHex $pgmxx(2)] #tk_messageBox -type ok -message "$regd $regs" # source WRA if { $regs == 0 } { set tmp $xwrav } # source WRB if { $regs == 1 } { set tmp $xwrbv } # source Data Point Register if { $regs == 2 } { set tmp $xdprv } # source Servo motor register if { $regs == 4 } { set tmp $xservo } # source Right Motor Register if { $regs == 5 } { set tmp $xrightmotor } # source Left Motor Register if { $regs == 6 } { set tmp $xleftmotor } # source Sensor register if { $regs == 8 } { set tmp $xsensor } # source Right Encoder if { $regs == 9 } { set tmp $xrightrotary } # source Left Encoder if { $regs == 10 } { set tmp $xleftrotary } # destination WRA if { $regd == 0 } { set xwrav $tmp } # destination WRB if { $regd == 1 } { set xwrbv $tmp } # destination Data Point Register if { $regd == 2 } { set xdprv $tmp } # destination Servo motor register if { $regd == 4 } { set xservo $tmp } # destination Right Motor Register if { $regd == 5 } { set xrightmotor $tmp } # destination Left Motor Register if { $regd == 6 } { set xleftmotor $tmp } } # MVI instruction if { $opcode == 1 } { # register set reg [getHex $pgmxx(1)] # value set value 0 set dv [getHex $pgmxx(2)] ; set value [expr $value * 16 + $dv] set dv [getHex $pgmxx(3)] ; set value [expr $value * 16 + $dv] set dv [getHex $pgmxx(4)] ; set value [expr $value * 16 + $dv] # WA if { $reg == 0 } { set xwrav $value } # WB if { $reg == 1 } { set xwrbv $value } # DPR if { $reg == 2 } { set xdprv $value } # Servo motor register if { $reg == 4 } { set xservo $value } # Right Motor Register if { $reg == 5 } { set xrightmotor $value } # Left Motor Register if { $reg == 6 } { set xleftmotor $value } } # EQ instruction if { $opcode == 2 } { # register set reg [getHex $pgmxx(1)] # value set value 0 set dv [getHex $pgmxx(2)] ; set value [expr $value * 16 + $dv] set dv [getHex $pgmxx(3)] ; set value [expr $value * 16 + $dv] set dv [getHex $pgmxx(4)] ; set value [expr $value * 16 + $dv] # WA if { $reg == 0 } { set tmp "" # == if { $xwrav == $value } { set tmp "1$tmp" } else { set tmp "0$tmp" } # negative if { $xwrav & 512 } { set tmp "1$tmp" } else { set tmp "0$tmp" } # update flag set xflag $tmp } # WB if { $reg == 1 } { set tmp "" # == if { $xwrbv == $value } { set tmp "1$tmp" } else { set tmp "0$tmp" } # negative if { $xwrbv & 512 } { set tmp "1$tmp" } else { set tmp "0$tmp" } # update flag set xflag $tmp } } # INC instruction if { $opcode == 3 } { # register set reg [getHex $pgmxx(1)] # WA if { $reg == 0 } { set xwrav [expr $xwrav + 1] } # WB if { $reg == 1 } { set xwrbv [expr $xwrbv + 1] } # Data Pointer Register if { $reg == 2 } { set xdprv [expr $xdprv + 1] } } # DEC instruction if { $opcode == 4 } { # register set reg [getHex $pgmxx(1)] # WA if { $reg == 0 } { set xwrav [expr $xwrav - 1] } # WB if { $reg == 1 } { set xwrbv [expr $xwrbv - 1] } # Data Pointer Register if { $reg == 2 } { set xdprv [expr $xdprv - 1] } } # show memory ShowMemory 0 } } proc getCode {x} { # get command set opcode [lindex $x 0] # get operand set operand [lindex $x end] set location [string first "," $operand 0] # default set car "" set cdr "" # if { $location > 0 } { # calculate location set before [expr $location-1] set after [expr $location+1] # convert set car [string range $operand 0 $before] set cdr [string range $operand $after end] } # conversion if { $opcode == "LD" } { # pat set pat "000000000000" # add register name if { $car == "WA" } { if { $cdr == "DPR" } { set xcode "10001000$pat" } else { set xcode "10000000" set xcode "$xcode[convBinary $cdr]" } } if { $car == "WB" } { if { $cdr == "DPR" } { set xcode "10000001$pat" } else { set xcode "10001001" set xcode "$xcode[convBinary $cdr]" } } } if { $opcode == "ST" } { # pat set pat "000000000000" # add register name if { $car == "WA" } { if { $cdr == "DPR" } { set xcode "10011000$pat" } else { set xcode "10010000" set xcode "$xcode[convBinary $cdr]" } } if { $car == "WB" } { if { $cdr == "DPR" } { set xcode "10011001$pat" } else { set xcode "10010001" set xcode "$xcode[convBinary $cdr]" } } } if { $opcode == "JNG" } { set xcode "10100010[convBinary $operand]" } if { $opcode == "JZE" } { set xcode "10110001[convBinary $operand]" } if { $opcode == "JMP" } { set xcode "11000000[convBinary $operand]" } if { $opcode == "MOV" } { set xcode "0000" # destination register name set dst [getRegValue $car] # souce register name set src [getRegValue $cdr] # set pat "00000000" # concatenate set xcode "$xcode$dst$src$pat" } if { $opcode == "MVI" } { # add register name if { $car == "WA" } { set xcode "00010000" } if { $car == "WB" } { set xcode "00010001" } if { $car == "DPR" } { set xcode "00010010" } if { $car == "SMR" } { set xcode "00010100" } if { $car == "RMR" } { set xcode "00010101" } if { $car == "LMR" } { set xcode "00010110" } set xcode "$xcode[convBinary $cdr]" } if { $opcode == "EQ" } { # add register name if { $car == "WA" } { set xcode "00100000" } if { $car == "WB" } { set xcode "00100001" } set xcode "$xcode[convBinary $cdr]" } if { $opcode == "INC" } { # pat set pat "0000000000" # add register name if { $operand == "WA" } { set xcode "00110000" } if { $operand == "WB" } { set xcode "00110001" } if { $operand == "DPR" } { set xcode "00110010" } set xcode "$xcode$pat" } if { $opcode == "DEC" } { # pat set pat "0000000000" # add register name if { $operand == "WA" } { set xcode "01000001" } if { $operand == "WB" } { set xcode "01000011" } if { $operand == "DPR" } { set xcode "01000010" } set xcode "$xcode$pat" } # seperate set result0 [transHex [string range $xcode 0 3]] set result1 [transHex [string range $xcode 4 7]] set result2 [transHex [string range $xcode 8 11]] set result3 [transHex [string range $xcode 12 15]] set result4 [transHex [string range $xcode 16 end]] # concatenate set result "$result0$result1$result2$result3$result4" # tk_messageBox -type ok -message "$x => $result" return $result } proc h2b {x} { # separate set tmp $x # separate for {set i 0} {$i < 12} {incr i} { set res($i) [expr $tmp % 2] ; set tmp [expr $tmp / 2] ; } set res(0) [expr $tmp % 2] ; set tmp [expr $tmp / 2] ; # concatenate set result "$res(11)$res(10)$res(9)$res(8)" set result "$result$res(7)$res(6)$res(5)$res(4)" set result "$result$res(3)$res(2)$res(1)$res(0)" # return $result } proc getHex {x} { set result $x if {[string tolower $x] == "a"} { set result 10 } if {[string tolower $x] == "b"} { set result 11 } if {[string tolower $x] == "c"} { set result 12 } if {[string tolower $x] == "d"} { set result 13 } if {[string tolower $x] == "e"} { set result 14 } if {[string tolower $x] == "f"} { set result 15 } return $result } proc pushVal {x} { global msft set xx $x # shift set msft [expr $msft * 2] # store LSB set msft [expr $msft + $xx] } proc pullVal {x} { global msft # get LSB set result [expr $msft % 2] # shift set msft [expr $msft / 2] # return $result } proc ShowMemory {x} { global memory # delete .lstMemory delete 0 end for {set i 0} {$i < 4096} {incr i} { .lstMemory insert end "[format "%04d" $i] [h2b $memory($i)]" } } proc calcNumber16 {x y} { # calculate set result [expr $x * 16 + $y] return $result } proc convBinary {x} { set tmp $x # separate for {set i 0} {$i < 12} {incr i} { set res($i) [expr $tmp % 2] ; set tmp [expr $tmp / 2] ; } # concatenate set result "$res(11)$res(10)$res(9)$res(8)$res(7)$res(6)$res(5)$res(4)" set result "$result$res(3)$res(2)$res(1)$res(0)" # return $result } proc getRegValue {x} { set tmp $x # judge if { $tmp == "WA" } { set result "0000" } if { $tmp == "WB" } { set result "0001" } if { $tmp == "DPR" } { set result "0010" } if { $tmp == "SMR" } { set result "0100" } if { $tmp == "RMR" } { set result "0101" } if { $tmp == "LMR" } { set result "0110" } if { $tmp == "SR" } { set result "1000" } if { $tmp == "RRE" } { set result "1001" } if { $tmp == "LRE" } { set result "1010" } return $result } proc transHex {x} { # if { $x == "0000" } { set result "0" } if { $x == "0001" } { set result "1" } if { $x == "0010" } { set result "2" } if { $x == "0011" } { set result "3" } if { $x == "0100" } { set result "4" } if { $x == "0101" } { set result "5" } if { $x == "0110" } { set result "6" } if { $x == "0111" } { set result "7" } if { $x == "1000" } { set result "8" } if { $x == "1001" } { set result "9" } if { $x == "1010" } { set result "a" } if { $x == "1011" } { set result "b" } if { $x == "1100" } { set result "c" } if { $x == "1101" } { set result "d" } if { $x == "1110" } { set result "e" } if { $x == "1111" } { set result "f" } return $result } ####################################### # window area placing ####################################### grid .lblFileNameLabel -column 0 -row 0 grid .lblFileName -column 0 -row 1 grid .lstCode -column 0 -row 2 grid .lblMemory -column 0 -row 3 grid .lstMemory -column 0 -row 4 grid .lblIndex -column 0 -row 5 grid .lblCode -column 0 -row 6 grid .scbLadderV -column 1 -row 2 -sticky ns grid .scbMemoryV -column 1 -row 4 -sticky ns grid .lblIndexV -column 2 -row 5 grid .lblCodeV -column 2 -row 6 grid .btnLoad -column 3 -row 0 grid .btnZero -column 3 -row 5 grid .btnStep -column 3 -row 6 grid .btnExit -column 6 -row 14 grid .lblFlagStatus -column 0 -row 8 grid .lblFlagStatusV -column 1 -row 8 grid .lblWorkingRegisterA -column 4 -row 5 grid .lblWorkingRegisterB -column 4 -row 6 grid .lblDataPointRegister -column 4 -row 7 grid .lblSensor -column 4 -row 8 grid .lblLeftRotary -column 4 -row 9 grid .lblRightRotary -column 4 -row 10 grid .lblServo -column 4 -row 11 grid .lblLeftMotor -column 4 -row 12 grid .lblRightMotor -column 4 -row 13 grid .lblWorkingRegisterAV -column 5 -row 5 grid .lblWorkingRegisterBV -column 5 -row 6 grid .lblDataPointRegisterV -column 5 -row 7 grid .txtSensor -column 5 -row 8 grid .txtLeftRotary -column 5 -row 9 grid .txtRightRotary -column 5 -row 10 grid .lblServoV -column 5 -row 11 grid .lblLeftMotorV -column 5 -row 12 grid .lblRightMotorV -column 5 -row 13
シーケンス作成  アセンブラ、シミュレータが出来たので、MCR_VCマシンを  動かすシーケンスは、どうするのかを考えます。  プロセッサの動作は、以下を繰返すだけです。
  1. 路面状況入手
  2. エンコーダから回転数入手
  3. 取得した情報から、モータに与えるDUTY比計算
  4. モータドライバのカウンタに、DUTY比を設定
  5. 1に戻る
 上の動作を、ニモニックで記述します。  路面状況入手   路面状況は、カメラ相当のセンサーが入手し   レジスタSRに格納されています。   MOV命令でSRレジスタの内容を、WorkingRegisterに   転送すれば、路面状況の入手は完了です。   インストラクションは、以下。 MOV WA,SR   WorkingRegisterから、メモリのどこかにコピーして   おけばよいので、それを付加します。 MOV WA,SR MVI DPR,100 ST WA,DPR INC DPR  エンコーダから回転数入手   左右のエンコーダカウント値は、2つのレジスタLRE、RREに   格納されているので、WorkingRegisterに転送し、メモリの   どこかに保存しておきます。   動作を命令に変換すると、以下。 MOV WB,LRE ST WB,DPR INC DPR MOV WB,RRE ST WB,DPR  モータに与えるDUTY比計算   路面状況はWorkingRegisterに保存されているので   EQ命令を利用して、どういう値になっているかを   知り、対応したDUTY比を3つのモータレジスタに   転送します。   DUTY比設定は以下。 MVI WB,95 MOV SMR,WB MVI WB,25 MOV LMR,WB MVI WB,35 MOV RMR,WB JMP 1023   センサー値を比較して、その値と一致したときと   異なるときの処理は、単純です。 EQ WA,24 JZE 100 EQ WA,3 JZE 120   分岐先で、DUTY比設定したなら、同じシーケンスを   繰り返すだけです。 JMP 0  NORMAL、CRANK、LANE_CHANGEの処理は、状態を  表現してメモリの中にいれます。情報を出入れ  するメモリは、DataPointerRegisterにアドレス  を与えて、LD、ST命令を使うだけで操作できます。  また、状態判定はEQ命令を使えば充分です。  プログラムは、EEPROMの中に格納して動かします。  FPGAの中に簡易プロセッサを入れるので、電源を入れたとき  EEPROMの内容をリードし、内部SRAMに転換します。  手持ちのEEPROMのうち、IICバスでないものを利用します。  IICバスでは、データ交換に1ピンを使うので、ピン利用の  効率はよいですが、アドレスを与えてからデータを受取る  ために、一度ピンの入出力を変更するのが煩雑です。  入力、出力のピン方向が確定しているデバイスを使います。

目次

inserted by FC2 system