Line 1... |
Line 1... |
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
--
|
--
|
-- 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.4 2006-05-27 19:14:18 arniml Exp $
|
-- $Id: t400_decoder.vhd,v 1.5 2006-05-28 15:32:14 arniml Exp $
|
--
|
--
|
-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org)
|
-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org)
|
--
|
--
|
-- All rights reserved
|
-- All rights reserved
|
--
|
--
|
Line 208... |
Line 208... |
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
|
|
-- 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
|
|
-- force NOP instruction when vectoring to interrupt routine
|
|
ibyte1_q <= "01000100";
|
|
mnemonic_q <= MN_NOP;
|
|
multi_byte_q <= false;
|
|
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;
|
Line 271... |
Line 279... |
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 no_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
|
Line 289... |
Line 297... |
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;
|
no_int_v := false;
|
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;
|
Line 388... |
Line 396... |
end if;
|
end if;
|
|
|
-- Mnemonic JID -------------------------------------------------------
|
-- Mnemonic JID -------------------------------------------------------
|
when MN_JID =>
|
when MN_JID =>
|
force_mc_s <= true;
|
force_mc_s <= true;
|
no_int_v := true;
|
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;
|
Line 407... |
Line 415... |
pc_op_o <= PC_NONE;
|
pc_op_o <= PC_NONE;
|
end if;
|
end if;
|
|
|
-- Mnemonic JMP -------------------------------------------------------
|
-- Mnemonic JMP -------------------------------------------------------
|
when MN_JMP =>
|
when MN_JMP =>
|
no_int_v := true;
|
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 =>
|
no_int_v := true;
|
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
|
Line 434... |
Line 442... |
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- Mnemonic JSR -------------------------------------------------------
|
-- Mnemonic JSR -------------------------------------------------------
|
when MN_JSR =>
|
when MN_JSR =>
|
no_int_v := true;
|
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 =>
|
no_int_v := true;
|
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
|
Line 456... |
Line 464... |
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- Mnemonic RETSK -----------------------------------------------------
|
-- Mnemonic RETSK -----------------------------------------------------
|
when MN_RETSK =>
|
when MN_RETSK =>
|
no_int_v := true;
|
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;
|
Line 513... |
Line 521... |
end if;
|
end if;
|
|
|
-- Mnemonic LQID ------------------------------------------------------
|
-- Mnemonic LQID ------------------------------------------------------
|
when MN_LQID =>
|
when MN_LQID =>
|
force_mc_s <= true;
|
force_mc_s <= true;
|
no_int_v := true;
|
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;
|
Line 638... |
Line 646... |
end if;
|
end if;
|
|
|
-- Mnemonic LBI -------------------------------------------------------
|
-- Mnemonic LBI -------------------------------------------------------
|
when MN_LBI =>
|
when MN_LBI =>
|
is_lbi_o <= true;
|
is_lbi_o <= true;
|
no_int_v := true;
|
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;
|
Line 780... |
Line 788... |
-- 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;
|
no_int_v := true;
|
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;
|
Line 815... |
Line 823... |
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 not no_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
|
pc_op_o <= PC_INT;
|
|
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;
|
-- 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;
|
Line 849... |
Line 857... |
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- File History:
|
-- File History:
|
--
|
--
|
-- $Log: not supported by cvs2svn $
|
-- $Log: not supported by cvs2svn $
|
|
-- Revision 1.4 2006/05/27 19:14:18 arniml
|
|
-- interrupt functionality added
|
|
--
|
-- Revision 1.3 2006/05/22 00:02:36 arniml
|
-- Revision 1.3 2006/05/22 00:02:36 arniml
|
-- instructions ININ and INIL implemented
|
-- instructions ININ and INIL implemented
|
--
|
--
|
-- Revision 1.2 2006/05/07 02:24:16 arniml
|
-- Revision 1.2 2006/05/07 02:24:16 arniml
|
-- fix sensitivity list
|
-- fix sensitivity list
|