
それでは,命令デコーダとシーケンサの設計を行います.命令デコーダとシー
ケンサの記述は穴埋め形式で行ってもらいますが,ソースプログラムは,下の
“GET”ボタンを押すことで入手可能です.まず,“GET”
ボタンを押して,ソースを各自の作業ディレクトリにダウンロードして下さい
.この際に,“Selection”欄でセーブする場所を指定できますので,各
自の作業ディレクトリを指定し“idc_seq.vhd”というファイルネームにして
下さい.
演習
次へ進む ( 解説:デコーダ・シーケンサの考え方 )
以下にサンプルとなるデコーダ・シーケンサ部分のソースを示します.なお,演習に関する部分は
空白としています.
-- IDC_SEQ.VHD for KITE-1
-- KITE-1 Instruction Decoder & Sequencer Unit
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity IDC_SEQ is
port(
IR : in STD_LOGIC_VECTOR(15 downto 0); --命令コードの入力
FR : in STD_LOGIC_VECTOR(3 downto 0); --フラグ情報の入力
S_ALU : out STD_LOGIC_VECTOR(3 downto 0); --ALU用制御信号
IR_R : out STD_LOGIC_VECTOR(2 downto 0); --IRの読み出し制御信号
MREQ : out STD_LOGIC; --メモリ・リクエスト信号
IORQ : out STD_LOGIC; --I/Oリクエスト信号
RW : out STD_LOGIC; --リード・ライト信号
ICS : out STD_LOGIC; --命令完了信号
IR_W : out STD_LOGIC; --IRの書き込み制御信号
ACC_W : out STD_LOGIC; --ACCの書き込み制御信号
ACC_R : out STD_LOGIC; --ACCの読み出し制御信号
PC_W : out STD_LOGIC; --PCの書き込み制御信号
PC_R : out STD_LOGIC; --PCの読み出し制御信号
PC_INC : out STD_LOGIC; --PCのインクリメント制御信号
SP_W : out STD_LOGIC; --SPの書き込み制御信号
SP_R : out STD_LOGIC; --SPの読み出し制御信号
IX_W : out STD_LOGIC; --IXの書き込み制御信号
IX_R : out STD_LOGIC; --IXの読み出し制御信号
MAR_W : out STD_LOGIC; --MARの書き込み制御信号
BUF1_W : out STD_LOGIC; --BUF1の書き込み制御信号
BUF2_W : out STD_LOGIC; --BUF2の書き込み制御信号
BUF2_R : out STD_LOGIC; --BUF2の読み出し制御信号
FR_W : out STD_LOGIC; --FRの書き込み制御信号
S_DBI : out STD_LOGIC; --データ・バスの入力制御信号
HALT : out STD_LOGIC; --ホルト信号
ACK : in STD_LOGIC; --アクナリッジ信号
CLK : in STD_LOGIC; --シーケンサ用クロック信号
RESET : in STD_LOGIC); --リセット信号
end IDC_SEQ;
architecture BEHA of IDC_SEQ is
--シーケンサ用のステート定義
type STATE_TYPE is
(
V0,V1,V2, --Vector Start
F0,F1,DECO, --Inst. Fetch
LD_IM, --LD Immediate
LD_D1,LD_D2,LD_D3, --LD Direct
--@@@@@@@
--
-- 演習1 : type による型定義 (命令ステートの定義)
--
--@@@@@@
ST_D1,ST_D2,ST_D3,ST_D4, --ST Direct
ST_IX1,ST_IX2,ST_IX3,
ST_IX4,ST_IX5,ST_IX6, --ST Index
INN1,INN2,INN3, --IN
OUTT1,OUTT2,OUTT3,OUTT4, --OUT
JPP, --JP,JPC,JPS,JPZ,JPV
CALC_IM1,CALC_IM2,CALC_IM3, --ADD_IM,SUB_IM,AND_IM,OR_IM,EOR_IM
CALC_IX1,CALC_IX2,CALC_IX3,
CALC_IX4,CALC_IX5,CALC_IX6, --ADD_IX,SUB_IX,AND_IX,OR_IX,EOR_IX
CALC_REG1,CALC_REG2,CALC_REG3, --INC,DEC
CALC1,CALC2,CALC3, --NOT,LSL,ASL,LSR,ASR,ROL,ROR,SWP
MVV, --MV
CALL1,CALL2,CALL3,CALL4,CALL5,
CALL6,CALL7, --CALL
RET1,RET2,RET3,RET4,RET5, --RET
PUSH1,PUSH2,PUSH3,
PUSH4,PUSH5,PUSH6, --PUSH
POP1,POP2,POP3,POP4,POP5, --POP
NOP1, --NOP
HALT1 --HALT
);
--命令デコード用の命令定義
type INST_TYPE is
(
LD_IM, --LD Immediate
LD_D, --LD Direct
LD_IX, --LD Index
ST_D, --ST Direct
ST_IX, --ST Index
CALL, --CALL
RET, --RET
PUSH, --PUSH
POP, --POP
ADD_IX, --ADD Index
SUB_IX, --SUB Index
AND_IX, --AND Index
OR_IX, --OR Index
EOR_IX, --EOR Index
ADD_IM, --ADD Immediate
SUB_IM, --SUB Immediate
AND_IM, --AND Immediate
OR_IM, --OR Immediate
EOR_IM, --EOR Immediate
NOTT, --NOT
INC, --INC
DEC, --DEC
LSL, --LSL
ASL, --ASL
LSR, --LSR
ASR, --ASR
ROLL, --ROL
RORR, --ROR
SWAP, --SWAP
JP, --JP,JPC,JPS,JPZ,JPV
HAL, --HALT
INN, --IN
OUTT, --OUT
MV, --MV
NOP); --NOP
signal PRESENT_STATE : STATE_TYPE; --シーケンサ用状態遷移変数
signal PRESENT_INST : INST_TYPE; --命令デコード用変数
signal START : STD_LOGIC;
begin
--命令デコート部
--@@@@@@@
--
-- 演習2 : 順次処理文による組合せ回路の記述法 (命令デコーダ)
--
--@@@@@@
begin
case IR(15 downto 12) is
when "0000" => PRESENT_INST <= LD_D;
when "0001" => PRESENT_INST <= ST_D;
when "0010" => PRESENT_INST <= CALL;
when "0011" => PRESENT_INST <= JP;
when "0100" =>
if FR(0) = '1' then
PRESENT_INST <= JP; -- JPc
else
PRESENT_INST <= NOP;
end if;
when "0101" => -- JPz
if FR(2) = '1' then
PRESENT_INST <= JP;
else
PRESENT_INST <= NOP;
end if;
when "0110" => -- JPs
if FR(3) = '1' then
PRESENT_INST <= JP;
else
PRESENT_INST <= NOP;
end if;
when "0111" => -- JPv
if FR(1) = '1' then
PRESENT_INST <= JP;
else
PRESENT_INST <= NOP;
end if;
when others => PRESENT_INST <= HAL;
end case;
case IR(15 downto 10) is
when "111110" => PRESENT_INST <= HAL;
when "110010" => PRESENT_INST <= INN;
when "110011" => PRESENT_INST <= OUTT;
when "110101" => PRESENT_INST <= PUSH;
when "110100" => PRESENT_INST <= POP;
when "111000" => PRESENT_INST <= RET;
when "111100" => PRESENT_INST <= MV;
when "111111" => PRESENT_INST <= NOP;
when "100010" => PRESENT_INST <= INC;
when "100011" => PRESENT_INST <= DEC;
when "101000" => PRESENT_INST <= LSL;
when "101001" => PRESENT_INST <= ASL;
when "101010" => PRESENT_INST <= LSR;
when "101011" => PRESENT_INST <= ASR;
when "101100" => PRESENT_INST <= ROLL;
when "101101" => PRESENT_INST <= RORR;
when "101111" => PRESENT_INST <= SWAP;
when "100111" => PRESENT_INST <= NOTT;
when others => NULL;
end case;
case IR(15 downto 8) is
when "11000001" => PRESENT_INST <= LD_IM;
when "10010001" => PRESENT_INST <= OR_IM;
when "10000001" => PRESENT_INST <= ADD_IM;
when "10000101" => PRESENT_INST <= SUB_IM;
when "10010101" => PRESENT_INST <= EOR_IM;
when "10011001" => PRESENT_INST <= AND_IM;
--@@@@@@@
--
-- 演習2 : 順次処理文による組合せ回路の記述法 (命令デコーダ)
--
--@@@@@@
when "11000110" => PRESENT_INST <= ST_IX;
when "10000010" => PRESENT_INST <= ADD_IX;
when "10000110" => PRESENT_INST <= SUB_IX;
when "10011010" => PRESENT_INST <= AND_IX;
when "10010010" => PRESENT_INST <= OR_IX;
when "10010110" => PRESENT_INST <= EOR_IX;
when others => NULL;
end case;
end process DECODE_PROC;
-- シーケンサ用スタート信号の生成
START_LATCH : process(CLK)
begin
if (CLK'event and CLK = '1') then
START <= RESET;
end if;
end process START_LATCH;
--シーケンサ部(状態遷移)
--@@@@@@@
--
-- 演習3 : 順次処理文による順序回路の記述法 (ステートマシンその1)
--
--@@@@@@
case PRESENT_STATE is
when V0 => --ベクトルスタート
if START = '1' then
PRESENT_STATE <= V1;
end if;
when V1 =>
if ACK = '1' then
PRESENT_STATE <= V2;
end if;
when V2 => PRESENT_STATE <= F0;
when F0 => PRESENT_STATE <= F1; --命令フェッチ
when F1 =>
if ACK = '1' then
PRESENT_STATE <= DECO;
end if;
when DECO => --命令デコード
case PRESENT_INST is
when LD_IM => PRESENT_STATE <= LD_IM;
when LD_D => PRESENT_STATE <= LD_D1;
when LD_IX => PRESENT_STATE <= LD_IX1;
when ST_D => PRESENT_STATE <= ST_D1;
when ST_IX => PRESENT_STATE <= ST_IX1;
when INN => PRESENT_STATE <= INN1;
when OUTT => PRESENT_STATE <= OUTT1;
when JP => PRESENT_STATE <= JPP;
when MV => PRESENT_STATE <= MVV;
when ADD_IX | SUB_IX | AND_IX | OR_IX | EOR_IX =>
PRESENT_STATE <= CALC_IX1;
when ADD_IM | SUB_IM | AND_IM | OR_IM | EOR_IM =>
PRESENT_STATE <= CALC_IM1;
when INC | DEC => PRESENT_STATE <= CALC_REG1;
when NOTT | LSL | ASL | LSR | ASR | ROLL | RORR | SWAP =>
PRESENT_STATE <= CALC1;
when CALL => PRESENT_STATE <= CALL1;
when RET => PRESENT_STATE <= RET1;
when PUSH => PRESENT_STATE <= PUSH1;
when POP => PRESENT_STATE <= POP1;
when NOP => PRESENT_STATE <= NOP1;
when HAL => PRESENT_STATE <= HALT1;
when others => PRESENT_STATE <= HALT1;
end case;
when LD_IM => PRESENT_STATE <= F0; --LD Immediate
when LD_D1 => PRESENT_STATE <= LD_D2; --LD Direct
when LD_D2 =>
if ACK = '1' then
PRESENT_STATE <= LD_D3;
end if;
when LD_D3 => PRESENT_STATE <= F0;
--@@@@@@@
--
-- 演習4 : 順序回路における状態遷移の記述法 (ステートマシンその2)
--
--@@@@@@
when ST_D1 => PRESENT_STATE <= ST_D2; --ST Direct
when ST_D2 => PRESENT_STATE <= ST_D3;
when ST_D3 =>
if ACK = '1' then
PRESENT_STATE <= ST_D4;
end if;
when ST_D4 => PRESENT_STATE <= F0;
when ST_IX1 => PRESENT_STATE <= ST_IX2; --ST Index
when ST_IX2 => PRESENT_STATE <= ST_IX3;
when ST_IX3 => PRESENT_STATE <= ST_IX4;
when ST_IX4 => PRESENT_STATE <= ST_IX5;
when ST_IX5 =>
if ACK = '1' then
PRESENT_STATE <= ST_IX6;
end if;
when ST_IX6 => PRESENT_STATE <= F0;
when INN1 => PRESENT_STATE <= INN2; --IN
when INN2 =>
if ACK = '1' then
PRESENT_STATE <= INN3;
end if;
when INN3 => PRESENT_STATE <= F0;
when OUTT1 => PRESENT_STATE <= OUTT2; --OUT
when OUTT2 => PRESENT_STATE <= OUTT3;
when OUTT3 =>
if ACK = '1' then
PRESENT_STATE <= OUTT4;
end if;
when OUTT4 => PRESENT_STATE <= F0;
when JPP => PRESENT_STATE <= F0; --JP
when MVV => PRESENT_STATE <= F0; --MV
when CALC_IX1 =>PRESENT_STATE <= CALC_IX2; --CALC Index
when CALC_IX2 =>PRESENT_STATE <= CALC_IX3;
when CALC_IX3 =>PRESENT_STATE <= CALC_IX4;
when CALC_IX4 =>
if ACK = '1' then
PRESENT_STATE <= CALC_IX5;
end if;
when CALC_IX5 =>PRESENT_STATE <= CALC_IX6;
when CALC_IX6 =>PRESENT_STATE <= F0;
when CALC_IM1 =>PRESENT_STATE <= CALC_IM2; --CALC Immediate
when CALC_IM2 =>PRESENT_STATE <= CALC_IM3;
when CALC_IM3 =>PRESENT_STATE <= F0;
when CALC_REG1=>PRESENT_STATE <= CALC_REG2; --CALC REG
when CALC_REG2=>PRESENT_STATE <= CALC_REG3;
when CALC_REG3=>PRESENT_STATE <= F0;
when CALC1 => PRESENT_STATE <= CALC2; --CALC
when CALC2 => PRESENT_STATE <= CALC3;
when CALC3 => PRESENT_STATE <= F0;
when CALL1 => PRESENT_STATE <= CALL2; --CALL
when CALL2 => PRESENT_STATE <= CALL3;
when CALL3 => PRESENT_STATE <= CALL4;
when CALL4 => PRESENT_STATE <= CALL5;
when CALL5 =>
if ACK = '1' then
PRESENT_STATE <= CALL6;
end if;
when CALL6 => PRESENT_STATE <= CALL7;
when CALL7 => PRESENT_STATE <= F0;
when RET1 => PRESENT_STATE <= RET2; --RET
when RET2 => PRESENT_STATE <= RET3;
when RET3 => PRESENT_STATE <= RET4;
when RET4 =>
if ACK = '1' then
PRESENT_STATE <= RET5;
end if;
when RET5 => PRESENT_STATE <= F0;
when PUSH1 => PRESENT_STATE <= PUSH2; --PUSH
when PUSH2 => PRESENT_STATE <= PUSH3;
when PUSH3 => PRESENT_STATE <= PUSH4;
when PUSH4 => PRESENT_STATE <= PUSH5;
when PUSH5 =>
if ACK = '1' then
PRESENT_STATE <= PUSH6;
end if;
when PUSH6 => PRESENT_STATE <= F0;
when POP1 => PRESENT_STATE <= POP2; --POP
when POP2 => PRESENT_STATE <= POP3;
when POP3 => PRESENT_STATE <= POP4;
when POP4 =>
if ACK = '1' then
PRESENT_STATE <= POP5;
end if;
when POP5 => PRESENT_STATE <= F0;
when NOP1 => PRESENT_STATE <= F0;
when HALT1 => PRESENT_STATE <= HALT1;
when others => PRESENT_STATE <= V0;
end case;
end if;
end process SEQ_PROC;
--シーケンサ部(出力信号生成)
OUTPUT_SIGNALS : process(PRESENT_STATE,PRESENT_INST,
IR(7),IR(3 downto 0))
begin
--出力信号の初期化
MREQ <= '0';
RW <= '0';
IORQ <= '0';
IR_W <= '0'; IR_R <= "110";
ACC_W <= '0'; ACC_R <= '0';
PC_W <= '0'; PC_R <= '0'; PC_INC <= '0';
SP_W <= '0'; SP_R <= '0';
IX_W <= '0'; IX_R <= '0';
BUF1_W <= '0';
BUF2_W <= '0'; BUF2_R <= '0';
MAR_W <= '0';
FR_W <= '0';
S_ALU <= "0000";
ICS <= '0';
HALT <= '0';
S_DBI <= '0';
case (PRESENT_STATE) is
when V0 => HALT <= '1'; --Vector Start
when V1 => MREQ <= '1';
when V2 => MREQ <= '1';
PC_W <= '1';
S_DBI <= '1';
when F0 => PC_R <= '1'; --Inst. Fetch
PC_INC <= '1';
MAR_W <= '1';
when F1 => MREQ <= '1';
when DECO => MREQ <= '1';
IR_W <= '1';
S_DBI <= '1';
when LD_IM => IR_R <= "101"; --LD Immediate
ACC_W <= '1';
ICS <= '1';
when LD_D1 => IR_R <= "011"; --LD Direct
MAR_W <= '1';
when LD_D2 => MREQ <= '1';
when LD_D3 => MREQ <= '1';
ACC_W <= '1';
S_DBI <= '1';
ICS <= '1';
--@@@@@@@
--
-- 演習5 : 制御信号の生成
--
--@@@@@@
when ST_D1 => IR_R <= "011"; --ST Direct
MAR_W <= '1';
when ST_D2 => RW <= '1';
ACC_R <= '1';
when ST_D3 => RW <= '1';
ACC_R <= '1';
MREQ <= '1';
when ST_D4 => RW <= '1';
ACC_R <= '1';
ICS <= '1';
when ST_IX1 => IX_R <= '1'; --ST Index
BUF1_W <= '1';
when ST_IX2 => if IR(7) = '1' then
IR_R <= "001";
else
IR_R <= "101";
end if;
BUF2_W <= '1';
when ST_IX3 => BUF2_R <= '1';
MAR_W <= '1';
when ST_IX4 => RW <= '1';
ACC_R <= '1';
when ST_IX5 => RW <= '1';
ACC_R <= '1';
MREQ <= '1';
when ST_IX6 => RW <= '1';
ACC_R <= '1';
ICS <= '1';
when INN1 => IR_R <= "101"; --IN
MAR_W <= '1';
when INN2 => IORQ <= '1';
when INN3 => IORQ <= '1';
ACC_W <= '1';
S_DBI <= '1';
ICS <= '1';
when OUTT1 => IR_R <= "101"; --OUT
MAR_W <= '1';
when OUTT2 => RW <= '1';
ACC_R <= '1';
when OUTT3 => RW <= '1';
ACC_R <= '1';
IORQ <= '1';
when OUTT4 => RW <= '1';
ACC_R <= '1';
ICS <= '1';
when JPP => IR_R <= "011"; --JP
PC_W <= '1';
ICS <= '1';
when MVV => --MV
case IR(1 downto 0) is
when "00" => ACC_R <= '1';
when "01" => SP_R <= '1';
when "10" => IX_R <= '1';
when "11" => PC_R <= '1';
when others => NULL;
end case;
case IR(3 downto 2) is
when "00" => ACC_W <= '1';
when "01" => SP_W <= '1';
when "10" => IX_W <= '1';
when "11" => PC_W <= '1';
when others => NULL;
end case;
ICS <= '1';
when CALC_IX1 =>IX_R <= '1'; --CALC Index
BUF1_W <= '1';
when CALC_IX2 =>if IR(7) = '1' then
IR_R <= "001";
else
IR_R <= "101";
end if;
BUF2_W <= '1';
when CALC_IX3 =>BUF2_R <= '1';
MAR_W <= '1';
when CALC_IX4 =>ACC_R <= '1';
BUF1_W <= '1';
MREQ <= '1';
when CALC_IX5 =>BUF2_W <= '1';
FR_W <= '1';
MREQ <= '1';
S_DBI <= '1';
case PRESENT_INST is
when ADD_IX => S_ALU <= "0000";
when SUB_IX => S_ALU <= "0001";
when AND_IX => S_ALU <= "0101";
when OR_IX => S_ALU <= "0100";
when EOR_IX => S_ALU <= "0110";
when others => S_ALU <= "0000";
end case;
when CALC_IX6 =>BUF2_R <= '1';
ACC_W <= '1';
ICS <= '1';
when CALC_IM1 =>BUF1_W <= '1'; --CALC Immediate
ACC_R <= '1';
when CALC_IM2 =>BUF2_W <= '1';
FR_W <= '1';
case PRESENT_INST is
when ADD_IM => S_ALU <= "0000";
if IR(7) = '1' then
IR_R <= "001";
else
IR_R <= "101";
end if;
when SUB_IM => S_ALU <= "0001";
if IR(7) = '1' then
IR_R <= "001";
else
IR_R <= "101";
end if;
when AND_IM => S_ALU <= "0101";
IR_R <= "001";
when OR_IM => S_ALU <= "0100";
IR_R <= "101";
when EOR_IM => S_ALU <= "0110";
IR_R <= "101";
when others => S_ALU <= "0000";
end case;
when CALC_IM3 =>ACC_W <= '1';
BUF2_R <= '1';
ICS <= '1';
when CALC_REG1 => --CALC REG
BUF1_W <= '1';
case IR(1 downto 0) is
when "00" => ACC_R <= '1';
when "01" => SP_R <= '1';
when "10" => IX_R <= '1';
when "11" => PC_R <= '1';
when others => NULL;
end case;
when CALC_REG2 =>
FR_W <= '1';
BUF2_W <= '1';
if PRESENT_INST = INC then
S_ALU <= "0010";
else
S_ALU <= "0011";
end if;
when CALC_REG3 =>
BUF2_R <= '1';
case IR(3 downto 2) is
when "00" => ACC_W <= '1';
when "01" => SP_W <= '1';
when "10" => IX_W <= '1';
when "11" => PC_W <= '1';
when others => NULL;
end case;
ICS <= '1';
when CALC1 => BUF1_W <= '1'; --CALC
ACC_R <= '1';
when CALC2 => BUF2_W <= '1';
FR_W <= '1';
case PRESENT_INST is
when NOTT => S_ALU <= "0111";
when LSL => S_ALU <= "1000";
when ASL => S_ALU <= "1001";
when LSR => S_ALU <= "1010";
when ASR => S_ALU <= "1011";
when ROLL => S_ALU <= "1100";
when RORR => S_ALU <= "1101";
when SWAP => S_ALU <= "1110";
when others => S_ALU <= "0000";
end case;
when CALC3 => BUF2_R <= '1';
ACC_W <= '1';
ICS <= '1';
when CALL1 => SP_R <= '1'; --CALL
BUF1_W <= '1';
when CALL2 => BUF2_W <= '1';
S_ALU <= "0011";
when CALL3 => BUF2_R <= '1';
SP_W <= '1';
MAR_W <= '1';
when CALL4 => RW <= '1';
PC_R <= '1';
when CALL5 => RW <= '1';
PC_R <= '1';
MREQ <= '1';
when CALL6 => RW <= '1';
PC_R <= '1';
when CALL7 => IR_R <= "011";
PC_W <= '1';
ICS <= '1';
when RET1 => SP_R <= '1'; --RET
BUF1_W <= '1';
MAR_W <= '1';
when RET2 => BUF2_W <= '1';
S_ALU <= "0010";
when RET3 => BUF2_R <= '1';
SP_W <= '1';
when RET4 => MREQ <= '1';
when RET5 => MREQ <= '1';
S_DBI <= '1';
PC_W <= '1';
ICS <= '1';
when PUSH1 => SP_R <= '1'; --PUSH
BUF1_W <= '1';
when PUSH2 => BUF2_W <= '1';
S_ALU <= "0011";
when PUSH3 => BUF2_R <= '1';
SP_W <= '1';
MAR_W <= '1';
when PUSH4 => RW <= '1';
ACC_R <= '1';
when PUSH5 => RW <= '1';
ACC_R <= '1';
MREQ <= '1';
when PUSH6 => RW <= '1';
ACC_R <= '1';
ICS <= '1';
when POP1 => SP_R <= '1'; --POP
BUF1_W <= '1';
MAR_W <= '1';
when POP2 => BUF2_W <= '1';
S_ALU <= "0010";
when POP3 => BUF2_R <= '1';
SP_W <= '1';
when POP4 => MREQ <= '1';
when POP5 => MREQ <= '1';
S_DBI <= '1';
ACC_W <= '1';
ICS <= '1';
when NOP1 => ICS <= '1'; --NOP
when HALT1 => ICS <= '1'; --HALT
HALT <= '1';
when others => HALT <= '1';
end case;
end process OUTPUT_SIGNALS;
end BEHA;
演習
ホーム
シーケンサの設計
シミュレーション
辞書
This is my e-mail address:
arch_www
< www@cs.kumamoto-u.ac.jp >
Copyright(C)KITE Microprocessor Project,1996