目次
前
次
Micro Controller
マイクロコンピュータは、毎年毎年新しい製品が
発表され、販売されます。
新しいマイクロコンピュータにより、高機能、低消費電力
を実現できることもありますが、企業が過去に製品として
出荷し、メンテナンスや不具合修正などが発生した場合は
出荷時マイコンを利用したいと思うのが常です。
CPLD/FPGAは、マクロ数やゲート数が膨大になった最近では
市販されなくなったマイコンをそっくり実現してしまい、
ファームウエアやハードウエアをメンテナンスしたり、修正
できるようになりました。
ここでは、単行本で紹介された「ゼロコン」を設計、開発し
FPGA(Xilinx Spartan3)に入れてみます。
ただし、フラグの中で使わないと考えられる場合
仕様から外します。
Pythonでアセンブラ、逆アセンブラ、シミュレータを
作成後、VHDLで「ゼロコン」を開発します。
Pythonを利用するのは、文字列処理が簡単になるのと
GUIベースのシミュレータが、自分にとって作り易い
からです。
仕様理解
「ゼロコン」は、絶版であるCQ出版の単行本に仕様が
公開されています。
既存の8ビットマイコンを、シミュレーション
する目的で、設計されているとか。
内部構成は、次のブロック図で示されています。
命令は3種類だけで、上のブロック図からデータを
左から右に動かすことと分岐処理だけに、限定して
います。
3種類の命令フォーマットは、以下になっています。
G1、G2はバスから出し入れするデータが、どのレジスタ
であるのかを指定します。
- 00000 acc
- 00001 psw
- 00010 adh
- 00011 adl
- 00100 mem
- 00101 tmr
- 00110 pio
- 00111 sio
- 10000 reg0
- 10001 reg1
- 10010 reg2
- 10011 reg3
- 10100 reg4
- 10101 reg5
- 10110 reg6
- 10111 reg7
- 11000 reg8
- 11001 reg9
- 11010 rega
- 11011 regb
- 11100 regc
- 11101 regd
- 11110 rege
- 11111 regf
FUNCはALUに対する演算命令種別を表します。
- 0000 (through)
- 0001 inc(increment)
- 0010 incc(increment with carry)
- 0011 dec(decrement)
- 0100 decc(decrement with carry)
- 0101 add
- 0110 adc(add with carry)
- 0111 sub(subtract)
- 1000 sbc(subtract with borrow)
- 1001 and
- 1010 or
- 1011 xor(exclusive or)
- 1100 rr(rotate right through carry)
- 1101 rl(rotate left through carry)
- 1110 rrc(rotate right)
- 1111 rlc(rotate left)
G3はPSWに格納する値を、ALUの出力であるstatus値
とするのか、バスにあるデータにするかを指定します。
分岐命令では、無条件分岐と条件分岐を指定できる仕様です。
条件分岐では、ifビットを1にします。
無条件分岐では、ifビットを0にします。
条件分岐では、どのstatusを利用するかをCNDで指定します。
- 111 sign
- 110 zero
- 101 si(SI running)
- 100 half carry
- 011 so(SO running)
- 010 over flow and parity
- 001 negative
- 000 carry
条件分岐時に肯定応答するか否定応答するのかを
ntフラグで指定します。
0:肯定応答、1:否定応答にします。
AC、PGは、プログラムメモリ中のどこに分岐するのかを
指定します。
「ゼロコン」では、プログラムメモリを32kワードとして
256ページで扱います。1ページは、128ワードです。
ページ単位でプログラムを扱うので、分岐はページ内か
ページ外かの指定が必要です。ページ内か外かを指定
するビットがPGです。
ページ専用レジスタがないので、ACC(アキュムレータ)を
使い、ページを指定します。
より使いやすくするため、ゼロページと他のページを区別
できるようにします。ゼロページへの分岐では、ACビット
を0にし、それ以外のページ分岐では、ACビットを1に
します。
プログラムメモリをページで管理すると、他のマイコンの
動作をシミュレーションしやすくなるとか。
メモリ構成は、ハーバードアーキテクチャでプログラミング
メモリとデータメモリが、独立しています。
プログラムは1ワード=16ビット、データは1ワード=8ビット
構成になっています。
汎用レジスタが16個あり、他にデータメモリを指定するための
レジスタが2個、アキュムレータ、パラレルI/O、シリアルI/O
があります。
アセンブラ作成
「ゼロコン」のアセンブラを作成します。
アセンブリ言語から機械語に変換するプログラムが
アセンブラなので、アセンブリ言語の仕様を書籍で
確認します。
アセンブリ言語の仕様は、以下となっています。
行ごとに、次のフォーマットで記述する。
[ラベル:] [機械語命令] [;コメント]
[]で囲んだ部分は、なくてもよいとします。
この仕様から、3つのことが読み取れます。
コメントは、「;」を先頭にして指定する
機械語命令を記述するとき、ラベルを使うなら「:」をつける
空白行も扱う
機械語命令は、演算転送、定数設定、分岐だけなので
仕様となる書式をまとめると、以下です。
register_label=register_label
register_label,psw=register label
register_label=function(register label)
register_label,psw=function(register label)
register_label=constant_value
if condition goto address
if condition goto zero,address
if condition goto acc,address
goto address
goto zero,address
goto acc,address
アセンブリ言語は、機械語命令を生成する他に
擬似命令を使う方が、よりプログラムコードを
記述しやすくなります。
今回は、2つの擬似命令を使います。
.equ ラベルによるマクロ定義
.org エントリーアドレス指定
マクロ定義は、次の書式で扱います。
label_name .equ constant
label_name .equ register_name
label_name .equ fixed label_name
エントリーは、次の書式で扱います。
.org address
.org page_number,address
ここまでで、アセンブリ言語の1行あたりの解釈方法を
決めたので、アセンブラの方式をどうするか考えます。
処理を記述しやすい、2パスアセンブラにします。
1パス目でラベルと数値、ラベルとデータ、ラベルと
アドレスの対応表を作成します。
2パス目で機械語を生成します。
Pythonを利用します。
(under construction)
逆アセンブラ作成
(under construction)
シミュレータ作成
(under construction)
方式設計
制御回路、ALU、レジスタ等をcomponentで指定して
使えるようにします。
レジスタは、すべて8ビットなので、74HC574に
近い形式のレジスタを利用すると考えます。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity t574 is
port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ;
-- data input
Din : in std_logic_vector(7 downto 0) ;
-- control
nLOAD : in std_logic ;
-- data output
Dout : out std_logic_vector(7 downto 0) -- ;
) ;
end t574 ;
architecture Behavioral of t574 is
-- input
signal iDin : std_logic_vector(7 downto 0) ;
-- output
signal iDout : std_logic_vector(7 downto 0) ;
begin
-- input
iDin <= Din ;
-- output
Dout <= iDout ;
-- register control
process (nRESET,CLOCK)
begin
if ( nRESET = '0' ) then
iDout <= X"00" ;
elsif rising_edge(CLOCK) then
if ( nLOAD = '0' ) then
iDout <= iDin ;
end if ;
end if ;
end process ;
end Behavioral;
ALUは、4種の演算種別が指定されているので
それに対応したデコーダを定義します。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity talu is
port (
-- data input
DinA : in std_logic_vector(7 downto 0) ;
DinB : in std_logic_vector(7 downto 0) ;
Cin : in std_logic ;
-- function
SFUNC : in std_logic_vector(3 downto 0) ;
-- result
Dout : out std_logic_vector(7 downto 0) ;
-- flags
XFLAGS : out std_logic_vector(5 downto 0) -- ;
) ;
end talu ;
architecture Behavioral of talu is
-- input
signal iDinA : std_logic_vector(7 downto 0) ;
signal iDinB : std_logic_vector(7 downto 0) ;
signal iCin : std_logic ;
-- output
signal iRESULT : std_logic_vector(8 downto 0) ;
signal iDout : std_logic_vector(7 downto 0) ;
signal iXFLAGS : std_logic_vector(5 downto 0) ;
begin
-- input
iDinA <= DinA ;
iDinB <= DinB ;
iCin <= Cin ;
-- output
Dout <= iDout ;
-- decode
iRESULT <= (iDinB + '1') when ( SFUNC = X"1" ) else
(iDinB + '1' + iCin) when ( SFUNC = X"2" ) else
(iDinB - '1') when ( SFUNC = X"3" ) else
(iDinB - '1' - iCin) when ( SFUNC = X"4" ) else
(iDinA + iDinB) when ( SFUNC = X"5" ) else
(iDinA + iDinB + iCin) when ( SFUNC = X"6" ) else
(iDinA - iDinB) when ( SFUNC = X"7" ) else
(iDinA - iDinB - iCin) when ( SFUNC = X"8" ) else
(iDinA and iDinB) when ( SFUNC = X"9" ) else
(iDinA or iDinB) when ( SFUNC = X"A" ) else
(iDinA xor iDinB) when ( SFUNC = X"B" ) else
('0' & iDinB) ;
end Behavioral;
(under construction)
ブロック図作成
(under construction)
目次
前
次