-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
--
|
--
|
-- The decoder unit.
|
-- The decoder unit.
|
-- Implements the instruction opcodes and controls all units of the T400 core.
|
-- Implements the instruction opcodes and controls all units of the T400 core.
|
--
|
--
|
-- $Id: t400_decoder.vhd,v 1.7 2008-05-01 19:49:55 arniml Exp $
|
-- $Id: t400_decoder.vhd 179 2009-04-01 19:48:38Z arniml $
|
--
|
--
|
-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org)
|
-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org)
|
--
|
--
|
-- All rights reserved
|
-- All rights reserved
|
--
|
--
|
-- Redistribution and use in source and synthezised forms, with or without
|
-- Redistribution and use in source and synthezised forms, with or without
|
-- modification, are permitted provided that the following conditions are met:
|
-- modification, are permitted provided that the following conditions are met:
|
--
|
--
|
-- Redistributions of source code must retain the above copyright notice,
|
-- Redistributions of source code must retain the above copyright notice,
|
-- this list of conditions and the following disclaimer.
|
-- this list of conditions and the following disclaimer.
|
--
|
--
|
-- Redistributions in synthesized form must reproduce the above copyright
|
-- Redistributions in synthesized form must reproduce the above copyright
|
-- notice, this list of conditions and the following disclaimer in the
|
-- notice, this list of conditions and the following disclaimer in the
|
-- documentation and/or other materials provided with the distribution.
|
-- documentation and/or other materials provided with the distribution.
|
--
|
--
|
-- Neither the name of the author nor the names of other contributors may
|
-- Neither the name of the author nor the names of other contributors may
|
-- be used to endorse or promote products derived from this software without
|
-- be used to endorse or promote products derived from this software without
|
-- specific prior written permission.
|
-- specific prior written permission.
|
--
|
--
|
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
-- POSSIBILITY OF SUCH DAMAGE.
|
-- POSSIBILITY OF SUCH DAMAGE.
|
--
|
--
|
-- Please report bugs to the author, but before you do so, please
|
-- Please report bugs to the author, but before you do so, please
|
-- make sure that this is not a derivative work and that
|
-- make sure that this is not a derivative work and that
|
-- you have the latest version of this file.
|
-- you have the latest version of this file.
|
--
|
--
|
-- The latest version of this file can be found at:
|
-- The latest version of this file can be found at:
|
-- http://www.opencores.org/cvsweb.shtml/t400/
|
-- http://www.opencores.org/cvsweb.shtml/t400/
|
--
|
--
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
|
|
use work.t400_opt_pack.all;
|
use work.t400_opt_pack.all;
|
use work.t400_pack.all;
|
use work.t400_pack.all;
|
|
|
entity t400_decoder is
|
entity t400_decoder is
|
|
|
generic (
|
generic (
|
opt_type_g : integer := t400_opt_type_420_c
|
opt_type_g : integer := t400_opt_type_420_c
|
);
|
);
|
port (
|
port (
|
-- System Interface -------------------------------------------------------
|
-- System Interface -------------------------------------------------------
|
ck_i : in std_logic;
|
ck_i : in std_logic;
|
ck_en_i : in boolean;
|
ck_en_i : in boolean;
|
por_i : in boolean;
|
por_i : in boolean;
|
res_i : in boolean;
|
res_i : in boolean;
|
out_en_i : in boolean;
|
out_en_i : in boolean;
|
in_en_i : in boolean;
|
in_en_i : in boolean;
|
icyc_en_i : in boolean;
|
icyc_en_i : in boolean;
|
-- Module Control Interface -----------------------------------------------
|
-- Module Control Interface -----------------------------------------------
|
pc_op_o : out pc_op_t;
|
pc_op_o : out pc_op_t;
|
stack_op_o : out stack_op_t;
|
stack_op_o : out stack_op_t;
|
dmem_op_o : out dmem_op_t;
|
dmem_op_o : out dmem_op_t;
|
b_op_o : out b_op_t;
|
b_op_o : out b_op_t;
|
skip_op_o : out skip_op_t;
|
skip_op_o : out skip_op_t;
|
alu_op_o : out alu_op_t;
|
alu_op_o : out alu_op_t;
|
io_l_op_o : out io_l_op_t;
|
io_l_op_o : out io_l_op_t;
|
io_d_op_o : out io_d_op_t;
|
io_d_op_o : out io_d_op_t;
|
io_g_op_o : out io_g_op_t;
|
io_g_op_o : out io_g_op_t;
|
io_in_op_o : out io_in_op_t;
|
io_in_op_o : out io_in_op_t;
|
sio_op_o : out sio_op_t;
|
sio_op_o : out sio_op_t;
|
dec_data_o : out dec_data_t;
|
dec_data_o : out dec_data_t;
|
en_o : out dw_t;
|
en_o : out dw_t;
|
-- Skip Interface ---------------------------------------------------------
|
-- Skip Interface ---------------------------------------------------------
|
skip_i : in boolean;
|
skip_i : in boolean;
|
skip_lbi_i : in boolean;
|
skip_lbi_i : in boolean;
|
is_lbi_o : out boolean;
|
is_lbi_o : out boolean;
|
int_i : in boolean;
|
int_i : in boolean;
|
-- Program Memory Interface -----------------------------------------------
|
-- Program Memory Interface -----------------------------------------------
|
pm_addr_i : in pc_t;
|
pm_addr_i : in pc_t;
|
pm_data_i : in byte_t
|
pm_data_i : in byte_t
|
);
|
);
|
|
|
end t400_decoder;
|
end t400_decoder;
|
|
|
|
|
library ieee;
|
library ieee;
|
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
|
|
use work.t400_mnemonic_pack.all;
|
use work.t400_mnemonic_pack.all;
|
|
|
architecture rtl of t400_decoder is
|
architecture rtl of t400_decoder is
|
|
|
signal cyc_cnt_q : unsigned(2 downto 0);
|
signal cyc_cnt_q : unsigned(2 downto 0);
|
signal ibyte1_q,
|
signal ibyte1_q,
|
ibyte2_q : byte_t;
|
ibyte2_q : byte_t;
|
|
|
signal opcode_s : byte_t;
|
signal opcode_s : byte_t;
|
signal second_cyc_q : boolean;
|
signal second_cyc_q : boolean;
|
signal mnemonic_rec_s : mnemonic_rec_t;
|
signal mnemonic_rec_s : mnemonic_rec_t;
|
signal mnemonic_s,
|
signal mnemonic_s,
|
mnemonic_q : mnemonic_t;
|
mnemonic_q : mnemonic_t;
|
signal multi_byte_s,
|
signal multi_byte_s,
|
multi_byte_q : boolean;
|
multi_byte_q : boolean;
|
signal last_cycle_s : boolean;
|
signal last_cycle_s : boolean;
|
signal force_mc_s : boolean;
|
signal force_mc_s : boolean;
|
|
|
signal en_q : dw_t;
|
signal en_q : dw_t;
|
signal set_en_s : boolean;
|
signal set_en_s : boolean;
|
signal ack_int_s : boolean;
|
signal ack_int_s : boolean;
|
|
|
begin
|
begin
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- Theory of operation:
|
-- Theory of operation:
|
--
|
--
|
-- a) One instruction cycle lasts at least 4 ck_i cycles.
|
-- a) One instruction cycle lasts at least 4 ck_i cycles.
|
-- b) PC for instruction/parameter fetch must be valid during cycle 2.
|
-- b) PC for instruction/parameter fetch must be valid during cycle 2.
|
-- => cycle 2 is the opcode fetch cycle
|
-- => cycle 2 is the opcode fetch cycle
|
-- c) Cycle 3 is the opcode decode cycle.
|
-- c) Cycle 3 is the opcode decode cycle.
|
-- => opcode_s is valid with cycle 3
|
-- => opcode_s is valid with cycle 3
|
-- d) mnemonic_q is then valid with cycle 0 until end of instruction.
|
-- d) mnemonic_q is then valid with cycle 0 until end of instruction.
|
-- So is ibyte1_q.
|
-- So is ibyte1_q.
|
-- e) PC for is incremented during last instruction cycle.
|
-- e) PC for is incremented during last instruction cycle.
|
-- => fetch of either new instruction or second instruction byte
|
-- => fetch of either new instruction or second instruction byte
|
-- f) Second instruction byte is saved in ibyte2_q for cycle 0.
|
-- f) Second instruction byte is saved in ibyte2_q for cycle 0.
|
-- Valid until end of instruction.
|
-- Valid until end of instruction.
|
--
|
--
|
-- Constraints:
|
-- Constraints:
|
--
|
--
|
-- a) PC of next instruction must be pushed in cycle 0 or 1.
|
-- a) PC of next instruction must be pushed in cycle 0 or 1.
|
-- b) PC for next instruction must be poped latest in cycle 1.
|
-- b) PC for next instruction must be poped latest in cycle 1.
|
-- c) PC for next instruction can only be calculated latest in cycle 1.
|
-- c) PC for next instruction can only be calculated latest in cycle 1.
|
-- d) IO output is enabled by out_en_i
|
-- d) IO output is enabled by out_en_i
|
-- e) IO inputs are sampled with in_en_i
|
-- e) IO inputs are sampled with in_en_i
|
--
|
--
|
-- d) and e) are required for proper timing in relation to phi1
|
-- d) and e) are required for proper timing in relation to phi1
|
-- (SK clock/sync output).
|
-- (SK clock/sync output).
|
--
|
--
|
-- Conventions:
|
-- Conventions:
|
--
|
--
|
-- a) ALU operations take place in cycle 1.
|
-- a) ALU operations take place in cycle 1.
|
--
|
--
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
last_cycle_s <= (not multi_byte_q and
|
last_cycle_s <= (not multi_byte_q and
|
not second_cyc_q and not force_mc_s)
|
not second_cyc_q and not force_mc_s)
|
or
|
or
|
second_cyc_q;
|
second_cyc_q;
|
|
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- Process seq
|
-- Process seq
|
--
|
--
|
-- Purpose:
|
-- Purpose:
|
-- Implements the various sequential elements.
|
-- Implements the various sequential elements.
|
-- Cycle counter:
|
-- Cycle counter:
|
-- It identifies the execution cycle of the
|
-- It identifies the execution cycle of the
|
-- current instruction.
|
-- current instruction.
|
-- Instruction registers:
|
-- Instruction registers:
|
-- They save the first and second byte of an instruction for
|
-- They save the first and second byte of an instruction for
|
-- further processing.
|
-- further processing.
|
-- New instruction flag:
|
-- New instruction flag:
|
-- Indicates when a new instruction is fetched from the program
|
-- Indicates when a new instruction is fetched from the program
|
-- memory. Implemented as a flip-flop to control the multiplexer
|
-- memory. Implemented as a flip-flop to control the multiplexer
|
-- which saves power by gating the combinational opcode decoder.
|
-- which saves power by gating the combinational opcode decoder.
|
-- Mnemonic register:
|
-- Mnemonic register:
|
-- Latches the decoded mnemonic of the current instruction.
|
-- Latches the decoded mnemonic of the current instruction.
|
-- Multi byte flag:
|
-- Multi byte flag:
|
-- Latches the decoded multi byte status information.
|
-- Latches the decoded multi byte status information.
|
--
|
--
|
seq: process (ck_i, por_i)
|
seq: process (ck_i, por_i)
|
begin
|
begin
|
if por_i then
|
if por_i then
|
cyc_cnt_q <= to_unsigned(1, cyc_cnt_q'length);
|
cyc_cnt_q <= to_unsigned(1, cyc_cnt_q'length);
|
second_cyc_q <= false;
|
second_cyc_q <= false;
|
ibyte1_q <= (others => '0');
|
ibyte1_q <= (others => '0');
|
ibyte2_q <= (others => '0');
|
ibyte2_q <= (others => '0');
|
mnemonic_q <= MN_CLRA;
|
mnemonic_q <= MN_CLRA;
|
multi_byte_q <= false;
|
multi_byte_q <= false;
|
en_q <= (others => '0');
|
en_q <= (others => '0');
|
|
|
elsif ck_i'event and ck_i = '1' then
|
elsif ck_i'event and ck_i = '1' then
|
if res_i then
|
if res_i then
|
-- synchronous reset upon external reset event
|
-- synchronous reset upon external reset event
|
mnemonic_q <= MN_CLRA;
|
mnemonic_q <= MN_CLRA;
|
multi_byte_q <= false;
|
multi_byte_q <= false;
|
cyc_cnt_q <= (others => '0');
|
cyc_cnt_q <= (others => '0');
|
en_q <= (others => '0');
|
en_q <= (others => '0');
|
|
|
elsif ck_en_i then
|
elsif ck_en_i then
|
-- cycle counter ------------------------------------------------------
|
-- cycle counter ------------------------------------------------------
|
if icyc_en_i then
|
if icyc_en_i then
|
-- new instruction cycle started
|
-- new instruction cycle started
|
cyc_cnt_q <= (others => '0');
|
cyc_cnt_q <= (others => '0');
|
elsif cyc_cnt_q /= 4 then
|
elsif cyc_cnt_q /= 4 then
|
cyc_cnt_q <= cyc_cnt_q + 1;
|
cyc_cnt_q <= cyc_cnt_q + 1;
|
end if;
|
end if;
|
|
|
-- second cycle flag --------------------------------------------------
|
-- second cycle flag --------------------------------------------------
|
if icyc_en_i then
|
if icyc_en_i then
|
if not last_cycle_s then
|
if not last_cycle_s then
|
second_cyc_q <= true;
|
second_cyc_q <= true;
|
else
|
else
|
second_cyc_q <= false;
|
second_cyc_q <= false;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- instruction byte 1 and mnemonic info -------------------------------
|
-- instruction byte 1 and mnemonic info -------------------------------
|
if icyc_en_i and last_cycle_s then
|
if icyc_en_i and last_cycle_s then
|
if not ack_int_s then
|
if not ack_int_s then
|
-- update instruction descriptors in normal mode
|
-- update instruction descriptors in normal mode
|
ibyte1_q <= pm_data_i;
|
ibyte1_q <= pm_data_i;
|
mnemonic_q <= mnemonic_s;
|
mnemonic_q <= mnemonic_s;
|
multi_byte_q <= multi_byte_s;
|
multi_byte_q <= multi_byte_s;
|
else
|
else
|
-- force NOP instruction when vectoring to interrupt routine
|
-- force NOP instruction when vectoring to interrupt routine
|
ibyte1_q <= "01000100";
|
ibyte1_q <= "01000100";
|
mnemonic_q <= MN_NOP;
|
mnemonic_q <= MN_NOP;
|
multi_byte_q <= false;
|
multi_byte_q <= false;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- instruction byte 2 -------------------------------------------------
|
-- instruction byte 2 -------------------------------------------------
|
if icyc_en_i and not last_cycle_s then
|
if icyc_en_i and not last_cycle_s then
|
ibyte2_q <= pm_data_i;
|
ibyte2_q <= pm_data_i;
|
end if;
|
end if;
|
|
|
-- EN register --------------------------------------------------------
|
-- EN register --------------------------------------------------------
|
if set_en_s then
|
if set_en_s then
|
en_q <= ibyte2_q(dw_range_t);
|
en_q <= ibyte2_q(dw_range_t);
|
elsif ack_int_s then
|
elsif ack_int_s then
|
-- reset interrupt enable when INT has been acknowledged
|
-- reset interrupt enable when INT has been acknowledged
|
en_q(1) <= '0';
|
en_q(1) <= '0';
|
end if;
|
end if;
|
|
|
end if;
|
end if;
|
end if;
|
end if;
|
end process seq;
|
end process seq;
|
--
|
--
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- Opcode multiplexer
|
-- Opcode multiplexer
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
opcode_s <= pm_data_i
|
opcode_s <= pm_data_i
|
when icyc_en_i else
|
when icyc_en_i else
|
ibyte1_q;
|
ibyte1_q;
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- Opcode decoder table
|
-- Opcode decoder table
|
--
|
--
|
mnemonic_rec_s <= decode_opcode_f(opcode => opcode_s,
|
mnemonic_rec_s <= decode_opcode_f(opcode => opcode_s,
|
opt_type => opt_type_g);
|
opt_type => opt_type_g);
|
--
|
--
|
mnemonic_s <= mnemonic_rec_s.mnemonic;
|
mnemonic_s <= mnemonic_rec_s.mnemonic;
|
multi_byte_s <= mnemonic_rec_s.multi_byte;
|
multi_byte_s <= mnemonic_rec_s.multi_byte;
|
--
|
--
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- Process decoder_ctrl
|
-- Process decoder_ctrl
|
--
|
--
|
-- Purpose:
|
-- Purpose:
|
-- Implements the controlling logic of the decoder module.
|
-- Implements the controlling logic of the decoder module.
|
--
|
--
|
decoder_ctrl: process (icyc_en_i,
|
decoder_ctrl: process (icyc_en_i,
|
out_en_i, in_en_i,
|
out_en_i, in_en_i,
|
cyc_cnt_q,
|
cyc_cnt_q,
|
mnemonic_q, second_cyc_q, last_cycle_s,
|
mnemonic_q, second_cyc_q, last_cycle_s,
|
ibyte1_q, ibyte2_q,
|
ibyte1_q, ibyte2_q,
|
skip_i, skip_lbi_i,
|
skip_i, skip_lbi_i,
|
en_q, int_i,
|
en_q, int_i,
|
pm_addr_i, pm_data_i)
|
pm_addr_i, pm_data_i)
|
variable cyc_v : natural range 0 to 4;
|
variable cyc_v : natural range 0 to 4;
|
variable t41x_type_v,
|
variable t41x_type_v,
|
t420_type_v : boolean;
|
t420_type_v : boolean;
|
variable en_int_v : boolean;
|
variable en_int_v : boolean;
|
begin
|
begin
|
-- default assignments
|
-- default assignments
|
pc_op_o <= PC_NONE;
|
pc_op_o <= PC_NONE;
|
stack_op_o <= STACK_NONE;
|
stack_op_o <= STACK_NONE;
|
dmem_op_o <= DMEM_RB; -- default is read via B
|
dmem_op_o <= DMEM_RB; -- default is read via B
|
b_op_o <= B_NONE;
|
b_op_o <= B_NONE;
|
skip_op_o <= SKIP_NONE;
|
skip_op_o <= SKIP_NONE;
|
alu_op_o <= ALU_NONE;
|
alu_op_o <= ALU_NONE;
|
io_l_op_o <= IOL_NONE;
|
io_l_op_o <= IOL_NONE;
|
io_d_op_o <= IOD_NONE;
|
io_d_op_o <= IOD_NONE;
|
io_g_op_o <= IOG_NONE;
|
io_g_op_o <= IOG_NONE;
|
io_in_op_o <= IOIN_NONE;
|
io_in_op_o <= IOIN_NONE;
|
sio_op_o <= SIO_NONE;
|
sio_op_o <= SIO_NONE;
|
dec_data_o <= (others => '0');
|
dec_data_o <= (others => '0');
|
is_lbi_o <= false;
|
is_lbi_o <= false;
|
set_en_s <= false;
|
set_en_s <= false;
|
force_mc_s <= false;
|
force_mc_s <= false;
|
en_int_v := true;
|
en_int_v := true;
|
ack_int_s <= false;
|
ack_int_s <= false;
|
cyc_v := to_integer(cyc_cnt_q);
|
cyc_v := to_integer(cyc_cnt_q);
|
-- determine type
|
-- determine type
|
t41x_type_v := opt_type_g = t400_opt_type_410_c;
|
t41x_type_v := opt_type_g = t400_opt_type_410_c;
|
t420_type_v := opt_type_g = t400_opt_type_420_c;
|
t420_type_v := opt_type_g = t400_opt_type_420_c;
|
|
|
if icyc_en_i then
|
if icyc_en_i then
|
-- immediately increment program counter
|
-- immediately increment program counter
|
-- this happens at two occasions:
|
-- this happens at two occasions:
|
-- a) right before new mnemonic becomes valid
|
-- a) right before new mnemonic becomes valid
|
-- b) before the second instruction cycle begins
|
-- b) before the second instruction cycle begins
|
pc_op_o <= PC_INC_PC;
|
pc_op_o <= PC_INC_PC;
|
end if;
|
end if;
|
|
|
if icyc_en_i and last_cycle_s then
|
if icyc_en_i and last_cycle_s then
|
-- update skip state when last instruction cycle ends
|
-- update skip state when last instruction cycle ends
|
skip_op_o <= SKIP_UPDATE;
|
skip_op_o <= SKIP_UPDATE;
|
end if;
|
end if;
|
|
|
-- skip instruction execution
|
-- skip instruction execution
|
if not skip_i then
|
if not skip_i then
|
-- implement instruction control
|
-- implement instruction control
|
case mnemonic_q is
|
case mnemonic_q is
|
-- Mnemonic ASC -------------------------------------------------------
|
-- Mnemonic ASC -------------------------------------------------------
|
when MN_ASC =>
|
when MN_ASC =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_ADD_C;
|
alu_op_o <= ALU_ADD_C;
|
skip_op_o <= SKIP_CARRY;
|
skip_op_o <= SKIP_CARRY;
|
end if;
|
end if;
|
|
|
-- Mnemonic ADD -------------------------------------------------------
|
-- Mnemonic ADD -------------------------------------------------------
|
when MN_ADD =>
|
when MN_ADD =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_ADD;
|
alu_op_o <= ALU_ADD;
|
end if;
|
end if;
|
|
|
-- Mnemonic ADT -------------------------------------------------------
|
-- Mnemonic ADT -------------------------------------------------------
|
when MN_ADT =>
|
when MN_ADT =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_ADD_10;
|
alu_op_o <= ALU_ADD_10;
|
end if;
|
end if;
|
|
|
-- Mnemonic AISC ------------------------------------------------------
|
-- Mnemonic AISC ------------------------------------------------------
|
when MN_AISC =>
|
when MN_AISC =>
|
dec_data_o(dw_range_t) <= ibyte1_q(dw_range_t);
|
dec_data_o(dw_range_t) <= ibyte1_q(dw_range_t);
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_ADD_DEC;
|
alu_op_o <= ALU_ADD_DEC;
|
skip_op_o <= SKIP_CARRY;
|
skip_op_o <= SKIP_CARRY;
|
end if;
|
end if;
|
|
|
-- Mnemonic CASC ------------------------------------------------------
|
-- Mnemonic CASC ------------------------------------------------------
|
when MN_CASC =>
|
when MN_CASC =>
|
case cyc_v is
|
case cyc_v is
|
when 0 =>
|
when 0 =>
|
alu_op_o <= ALU_COMP;
|
alu_op_o <= ALU_COMP;
|
when 1 =>
|
when 1 =>
|
alu_op_o <= ALU_ADD_C;
|
alu_op_o <= ALU_ADD_C;
|
skip_op_o <= SKIP_CARRY;
|
skip_op_o <= SKIP_CARRY;
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
|
|
-- Mnemonic CLRA ------------------------------------------------------
|
-- Mnemonic CLRA ------------------------------------------------------
|
when MN_CLRA =>
|
when MN_CLRA =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_CLRA;
|
alu_op_o <= ALU_CLRA;
|
end if;
|
end if;
|
|
|
-- Mnemonic COMP ------------------------------------------------------
|
-- Mnemonic COMP ------------------------------------------------------
|
when MN_COMP =>
|
when MN_COMP =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_COMP;
|
alu_op_o <= ALU_COMP;
|
end if;
|
end if;
|
|
|
-- Mnemonic NOP -------------------------------------------------------
|
-- Mnemonic NOP -------------------------------------------------------
|
when MN_NOP =>
|
when MN_NOP =>
|
-- do nothing
|
-- do nothing
|
null;
|
null;
|
|
|
-- Mnemonic C ---------------------------------------------------------
|
-- Mnemonic C ---------------------------------------------------------
|
when MN_C =>
|
when MN_C =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
if ibyte1_q(4) = '1' then
|
if ibyte1_q(4) = '1' then
|
alu_op_o <= ALU_RC;
|
alu_op_o <= ALU_RC;
|
else
|
else
|
alu_op_o <= ALU_SC;
|
alu_op_o <= ALU_SC;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- Mnemonic XOR -------------------------------------------------------
|
-- Mnemonic XOR -------------------------------------------------------
|
when MN_XOR =>
|
when MN_XOR =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_XOR;
|
alu_op_o <= ALU_XOR;
|
end if;
|
end if;
|
|
|
-- Mnemonic JID -------------------------------------------------------
|
-- Mnemonic JID -------------------------------------------------------
|
when MN_JID =>
|
when MN_JID =>
|
force_mc_s <= true;
|
force_mc_s <= true;
|
en_int_v := false;
|
en_int_v := false;
|
dec_data_o(byte_t'range) <= pm_data_i;
|
dec_data_o(byte_t'range) <= pm_data_i;
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
if not second_cyc_q then
|
if not second_cyc_q then
|
-- first cycle: load PC from A and M
|
-- first cycle: load PC from A and M
|
pc_op_o <= PC_LOAD_A_M;
|
pc_op_o <= PC_LOAD_A_M;
|
else
|
else
|
-- second cycle: load PC from program memory
|
-- second cycle: load PC from program memory
|
pc_op_o <= PC_LOAD_8;
|
pc_op_o <= PC_LOAD_8;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
if icyc_en_i and not second_cyc_q then
|
if icyc_en_i and not second_cyc_q then
|
-- do not increment PC for second instruction cycle
|
-- do not increment PC for second instruction cycle
|
pc_op_o <= PC_NONE;
|
pc_op_o <= PC_NONE;
|
end if;
|
end if;
|
|
|
-- Mnemonic JMP -------------------------------------------------------
|
-- Mnemonic JMP -------------------------------------------------------
|
when MN_JMP =>
|
when MN_JMP =>
|
en_int_v := false;
|
en_int_v := false;
|
dec_data_o <= ibyte1_q(1) & ibyte1_q(0) & ibyte2_q;
|
dec_data_o <= ibyte1_q(1) & ibyte1_q(0) & ibyte2_q;
|
if second_cyc_q and cyc_v = 1 then
|
if second_cyc_q and cyc_v = 1 then
|
pc_op_o <= PC_LOAD;
|
pc_op_o <= PC_LOAD;
|
end if;
|
end if;
|
|
|
-- Mnemonic JP_JSRP ---------------------------------------------------
|
-- Mnemonic JP_JSRP ---------------------------------------------------
|
when MN_JP_JSRP =>
|
when MN_JP_JSRP =>
|
en_int_v := false;
|
en_int_v := false;
|
-- universal decoder data
|
-- universal decoder data
|
dec_data_o <= '0' & "01" & ibyte1_q(6 downto 0);
|
dec_data_o <= '0' & "01" & ibyte1_q(6 downto 0);
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
if pm_addr_i(9 downto 7) = "001" then
|
if pm_addr_i(9 downto 7) = "001" then
|
-- JP within pages 2 & 3
|
-- JP within pages 2 & 3
|
pc_op_o <= PC_LOAD_7;
|
pc_op_o <= PC_LOAD_7;
|
elsif ibyte1_q(6) = '1' then
|
elsif ibyte1_q(6) = '1' then
|
-- JP outside of pages 2 & 3
|
-- JP outside of pages 2 & 3
|
pc_op_o <= PC_LOAD_6;
|
pc_op_o <= PC_LOAD_6;
|
else
|
else
|
-- JSRP to page 2
|
-- JSRP to page 2
|
pc_op_o <= PC_LOAD;
|
pc_op_o <= PC_LOAD;
|
stack_op_o <= STACK_PUSH;
|
stack_op_o <= STACK_PUSH;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- Mnemonic JSR -------------------------------------------------------
|
-- Mnemonic JSR -------------------------------------------------------
|
when MN_JSR =>
|
when MN_JSR =>
|
en_int_v := false;
|
en_int_v := false;
|
dec_data_o <= ibyte1_q(1) & ibyte1_q(0) & ibyte2_q;
|
dec_data_o <= ibyte1_q(1) & ibyte1_q(0) & ibyte2_q;
|
if second_cyc_q and cyc_v = 1 then
|
if second_cyc_q and cyc_v = 1 then
|
pc_op_o <= PC_LOAD;
|
pc_op_o <= PC_LOAD;
|
stack_op_o <= STACK_PUSH;
|
stack_op_o <= STACK_PUSH;
|
end if;
|
end if;
|
|
|
-- Mnemonic RET -------------------------------------------------------
|
-- Mnemonic RET -------------------------------------------------------
|
when MN_RET =>
|
when MN_RET =>
|
en_int_v := false;
|
en_int_v := false;
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
pc_op_o <= PC_POP;
|
pc_op_o <= PC_POP;
|
stack_op_o <= STACK_POP;
|
stack_op_o <= STACK_POP;
|
|
|
if t420_type_v then
|
if t420_type_v then
|
-- always restore skip state in case this was an interrupt
|
-- always restore skip state in case this was an interrupt
|
skip_op_o <= SKIP_POP;
|
skip_op_o <= SKIP_POP;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- Mnemonic RETSK -----------------------------------------------------
|
-- Mnemonic RETSK -----------------------------------------------------
|
when MN_RETSK =>
|
when MN_RETSK =>
|
en_int_v := false;
|
en_int_v := false;
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
pc_op_o <= PC_POP;
|
pc_op_o <= PC_POP;
|
stack_op_o <= STACK_POP;
|
stack_op_o <= STACK_POP;
|
skip_op_o <= SKIP_NOW;
|
skip_op_o <= SKIP_NOW;
|
end if;
|
end if;
|
|
|
-- Mnemonic LD --------------------------------------------------------
|
-- Mnemonic LD --------------------------------------------------------
|
when MN_LD =>
|
when MN_LD =>
|
dec_data_o(br_range_t) <= ibyte1_q(br_range_t);
|
dec_data_o(br_range_t) <= ibyte1_q(br_range_t);
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_LOAD_M;
|
alu_op_o <= ALU_LOAD_M;
|
b_op_o <= B_XOR_BR;
|
b_op_o <= B_XOR_BR;
|
end if;
|
end if;
|
|
|
-- Mnemonic LDD_XAD ---------------------------------------------------
|
-- Mnemonic LDD_XAD ---------------------------------------------------
|
when MN_LDD_XAD =>
|
when MN_LDD_XAD =>
|
-- preload decoder data
|
-- preload decoder data
|
dec_data_o(b_range_t) <= ibyte2_q(b_range_t);
|
dec_data_o(b_range_t) <= ibyte2_q(b_range_t);
|
|
|
if second_cyc_q then
|
if second_cyc_q then
|
case ibyte2_q(7 downto 6) is
|
case ibyte2_q(7 downto 6) is
|
-- LDD
|
-- LDD
|
when "00" =>
|
when "00" =>
|
if not t41x_type_v then
|
if not t41x_type_v then
|
case cyc_v is
|
case cyc_v is
|
when 1 =>
|
when 1 =>
|
dmem_op_o <= DMEM_RDEC;
|
dmem_op_o <= DMEM_RDEC;
|
when 2 =>
|
when 2 =>
|
alu_op_o <= ALU_LOAD_M;
|
alu_op_o <= ALU_LOAD_M;
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
end if;
|
end if;
|
-- XAD
|
-- XAD
|
when "10" =>
|
when "10" =>
|
if not t41x_type_v or
|
if not t41x_type_v or
|
unsigned(ibyte2_q(b_range_t)) = 63 then
|
unsigned(ibyte2_q(b_range_t)) = 63 then
|
case cyc_v is
|
case cyc_v is
|
when 1 =>
|
when 1 =>
|
dmem_op_o <= DMEM_RDEC;
|
dmem_op_o <= DMEM_RDEC;
|
when 2 =>
|
when 2 =>
|
alu_op_o <= ALU_LOAD_M;
|
alu_op_o <= ALU_LOAD_M;
|
dmem_op_o <= DMEM_WDEC_SRC_A;
|
dmem_op_o <= DMEM_WDEC_SRC_A;
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
-- Mnemonic LQID ------------------------------------------------------
|
-- Mnemonic LQID ------------------------------------------------------
|
when MN_LQID =>
|
when MN_LQID =>
|
force_mc_s <= true;
|
force_mc_s <= true;
|
en_int_v := false;
|
en_int_v := false;
|
if not second_cyc_q then
|
if not second_cyc_q then
|
-- first cycle: push PC and set PC from A/M,
|
-- first cycle: push PC and set PC from A/M,
|
-- read IOL from program memory
|
-- read IOL from program memory
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
stack_op_o <= STACK_PUSH;
|
stack_op_o <= STACK_PUSH;
|
pc_op_o <= PC_LOAD_A_M;
|
pc_op_o <= PC_LOAD_A_M;
|
end if;
|
end if;
|
|
|
if out_en_i then
|
if out_en_i then
|
io_l_op_o <= IOL_LOAD_PM;
|
io_l_op_o <= IOL_LOAD_PM;
|
end if;
|
end if;
|
else
|
else
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
-- second cycle: pop PC
|
-- second cycle: pop PC
|
stack_op_o <= STACK_POP;
|
stack_op_o <= STACK_POP;
|
pc_op_o <= PC_POP;
|
pc_op_o <= PC_POP;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
if icyc_en_i and not second_cyc_q then
|
if icyc_en_i and not second_cyc_q then
|
-- do not increment PC for second instruction cycle
|
-- do not increment PC for second instruction cycle
|
pc_op_o <= PC_NONE;
|
pc_op_o <= PC_NONE;
|
end if;
|
end if;
|
|
|
-- Mnemonic RMB -------------------------------------------------------
|
-- Mnemonic RMB -------------------------------------------------------
|
when MN_RMB =>
|
when MN_RMB =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
dmem_op_o <= DMEM_WB_RES_BIT;
|
dmem_op_o <= DMEM_WB_RES_BIT;
|
-- select bit to be reset
|
-- select bit to be reset
|
case ibyte1_q(dw_range_t) is
|
case ibyte1_q(dw_range_t) is
|
when "1100" =>
|
when "1100" =>
|
dec_data_o(dw_range_t) <= "0001";
|
dec_data_o(dw_range_t) <= "0001";
|
when "0101" =>
|
when "0101" =>
|
dec_data_o(dw_range_t) <= "0010";
|
dec_data_o(dw_range_t) <= "0010";
|
when "0010" =>
|
when "0010" =>
|
dec_data_o(dw_range_t) <= "0100";
|
dec_data_o(dw_range_t) <= "0100";
|
when "0011" =>
|
when "0011" =>
|
dec_data_o(dw_range_t) <= "1000";
|
dec_data_o(dw_range_t) <= "1000";
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
-- Mnemonic SMB -------------------------------------------------------
|
-- Mnemonic SMB -------------------------------------------------------
|
when MN_SMB =>
|
when MN_SMB =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
dmem_op_o <= DMEM_WB_SET_BIT;
|
dmem_op_o <= DMEM_WB_SET_BIT;
|
-- select bit to be set
|
-- select bit to be set
|
case ibyte1_q(dw_range_t) is
|
case ibyte1_q(dw_range_t) is
|
when "1101" =>
|
when "1101" =>
|
dec_data_o(dw_range_t) <= "0001";
|
dec_data_o(dw_range_t) <= "0001";
|
when "0111" =>
|
when "0111" =>
|
dec_data_o(dw_range_t) <= "0010";
|
dec_data_o(dw_range_t) <= "0010";
|
when "0110" =>
|
when "0110" =>
|
dec_data_o(dw_range_t) <= "0100";
|
dec_data_o(dw_range_t) <= "0100";
|
when "1011" =>
|
when "1011" =>
|
dec_data_o(dw_range_t) <= "1000";
|
dec_data_o(dw_range_t) <= "1000";
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
-- Mnemonic STII ------------------------------------------------------
|
-- Mnemonic STII ------------------------------------------------------
|
when MN_STII =>
|
when MN_STII =>
|
dec_data_o(dw_range_t) <= ibyte1_q(dw_range_t);
|
dec_data_o(dw_range_t) <= ibyte1_q(dw_range_t);
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
dmem_op_o <= DMEM_WB_SRC_DEC;
|
dmem_op_o <= DMEM_WB_SRC_DEC;
|
b_op_o <= B_INC_BD;
|
b_op_o <= B_INC_BD;
|
end if;
|
end if;
|
|
|
-- Mnemonic X ---------------------------------------------------------
|
-- Mnemonic X ---------------------------------------------------------
|
when MN_X =>
|
when MN_X =>
|
dec_data_o(br_range_t) <= ibyte1_q(br_range_t);
|
dec_data_o(br_range_t) <= ibyte1_q(br_range_t);
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_LOAD_M;
|
alu_op_o <= ALU_LOAD_M;
|
dmem_op_o <= DMEM_WB_SRC_A;
|
dmem_op_o <= DMEM_WB_SRC_A;
|
b_op_o <= B_XOR_BR;
|
b_op_o <= B_XOR_BR;
|
end if;
|
end if;
|
|
|
-- Mnemonic XDS -------------------------------------------------------
|
-- Mnemonic XDS -------------------------------------------------------
|
when MN_XDS =>
|
when MN_XDS =>
|
dec_data_o(br_range_t) <= ibyte1_q(br_range_t);
|
dec_data_o(br_range_t) <= ibyte1_q(br_range_t);
|
case cyc_v is
|
case cyc_v is
|
when 1 =>
|
when 1 =>
|
alu_op_o <= ALU_LOAD_M;
|
alu_op_o <= ALU_LOAD_M;
|
dmem_op_o <= DMEM_WB_SRC_A;
|
dmem_op_o <= DMEM_WB_SRC_A;
|
b_op_o <= B_DEC_BD;
|
b_op_o <= B_DEC_BD;
|
when 2 =>
|
when 2 =>
|
b_op_o <= B_XOR_BR;
|
b_op_o <= B_XOR_BR;
|
skip_op_o <= SKIP_BD_UFLOW;
|
skip_op_o <= SKIP_BD_UFLOW;
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
|
|
-- Mnemonic XIS -------------------------------------------------------
|
-- Mnemonic XIS -------------------------------------------------------
|
when MN_XIS =>
|
when MN_XIS =>
|
dec_data_o(br_range_t) <= ibyte1_q(br_range_t);
|
dec_data_o(br_range_t) <= ibyte1_q(br_range_t);
|
case cyc_v is
|
case cyc_v is
|
when 1 =>
|
when 1 =>
|
alu_op_o <= ALU_LOAD_M;
|
alu_op_o <= ALU_LOAD_M;
|
dmem_op_o <= DMEM_WB_SRC_A;
|
dmem_op_o <= DMEM_WB_SRC_A;
|
b_op_o <= B_INC_BD;
|
b_op_o <= B_INC_BD;
|
when 2 =>
|
when 2 =>
|
b_op_o <= B_XOR_BR;
|
b_op_o <= B_XOR_BR;
|
skip_op_o <= SKIP_BD_OFLOW;
|
skip_op_o <= SKIP_BD_OFLOW;
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
|
|
-- Mnemonic CAB -------------------------------------------------------
|
-- Mnemonic CAB -------------------------------------------------------
|
when MN_CAB =>
|
when MN_CAB =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
b_op_o <= B_SET_BD;
|
b_op_o <= B_SET_BD;
|
end if;
|
end if;
|
|
|
-- Mnemonic CBA -------------------------------------------------------
|
-- Mnemonic CBA -------------------------------------------------------
|
when MN_CBA =>
|
when MN_CBA =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_LOAD_BD;
|
alu_op_o <= ALU_LOAD_BD;
|
end if;
|
end if;
|
|
|
-- Mnemonic LBI -------------------------------------------------------
|
-- Mnemonic LBI -------------------------------------------------------
|
when MN_LBI =>
|
when MN_LBI =>
|
is_lbi_o <= true;
|
is_lbi_o <= true;
|
en_int_v := false;
|
en_int_v := false;
|
dec_data_o(br_range_t) <= ibyte1_q(br_range_t);
|
dec_data_o(br_range_t) <= ibyte1_q(br_range_t);
|
dec_data_o(bd_range_t) <= ibyte1_q(bd_range_t);
|
dec_data_o(bd_range_t) <= ibyte1_q(bd_range_t);
|
if cyc_v = 1 and not skip_lbi_i then
|
if cyc_v = 1 and not skip_lbi_i then
|
-- increment Bd by 1
|
-- increment Bd by 1
|
b_op_o <= B_SET_B_INC;
|
b_op_o <= B_SET_B_INC;
|
skip_op_o <= SKIP_LBI;
|
skip_op_o <= SKIP_LBI;
|
end if;
|
end if;
|
|
|
-- Mnemonic XABR ------------------------------------------------------
|
-- Mnemonic XABR ------------------------------------------------------
|
when MN_XABR =>
|
when MN_XABR =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_LOAD_BR;
|
alu_op_o <= ALU_LOAD_BR;
|
b_op_o <= B_SET_BR;
|
b_op_o <= B_SET_BR;
|
end if;
|
end if;
|
|
|
-- Mnemonic SKC -------------------------------------------------------
|
-- Mnemonic SKC -------------------------------------------------------
|
when MN_SKC =>
|
when MN_SKC =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
skip_op_o <= SKIP_C;
|
skip_op_o <= SKIP_C;
|
end if;
|
end if;
|
|
|
-- Mnemonic SKE -------------------------------------------------------
|
-- Mnemonic SKE -------------------------------------------------------
|
when MN_SKE =>
|
when MN_SKE =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
skip_op_o <= SKIP_A_M;
|
skip_op_o <= SKIP_A_M;
|
end if;
|
end if;
|
|
|
-- Mnemonic SKMBZ -----------------------------------------------------
|
-- Mnemonic SKMBZ -----------------------------------------------------
|
when MN_SKMBZ =>
|
when MN_SKMBZ =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
skip_op_o <= SKIP_M_BIT;
|
skip_op_o <= SKIP_M_BIT;
|
-- select bit to be checked
|
-- select bit to be checked
|
case ibyte1_q is
|
case ibyte1_q is
|
when "00000001" =>
|
when "00000001" =>
|
dec_data_o(dw_range_t) <= "0001";
|
dec_data_o(dw_range_t) <= "0001";
|
when "00010001" =>
|
when "00010001" =>
|
dec_data_o(dw_range_t) <= "0010";
|
dec_data_o(dw_range_t) <= "0010";
|
when "00000011" =>
|
when "00000011" =>
|
dec_data_o(dw_range_t) <= "0100";
|
dec_data_o(dw_range_t) <= "0100";
|
when "00010011" =>
|
when "00010011" =>
|
dec_data_o(dw_range_t) <= "1000";
|
dec_data_o(dw_range_t) <= "1000";
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
-- Mnemonic SKT -------------------------------------------------------
|
-- Mnemonic SKT -------------------------------------------------------
|
when MN_SKT =>
|
when MN_SKT =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
skip_op_o <= SKIP_TIMER;
|
skip_op_o <= SKIP_TIMER;
|
end if;
|
end if;
|
|
|
-- Mnemonic XAS -------------------------------------------------------
|
-- Mnemonic XAS -------------------------------------------------------
|
when MN_XAS =>
|
when MN_XAS =>
|
if out_en_i then
|
if out_en_i then
|
sio_op_o <= SIO_LOAD;
|
sio_op_o <= SIO_LOAD;
|
alu_op_o <= ALU_LOAD_SIO;
|
alu_op_o <= ALU_LOAD_SIO;
|
end if;
|
end if;
|
|
|
-- Mnemonic EXT -------------------------------------------------------
|
-- Mnemonic EXT -------------------------------------------------------
|
when MN_EXT =>
|
when MN_EXT =>
|
if second_cyc_q then
|
if second_cyc_q then
|
case ibyte2_q is
|
case ibyte2_q is
|
-- CAMQ
|
-- CAMQ
|
when "00111100" =>
|
when "00111100" =>
|
if out_en_i then
|
if out_en_i then
|
io_l_op_o <= IOL_LOAD_AM;
|
io_l_op_o <= IOL_LOAD_AM;
|
end if;
|
end if;
|
-- CQMA
|
-- CQMA
|
when "00101100" =>
|
when "00101100" =>
|
if not t41x_type_v and in_en_i then
|
if not t41x_type_v and in_en_i then
|
io_l_op_o <= IOL_OUTPUT_Q;
|
io_l_op_o <= IOL_OUTPUT_Q;
|
alu_op_o <= ALU_LOAD_Q;
|
alu_op_o <= ALU_LOAD_Q;
|
dmem_op_o <= DMEM_WB_SRC_Q;
|
dmem_op_o <= DMEM_WB_SRC_Q;
|
end if;
|
end if;
|
-- SKGZ
|
-- SKGZ
|
when "00100001" =>
|
when "00100001" =>
|
if in_en_i then
|
if in_en_i then
|
skip_op_o <= SKIP_G_ZERO;
|
skip_op_o <= SKIP_G_ZERO;
|
end if;
|
end if;
|
-- SKGBZ
|
-- SKGBZ
|
when "00000001" =>
|
when "00000001" =>
|
if in_en_i then
|
if in_en_i then
|
skip_op_o <= SKIP_G_BIT;
|
skip_op_o <= SKIP_G_BIT;
|
dec_data_o(dw_range_t) <= "0001";
|
dec_data_o(dw_range_t) <= "0001";
|
end if;
|
end if;
|
when "00010001" =>
|
when "00010001" =>
|
if in_en_i then
|
if in_en_i then
|
skip_op_o <= SKIP_G_BIT;
|
skip_op_o <= SKIP_G_BIT;
|
dec_data_o(dw_range_t) <= "0010";
|
dec_data_o(dw_range_t) <= "0010";
|
end if;
|
end if;
|
when "00000011" =>
|
when "00000011" =>
|
if in_en_i then
|
if in_en_i then
|
skip_op_o <= SKIP_G_BIT;
|
skip_op_o <= SKIP_G_BIT;
|
dec_data_o(dw_range_t) <= "0100";
|
dec_data_o(dw_range_t) <= "0100";
|
end if;
|
end if;
|
when "00010011" =>
|
when "00010011" =>
|
if in_en_i then
|
if in_en_i then
|
skip_op_o <= SKIP_G_BIT;
|
skip_op_o <= SKIP_G_BIT;
|
dec_data_o(dw_range_t) <= "1000";
|
dec_data_o(dw_range_t) <= "1000";
|
end if;
|
end if;
|
-- ING
|
-- ING
|
when "00101010" =>
|
when "00101010" =>
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
alu_op_o <= ALU_LOAD_G;
|
alu_op_o <= ALU_LOAD_G;
|
end if;
|
end if;
|
-- INL
|
-- INL
|
when "00101110" =>
|
when "00101110" =>
|
if in_en_i then
|
if in_en_i then
|
io_l_op_o <= IOL_OUTPUT_L;
|
io_l_op_o <= IOL_OUTPUT_L;
|
alu_op_o <= ALU_LOAD_Q;
|
alu_op_o <= ALU_LOAD_Q;
|
dmem_op_o <= DMEM_WB_SRC_Q;
|
dmem_op_o <= DMEM_WB_SRC_Q;
|
end if;
|
end if;
|
-- ININ
|
-- ININ
|
when "00101000" =>
|
when "00101000" =>
|
if not t41x_type_v and in_en_i then
|
if not t41x_type_v and in_en_i then
|
alu_op_o <= ALU_LOAD_IN;
|
alu_op_o <= ALU_LOAD_IN;
|
end if;
|
end if;
|
-- INIL
|
-- INIL
|
when "00101001" =>
|
when "00101001" =>
|
if not t41x_type_v and in_en_i then
|
if not t41x_type_v and in_en_i then
|
alu_op_o <= ALU_LOAD_IL;
|
alu_op_o <= ALU_LOAD_IL;
|
io_in_op_o <= IOIN_INIL;
|
io_in_op_o <= IOIN_INIL;
|
end if;
|
end if;
|
-- OBD
|
-- OBD
|
when "00111110" =>
|
when "00111110" =>
|
if out_en_i then
|
if out_en_i then
|
io_d_op_o <= IOD_LOAD;
|
io_d_op_o <= IOD_LOAD;
|
end if;
|
end if;
|
-- OMG
|
-- OMG
|
when "00111010" =>
|
when "00111010" =>
|
if out_en_i then
|
if out_en_i then
|
io_g_op_o <= IOG_LOAD_M;
|
io_g_op_o <= IOG_LOAD_M;
|
end if;
|
end if;
|
-- multiple codes
|
-- multiple codes
|
when others =>
|
when others =>
|
-- apply default decoder output, largest required vector
|
-- apply default decoder output, largest required vector
|
dec_data_o(b_range_t) <= ibyte2_q(b_range_t);
|
dec_data_o(b_range_t) <= ibyte2_q(b_range_t);
|
-- LBI
|
-- LBI
|
if ibyte2_q(7 downto 6) = "10" and not t41x_type_v then
|
if ibyte2_q(7 downto 6) = "10" and not t41x_type_v then
|
is_lbi_o <= true;
|
is_lbi_o <= true;
|
en_int_v := false;
|
en_int_v := false;
|
if cyc_v > 0 and not skip_lbi_i then
|
if cyc_v > 0 and not skip_lbi_i then
|
b_op_o <= B_SET_B;
|
b_op_o <= B_SET_B;
|
skip_op_o <= SKIP_LBI;
|
skip_op_o <= SKIP_LBI;
|
end if;
|
end if;
|
end if;
|
end if;
|
-- LEI
|
-- LEI
|
if ibyte2_q(7 downto 4) = "0110" and in_en_i then
|
if ibyte2_q(7 downto 4) = "0110" and in_en_i then
|
-- dec_data_o applied by default
|
-- dec_data_o applied by default
|
set_en_s <= true;
|
set_en_s <= true;
|
|
|
-- acknowledge pending interrupt when EN(1) is not
|
-- acknowledge pending interrupt when EN(1) is not
|
-- enabled - will clear them until interrupts are
|
-- enabled - will clear them until interrupts are
|
-- enabled with EN(1) = '1'
|
-- enabled with EN(1) = '1'
|
if en_q(1) = '0' then
|
if en_q(1) = '0' then
|
io_in_op_o <= IOIN_INTACK;
|
io_in_op_o <= IOIN_INTACK;
|
end if;
|
end if;
|
end if;
|
end if;
|
-- OGI
|
-- OGI
|
if ibyte2_q(7 downto 4) = "0101" and out_en_i and
|
if ibyte2_q(7 downto 4) = "0101" and out_en_i and
|
not t41x_type_v then
|
not t41x_type_v then
|
-- dec_data_o applied by default
|
-- dec_data_o applied by default
|
io_g_op_o <= IOG_LOAD_DEC;
|
io_g_op_o <= IOG_LOAD_DEC;
|
end if;
|
end if;
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
|
|
-- Interrupt handling -----------------------------------------------------
|
-- Interrupt handling -----------------------------------------------------
|
if t420_type_v and
|
if t420_type_v and
|
en_q(1) = '1' and int_i and en_int_v then
|
en_q(1) = '1' and int_i and en_int_v then
|
if last_cycle_s then
|
if last_cycle_s then
|
if cyc_v = 1 then
|
if cyc_v = 1 then
|
stack_op_o <= STACK_PUSH;
|
stack_op_o <= STACK_PUSH;
|
end if;
|
end if;
|
if icyc_en_i then
|
if icyc_en_i then
|
ack_int_s <= true;
|
ack_int_s <= true;
|
io_in_op_o <= IOIN_INTACK;
|
io_in_op_o <= IOIN_INTACK;
|
pc_op_o <= PC_INT;
|
pc_op_o <= PC_INT;
|
-- push skip state that was determined by current instruction
|
-- push skip state that was determined by current instruction
|
-- and will be valid for the next instruction which is delayed
|
-- and will be valid for the next instruction which is delayed
|
-- by the interrupt
|
-- by the interrupt
|
skip_op_o <= SKIP_PUSH;
|
skip_op_o <= SKIP_PUSH;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
end process decoder_ctrl;
|
end process decoder_ctrl;
|
--
|
--
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
|
|
|
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
-- Output mapping
|
-- Output mapping
|
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
en_o <= en_q;
|
en_o <= en_q;
|
|
|
end rtl;
|
end rtl;
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- File History:
|
|
--
|
|
-- $Log: not supported by cvs2svn $
|
|
-- Revision 1.6 2006/06/05 14:20:34 arniml
|
|
-- interface comments added
|
|
--
|
|
-- Revision 1.5 2006/05/28 15:32:14 arniml
|
|
-- execute virtual NOP at location 0x0ff when vectoring to interrupt routine
|
|
--
|
|
-- Revision 1.4 2006/05/27 19:14:18 arniml
|
|
-- interrupt functionality added
|
|
--
|
|
-- Revision 1.3 2006/05/22 00:02:36 arniml
|
|
-- instructions ININ and INIL implemented
|
|
--
|
|
-- Revision 1.2 2006/05/07 02:24:16 arniml
|
|
-- fix sensitivity list
|
|
--
|
|
-- Revision 1.1.1.1 2006/05/06 01:56:44 arniml
|
|
-- import from local CVS repository, LOC_CVS_0_1
|
|
--
|
|
-------------------------------------------------------------------------------
|
|
|
|
No newline at end of file
|
No newline at end of file
|