OpenCores
URL https://opencores.org/ocsvn/t48/t48/trunk

Subversion Repositories t48

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /t48/tags/rel_0_1_beta/rtl
    from Rev 251 to Rev 292
    Reverse comparison

Rev 251 → Rev 292

/vhdl/t48_core.vhd
0,0 → 1,652
-------------------------------------------------------------------------------
--
-- T48 Microcontroller Core
--
-- $Id: t48_core.vhd,v 1.7 2004-05-01 11:58:04 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-- Limitations :
-- =============
--
-- Compared to the original MCS-48 architecture, the following limitations
-- apply:
--
-- * Nibble-wide instructions addressing expander port implemented but
-- not verified in detail.
--
-- * Single-step mode not implemented.
-- Not selected for future implementation.
--
-- * Reading of internal Program Memory not implemented.
-- Not selected for future implementation.
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity t48_core is
 
generic (
-- divide XTAL1 by 3 to derive Clock States
xtal_div_3_g : integer := 1;
-- store mnemonic in flip-flops (registered-out)
register_mnemonic_g : integer := 1;
-- include the port 1 module
include_port1_g : integer := 1;
-- include the port 2 module
include_port2_g : integer := 1;
-- include the BUS module
include_bus_g : integer := 1;
-- include the timer module
include_timer_g : integer := 1;
-- state in which T1 is sampled (3 or 4)
sample_t1_state_g : integer := 4
);
 
port (
-- T48 Interface ----------------------------------------------------------
xtal_i : in std_logic;
reset_i : in std_logic;
t0_i : in std_logic;
t0_o : out std_logic;
t0_dir_o : out std_logic;
int_n_i : in std_logic;
ea_i : in std_logic;
rd_n_o : out std_logic;
psen_n_o : out std_logic;
wr_n_o : out std_logic;
ale_o : out std_logic;
db_i : in std_logic_vector( 7 downto 0);
db_o : out std_logic_vector( 7 downto 0);
db_dir_o : out std_logic;
t1_i : in std_logic;
p2_i : in std_logic_vector( 7 downto 0);
p2_o : out std_logic_vector( 7 downto 0);
p2_low_imp_o : out std_logic;
p1_i : in std_logic_vector( 7 downto 0);
p1_o : out std_logic_vector( 7 downto 0);
p1_low_imp_o : out std_logic;
prog_n_o : out std_logic;
-- Core Interface ---------------------------------------------------------
clk_i : in std_logic;
en_clk_i : in std_logic;
xtal3_o : out std_logic;
dmem_addr_o : out std_logic_vector( 7 downto 0);
dmem_we_o : out std_logic;
dmem_data_i : in std_logic_vector( 7 downto 0);
dmem_data_o : out std_logic_vector( 7 downto 0);
pmem_addr_o : out std_logic_vector(11 downto 0);
pmem_data_i : in std_logic_vector( 7 downto 0)
);
 
end t48_core;
 
 
use work.alu_pack.alu_op_t;
use work.cond_branch_pack.branch_conditions_t;
use work.cond_branch_pack.comp_value_t;
use work.dmem_ctrl_pack.dmem_addr_ident_t;
use work.pmem_ctrl_pack.pmem_addr_ident_t;
use work.t48_comp_pack.all;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.word_t;
use work.t48_pack.pmem_addr_t;
use work.t48_pack.mstate_t;
use work.t48_pack.to_stdLogic;
use work.t48_pack.to_boolean;
 
architecture struct of t48_core is
 
signal t48_data_s : word_t;
 
signal en_clk_s : boolean;
 
-- ALU signals
signal alu_data_s : word_t;
signal alu_write_accu_s : boolean;
signal alu_write_shadow_s : boolean;
signal alu_write_temp_reg_s : boolean;
signal alu_read_alu_s : boolean;
signal alu_carry_s : std_logic;
signal alu_aux_carry_s : std_logic;
signal alu_op_s : alu_op_t;
signal alu_use_carry_s : boolean;
signal alu_da_high_s : boolean;
signal alu_da_overflow_s : boolean;
signal alu_accu_low_s : boolean;
signal alu_p06_temp_reg_s : boolean;
signal alu_p60_temp_reg_s : boolean;
 
-- BUS signals
signal bus_write_bus_s : boolean;
signal bus_read_bus_s : boolean;
signal bus_output_pcl_s : boolean;
signal bus_bidir_bus_s : boolean;
signal bus_data_s : word_t;
 
-- Clock Controller signals
signal clk_multi_cycle_s : boolean;
signal clk_assert_psen_s : boolean;
signal clk_assert_prog_s : boolean;
signal clk_assert_rd_s : boolean;
signal clk_assert_wr_s : boolean;
signal clk_mstate_s : mstate_t;
signal clk_second_cycle_s : boolean;
signal psen_s : boolean;
signal prog_s : boolean;
signal rd_s : boolean;
signal wr_s : boolean;
signal ale_s : boolean;
signal xtal3_s : boolean;
 
-- Conditional Branch Logic signals
signal cnd_compute_take_s : boolean;
signal cnd_branch_cond_s : branch_conditions_t;
signal cnd_take_branch_s : boolean;
signal cnd_comp_value_s : comp_value_t;
signal cnd_f1_s : std_logic;
signal cnd_tf_s : std_logic;
 
-- Data Memory Controller signals
signal dm_write_dmem_addr_s : boolean;
signal dm_write_dmem_s : boolean;
signal dm_read_dmem_s : boolean;
signal dm_addr_type_s : dmem_addr_ident_t;
signal dm_data_s : word_t;
 
-- Decoder signals
signal dec_data_s : word_t;
 
-- Port 1 signals
signal p1_write_p1_s : boolean;
signal p1_read_p1_s : boolean;
signal p1_read_reg_s : boolean;
signal p1_data_s : word_t;
 
-- Port 2 signals
signal p2_write_p2_s : boolean;
signal p2_write_exp_s : boolean;
signal p2_read_p2_s : boolean;
signal p2_read_reg_s : boolean;
signal p2_read_exp_s : boolean;
signal p2_output_pch_s : boolean;
signal p2_output_exp_s : boolean;
signal p2_data_s : word_t;
 
-- Program Memory Controller signals
signal pm_write_pcl_s : boolean;
signal pm_read_pcl_s : boolean;
signal pm_write_pch_s : boolean;
signal pm_read_pch_s : boolean;
signal pm_read_pmem_s : boolean;
signal pm_inc_pc_s : boolean;
signal pm_write_pmem_addr_s : boolean;
signal pm_data_s : word_t;
signal pm_addr_type_s : pmem_addr_ident_t;
signal pmem_addr_s : pmem_addr_t;
 
-- PSW signals
signal psw_read_psw_s : boolean;
signal psw_read_sp_s : boolean;
signal psw_write_psw_s : boolean;
signal psw_write_sp_s : boolean;
signal psw_carry_s : std_logic;
signal psw_aux_carry_s : std_logic;
signal psw_f0_s : std_logic;
signal psw_bs_s : std_logic;
signal psw_special_data_s : std_logic;
signal psw_inc_stackp_s : boolean;
signal psw_dec_stackp_s : boolean;
signal psw_write_carry_s : boolean;
signal psw_write_aux_carry_s : boolean;
signal psw_write_f0_s : boolean;
signal psw_write_bs_s : boolean;
signal psw_data_s : word_t;
 
-- Timer signals
signal tim_overflow_s : boolean;
signal tim_of_s : std_logic;
signal tim_read_timer_s : boolean;
signal tim_write_timer_s : boolean;
signal tim_start_t_s : boolean;
signal tim_start_cnt_s : boolean;
signal tim_stop_tcnt_s : boolean;
signal tim_data_s : word_t;
 
begin
 
-----------------------------------------------------------------------------
-- Check generics for valid values.
-----------------------------------------------------------------------------
-- pragma translate_off
assert include_timer_g = 0 or include_timer_g = 1
report "include_timer_g must be either 1 or 0!"
severity failure;
 
assert include_port1_g = 0 or include_port1_g = 1
report "include_port1_g must be either 1 or 0!"
severity failure;
 
assert include_port2_g = 0 or include_port2_g = 1
report "include_port2_g must be either 1 or 0!"
severity failure;
 
assert include_bus_g = 0 or include_bus_g = 1
report "include_bus_g must be either 1 or 0!"
severity failure;
-- pragma translate_on
 
 
en_clk_s <= to_boolean(en_clk_i);
 
alu_b : alu
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
data_o => alu_data_s,
write_accu_i => alu_write_accu_s,
write_shadow_i => alu_write_shadow_s,
write_temp_reg_i => alu_write_temp_reg_s,
read_alu_i => alu_read_alu_s,
carry_i => psw_carry_s,
carry_o => alu_carry_s,
aux_carry_o => alu_aux_carry_s,
alu_op_i => alu_op_s,
use_carry_i => alu_use_carry_s,
da_high_i => alu_da_high_s,
da_overflow_o => alu_da_overflow_s,
accu_low_i => alu_accu_low_s,
p06_temp_reg_i => alu_p06_temp_reg_s,
p60_temp_reg_i => alu_p60_temp_reg_s
);
 
bus_mux_b : bus_mux
port map (
alu_data_i => alu_data_s,
bus_data_i => bus_data_s,
dec_data_i => dec_data_s,
dm_data_i => dm_data_s,
pm_data_i => pm_data_s,
p1_data_i => p1_data_s,
p2_data_i => p2_data_s,
psw_data_i => psw_data_s,
tim_data_i => tim_data_s,
data_o => t48_data_s
);
 
clock_ctrl_b : clock_ctrl
generic map (
xtal_div_3_g => xtal_div_3_g
)
port map (
clk_i => clk_i,
xtal_i => xtal_i,
res_i => reset_i,
en_clk_i => en_clk_s,
xtal3_o => xtal3_s,
multi_cycle_i => clk_multi_cycle_s,
assert_psen_i => clk_assert_psen_s,
assert_prog_i => clk_assert_prog_s,
assert_rd_i => clk_assert_rd_s,
assert_wr_i => clk_assert_wr_s,
mstate_o => clk_mstate_s,
second_cycle_o => clk_second_cycle_s,
ale_o => ale_s,
psen_o => psen_s,
prog_o => prog_s,
rd_o => rd_s,
wr_o => wr_s
);
 
cond_branch_b : cond_branch
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
compute_take_i => cnd_compute_take_s,
branch_cond_i => cnd_branch_cond_s,
take_branch_o => cnd_take_branch_s,
accu_i => alu_data_s,
t0_i => To_X01Z(t0_i),
t1_i => To_X01Z(t1_i),
int_n_i => int_n_i,
f0_i => psw_f0_s,
f1_i => cnd_f1_s,
tf_i => cnd_tf_s,
carry_i => psw_carry_s,
comp_value_i => cnd_comp_value_s
);
 
use_db_bus: if include_bus_g = 1 generate
db_bus_b : db_bus
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
ea_i => ea_i,
data_i => t48_data_s,
data_o => bus_data_s,
write_bus_i => bus_write_bus_s,
read_bus_i => bus_read_bus_s,
output_pcl_i => bus_output_pcl_s,
bidir_bus_i => bus_bidir_bus_s,
pcl_i => pmem_addr_s(word_t'range),
db_i => db_i,
db_o => db_o,
db_dir_o => db_dir_o
);
end generate;
 
skip_db_bus: if include_bus_g = 0 generate
bus_data_s <= (others => bus_idle_level_c);
db_o <= (others => '0');
db_dir_o <= '0';
end generate;
 
decoder_b : decoder
generic map (
register_mnemonic_g => register_mnemonic_g
)
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
ea_i => ea_i,
ale_i => ale_s,
int_n_i => int_n_i,
t0_dir_o => t0_dir_o,
data_i => t48_data_s,
data_o => dec_data_s,
alu_write_accu_o => alu_write_accu_s,
alu_write_shadow_o => alu_write_shadow_s,
alu_write_temp_reg_o => alu_write_temp_reg_s,
alu_read_alu_o => alu_read_alu_s,
bus_write_bus_o => bus_write_bus_s,
bus_read_bus_o => bus_read_bus_s,
dm_write_dmem_addr_o => dm_write_dmem_addr_s,
dm_write_dmem_o => dm_write_dmem_s,
dm_read_dmem_o => dm_read_dmem_s,
p1_write_p1_o => p1_write_p1_s,
p1_read_p1_o => p1_read_p1_s,
pm_write_pcl_o => pm_write_pcl_s,
p2_write_p2_o => p2_write_p2_s,
p2_write_exp_o => p2_write_exp_s,
p2_read_p2_o => p2_read_p2_s,
pm_read_pcl_o => pm_read_pcl_s,
pm_write_pch_o => pm_write_pch_s,
pm_read_pch_o => pm_read_pch_s,
pm_read_pmem_o => pm_read_pmem_s,
psw_read_psw_o => psw_read_psw_s,
psw_read_sp_o => psw_read_sp_s,
psw_write_psw_o => psw_write_psw_s,
psw_write_sp_o => psw_write_sp_s,
alu_carry_i => alu_carry_s,
alu_op_o => alu_op_s,
alu_use_carry_o => alu_use_carry_s,
alu_da_high_o => alu_da_high_s,
alu_da_overflow_i => alu_da_overflow_s,
alu_accu_low_o => alu_accu_low_s,
alu_p06_temp_reg_o => alu_p06_temp_reg_s,
alu_p60_temp_reg_o => alu_p60_temp_reg_s,
bus_output_pcl_o => bus_output_pcl_s,
bus_bidir_bus_o => bus_bidir_bus_s,
clk_multi_cycle_o => clk_multi_cycle_s,
clk_assert_psen_o => clk_assert_psen_s,
clk_assert_prog_o => clk_assert_prog_s,
clk_assert_rd_o => clk_assert_rd_s,
clk_assert_wr_o => clk_assert_wr_s,
clk_mstate_i => clk_mstate_s,
clk_second_cycle_i => clk_second_cycle_s,
cnd_compute_take_o => cnd_compute_take_s,
cnd_branch_cond_o => cnd_branch_cond_s,
cnd_take_branch_i => cnd_take_branch_s,
cnd_comp_value_o => cnd_comp_value_s,
cnd_f1_o => cnd_f1_s,
cnd_tf_o => cnd_tf_s,
dm_addr_type_o => dm_addr_type_s,
tim_read_timer_o => tim_read_timer_s,
tim_write_timer_o => tim_write_timer_s,
tim_start_t_o => tim_start_t_s,
tim_start_cnt_o => tim_start_cnt_s,
tim_stop_tcnt_o => tim_stop_tcnt_s,
p1_read_reg_o => p1_read_reg_s,
p2_read_reg_o => p2_read_reg_s,
p2_read_exp_o => p2_read_exp_s,
p2_output_pch_o => p2_output_pch_s,
p2_output_exp_o => p2_output_exp_s,
pm_inc_pc_o => pm_inc_pc_s,
pm_write_pmem_addr_o => pm_write_pmem_addr_s,
pm_addr_type_o => pm_addr_type_s,
psw_special_data_o => psw_special_data_s,
psw_carry_i => psw_carry_s,
psw_aux_carry_i => psw_aux_carry_s,
psw_f0_i => psw_f0_s,
psw_inc_stackp_o => psw_inc_stackp_s,
psw_dec_stackp_o => psw_dec_stackp_s,
psw_write_carry_o => psw_write_carry_s,
psw_write_aux_carry_o => psw_write_aux_carry_s,
psw_write_f0_o => psw_write_f0_s,
psw_write_bs_o => psw_write_bs_s,
tim_overflow_i => tim_overflow_s
);
 
dmem_ctrl_b : dmem_ctrl
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
write_dmem_addr_i => dm_write_dmem_addr_s,
write_dmem_i => dm_write_dmem_s,
read_dmem_i => dm_read_dmem_s,
addr_type_i => dm_addr_type_s,
bank_select_i => psw_bs_s,
data_o => dm_data_s,
dmem_data_i => dmem_data_i,
dmem_addr_o => dmem_addr_o,
dmem_we_o => dmem_we_o,
dmem_data_o => dmem_data_o
);
 
use_timer: if include_timer_g = 1 generate
timer_b : timer
generic map (
sample_t1_state_g => sample_t1_state_g
)
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
t1_i => To_X01Z(t1_i),
clk_mstate_i => clk_mstate_s,
data_i => t48_data_s,
data_o => tim_data_s,
read_timer_i => tim_read_timer_s,
write_timer_i => tim_write_timer_s,
start_t_i => tim_start_t_s,
start_cnt_i => tim_start_cnt_s,
stop_tcnt_i => tim_stop_tcnt_s,
overflow_o => tim_of_s
);
end generate;
 
skip_timer: if include_timer_g = 0 generate
tim_data_s <= (others => bus_idle_level_c);
tim_of_s <= '0';
end generate;
 
tim_overflow_s <= to_boolean(tim_of_s);
 
use_p1: if include_port1_g = 1 generate
p1_b : p1
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
data_o => p1_data_s,
write_p1_i => p1_write_p1_s,
read_p1_i => p1_read_p1_s,
read_reg_i => p1_read_reg_s,
p1_i => p1_i,
p1_o => p1_o,
p1_low_imp_o => p1_low_imp_o
);
end generate;
 
skip_p1: if include_port1_g = 0 generate
p1_data_s <= (others => bus_idle_level_c);
p1_o <= (others => '0');
p1_low_imp_o <= '0';
end generate;
 
use_p2: if include_port2_g = 1 generate
p2_b : p2
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
data_o => p2_data_s,
write_p2_i => p2_write_p2_s,
write_exp_i => p2_write_exp_s,
read_p2_i => p2_read_p2_s,
read_reg_i => p2_read_reg_s,
read_exp_i => p2_read_exp_s,
output_pch_i => p2_output_pch_s,
output_exp_i => p2_output_exp_s,
pch_i => pmem_addr_s(11 downto 8),
p2_i => p2_i,
p2_o => p2_o,
p2_low_imp_o => p2_low_imp_o
);
end generate;
 
skip_p2: if include_port2_g = 0 generate
p2_data_s <= (others => bus_idle_level_c);
p2_o <= (others => '0');
p2_low_imp_o <= '0';
end generate;
 
pmem_ctrl_b : pmem_ctrl
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
data_o => pm_data_s,
write_pcl_i => pm_write_pcl_s,
read_pcl_i => pm_read_pcl_s,
write_pch_i => pm_write_pch_s,
read_pch_i => pm_read_pch_s,
inc_pc_i => pm_inc_pc_s,
write_pmem_addr_i => pm_write_pmem_addr_s,
addr_type_i => pm_addr_type_s,
read_pmem_i => pm_read_pmem_s,
pmem_addr_o => pmem_addr_s,
pmem_data_i => pmem_data_i
);
 
psw_b : psw
port map (
clk_i => clk_i,
res_i => reset_i,
en_clk_i => en_clk_s,
data_i => t48_data_s,
data_o => psw_data_s,
read_psw_i => psw_read_psw_s,
read_sp_i => psw_read_sp_s,
write_psw_i => psw_write_psw_s,
write_sp_i => psw_write_sp_s,
special_data_i => psw_special_data_s,
inc_stackp_i => psw_inc_stackp_s,
dec_stackp_i => psw_dec_stackp_s,
write_carry_i => psw_write_carry_s,
write_aux_carry_i => psw_write_aux_carry_s,
write_f0_i => psw_write_f0_s,
write_bs_i => psw_write_bs_s,
carry_o => psw_carry_s,
aux_carry_i => alu_aux_carry_s,
aux_carry_o => psw_aux_carry_s,
f0_o => psw_f0_s,
bs_o => psw_bs_s
);
 
 
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
ale_o <= to_stdLogic(ale_s);
t0_o <= clk_i;
psen_n_o <= to_stdLogic(not psen_s);
prog_n_o <= to_stdLogic(not prog_s);
rd_n_o <= to_stdLogic(not rd_s);
wr_n_o <= to_stdLogic(not wr_s);
xtal3_o <= to_stdLogic(xtal3_s);
pmem_addr_o <= pmem_addr_s;
 
end struct;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.6 2004/04/07 22:09:03 arniml
-- remove unused signals
--
-- Revision 1.5 2004/04/04 14:18:53 arniml
-- add measures to implement XCHD
--
-- Revision 1.4 2004/03/29 19:39:58 arniml
-- rename pX_limp to pX_low_imp
--
-- Revision 1.3 2004/03/28 21:27:50 arniml
-- update wiring for DA support
--
-- Revision 1.2 2004/03/28 13:13:20 arniml
-- connect control signal for Port 2 expander
--
-- Revision 1.1 2004/03/23 21:31:53 arniml
-- initial check-in
--
-------------------------------------------------------------------------------
/vhdl/decoder.vhd
0,0 → 1,1919
-------------------------------------------------------------------------------
--
-- The Decoder unit.
-- It decodes the instruction opcodes and executes them.
--
-- $Id: decoder.vhd,v 1.10 2004-04-25 16:22:03 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_t;
use work.t48_pack.mstate_t;
use work.alu_pack.alu_op_t;
use work.cond_branch_pack.all;
use work.dmem_ctrl_pack.all;
use work.pmem_ctrl_pack.all;
 
entity decoder is
 
generic (
-- store mnemonic in flip-flops (registered-out)
register_mnemonic_g : integer := 1
);
 
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
ea_i : in std_logic;
ale_i : in boolean;
int_n_i : in std_logic;
t0_dir_o : out std_logic;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
stack_high_o : out boolean;
alu_write_accu_o : out boolean;
alu_write_shadow_o : out boolean;
alu_write_temp_reg_o : out boolean;
alu_read_alu_o : out boolean;
bus_write_bus_o : out boolean;
bus_read_bus_o : out boolean;
dm_write_dmem_addr_o : out boolean;
dm_write_dmem_o : out boolean;
dm_read_dmem_o : out boolean;
p1_write_p1_o : out boolean;
p1_read_p1_o : out boolean;
p2_write_p2_o : out boolean;
p2_write_exp_o : out boolean;
p2_read_p2_o : out boolean;
p2_read_exp_o : out boolean;
pm_write_pcl_o : out boolean;
pm_read_pcl_o : out boolean;
pm_write_pch_o : out boolean;
pm_read_pch_o : out boolean;
pm_read_pmem_o : out boolean;
psw_read_psw_o : out boolean;
psw_read_sp_o : out boolean;
psw_write_psw_o : out boolean;
psw_write_sp_o : out boolean;
-- ALU Interface ----------------------------------------------------------
alu_carry_i : in std_logic;
alu_op_o : out alu_op_t;
alu_use_carry_o : out boolean;
alu_da_high_o : out boolean;
alu_accu_low_o : out boolean;
alu_p06_temp_reg_o : out boolean;
alu_p60_temp_reg_o : out boolean;
alu_da_overflow_i : in boolean;
-- BUS Interface ----------------------------------------------------------
bus_output_pcl_o : out boolean;
bus_bidir_bus_o : out boolean;
-- Clock Controller Interface ---------------------------------------------
clk_multi_cycle_o : out boolean;
clk_assert_psen_o : out boolean;
clk_assert_prog_o : out boolean;
clk_assert_rd_o : out boolean;
clk_assert_wr_o : out boolean;
clk_mstate_i : in mstate_t;
clk_second_cycle_i : in boolean;
-- Conditional Branch Logic Interface -------------------------------------
cnd_compute_take_o : out boolean;
cnd_branch_cond_o : out branch_conditions_t;
cnd_take_branch_i : in boolean;
cnd_comp_value_o : out comp_value_t;
cnd_f1_o : out std_logic;
cnd_tf_o : out std_logic;
-- Data Memory Controller Interface ---------------------------------------
dm_addr_type_o : out dmem_addr_ident_t;
-- Port 1 Interface -------------------------------------------------------
p1_read_reg_o : out boolean;
-- Port 2 Interface -------------------------------------------------------
p2_read_reg_o : out boolean;
p2_output_pch_o : out boolean;
p2_output_exp_o : out boolean;
-- Program Memory Controller Interface ------------------------------------
pm_inc_pc_o : out boolean;
pm_write_pmem_addr_o : out boolean;
pm_addr_type_o : out pmem_addr_ident_t;
-- Program Status Word Interface ------------------------------------------
psw_special_data_o : out std_logic;
psw_carry_i : in std_logic;
psw_aux_carry_i : in std_logic;
psw_f0_i : in std_logic;
psw_inc_stackp_o : out boolean;
psw_dec_stackp_o : out boolean;
psw_write_carry_o : out boolean;
psw_write_aux_carry_o : out boolean;
psw_write_f0_o : out boolean;
psw_write_bs_o : out boolean;
-- Timer Interface --------------------------------------------------------
tim_read_timer_o : out boolean;
tim_write_timer_o : out boolean;
tim_start_t_o : out boolean;
tim_start_cnt_o : out boolean;
tim_stop_tcnt_o : out boolean;
tim_overflow_i : in boolean
);
 
end decoder;
 
 
use work.t48_pack.all;
use work.alu_pack.all;
use work.decoder_pack.all;
 
use work.t48_comp_pack.opc_decoder;
use work.t48_comp_pack.int;
 
-- pragma translate_off
use work.t48_tb_pack.tb_istrobe_s;
-- pragma translate_on
 
architecture rtl of decoder is
 
-- Opcode Decoder
signal opc_multi_cycle_s : boolean;
signal opc_read_bus_s : boolean;
signal opc_inj_int_s : boolean;
signal opc_opcode_s : word_t;
signal opc_mnemonic_s : mnemonic_t;
signal last_cycle_s : boolean;
 
-- state translators
signal assert_psen_s : boolean;
 
-- branch taken handshake
signal branch_taken_s,
branch_taken_q : boolean;
signal pm_inc_pc_s : boolean;
signal pm_write_pmem_addr_s : boolean;
-- additional signal to increment PC during CALL
signal add_inc_pc_s : boolean;
-- addtional signal to set PC during RET(R)
signal add_write_pmem_addr_s : boolean;
 
-- Flag 1
signal clear_f1_s,
cpl_f1_s : boolean;
signal f1_q : std_logic;
-- memory bank select
signal clear_mb_s,
set_mb_s : boolean;
signal mb_q : std_logic;
 
-- T0 direction selection
signal ent0_clk_s : boolean;
signal t0_dir_q : std_logic;
 
signal data_s : word_t;
signal read_dec_s : boolean;
 
signal tf_s : std_logic;
 
signal bus_read_bus_s : boolean;
signal add_read_bus_s : boolean;
 
signal dm_write_dmem_s : boolean;
 
-- interrupt handling
signal jtf_executed_s : boolean;
signal en_tcnti_s : boolean;
signal dis_tcnti_s : boolean;
signal en_i_s : boolean;
signal dis_i_s : boolean;
signal tim_int_s : boolean;
signal retr_executed_s : boolean;
signal int_executed_s : boolean;
signal int_pending_s : boolean;
 
-- pragma translate_off
signal istrobe_res_q : std_logic;
signal istrobe_q : std_logic;
signal injected_int_q : std_logic;
-- pragma translate_on
 
begin
 
-----------------------------------------------------------------------------
-- Opcode Decoder
-----------------------------------------------------------------------------
opc_decoder_b : opc_decoder
generic map (
register_mnemonic_g => register_mnemonic_g
)
port map (
clk_i => clk_i,
res_i => res_i,
en_clk_i => en_clk_i,
data_i => data_i,
read_bus_i => opc_read_bus_s,
inj_int_i => opc_inj_int_s,
opcode_o => opc_opcode_s,
mnemonic_o => opc_mnemonic_s,
multi_cycle_o => opc_multi_cycle_s
);
 
 
-----------------------------------------------------------------------------
-- Interrupt Controller.
-----------------------------------------------------------------------------
int_b : int
port map (
clk_i => clk_i,
res_i => res_i,
en_clk_i => en_clk_i,
clk_mstate_i => clk_mstate_i,
jtf_executed_i => jtf_executed_s,
tim_overflow_i => tim_overflow_i,
tf_o => tf_s,
en_tcnti_i => en_tcnti_s,
dis_tcnti_i => dis_tcnti_s,
int_n_i => int_n_i,
ale_i => ale_i,
last_cycle_i => last_cycle_s,
en_i_i => en_i_s,
dis_i_i => dis_i_s,
ext_int_o => open,
tim_int_o => tim_int_s,
retr_executed_i => retr_executed_s,
int_executed_i => int_executed_s,
int_pending_o => int_pending_s
);
 
last_cycle_s <= not opc_multi_cycle_s or
(opc_multi_cycle_s and clk_second_cycle_i);
 
-----------------------------------------------------------------------------
-- Process machine_cycle
--
-- Purpose:
-- Generates the control signals that are basically needed for the
-- handling of a machine cycle.
--
machine_cycle: process (clk_mstate_i,
clk_second_cycle_i,
last_cycle_s,
ea_i,
assert_psen_s,
branch_taken_q,
int_pending_s)
 
variable need_address_v : boolean;
 
begin
-- default assignments
clk_assert_psen_o <= false;
pm_inc_pc_s <= false;
pm_write_pmem_addr_s <= false;
pm_read_pmem_o <= false;
bus_output_pcl_o <= false;
p2_output_pch_o <= false;
opc_read_bus_s <= false;
opc_inj_int_s <= false;
bus_read_bus_s <= false;
 
need_address_v := not clk_second_cycle_i or
(clk_second_cycle_i and assert_psen_s);
 
case clk_mstate_i is
when MSTATE1 =>
if need_address_v and not int_pending_s then
if ea_i = '0' then
pm_read_pmem_o <= true;
else
bus_read_bus_s <= true;
p2_output_pch_o <= true;
end if;
end if;
 
if not clk_second_cycle_i then
if not int_pending_s then
opc_read_bus_s <= true;
else
opc_inj_int_s <= true; -- inject interrupt call
end if;
end if;
 
when MSTATE2 =>
if need_address_v and not branch_taken_q and
not int_pending_s then
pm_inc_pc_s <= true;
end if;
 
when MSTATE3 =>
if need_address_v then
pm_write_pmem_addr_s <= true;
end if;
 
if ea_i = '1' and
(need_address_v and last_cycle_s) then
bus_output_pcl_o <= true;
end if;
 
when MSTATE4 =>
if ea_i = '1' and
(need_address_v or last_cycle_s) then
clk_assert_psen_o <= true;
p2_output_pch_o <= true;
bus_output_pcl_o <= true;
end if;
 
when MSTATE5 =>
if ea_i = '1' and
(need_address_v and last_cycle_s) then
clk_assert_psen_o <= true;
p2_output_pch_o <= true;
end if;
 
when others =>
-- pragma translate_off
assert false
report "Unkown machine state!"
severity error;
-- pragma translate_on
 
end case;
 
end process machine_cycle;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process decode
--
-- Purpose:
-- Indentifies each single instruction and steps through the related
-- execution sequence.
--
decode: process (alu_carry_i,
psw_aux_carry_i,
alu_da_overflow_i,
clk_mstate_i,
clk_second_cycle_i,
cnd_take_branch_i,
opc_opcode_s,
opc_mnemonic_s,
psw_carry_i,
psw_f0_i,
f1_q,
mb_q,
tim_int_s,
int_pending_s)
 
procedure address_indirect_3_f is
begin
-- apply dmem address from selected register for indirect mode
if opc_opcode_s(3) = '0' then
dm_read_dmem_o <= true;
dm_write_dmem_addr_o <= true;
dm_addr_type_o <= DM_PLAIN;
end if;
end;
 
procedure and_or_xor_add_4_f is
begin
-- write dmem contents to Temp Reg
dm_read_dmem_o <= true;
alu_write_temp_reg_o <= true;
end;
 
procedure and_or_xor_add_5_f (alu_op : alu_op_t) is
begin
-- perform ALU operation and store in Accumulator
alu_op_o <= alu_op;
alu_read_alu_o <= true;
alu_write_accu_o <= true;
end;
 
procedure cond_jump_c2_m1_f is
begin
-- store address in Program Counter low byte if branch has to
-- be taken
if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
pm_write_pcl_o <= true;
branch_taken_s <= true;
end if;
end;
 
begin
-- default assignments
data_s <= (others => '-');
read_dec_s <= false;
branch_taken_s <= false;
clear_f1_s <= false;
cpl_f1_s <= false;
clear_mb_s <= false;
set_mb_s <= false;
add_inc_pc_s <= false;
assert_psen_s <= false;
stack_high_o <= false;
alu_write_accu_o <= false;
alu_write_shadow_o <= false;
alu_write_temp_reg_o <= false;
alu_p06_temp_reg_o <= false;
alu_p60_temp_reg_o <= false;
alu_read_alu_o <= false;
bus_write_bus_o <= false;
bus_bidir_bus_o <= false;
dm_write_dmem_addr_o <= false;
dm_write_dmem_s <= false;
dm_read_dmem_o <= false;
pm_write_pcl_o <= false;
pm_read_pcl_o <= false;
pm_write_pch_o <= false;
pm_read_pch_o <= false;
pm_addr_type_o <= PM_PC;
psw_read_psw_o <= false;
psw_read_sp_o <= false;
psw_write_psw_o <= false;
psw_write_sp_o <= false;
alu_op_o <= ALU_NOP;
alu_use_carry_o <= false;
alu_da_high_o <= false;
alu_accu_low_o <= false;
clk_assert_prog_o <= false;
clk_assert_rd_o <= false;
clk_assert_wr_o <= false;
cnd_branch_cond_o <= COND_ON_BIT;
cnd_compute_take_o <= false;
cnd_comp_value_o <= opc_opcode_s(7 downto 5);
dm_addr_type_o <= DM_REG;
tim_read_timer_o <= false;
tim_write_timer_o <= false;
tim_start_t_o <= false;
tim_start_cnt_o <= false;
tim_stop_tcnt_o <= false;
p1_write_p1_o <= false;
p1_read_p1_o <= false;
p1_read_reg_o <= false;
p2_write_p2_o <= false;
p2_write_exp_o <= false;
p2_read_p2_o <= false;
p2_read_reg_o <= false;
p2_read_exp_o <= false;
p2_output_exp_o <= false;
psw_special_data_o <= '0';
psw_inc_stackp_o <= false;
psw_dec_stackp_o <= false;
psw_write_carry_o <= false;
psw_write_aux_carry_o <= false;
psw_write_f0_o <= false;
psw_write_bs_o <= false;
jtf_executed_s <= false;
en_tcnti_s <= false;
dis_tcnti_s <= false;
en_i_s <= false;
dis_i_s <= false;
retr_executed_s <= false;
int_executed_s <= false;
add_write_pmem_addr_s <= false;
ent0_clk_s <= false;
add_read_bus_s <= false;
 
-- prepare potential register indirect address mode
if not clk_second_cycle_i and clk_mstate_i = MSTATE2 then
data_s <= (others => '0');
if opc_opcode_s(3) = '1' then
data_s(2 downto 0) <= opc_opcode_s(2 downto 0);
else
data_s(2 downto 0) <= "00" & opc_opcode_s(0);
end if;
 
read_dec_s <= true;
dm_write_dmem_addr_o <= true;
dm_addr_type_o <= DM_REG;
end if;
 
case opc_mnemonic_s is
 
-- Mnemonic ADD ---------------------------------------------------------
when MN_ADD =>
case clk_mstate_i is
-- read RAM once for indirect address mode
when MSTATE3 =>
address_indirect_3_f;
 
-- store data from RAM to Temp Reg
when MSTATE4 =>
and_or_xor_add_4_f;
 
-- perform ADD and store in Accumulator
when MSTATE5 =>
and_or_xor_add_5_f(alu_op => ALU_ADD);
 
if opc_opcode_s(4) = '1' then
alu_use_carry_o <= true;
end if;
 
psw_special_data_o <= alu_carry_i;
psw_write_carry_o <= true;
psw_write_aux_carry_o <= true;
 
when others =>
null;
 
end case;
 
-- Mnemonic ADD_A_DATA --------------------------------------------------
when MN_ADD_A_DATA =>
assert_psen_s <= true;
 
if clk_second_cycle_i then
case clk_mstate_i is
-- write Temp Reg when contents of Program Memory is on bus
when MSTATE1 =>
alu_write_temp_reg_o <= true;
 
-- perform ADD and store in Accumulator
when MSTATE3 =>
and_or_xor_add_5_f(alu_op => ALU_ADD);
 
if opc_opcode_s(4) = '1' then
alu_use_carry_o <= true;
end if;
 
psw_special_data_o <= alu_carry_i;
psw_write_carry_o <= true;
psw_write_aux_carry_o <= true;
 
when others =>
null;
 
end case;
 
end if;
 
-- Mnemonic ANL ---------------------------------------------------------
when MN_ANL =>
case clk_mstate_i is
-- read RAM once for indirect address mode
when MSTATE3 =>
address_indirect_3_f;
 
-- store data from RAM to Temp Reg
when MSTATE4 =>
and_or_xor_add_4_f;
 
-- perform AND and store in Accumulator
when MSTATE5 =>
and_or_xor_add_5_f(alu_op => ALU_AND);
 
when others =>
null;
 
end case;
 
-- Mnemonic ANL_A_DATA --------------------------------------------------
when MN_ANL_A_DATA =>
assert_psen_s <= true;
 
if clk_second_cycle_i then
case clk_mstate_i is
-- write Temp Reg when contents of Program Memory is on bus
when MSTATE1 =>
alu_write_temp_reg_o <= true;
 
-- perform AND and store in Accumulator
when MSTATE3 =>
and_or_xor_add_5_f(alu_op => ALU_AND);
 
when others =>
null;
 
end case;
 
end if;
 
-- Mnemonic ANL_EXT -----------------------------------------------------
when MN_ANL_EXT =>
assert_psen_s <= true;
 
if not clk_second_cycle_i then
-- read port to Temp Reg
if clk_mstate_i = MSTATE5 then
if opc_opcode_s(1 downto 0) = "00" then
add_read_bus_s <= true;
elsif opc_opcode_s(1) = '0' then
p1_read_p1_o <= true;
p1_read_reg_o <= true;
else
p2_read_p2_o <= true;
p2_read_reg_o <= true;
end if;
 
alu_write_temp_reg_o <= true;
end if;
 
else
case clk_mstate_i is
-- write shadow Accumulator when contents of Program Memory is
-- on bus
when MSTATE1 =>
alu_write_shadow_o <= true;
 
-- loop shadow Accumulator through ALU to prevent update from
-- real Accumulator
when MSTATE2 =>
alu_read_alu_o <= true;
alu_write_shadow_o <= true;
 
-- write result of AND operation back to port
when MSTATE3 =>
alu_op_o <= ALU_AND;
alu_read_alu_o <= true;
 
if opc_opcode_s(1 downto 0) = "00" then
bus_write_bus_o <= true;
elsif opc_opcode_s(1) = '0' then
p1_write_p1_o <= true;
else
p2_write_p2_o <= true;
end if;
 
when others =>
null;
 
end case;
 
end if;
 
-- Mnemonic CALL --------------------------------------------------------
when MN_CALL =>
assert_psen_s <= true;
 
if not clk_second_cycle_i then
case clk_mstate_i is
-- read Stack Pointer and address Data Memory for low byte
-- also increment Program Counter to point to next instruction
when MSTATE3 =>
psw_read_sp_o <= true;
dm_write_dmem_addr_o <= true;
dm_addr_type_o <= DM_STACK;
 
-- only increment PC if this is not an injected CALL
-- injected CALLS are not located in Program Memory,
-- the PC points already to the instruction to be executed
-- after the interrupt
if not int_pending_s then
add_inc_pc_s <= true;
end if;
 
-- store Program Counter low byte on stack
when MSTATE4 =>
pm_read_pcl_o <= true;
dm_write_dmem_s <= true;
 
-- store Program Counter high byte and PSW on stack
-- increment Stack pointer
when MSTATE5 =>
psw_read_psw_o <= true;
pm_read_pch_o <= true;
dm_write_dmem_addr_o <= true;
dm_addr_type_o <= DM_STACK_HIGH;
dm_write_dmem_s <= true;
psw_inc_stackp_o <= true;
 
when others =>
null;
 
end case;
 
else
case clk_mstate_i is
-- store address in Program Counter low byte
when MSTATE1 =>
pm_write_pcl_o <= true;
branch_taken_s <= true;
if int_pending_s then
-- apply low part of vector address manually
data_s <= (others => '0');
data_s(1 downto 0) <= "11";
if tim_int_s then
data_s(2) <= '1';
end if;
read_dec_s <= true;
end if;
 
when MSTATE2 =>
pm_write_pch_o <= true;
read_dec_s <= true;
if not int_pending_s then
-- store high part of target address in Program Counter
data_s <= "0000" & mb_q & opc_opcode_s(7 downto 5);
else
-- apply high part of vector address manually
data_s <= (others => '0');
int_executed_s <= true;
end if;
 
when others =>
null;
 
end case;
 
end if;
 
-- Mnemonic CLR_A -------------------------------------------------------
when MN_CLR_A =>
-- write CLR output of ALU to Accumulator
if clk_mstate_i = MSTATE3 then
alu_op_o <= ALU_CLR;
alu_read_alu_o <= true;
alu_write_accu_o <= true;
end if;
 
-- Mnemonic CLR_C -------------------------------------------------------
when MN_CLR_C =>
-- store 0 to Carry
if clk_mstate_i = MSTATE3 then
psw_special_data_o <= '0';
psw_write_carry_o <= true;
end if;
 
-- Mnemonic CLR_F -------------------------------------------------------
when MN_CLR_F =>
-- store 0 to selected flag
if clk_mstate_i = MSTATE3 then
if opc_opcode_s(5) = '0' then
psw_special_data_o <= '0';
psw_write_f0_o <= true;
else
clear_f1_s <= true;
end if;
 
end if;
 
-- Mnemonic CPL_A -------------------------------------------------------
when MN_CPL_A =>
-- write CPL output of ALU to Accumulator
if clk_mstate_i = MSTATE3 then
alu_op_o <= ALU_CPL;
alu_read_alu_o <= true;
alu_write_accu_o <= true;
end if;
 
-- Mnemnonic CPL_C ------------------------------------------------------
when MN_CPL_C =>
-- write inverse of Carry to PSW
if clk_mstate_i = MSTATE3 then
psw_special_data_o <= not psw_carry_i;
psw_write_carry_o <= true;
end if;
 
-- Mnemonic CPL_F -------------------------------------------------------
when MN_CPL_f =>
-- write inverse of selected flag back to flag
if clk_mstate_i = MSTATE3 then
if opc_opcode_s(5) = '0' then
psw_special_data_o <= not psw_f0_i;
psw_write_f0_o <= true;
else
cpl_f1_s <= true;
end if;
 
end if;
 
-- Mnemonic DA ----------------------------------------------------------
when MN_DA =>
alu_op_o <= ALU_ADD;
 
case clk_mstate_i is
-- Step 1: Preload Temp Reg with 0x06
when MSTATE3 =>
alu_p06_temp_reg_o <= true;
 
-- Step 2: Check Auxiliary Carry and overflow on low nibble
-- Add 0x06 to shadow Accumulator if one is true
when MSTATE4 =>
if psw_aux_carry_i = '1' or alu_da_overflow_i then
alu_read_alu_o <= true;
alu_write_shadow_o <= true;
end if;
 
-- preload Temp Reg with 0x60
alu_p60_temp_reg_o <= true;
 
-- Step 3: Check overflow on high nibble
-- Add 0x60 to shadow Accumulator if true and store result
-- in Accumulator and PSW (only Carry)
when MSTATE5 =>
alu_da_high_o <= true;
 
if alu_da_overflow_i then
psw_special_data_o <= alu_carry_i;
else
alu_op_o <= ALU_NOP;
psw_special_data_o <= '0';
end if;
alu_read_alu_o <= true;
alu_write_accu_o <= true;
psw_write_carry_o <= true;
 
when others =>
null;
 
end case;
 
-- Mnemonic DEC ---------------------------------------------------------
when MN_DEC =>
case clk_mstate_i is
when MSTATE4 =>
-- DEC Rr: store data from RAM to shadow Accumulator
if opc_opcode_s(6) = '1' then
dm_read_dmem_o <= true;
alu_write_shadow_o <= true;
end if;
 
when MSTATE5 =>
alu_op_o <= ALU_DEC;
alu_read_alu_o <= true;
 
if opc_opcode_s(6) = '0' then
-- write DEC of Accumulator to Accumulator
alu_write_accu_o <= true;
else
-- store DEC of shadow Accumulator back to dmem
dm_write_dmem_s <= true;
end if;
 
when others =>
null;
 
end case;
 
-- Mnemonic DIS_EN_I ----------------------------------------------------
when MN_DIS_EN_I =>
if clk_mstate_i = MSTATE3 then
if opc_opcode_s(4) = '1' then
dis_i_s <= true;
else
en_i_s <= true;
end if;
end if;
 
-- Mnemonic DIS_EN_TCNTI ------------------------------------------------
when MN_DIS_EN_TCNTI =>
if clk_mstate_i = MSTATE3 then
if opc_opcode_s(4) = '1' then
dis_tcnti_s <= true;
else
en_tcnti_s <= true;
end if;
end if;
 
-- Mnemonic DJNZ --------------------------------------------------------
when MN_DJNZ =>
assert_psen_s <= true;
 
if not clk_second_cycle_i then
case clk_mstate_i is
-- store data from RAM to shadow Accumulator
when MSTATE4 =>
dm_read_dmem_o <= true;
alu_write_shadow_o <= true;
 
-- write DEC result of shadow Accumulator back to dmem and
-- conditional branch logic
when MSTATE5 =>
alu_op_o <= ALU_DEC;
alu_read_alu_o <= true;
dm_write_dmem_s <= true;
 
cnd_compute_take_o <= true;
cnd_branch_cond_o <= COND_Z;
cnd_comp_value_o(0) <= '0';
 
when others =>
null;
 
end case;
 
else
-- store address in Program Counter low byte if branch has to
-- be taken
cond_jump_c2_m1_f;
 
end if;
 
-- Mnemonic ENT0_CLK ----------------------------------------------------
when MN_ENT0_CLK =>
if clk_mstate_i = MSTATE3 then
ent0_clk_s <= true;
end if;
 
-- Mnemonic IN ----------------------------------------------------------
when MN_IN =>
-- read Port and store in Accumulator
if clk_second_cycle_i and clk_mstate_i = MSTATE2 then
alu_write_accu_o <= true;
 
if opc_opcode_s(1) = '0' then
p1_read_p1_o <= true;
else
p2_read_p2_o <= true;
end if;
end if;
 
-- Mnemonic INS ---------------------------------------------------------
when MN_INS =>
-- read BUS and store in Accumulator
if clk_second_cycle_i and clk_mstate_i = MSTATE2 then
alu_write_accu_o <= true;
 
add_read_bus_s <= true;
end if;
 
-- Mnemonic INC ---------------------------------------------------------
when MN_INC =>
case clk_mstate_i is
-- read RAM once for indirect address mode
when MSTATE3 =>
address_indirect_3_f;
 
when MSTATE4 =>
-- INC Rr; INC @ Rr: store data from RAM to shadow Accumulator
if opc_opcode_s(3 downto 2) /= "01" then
dm_read_dmem_o <= true;
alu_write_shadow_o <= true;
end if;
 
when MSTATE5 =>
alu_op_o <= ALU_INC;
alu_read_alu_o <= true;
 
if opc_opcode_s(3 downto 2) = "01" then
-- write INC output of ALU to Accumulator
alu_write_accu_o <= true;
else
-- store INC of shadow Accumulator back to dmem
dm_write_dmem_s <= true;
end if;
 
when others =>
null;
 
end case;
 
-- Mnemonic JBB ---------------------------------------------------------
when MN_JBB =>
assert_psen_s <= true;
cnd_branch_cond_o <= COND_ON_BIT;
 
if not clk_second_cycle_i then
-- read Accumulator and start branch calculation
if clk_mstate_i = MSTATE3 then
alu_read_alu_o <= true;
cnd_compute_take_o <= true;
-- cnd_comp_value_o is ok by default assignment
end if;
 
else
-- store address in Program Counter low byte if branch has to
-- be taken
cond_jump_c2_m1_f;
 
end if;
 
-- Mnemonic JC ----------------------------------------------------------
when MN_JC =>
assert_psen_s <= true;
cnd_branch_cond_o <= COND_C;
 
if not clk_second_cycle_i then
-- start branch calculation
if clk_mstate_i = MSTATE3 then
cnd_compute_take_o <= true;
cnd_comp_value_o(0) <= opc_opcode_s(4);
end if;
 
else
-- store address in Program Counter low byte if branch has to
-- be taken
cond_jump_c2_m1_f;
 
end if;
 
-- Mnemonic JF ----------------------------------------------------------
when MN_JF =>
assert_psen_s <= true;
 
if not clk_second_cycle_i then
-- start branch calculation
if clk_mstate_i = MSTATE3 then
cnd_compute_take_o <= true;
if opc_opcode_s(7) = '1' then
-- JF0
cnd_branch_cond_o <= COND_F0;
else
-- JF1
cnd_branch_cond_o <= COND_F1;
end if;
 
end if;
 
else
-- store address in Program Counter low byte if branch has to
-- be taken
cond_jump_c2_m1_f;
 
end if;
 
 
-- Mnemonic JMP ---------------------------------------------------------
when MN_JMP =>
assert_psen_s <= true;
 
if clk_second_cycle_i then
case clk_mstate_i is
-- store address in Program Counter low byte
when MSTATE1 =>
pm_write_pcl_o <= true;
branch_taken_s <= true;
 
-- store high part of target address in Program Counter
when MSTATE2 =>
data_s <= "0000" & mb_q & opc_opcode_s(7 downto 5);
read_dec_s <= true;
pm_write_pch_o <= true;
 
 
when others =>
null;
 
end case;
 
end if;
 
-- Mnemonic JMPP --------------------------------------------------------
when MN_JMPP =>
assert_psen_s <= true;
 
if not clk_second_cycle_i then
-- write Accumulator to Program Memory address
-- (skip page offset update from Program Counter)
if clk_mstate_i = MSTATE3 then
alu_read_alu_o <= true;
pm_addr_type_o <= PM_PAGE;
end if;
 
else
if clk_mstate_i = MSTATE1 then
-- store address in Program Counter low byte
pm_write_pcl_o <= true;
branch_taken_s <= true;
end if;
 
end if;
 
-- Mnemonic JNI ---------------------------------------------------------
when MN_JNI =>
assert_psen_s <= true;
cnd_branch_cond_o <= COND_INT;
 
if not clk_second_cycle_i then
-- start branch calculation
if clk_mstate_i = MSTATE3 then
cnd_compute_take_o <= true;
end if;
 
else
-- store address in Program Counter low byte if branch has to
-- be taken
cond_jump_c2_m1_f;
 
end if;
 
-- Mnemonic JT ----------------------------------------------------------
when MN_JT =>
assert_psen_s <= true;
if opc_opcode_s(6) = '0' then
cnd_branch_cond_o <= COND_T0;
else
cnd_branch_cond_o <= COND_T1;
end if;
 
if not clk_second_cycle_i then
-- start branch calculation
if clk_mstate_i = MSTATE3 then
cnd_compute_take_o <= true;
cnd_comp_value_o(0) <= opc_opcode_s(4);
end if;
 
else
-- store address in Program Counter low byte if branch has to
-- be taken
cond_jump_c2_m1_f;
 
end if;
 
-- Mnemonic JTF ---------------------------------------------------------
when MN_JTF =>
assert_psen_s <= true;
cnd_branch_cond_o <= COND_TF;
 
if not clk_second_cycle_i then
-- start branch calculation
if clk_mstate_i = MSTATE3 then
cnd_compute_take_o <= true;
jtf_executed_s <= true;
end if;
 
else
-- store address in Program Counter low byte if branch has to
-- be taken
cond_jump_c2_m1_f;
 
end if;
 
-- Mnemonic JZ ----------------------------------------------------------
when MN_JZ =>
assert_psen_s <= true;
cnd_branch_cond_o <= COND_Z;
 
if not clk_second_cycle_i then
-- read Accumulator and start branch calculation
if clk_mstate_i = MSTATE3 then
alu_read_alu_o <= true;
cnd_compute_take_o <= true;
cnd_comp_value_o(0) <= opc_opcode_s(6);
end if;
 
else
-- store address in Program Counter low byte if branch has to
-- be taken
cond_jump_c2_m1_f;
 
end if;
 
-- Mnemonic MOV_A_DATA --------------------------------------------------
when MN_MOV_A_DATA =>
assert_psen_s <= true;
 
-- Write Accumulator when contents of Program Memory is on bus
-- during machine state 1 of second cycle.
if clk_second_cycle_i and clk_mstate_i = MSTATE1 then
alu_write_accu_o <= true;
end if;
 
-- Mnemonic MOV_A_RR ----------------------------------------------------
when MN_MOV_A_RR =>
case clk_mstate_i is
-- read RAM once for indirect address mode
when MSTATE3 =>
address_indirect_3_f;
 
-- read data from RAM and store in Accumulator
when MSTATE4 =>
and_or_xor_add_4_f;
alu_write_accu_o <= true;
 
when others =>
null;
 
end case;
 
-- Mnemonic MOV_A_PSW ---------------------------------------------------
when MN_MOV_A_PSW =>
if clk_mstate_i = MSTATE3 then
psw_read_psw_o <= true;
psw_read_sp_o <= true;
alu_write_accu_o <= true;
end if;
 
-- Mnemoniv MOV_PSW_A ---------------------------------------------------
when MN_MOV_PSW_A =>
if clk_mstate_i = MSTATE3 then
alu_read_alu_o <= true;
psw_write_psw_o <= true;
psw_write_sp_o <= true;
end if;
 
-- Mnemonic MOV_RR ------------------------------------------------------
when MN_MOV_RR =>
case clk_mstate_i is
-- read RAM once for indirect address mode
when MSTATE3 =>
address_indirect_3_f;
 
-- write Accumulator to dmem
when MSTATE5 =>
alu_read_alu_o <= true;
dm_write_dmem_s <= true;
 
when others =>
null;
 
end case;
 
-- Mnemonic MOV_RR_DATA -------------------------------------------------
when MN_MOV_RR_DATA =>
assert_psen_s <= true;
 
-- read RAM once for indirect address mode
if not clk_second_cycle_i and clk_mstate_i = MSTATE3 then
address_indirect_3_f;
end if;
 
-- Write Data Memory when contents of Program Memory is on bus
-- during machine state 1 of second cycle.
if clk_second_cycle_i and clk_mstate_i = MSTATE1 then
dm_write_dmem_s <= true;
end if;
 
-- Mnemonic MOV_T -------------------------------------------------------
when MN_MOV_T =>
if clk_mstate_i = MSTATE3 then
if opc_opcode_s(5) = '1' then
alu_read_alu_o <= true; -- MOV T, A
tim_write_timer_o <= true;
else
tim_read_timer_o <= true; -- MOV A, T
alu_write_accu_o <= true;
end if;
end if;
 
-- Mnemonic OUTD_PP_A ---------------------------------------------------
when MN_OUTD_PP_A =>
clk_assert_prog_o <= true;
 
if not clk_second_cycle_i then
case clk_mstate_i is
-- propagate expander port number to Port 2
when MSTATE3 =>
 
data_s(7 downto 4) <= (others => '0');
data_s(1 downto 0) <= opc_opcode_s(1 downto 0);
-- decide which 8243 command to use
case opc_opcode_s(7 downto 4) is
when "1001" =>
data_s(3 downto 2) <= "11"; -- ANLD command
when "1000" =>
data_s(3 downto 2) <= "10"; -- ORLD command
when "0011" =>
data_s(3 downto 2) <= "01"; -- MOVD command
when others =>
null;
end case;
read_dec_s <= true;
p2_write_exp_o <= true;
 
-- output expander port number on Port 2 while active edge of PROG
-- write Accumulator to expander port
when MSTATE4 =>
p2_output_exp_o <= true;
 
alu_read_alu_o <= true;
p2_write_exp_o <= true;
 
when MSTATE5 =>
p2_output_exp_o <= true;
 
when others =>
null;
 
end case;
 
else
-- hold expander port until inactive edge of PROG
if clk_mstate_i = MSTATE1 or clk_mstate_i = MSTATE2 then
p2_output_exp_o <= true;
end if;
 
end if;
 
-- Mnemonic MOVD_A_PP ---------------------------------------------------
when MN_MOVD_A_PP =>
clk_assert_prog_o <= true;
 
if not clk_second_cycle_i then
case clk_mstate_i is
-- propagate expander port number to Port 2
when MSTATE3 =>
data_s <= "0000" &
"00" & -- 8243 command: read
opc_opcode_s(1 downto 0);
read_dec_s <= true;
p2_write_exp_o <= true;
 
-- output expander port number on Port 2 while active edge of PROG
-- write 1's to expander port to set lower nibble of Port 2 to input
when MSTATE4 =>
p2_output_exp_o <= true;
 
data_s(nibble_t'range) <= (others => '1');
read_dec_s <= true;
p2_write_exp_o <= true;
 
when MSTATE5 =>
p2_output_exp_o <= true;
 
when others =>
null;
 
end case;
 
else
case clk_mstate_i is
-- hold expander port until inactive edge of PROG
when MSTATE1 =>
p2_output_exp_o <= true;
 
-- hold expander port until inactive edge of PROG
-- write Accumulator with nibble of expander port
when MSTATE2 =>
p2_output_exp_o <= true;
p2_read_exp_o <= true;
alu_write_accu_o <= true;
 
when others =>
null;
 
end case;
 
end if;
 
-- Mnemonic MOVP --------------------------------------------------------
when MN_MOVP =>
assert_psen_s <= true;
 
if not clk_second_cycle_i then
-- write Accumulator to Program Memory address
-- (skip page offset update from Program Counter)
if clk_mstate_i = MSTATE3 then
alu_read_alu_o <= true;
if opc_opcode_s(6) = '0' then
pm_addr_type_o <= PM_PAGE;
else
pm_addr_type_o <= PM_PAGE3;
end if;
end if;
 
else
if clk_mstate_i = MSTATE1 then
-- store data from Program Memory in Accumulator
alu_write_accu_o <= true;
-- trick & treat to prevent additional PC increment
-- our branch target is the previously incremented PC!
branch_taken_s <= true;
end if;
 
end if;
 
-- Mnemonic MOVX --------------------------------------------------------
when MN_MOVX =>
bus_bidir_bus_o <= true;
 
if opc_opcode_s(4) = '0' then
clk_assert_rd_o <= true;
else
clk_assert_wr_o <= true;
end if;
 
if not clk_second_cycle_i then
case clk_mstate_i is
-- read dmem and put contents on BUS as external address
when MSTATE3 =>
dm_read_dmem_o <= true;
bus_write_bus_o <= true;
 
-- store contents of Accumulator to BUS
when MSTATE5 =>
if opc_opcode_s(4) = '1' then
alu_read_alu_o <= true;
bus_write_bus_o <= true;
end if;
 
when others =>
null;
end case;
else
if clk_mstate_i = MSTATE1 then
if opc_opcode_s(4) = '0' then
-- store contents of BUS in Accumulator
add_read_bus_s <= true;
alu_write_accu_o <= true;
else
-- store contents of Accumulator to BUS
alu_read_alu_o <= true;
bus_write_bus_o <= true;
end if;
end if;
 
end if;
 
-- Mnemonic NOP ---------------------------------------------------------
when MN_NOP =>
-- nothing to do
 
-- Mnemonic ORL ---------------------------------------------------------
when MN_ORL =>
case clk_mstate_i is
-- read RAM once for indirect address mode
when MSTATE3 =>
address_indirect_3_f;
 
-- store data from RAM to Temp Reg
when MSTATE4 =>
and_or_xor_add_4_f;
 
-- perform OR and store in Accumulator
when MSTATE5 =>
and_or_xor_add_5_f(alu_op => ALU_OR);
 
when others =>
null;
 
end case;
 
-- Mnemonic ORL_A_DATA --------------------------------------------------
when MN_ORL_A_DATA =>
assert_psen_s <= true;
 
if clk_second_cycle_i then
case clk_mstate_i is
-- write Temp Reg when contents of Program Memory is on bus
when MSTATE1 =>
alu_write_temp_reg_o <= true;
 
-- perform OR and store in Accumulator
when MSTATE3 =>
and_or_xor_add_5_f(alu_op => ALU_OR);
 
when others =>
null;
 
end case;
 
end if;
 
-- Mnemonic ORL_EXT -----------------------------------------------------
when MN_ORL_EXT =>
assert_psen_s <= true;
 
if not clk_second_cycle_i then
-- read port to Temp Reg
if clk_mstate_i = MSTATE5 then
if opc_opcode_s(1 downto 0) = "00" then
add_read_bus_s <= true;
elsif opc_opcode_s(1) = '0' then
p1_read_p1_o <= true;
p1_read_reg_o <= true;
else
p2_read_p2_o <= true;
p2_read_reg_o <= true;
end if;
 
alu_write_temp_reg_o <= true;
end if;
 
else
case clk_mstate_i is
-- write shadow Accumulator when contents of Program Memory is
-- on bus
when MSTATE1 =>
alu_write_shadow_o <= true;
 
-- loop shadow Accumulator through ALU to prevent update from
-- real Accumulator
when MSTATE2 =>
alu_read_alu_o <= true;
alu_write_shadow_o <= true;
 
-- write result of OR operation back to port
when MSTATE3 =>
alu_op_o <= ALU_OR;
alu_read_alu_o <= true;
 
if opc_opcode_s(1 downto 0) = "00" then
bus_write_bus_o <= true;
elsif opc_opcode_s(1) = '0' then
p1_write_p1_o <= true;
else
p2_write_p2_o <= true;
end if;
 
when others =>
null;
 
end case;
 
end if;
 
-- Mnemonic OUTL_EXT ----------------------------------------------------
when MN_OUTL_EXT =>
-- read Accumulator and store in Port/BUS output register
if clk_second_cycle_i and clk_mstate_i = MSTATE4 then
alu_read_alu_o <= true;
 
if opc_opcode_s(4) = '1' then
if opc_opcode_s(1) = '0' then
p1_write_p1_o <= true;
else
p2_write_p2_o <= true;
end if;
 
else
bus_write_bus_o <= true;
 
end if;
 
end if;
 
-- Mnemonic RET ---------------------------------------------------------
when MN_RET =>
if not clk_second_cycle_i then
case clk_mstate_i is
-- decrement Stack Pointer
when MSTATE3 =>
psw_dec_stackp_o <= true;
 
-- read Stack Pointer and address Data Memory for low byte
when MSTATE4 =>
psw_read_sp_o <= true;
dm_write_dmem_addr_o <= true;
dm_addr_type_o <= DM_STACK;
 
-- read Data Memory and store to Program Counter low
-- prepare address to Data memory for high byte
when MSTATE5 =>
dm_read_dmem_o <= true;
pm_write_pcl_o <= true;
dm_write_dmem_addr_o <= true;
dm_addr_type_o <= DM_STACK_HIGH;
 
when others =>
null;
 
end case;
 
else
case clk_mstate_i is
-- read Data Memory and store to Program Counter high and PSW
when MSTATE1 =>
dm_read_dmem_o <= true;
pm_write_pch_o <= true;
if opc_opcode_s(4) = '1' then
psw_write_psw_o <= true;
retr_executed_s <= true;
end if;
 
when MSTATE2 =>
add_write_pmem_addr_s <= true;
 
when others =>
null;
 
end case;
 
end if;
 
-- Mnemonic RL ----------------------------------------------------------
when MN_RL =>
if clk_mstate_i = MSTATE3 then
alu_op_o <= ALU_RL;
alu_read_alu_o <= true;
alu_write_accu_o <= true;
 
if opc_opcode_s(4) = '1' then
psw_special_data_o <= alu_carry_i;
psw_write_carry_o <= true;
alu_use_carry_o <= true;
end if;
end if;
 
-- Mnemonic RR ----------------------------------------------------------
when MN_RR =>
if clk_mstate_i = MSTATE3 then
alu_op_o <= ALU_RR;
alu_read_alu_o <= true;
alu_write_accu_o <= true;
 
if opc_opcode_s(4) = '0' then
psw_special_data_o <= alu_carry_i;
psw_write_carry_o <= true;
alu_use_carry_o <= true;
end if;
end if;
 
-- Mnemonic SEL_MB ------------------------------------------------------
when MN_SEL_MB =>
if clk_mstate_i = MSTATE3 then
if opc_opcode_s(4) = '1' then
set_mb_s <= true;
else
clear_mb_s <= true;
end if;
end if;
 
-- Mnemonic SEL_RB ------------------------------------------------------
when MN_SEL_RB =>
if clk_mstate_i = MSTATE3 then
psw_special_data_o <= opc_opcode_s(4);
psw_write_bs_o <= true;
end if;
 
-- Mnemonic STOP_TCNT ---------------------------------------------------
when MN_STOP_TCNT =>
if clk_mstate_i = MSTATE3 then
tim_stop_tcnt_o <= true;
end if;
 
-- Mnemonic STRT --------------------------------------------------------
when MN_STRT =>
if clk_mstate_i = MSTATE3 then
if opc_opcode_s(4) = '1' then
tim_start_t_o <= true;
else
tim_start_cnt_o <= true;
end if;
end if;
 
-- Mnemonic SWAP --------------------------------------------------------
when MN_SWAP =>
alu_op_o <= ALU_SWAP;
 
if clk_mstate_i = MSTATE3 then
alu_read_alu_o <= true;
alu_write_accu_o <= true;
end if;
 
-- Mnemonic XCH ---------------------------------------------------------
when MN_XCH =>
case clk_mstate_i is
-- read RAM once for indirect address mode
when MSTATE3 =>
address_indirect_3_f;
 
-- store data from RAM in Accumulator and Temp Reg
-- Accumulator is already shadowed!
when MSTATE4 =>
dm_read_dmem_o <= true;
alu_write_accu_o <= true;
alu_write_temp_reg_o <= true;
if opc_opcode_s(4) = '1' then
-- XCHD
-- only write lower nibble of Accumulator
alu_accu_low_o <= true;
end if;
 
-- store data from shadow (previous) Accumulator to dmem
when MSTATE5 =>
dm_write_dmem_s <= true;
alu_read_alu_o <= true;
if opc_opcode_s(4) = '1' then
-- XCHD
-- concatenate shadow Accumulator and Temp Reg
alu_op_o <= ALU_CONCAT;
end if;
 
when others =>
null;
 
end case;
 
-- Mnemonic XRL ---------------------------------------------------------
when MN_XRL =>
case clk_mstate_i is
-- read RAM once for indirect address mode
when MSTATE3 =>
address_indirect_3_f;
 
-- store data from RAM to Temp Reg
when MSTATE4 =>
and_or_xor_add_4_f;
 
-- perform XOR and store in Accumulator
when MSTATE5 =>
and_or_xor_add_5_f(alu_op => ALU_XOR);
 
when others =>
null;
 
end case;
 
-- Mnemonic XRL_A_DATA --------------------------------------------------
when MN_XRL_A_DATA =>
assert_psen_s <= true;
 
if clk_second_cycle_i then
case clk_mstate_i is
-- write Temp Reg when contents of Program Memory is on bus
when MSTATE1 =>
alu_write_temp_reg_o <= true;
 
-- perform XOR and store in Accumulator
when MSTATE3 =>
and_or_xor_add_5_f(alu_op => ALU_XOR);
 
when others =>
null;
 
end case;
 
end if;
 
-- Unimplemented mnemonic -----------------------------------------------
when others =>
-- this will behave like a NOP
 
-- pragma translate_off
assert false
report "Mnemonic not yet implemented."
severity warning;
-- pragma translate_on
 
end case;
 
end process decode;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process regs
--
-- Purpose:
-- Implements the various registes.
--
regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
branch_taken_q <= false;
f1_q <= '0';
mb_q <= '0';
t0_dir_q <= '0';
-- pragma translate_off
istrobe_res_q <= '1';
istrobe_q <= '0';
injected_int_q <= '0';
-- pragma translate_on
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
-- branch taken flag
if branch_taken_s then
branch_taken_q <= true;
elsif clk_mstate_i = MSTATE5 then
-- release flag when new instruction starts
branch_taken_q <= false;
end if;
 
-- Flag 1
if clear_f1_s then
f1_q <= '0';
elsif cpl_f1_s then
f1_q <= not f1_q;
end if;
 
-- Memory Bank select
if clear_mb_s then
mb_q <= '0';
elsif set_mb_s then
mb_q <= '1';
end if;
 
-- T0 direction selection
if ent0_clk_s then
t0_dir_q <= '1';
end if;
 
-- pragma translate_off
-- Marker for injected instruction ------------------------------------
if opc_inj_int_s then
injected_int_q <= '1';
elsif clk_mstate_i = MSTATE5 and last_cycle_s then
injected_int_q <= '0';
end if;
 
-- Remove istrobe after reset suppression -----------------------------
if clk_mstate_i = MSTATE5 and last_cycle_s then
istrobe_res_q <= '0';
end if;
-- pragma translate_on
 
end if;
 
-- pragma translate_off
-- Instruction Strobe ---------------------------------------------------
if clk_mstate_i = MSTATE5 and last_cycle_s and
injected_int_q = '0' then
if istrobe_res_q = '0' then
istrobe_q <= '1';
end if;
else
istrobe_q <= '0';
end if;
-- pragma translate_on
 
end if;
 
end process regs;
--
-----------------------------------------------------------------------------
 
-- pragma translate_off
-- assign to global signal for testbench
tb_istrobe_s <= istrobe_q;
-- pragma translate_on
 
 
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
clk_multi_cycle_o <= opc_multi_cycle_s;
cnd_f1_o <= f1_q;
cnd_tf_o <= tf_s;
data_o <= data_s
when read_dec_s else
(others => bus_idle_level_c);
dm_write_dmem_o <= dm_write_dmem_s and en_clk_i;
pm_inc_pc_o <= pm_inc_pc_s or add_inc_pc_s;
pm_write_pmem_addr_o <= pm_write_pmem_addr_s or add_write_pmem_addr_s;
t0_dir_o <= t0_dir_q;
bus_read_bus_o <= bus_read_bus_s or add_read_bus_s;
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.9 2004/04/24 11:22:55 arniml
-- removed superfluous signal from sensitivity list
--
-- Revision 1.8 2004/04/18 18:57:43 arniml
-- + enhance instruction strobe generation
-- + rework address output under EA=1 conditions
--
-- Revision 1.7 2004/04/15 22:06:05 arniml
-- + add marker for injected calls
-- + suppress intstruction strobes for injected calls
--
-- Revision 1.6 2004/04/14 20:53:33 arniml
-- make istrobe visible through testbench package
--
-- Revision 1.5 2004/04/07 22:09:03 arniml
-- remove unused signals
--
-- Revision 1.4 2004/04/04 14:18:53 arniml
-- add measures to implement XCHD
--
-- Revision 1.3 2004/03/28 21:15:48 arniml
-- implemented mnemonic DA
--
-- Revision 1.2 2004/03/28 13:06:32 arniml
-- implement mnemonics:
-- + MOVD_A_PP
-- + OUTD_PP_A -> ANLD PP, A; MOVD PP, A; ORLD PP, A
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
-------------------------------------------------------------------------------
/vhdl/cond_branch.vhd
0,0 → 1,212
-------------------------------------------------------------------------------
--
-- The Conditional Branch Logic unit.
-- Decisions whether to take a jump or not are made here.
--
-- $Id: cond_branch.vhd,v 1.2 2004-04-24 23:44:25 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_t;
 
use work.cond_branch_pack.all;
 
entity cond_branch is
 
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- Decoder Interface ------------------------------------------------------
compute_take_i : in boolean;
branch_cond_i : in branch_conditions_t;
take_branch_o : out boolean;
accu_i : in word_t;
t0_i : in std_logic;
t1_i : in std_logic;
int_n_i : in std_logic;
f0_i : in std_logic;
f1_i : in std_logic;
tf_i : in std_logic;
carry_i : in std_logic;
comp_value_i : in comp_value_t
);
 
end cond_branch;
 
 
library ieee;
use ieee.numeric_std.all;
 
use work.t48_pack.res_active_c;
use work.t48_pack.clk_active_c;
 
architecture rtl of cond_branch is
 
-- marker for branch taken
signal take_branch_s,
take_branch_q : boolean;
 
begin
 
-----------------------------------------------------------------------------
-- Process decide_take
--
-- Purpose:
-- Decides whether a branch has to be taken or not.
--
decide_take: process (accu_i,
branch_cond_i,
t0_i, t1_i,
int_n_i,
f0_i, f1_i,
tf_i,
carry_i,
comp_value_i)
variable or_v : std_logic;
begin
-- default assignment
take_branch_s <= false;
or_v := '0';
 
case branch_cond_i is
-- Branch On: Accumulator Bit -------------------------------------------
when COND_ON_BIT =>
if accu_i(TO_INTEGER(UNSIGNED(comp_value_i))) = '1' then
take_branch_s <= true;
end if;
 
-- Branch On: Accumulator Zero ------------------------------------------
when COND_Z =>
for i in accu_i'range loop
or_v := or_v or accu_i(i);
end loop;
take_branch_s <= or_v = not comp_value_i(0);
 
-- Branch On: Carry -----------------------------------------------------
when COND_C =>
take_branch_s <= carry_i = comp_value_i(0);
 
-- Branch On: Flag 0 ----------------------------------------------------
when COND_F0 =>
take_branch_s <= f0_i = '1';
 
-- Branch On: Flag 1 ----------------------------------------------------
when COND_F1 =>
take_branch_s <= f1_i = '1';
 
-- Branch On: Interrupt -------------------------------------------------
when COND_INT =>
take_branch_s <= int_n_i = '0';
 
-- Branch On: Test 0 ----------------------------------------------------
when COND_T0 =>
take_branch_s <= t0_i = comp_value_i(0);
 
-- Branch On: Test 1 ----------------------------------------------------
when COND_T1 =>
take_branch_s <= t1_i = comp_value_i(0);
 
-- Branch On: Timer Flag ------------------------------------------------
when COND_TF =>
take_branch_s <= tf_i = '1';
 
when others =>
-- pragma translate_off
assert false
report "Unknown branch condition specified!"
severity error;
-- pragma translate_on
 
end case;
 
end process decide_take;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process reg
--
-- Purpose:
-- Implement the marker register.
--
reg: process (res_i, clk_i)
begin
if res_i = res_active_c then
take_branch_q <= false;
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
if compute_take_i then
take_branch_q <= take_branch_s;
end if;
 
end if;
 
end if;
 
end process reg;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
take_branch_o <= take_branch_q;
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------
/vhdl/system/lpm_rom.vhd
0,0 → 1,437
--------------------------------------------------------------------------
-- This VHDL file was developed by Altera Corporation. It may be
-- freely copied and/or distributed at no cost. Any persons using this
-- file for any purpose do so at their own risk, and are responsible for
-- the results of such use. Altera Corporation does not guarantee that
-- this file is complete, correct, or fit for any particular purpose.
-- NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. This notice must
-- accompany any copy of this file.
--
--------------------------------------------------------------------------
-- LPM Synthesizable Models (Support string type generic)
--------------------------------------------------------------------------
-- Version 2.0 (lpm 220) Date 01/04/00
--
-- 1. Fixed LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO and LPM_ROM to correctly
-- read in values from LPM_FILE (*.hex) when the DATA width is greater
-- than 16 bits.
-- 2. Explicit sign conversions are added to standard logic vector
-- comparisons in LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO, LPM_ROM, and
-- LPM_COMPARE.
-- 3. LPM_FIFO_DC is rewritten to have correct outputs.
-- 4. LPM_FIFO outputs zeros when nothing has been read from it, and
-- outputs LPM_NUMWORDS mod exp(2, LPM_WIDTHU) when it is full.
-- 5. Fixed LPM_DIVIDE to divide correctly.
--------------------------------------------------------------------------
-- Version 1.9 (lpm 220) Date 11/30/99
--
-- 1. Fixed UNUSED file not found problem and initialization problem
-- with LPM_RAM_DP, LPM_RAM_DQ, and LPM_RAM_IO.
-- 2. Fixed LPM_MULT when SUM port is not used.
-- 3. Fixed LPM_FIFO_DC to enable read when rdclock and wrclock rise
-- at the same time.
-- 4. Fixed LPM_COUNTER comparison problem when signed library is loaded
-- and counter is incrementing.
-- 5. Got rid of "Illegal Character" error message at time = 0 ns when
-- simulating LPM_COUNTER.
--------------------------------------------------------------------------
-- Version 1.8 (lpm 220) Date 10/25/99
--
-- 1. Some LPM_PVALUE implementations were missing, and now implemented.
-- 2. Fixed LPM_COUNTER to count correctly without conversion overflow,
-- that is, when LPM_MODULUS = 2 ** LPM_WIDTH.
-- 3. Fixed LPM_RAM_DP sync process sensitivity list to detect wraddress
-- changes.
--------------------------------------------------------------------------
-- Version 1.7 (lpm 220) Date 07/13/99
--
-- Changed LPM_RAM_IO so that it can be used to simulate both MP2 and
-- Quartus behaviour and LPM220-compliant behaviour.
--------------------------------------------------------------------------
-- Version 1.6 (lpm 220) Date 06/15/99
--
-- 1. Fixed LPM_ADD_SUB sign extension problem and subtraction bug.
-- 2. Fixed LPM_COUNTER to use LPM_MODULUS value.
-- 3. Added CIN and COUT port, and discarded EQ port in LPM_COUNTER to
-- comply with the specfication.
-- 4. Included LPM_RAM_DP, LPM_RAM_DQ, LPM_RAM_IO, LPM_ROM, LPM_FIFO, and
-- LPM_FIFO_DC; they are all initialized to 0's.
--------------------------------------------------------------------------
-- Version 1.5 (lpm 220) Date 05/10/99
--
-- Changed LPM_MODULUS from string type to integer.
--------------------------------------------------------------------------
-- Version 1.4 (lpm 220) Date 02/05/99
--
-- 1. Added LPM_DIVIDE module.
-- 2. Added CLKEN port to LPM_MUX, LPM_DECODE, LPM_ADD_SUB, LPM_MULT
-- and LPM_COMPARE
-- 3. Replaced the constants holding string with the actual string.
--------------------------------------------------------------------------
-- Version 1.3 Date 07/30/96
--
-- Modification History
--
-- 1. Changed the DEFAULT value to "UNUSED" for LPM_SVALUE, LPM_AVALUE,
-- LPM_MODULUS, and LPM_NUMWORDS, LPM_HINT,LPM_STRENGTH, LPM_DIRECTION,
-- and LPM_PVALUE
--
-- 2. Added the two dimentional port components (AND, OR, XOR, and MUX).
--------------------------------------------------------------------------
-- Excluded Functions:
--
-- LPM_FSM and LPM_TTABLE
--
--------------------------------------------------------------------------
-- Assumptions:
--
-- 1. All ports and signal types are std_logic or std_logic_vector
-- from IEEE 1164 package.
-- 2. Synopsys std_logic_arith, std_logic_unsigned, and std_logic_signed
-- package are assumed to be accessible from IEEE library.
-- 3. lpm_component_package must be accessible from library work.
-- 4. The default value of LPM_SVALUE, LPM_AVALUE, LPM_MODULUS, LPM_HINT,
-- LPM_NUMWORDS, LPM_STRENGTH, LPM_DIRECTION, and LPM_PVALUE is
-- string "UNUSED".
--------------------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
--use work.LPM_COMPONENTS.all;
use std.textio.all;
 
entity LPM_ROM is
generic (LPM_WIDTH : positive;
LPM_WIDTHAD : positive;
LPM_NUMWORDS : natural := 0;
LPM_ADDRESS_CONTROL : string := "REGISTERED";
LPM_OUTDATA : string := "REGISTERED";
LPM_FILE : string;
LPM_TYPE : string := "LPM_ROM";
LPM_HINT : string := "UNUSED");
port (ADDRESS : in STD_LOGIC_VECTOR(LPM_WIDTHAD-1 downto 0);
INCLOCK : in STD_LOGIC := '0';
OUTCLOCK : in STD_LOGIC := '0';
MEMENAB : in STD_LOGIC := '1';
Q : out STD_LOGIC_VECTOR(LPM_WIDTH-1 downto 0));
 
function int_to_str( value : integer ) return string is
variable ivalue,index : integer;
variable digit : integer;
variable line_no: string(8 downto 1) := " ";
begin
ivalue := value;
index := 1;
while (ivalue > 0 ) loop
digit := ivalue MOD 10;
ivalue := ivalue/10;
case digit is
when 0 =>
line_no(index) := '0';
when 1 =>
line_no(index) := '1';
when 2 =>
line_no(index) := '2';
when 3 =>
line_no(index) := '3';
when 4 =>
line_no(index) := '4';
when 5 =>
line_no(index) := '5';
when 6 =>
line_no(index) := '6';
when 7 =>
line_no(index) := '7';
when 8 =>
line_no(index) := '8';
when 9 =>
line_no(index) := '9';
when others =>
ASSERT FALSE
REPORT "Illegal number!"
SEVERITY ERROR;
end case;
index := index + 1;
end loop;
return line_no;
end;
 
function hex_str_to_int( str : string ) return integer is
variable len : integer := str'length;
variable ivalue : integer := 0;
variable digit : integer;
begin
for i in len downto 1 loop
case str(i) is
when '0' =>
digit := 0;
when '1' =>
digit := 1;
when '2' =>
digit := 2;
when '3' =>
digit := 3;
when '4' =>
digit := 4;
when '5' =>
digit := 5;
when '6' =>
digit := 6;
when '7' =>
digit := 7;
when '8' =>
digit := 8;
when '9' =>
digit := 9;
when 'A' =>
digit := 10;
when 'a' =>
digit := 10;
when 'B' =>
digit := 11;
when 'b' =>
digit := 11;
when 'C' =>
digit := 12;
when 'c' =>
digit := 12;
when 'D' =>
digit := 13;
when 'd' =>
digit := 13;
when 'E' =>
digit := 14;
when 'e' =>
digit := 14;
when 'F' =>
digit := 15;
when 'f' =>
digit := 15;
when others =>
ASSERT FALSE
REPORT "Illegal character "& str(i) & "in Intel Hex File! "
SEVERITY ERROR;
end case;
ivalue := ivalue * 16 + digit;
end loop;
return ivalue;
end;
 
procedure Shrink_line(L : inout LINE; pos : in integer) is
subtype nstring is string(1 to pos);
variable stmp : nstring;
begin
if pos >= 1 then
read(l, stmp);
end if;
end;
 
end LPM_ROM;
 
architecture LPM_SYN of lpm_rom is
 
--type lpm_memory is array(lpm_numwords-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
type lpm_memory is array((2**lpm_widthad)-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
 
signal q2, q_tmp, q_reg : std_logic_vector(lpm_width-1 downto 0);
signal address_tmp, address_reg : std_logic_vector(lpm_widthad-1 downto 0);
 
begin
 
enable_mem: process(memenab, q2)
begin
if (memenab = '1') then
q <= q2;
else
q <= (OTHERS => 'Z');
end if;
end process;
 
sync: process(address, address_reg, q_tmp, q_reg)
begin
if (lpm_address_control = "REGISTERED") then
address_tmp <= address_reg;
else
address_tmp <= address;
end if;
if (lpm_outdata = "REGISTERED") then
q2 <= q_reg;
else
q2 <= q_tmp;
end if;
end process;
 
input_reg: process (inclock)
begin
if inclock'event and inclock = '1' then
address_reg <= address;
end if;
end process;
 
output_reg: process (outclock)
begin
if outclock'event and outclock = '1' then
q_reg <= q_tmp;
end if;
end process;
 
memory: process(memenab, address_tmp)
variable mem_data : lpm_memory;
variable mem_data_tmp : integer := 0;
variable mem_init: boolean := false;
variable i, j, k, lineno : integer := 0;
variable buf: line ;
variable booval: boolean ;
FILE mem_data_file: TEXT IS IN LPM_FILE;
variable base, byte, rec_type, datain, addr, checksum: string(2 downto 1);
variable startadd: string(4 downto 1);
variable ibase: integer := 0;
variable ibyte: integer := 0;
variable istartadd: integer := 0;
variable check_sum_vec, check_sum_vec_tmp: unsigned(7 downto 0);
begin
-- INITIALIZE --
if NOT(mem_init) then
-- INITIALIZE TO 0 --
for i in mem_data'LOW to mem_data'HIGH loop
mem_data(i) := (OTHERS => '0');
end loop;
 
if (LPM_FILE = "UNUSED") then
ASSERT FALSE
REPORT "Initialization file not found!"
SEVERITY ERROR;
else
WHILE NOT ENDFILE(mem_data_file) loop
booval := true;
READLINE(mem_data_file, buf);
lineno := lineno + 1;
check_sum_vec := (OTHERS => '0');
if (buf(buf'LOW) = ':') then
i := 1;
shrink_line(buf, i);
READ(L=>buf, VALUE=>byte, good=>booval);
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format!"
SEVERITY ERROR;
end if;
ibyte := hex_str_to_int(byte);
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(ibyte, 8);
READ(L=>buf, VALUE=>startadd, good=>booval);
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
SEVERITY ERROR;
end if;
istartadd := hex_str_to_int(startadd);
addr(2) := startadd(4);
addr(1) := startadd(3);
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length);
addr(2) := startadd(2);
addr(1) := startadd(1);
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length);
READ(L=>buf, VALUE=>rec_type, good=>booval);
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
SEVERITY ERROR;
end if;
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(rec_type), check_sum_vec'length);
else
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
SEVERITY ERROR;
end if;
case rec_type is
when "00"=> -- Data record
i := 0;
k := lpm_width / 8;
if ((lpm_width MOD 8) /= 0) then
k := k + 1;
end if;
-- k = no. of bytes per CAM entry.
while (i < ibyte) loop
mem_data_tmp := 0;
for j in 1 to k loop
READ(L=>buf, VALUE=>datain,good=>booval); -- read in data a byte (2 hex chars) at a time.
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
SEVERITY ERROR;
end if;
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(datain), check_sum_vec'length);
mem_data_tmp := mem_data_tmp * 256 + hex_str_to_int(datain);
end loop;
i := i + k;
mem_data(ibase + istartadd) := STD_LOGIC_VECTOR(to_unsigned(mem_data_tmp, lpm_width));
istartadd := istartadd + 1;
end loop;
when "01"=>
exit;
when "02"=>
ibase := 0;
if (ibyte /= 2) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format for record type 02! "
SEVERITY ERROR;
end if;
for i in 0 to (ibyte-1) loop
READ(L=>buf, VALUE=>base,good=>booval);
ibase := ibase * 256 + hex_str_to_int(base);
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
SEVERITY ERROR;
end if;
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(base), check_sum_vec'length);
end loop;
ibase := ibase * 16;
when OTHERS =>
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal record type in Intel Hex File! "
SEVERITY ERROR;
end case;
READ(L=>buf, VALUE=>checksum,good=>booval);
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Checksum is missing! "
SEVERITY ERROR;
end if;
 
check_sum_vec := unsigned(not (check_sum_vec)) + 1 ;
check_sum_vec_tmp := to_unsigned(hex_str_to_int(checksum),8);
 
if (unsigned(check_sum_vec) /= unsigned(check_sum_vec_tmp)) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Incorrect checksum!"
SEVERITY ERROR;
end if;
end loop;
end if;
mem_init := TRUE;
end if;
 
-- MEMORY FUNCTION --
--if memenab = '1' then
q_tmp <= mem_data(to_integer(UNSIGNED(address_tmp)));
--else
-- q_tmp <= (OTHERS => 'Z');
--end if;
end process;
 
end LPM_SYN;
 
 
---------------------------------------------------------------------------
 
 
-- pragma translate_off
configuration lpm_rom_c0 of lpm_rom is
 
for lpm_syn
end for;
 
end lpm_rom_c0;
-- pragma translate_on
/vhdl/system/lpm_ram_dq.vhd
0,0 → 1,439
--------------------------------------------------------------------------
-- This VHDL file was developed by Altera Corporation. It may be
-- freely copied and/or distributed at no cost. Any persons using this
-- file for any purpose do so at their own risk, and are responsible for
-- the results of such use. Altera Corporation does not guarantee that
-- this file is complete, correct, or fit for any particular purpose.
-- NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. This notice must
-- accompany any copy of this file.
--
--------------------------------------------------------------------------
-- LPM Synthesizable Models (Support string type generic)
--------------------------------------------------------------------------
-- Version 2.0 (lpm 220) Date 01/04/00
--
-- 1. Fixed LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO and LPM_ROM to correctly
-- read in values from LPM_FILE (*.hex) when the DATA width is greater
-- than 16 bits.
-- 2. Explicit sign conversions are added to standard logic vector
-- comparisons in LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO, LPM_ROM, and
-- LPM_COMPARE.
-- 3. LPM_FIFO_DC is rewritten to have correct outputs.
-- 4. LPM_FIFO outputs zeros when nothing has been read from it, and
-- outputs LPM_NUMWORDS mod exp(2, LPM_WIDTHU) when it is full.
-- 5. Fixed LPM_DIVIDE to divide correctly.
--------------------------------------------------------------------------
-- Version 1.9 (lpm 220) Date 11/30/99
--
-- 1. Fixed UNUSED file not found problem and initialization problem
-- with LPM_RAM_DP, LPM_RAM_DQ, and LPM_RAM_IO.
-- 2. Fixed LPM_MULT when SUM port is not used.
-- 3. Fixed LPM_FIFO_DC to enable read when rdclock and wrclock rise
-- at the same time.
-- 4. Fixed LPM_COUNTER comparison problem when signed library is loaded
-- and counter is incrementing.
-- 5. Got rid of "Illegal Character" error message at time = 0 ns when
-- simulating LPM_COUNTER.
--------------------------------------------------------------------------
-- Version 1.8 (lpm 220) Date 10/25/99
--
-- 1. Some LPM_PVALUE implementations were missing, and now implemented.
-- 2. Fixed LPM_COUNTER to count correctly without conversion overflow,
-- that is, when LPM_MODULUS = 2 ** LPM_WIDTH.
-- 3. Fixed LPM_RAM_DP sync process sensitivity list to detect wraddress
-- changes.
--------------------------------------------------------------------------
-- Version 1.7 (lpm 220) Date 07/13/99
--
-- Changed LPM_RAM_IO so that it can be used to simulate both MP2 and
-- Quartus behaviour and LPM220-compliant behaviour.
--------------------------------------------------------------------------
-- Version 1.6 (lpm 220) Date 06/15/99
--
-- 1. Fixed LPM_ADD_SUB sign extension problem and subtraction bug.
-- 2. Fixed LPM_COUNTER to use LPM_MODULUS value.
-- 3. Added CIN and COUT port, and discarded EQ port in LPM_COUNTER to
-- comply with the specfication.
-- 4. Included LPM_RAM_DP, LPM_RAM_DQ, LPM_RAM_IO, LPM_ROM, LPM_FIFO, and
-- LPM_FIFO_DC; they are all initialized to 0's.
--------------------------------------------------------------------------
-- Version 1.5 (lpm 220) Date 05/10/99
--
-- Changed LPM_MODULUS from string type to integer.
--------------------------------------------------------------------------
-- Version 1.4 (lpm 220) Date 02/05/99
--
-- 1. Added LPM_DIVIDE module.
-- 2. Added CLKEN port to LPM_MUX, LPM_DECODE, LPM_ADD_SUB, LPM_MULT
-- and LPM_COMPARE
-- 3. Replaced the constants holding string with the actual string.
--------------------------------------------------------------------------
-- Version 1.3 Date 07/30/96
--
-- Modification History
--
-- 1. Changed the DEFAULT value to "UNUSED" for LPM_SVALUE, LPM_AVALUE,
-- LPM_MODULUS, and LPM_NUMWORDS, LPM_HINT,LPM_STRENGTH, LPM_DIRECTION,
-- and LPM_PVALUE
--
-- 2. Added the two dimentional port components (AND, OR, XOR, and MUX).
--------------------------------------------------------------------------
-- Excluded Functions:
--
-- LPM_FSM and LPM_TTABLE
--
--------------------------------------------------------------------------
-- Assumptions:
--
-- 1. All ports and signal types are std_logic or std_logic_vector
-- from IEEE 1164 package.
-- 2. Synopsys std_logic_arith, std_logic_unsigned, and std_logic_signed
-- package are assumed to be accessible from IEEE library.
-- 3. lpm_component_package must be accessible from library work.
-- 4. The default value of LPM_SVALUE, LPM_AVALUE, LPM_MODULUS, LPM_HINT,
-- LPM_NUMWORDS, LPM_STRENGTH, LPM_DIRECTION, and LPM_PVALUE is
-- string "UNUSED".
--------------------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
--use IEEE.std_logic_unsigned.all;
use std.textio.all;
 
entity LPM_RAM_DQ is
generic (LPM_WIDTH : positive;
LPM_WIDTHAD : positive;
LPM_NUMWORDS : natural := 0;
LPM_INDATA : string := "REGISTERED";
LPM_ADDRESS_CONTROL: string := "REGISTERED";
LPM_OUTDATA : string := "REGISTERED";
LPM_FILE : string := "UNUSED";
LPM_TYPE : string := "LPM_RAM_DQ";
LPM_HINT : string := "UNUSED");
port (DATA : in std_logic_vector(LPM_WIDTH-1 downto 0);
ADDRESS : in std_logic_vector(LPM_WIDTHAD-1 downto 0);
INCLOCK : in std_logic := '0';
OUTCLOCK : in std_logic := '0';
WE : in std_logic;
Q : out std_logic_vector(LPM_WIDTH-1 downto 0));
 
function int_to_str( value : integer ) return string is
variable ivalue,index : integer;
variable digit : integer;
variable line_no: string(8 downto 1) := " ";
begin
ivalue := value;
index := 1;
while (ivalue > 0) loop
digit := ivalue MOD 10;
ivalue := ivalue/10;
case digit is
when 0 =>
line_no(index) := '0';
when 1 =>
line_no(index) := '1';
when 2 =>
line_no(index) := '2';
when 3 =>
line_no(index) := '3';
when 4 =>
line_no(index) := '4';
when 5 =>
line_no(index) := '5';
when 6 =>
line_no(index) := '6';
when 7 =>
line_no(index) := '7';
when 8 =>
line_no(index) := '8';
when 9 =>
line_no(index) := '9';
when others =>
ASSERT FALSE
REPORT "Illegal number!"
SEVERITY ERROR;
end case;
index := index + 1;
end loop;
return line_no;
end;
 
function hex_str_to_int( str : string ) return integer is
variable len : integer := str'length;
variable ivalue : integer := 0;
variable digit : integer;
begin
for i in len downto 1 loop
case str(i) is
when '0' =>
digit := 0;
when '1' =>
digit := 1;
when '2' =>
digit := 2;
when '3' =>
digit := 3;
when '4' =>
digit := 4;
when '5' =>
digit := 5;
when '6' =>
digit := 6;
when '7' =>
digit := 7;
when '8' =>
digit := 8;
when '9' =>
digit := 9;
when 'A' =>
digit := 10;
when 'a' =>
digit := 10;
when 'B' =>
digit := 11;
when 'b' =>
digit := 11;
when 'C' =>
digit := 12;
when 'c' =>
digit := 12;
when 'D' =>
digit := 13;
when 'd' =>
digit := 13;
when 'E' =>
digit := 14;
when 'e' =>
digit := 14;
when 'F' =>
digit := 15;
when 'f' =>
digit := 15;
when others =>
ASSERT FALSE
REPORT "Illegal character "& str(i) & "in Intel Hex File! "
SEVERITY ERROR;
end case;
ivalue := ivalue * 16 + digit;
end loop;
return ivalue;
end;
 
procedure Shrink_line(L : inout LINE; pos : in integer) is
subtype nstring is string(1 to pos);
variable stmp : nstring;
begin
if pos >= 1 then
read(l, stmp);
end if;
end;
 
end LPM_RAM_DQ;
 
architecture LPM_SYN of lpm_ram_dq is
 
--type lpm_memory is array(lpm_numwords-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
type lpm_memory is array((2**lpm_widthad)-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
 
signal data_tmp, data_reg : std_logic_vector(lpm_width-1 downto 0);
signal q_tmp, q_reg : std_logic_vector(lpm_width-1 downto 0) := (others => '0');
signal address_tmp, address_reg : std_logic_vector(lpm_widthad-1 downto 0);
signal we_tmp, we_reg : std_logic;
 
begin
 
sync: process(data, data_reg, address, address_reg,
we, we_reg, q_tmp, q_reg)
begin
if (lpm_address_control = "REGISTERED") then
address_tmp <= address_reg;
we_tmp <= we_reg;
else
address_tmp <= address;
we_tmp <= we;
end if;
if (lpm_indata = "REGISTERED") then
data_tmp <= data_reg;
else
data_tmp <= data;
end if;
if (lpm_outdata = "REGISTERED") then
q <= q_reg;
else
q <= q_tmp;
end if;
end process;
 
input_reg: process (inclock)
begin
if inclock'event and inclock = '1' then
data_reg <= data;
address_reg <= address;
we_reg <= we;
end if;
end process;
 
output_reg: process (outclock)
begin
if outclock'event and outclock = '1' then
q_reg <= q_tmp;
end if;
end process;
 
memory: process(data_tmp, we_tmp, address_tmp)
variable mem_data : lpm_memory;
variable mem_data_tmp : integer := 0;
variable mem_init: boolean := false;
variable i,j,k,lineno: integer := 0;
variable buf: line ;
variable booval: boolean ;
FILE unused_file: TEXT IS OUT "UNUSED";
FILE mem_data_file: TEXT IS IN LPM_FILE;
variable base, byte, rec_type, datain, addr, checksum: string(2 downto 1);
variable startadd: string(4 downto 1);
variable ibase: integer := 0;
variable ibyte: integer := 0;
variable istartadd: integer := 0;
variable check_sum_vec, check_sum_vec_tmp: unsigned(7 downto 0);
begin
-- INITIALIZE --
if NOT(mem_init) then
-- INITIALIZE TO 0 --
for i in mem_data'LOW to mem_data'HIGH loop
mem_data(i) := (OTHERS => '0');
end loop;
 
if (LPM_FILE = "UNUSED") then
ASSERT FALSE
REPORT "Initialization file not found!"
SEVERITY WARNING;
else
WHILE NOT ENDFILE(mem_data_file) loop
booval := true;
READLINE(mem_data_file, buf);
lineno := lineno + 1;
check_sum_vec := (OTHERS => '0');
if (buf(buf'LOW) = ':') then
i := 1;
shrink_line(buf, i);
READ(L=>buf, VALUE=>byte, good=>booval);
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format!"
SEVERITY ERROR;
end if;
ibyte := hex_str_to_int(byte);
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(ibyte, check_sum_vec'length);
READ(L=>buf, VALUE=>startadd, good=>booval);
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
SEVERITY ERROR;
end if;
istartadd := hex_str_to_int(startadd);
addr(2) := startadd(4);
addr(1) := startadd(3);
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length);
addr(2) := startadd(2);
addr(1) := startadd(1);
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length);
READ(L=>buf, VALUE=>rec_type, good=>booval);
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
SEVERITY ERROR;
end if;
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(rec_type), check_sum_vec'length);
else
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
SEVERITY ERROR;
end if;
case rec_type is
when "00"=> -- Data record
i := 0;
k := lpm_width / 8;
if ((lpm_width MOD 8) /= 0) then
k := k + 1;
end if;
-- k = no. of bytes per CAM entry.
while (i < ibyte) loop
mem_data_tmp := 0;
for j in 1 to k loop
READ(L=>buf, VALUE=>datain,good=>booval); -- read in data a byte (2 hex chars) at a time.
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
SEVERITY ERROR;
end if;
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(datain), check_sum_vec'length);
mem_data_tmp := mem_data_tmp * 256 + hex_str_to_int(datain);
end loop;
i := i + k;
mem_data(ibase + istartadd) := STD_LOGIC_VECTOR(to_unsigned(mem_data_tmp, lpm_width));
istartadd := istartadd + 1;
end loop;
when "01"=>
exit;
when "02"=>
ibase := 0;
if (ibyte /= 2) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format for record type 02! "
SEVERITY ERROR;
end if;
for i in 0 to (ibyte-1) loop
READ(L=>buf, VALUE=>base,good=>booval);
ibase := ibase * 256 + hex_str_to_int(base);
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
SEVERITY ERROR;
end if;
check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(base), check_sum_vec'length);
end loop;
ibase := ibase * 16;
when OTHERS =>
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Illegal record type in Intel Hex File! "
SEVERITY ERROR;
end case;
READ(L=>buf, VALUE=>checksum,good=>booval);
if not (booval) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Checksum is missing! "
SEVERITY ERROR;
end if;
 
check_sum_vec := unsigned(not (check_sum_vec)) + 1 ;
check_sum_vec_tmp := to_unsigned(hex_str_to_int(checksum), check_sum_vec_tmp'length);
 
if (unsigned(check_sum_vec) /= unsigned(check_sum_vec_tmp)) then
ASSERT FALSE
REPORT "[Line "& int_to_str(lineno) & "]:Incorrect checksum!"
SEVERITY ERROR;
end if;
end loop;
end if;
mem_init := TRUE;
end if;
 
-- MEMORY FUNCTION --
if we_tmp = '1' then
mem_data (to_integer(unsigned(address_tmp))) := data_tmp;
end if;
q_tmp <= mem_data(to_integer(unsigned(address_tmp)));
end process;
 
end LPM_SYN;
 
 
-- pragma translate_off
configuration lpm_ram_dq_c0 of lpm_ram_dq is
 
for lpm_syn
end for;
 
end lpm_ram_dq_c0;
-- pragma translate_on
/vhdl/system/t8039-c.vhd
0,0 → 1,27
-------------------------------------------------------------------------------
--
-- T8039 Microcontroller System
--
-- $Id: t8039-c.vhd,v 1.1 2004-04-18 18:51:10 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration t8039_struct_c0 of t8039 is
 
for struct
 
for ram_128_b : syn_ram
use configuration work.syn_ram_lpm_c0;
end for;
 
for t48_core_b : t48_core
use configuration work.t48_core_struct_c0;
end for;
 
end for;
 
end t8039_struct_c0;
/vhdl/system/t8039.vhd
0,0 → 1,223
-------------------------------------------------------------------------------
--
-- T8039 Microcontroller System
--
-- $Id: t8039.vhd,v 1.1 2004-04-18 18:51:10 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity t8039 is
 
port (
xtal_i : in std_logic;
reset_n_i : in std_logic;
t0_b : inout std_logic;
int_n_i : in std_logic;
ea_i : in std_logic;
rd_n_o : out std_logic;
psen_n_o : out std_logic;
wr_n_o : out std_logic;
ale_o : out std_logic;
db_b : inout std_logic_vector( 7 downto 0);
t1_i : in std_logic;
p2_b : inout std_logic_vector( 7 downto 0);
p1_b : inout std_logic_vector( 7 downto 0);
prog_n_o : out std_logic
);
 
end t8039;
 
 
use work.t48_core_comp_pack.t48_core;
use work.t48_core_comp_pack.syn_rom;
use work.t48_core_comp_pack.syn_ram;
 
architecture struct of t8039 is
 
signal t0_s : std_logic;
signal t0_dir_s : std_logic;
signal db_s : std_logic_vector( 7 downto 0);
signal db_dir_s : std_logic;
signal p2_s : std_logic_vector( 7 downto 0);
signal p2_low_imp_s : std_logic;
signal p1_s : std_logic_vector( 7 downto 0);
signal p1_low_imp_s : std_logic;
signal xtal3_s : std_logic;
signal dmem_addr_s : std_logic_vector( 7 downto 0);
signal dmem_we_s : std_logic;
signal dmem_data_from_s : std_logic_vector( 7 downto 0);
signal dmem_data_to_s : std_logic_vector( 7 downto 0);
signal pmem_data_s : std_logic_vector( 7 downto 0);
 
begin
 
-- no Program memory available
pmem_data_s <= (others => '0');
 
t48_core_b : t48_core
generic map (
xtal_div_3_g => 1,
register_mnemonic_g => 1,
include_port1_g => 1,
include_port2_g => 1,
include_bus_g => 1,
include_timer_g => 1,
sample_t1_state_g => 4
)
port map (
xtal_i => xtal_i,
reset_i => reset_n_i,
t0_i => t0_b,
t0_o => t0_s,
t0_dir_o => t0_dir_s,
int_n_i => int_n_i,
ea_i => ea_i,
rd_n_o => rd_n_o,
psen_n_o => psen_n_o,
wr_n_o => wr_n_o,
ale_o => ale_o,
db_i => db_b,
db_o => db_s,
db_dir_o => db_dir_s,
t1_i => t1_i,
p2_i => p2_b,
p2_o => p2_s,
p2_low_imp_o => p2_low_imp_s,
p1_i => p1_b,
p1_o => p1_s,
p1_low_imp_o => p1_low_imp_s,
prog_n_o => prog_n_o,
clk_i => xtal_i,
en_clk_i => xtal3_s,
xtal3_o => xtal3_s,
dmem_addr_o => dmem_addr_s,
dmem_we_o => dmem_we_s,
dmem_data_i => dmem_data_from_s,
dmem_data_o => dmem_data_to_s,
pmem_addr_o => open,
pmem_data_i => pmem_data_s
);
 
-----------------------------------------------------------------------------
-- Process bidirs
--
-- Purpose:
-- Assign bidirectional signals.
--
bidirs: process (t0_b, t0_s, t0_dir_s,
db_b, db_s, db_dir_s,
p1_b, p1_s, p1_low_imp_s,
p2_b, p2_s, p2_low_imp_s)
 
function open_collector_f(sig : std_logic) return std_logic is
variable sig_v : std_logic;
begin
sig_v := 'Z';
 
if sig = '0' then
sig_v := '0';
end if;
 
return sig_v;
end;
 
begin
-- Test 0 -----------------------------------------------------------------
if t0_dir_s = '1' then
t0_b <= t0_s;
else
t0_b <= 'Z';
end if;
 
-- Data Bus ---------------------------------------------------------------
if db_dir_s = '1' then
db_b <= db_s;
else
db_b <= (others => 'Z');
end if;
 
-- Port 1 -----------------------------------------------------------------
for i in p1_b'range loop
p1_b(i) <= open_collector_f(p1_s(i));
end loop;
-- if p1_low_imp_s = '1' then
-- p1_b <= p1_s;
-- else
-- p1_b <= (others => 'Z');
-- end if;
 
-- Port 2 -----------------------------------------------------------------
for i in p2_b'range loop
p2_b(i) <= open_collector_f(p2_s(i));
end loop;
-- if p2_low_imp_s = '1' then
-- p2_b <= p2_b_s;
-- else
-- p2_b <= (others => 'Z');
-- end if;
 
end process bidirs;
--
-----------------------------------------------------------------------------
 
ram_128_b : syn_ram
generic map (
address_width_g => 7
)
port map (
clk_i => xtal_i,
res_i => reset_n_i,
ram_addr_i => dmem_addr_s(6 downto 0),
ram_data_i => dmem_data_to_s,
ram_we_i => dmem_we_s,
ram_data_o => dmem_data_from_s
);
 
end struct;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-------------------------------------------------------------------------------
/vhdl/system/syn_ram-lpm-a.vhd
0,0 → 1,105
-------------------------------------------------------------------------------
--
-- A synchronous parametrizable RAM instantiating a standard RAM from
-- the Altera LPM.
--
-- $Id: syn_ram-lpm-a.vhd,v 1.2 2004-04-07 22:09:08 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
architecture lpm of syn_ram is
 
component lpm_ram_dq
generic (
LPM_WIDTH : positive;
LPM_TYPE : string := "LPM_RAM_DQ";
LPM_WIDTHAD : positive;
LPM_NUMWORDS : natural := 0;
LPM_FILE : string := "UNUSED";
LPM_INDATA : string := "REGISTERED";
LPM_ADDRESS_CONTROL : string := "REGISTERED";
LPM_OUTDATA : string := "UNREGISTERED";
LPM_HINT : string := "UNUSED"
);
port (
data : in std_logic_vector(LPM_WIDTH-1 downto 0);
address : in std_logic_vector(LPM_WIDTHAD-1 downto 0);
we : in std_logic;
inclock : in std_logic;
q : out std_logic_vector(LPM_WIDTH-1 downto 0)
);
end component;
 
begin
 
ram_b : lpm_ram_dq
generic map (
LPM_WIDTH => 8,
LPM_TYPE => "LPM_RAM_DQ",
LPM_WIDTHAD => address_width_g,
LPM_NUMWORDS => 2 ** address_width_g,
LPM_FILE => "UNUSED",
LPM_INDATA => "REGISTERED",
LPM_ADDRESS_CONTROL => "REGISTERED",
LPM_OUTDATA => "UNREGISTERED",
LPM_HINT => "UNUSED"
)
port map (
data => ram_data_i,
address => ram_addr_i,
we => ram_we_i,
inclock => clk_i,
q => ram_data_o
);
 
end lpm;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.1 2004/03/24 21:32:27 arniml
-- initial check-in
--
-------------------------------------------------------------------------------
/vhdl/system/t8048.vhd
0,0 → 1,234
-------------------------------------------------------------------------------
--
-- T8048 Microcontroller System
--
-- $Id: t8048.vhd,v 1.2 2004-03-29 19:40:14 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity t8048 is
 
port (
xtal_i : in std_logic;
reset_n_i : in std_logic;
t0_b : inout std_logic;
int_n_i : in std_logic;
ea_i : in std_logic;
rd_n_o : out std_logic;
psen_n_o : out std_logic;
wr_n_o : out std_logic;
ale_o : out std_logic;
db_b : inout std_logic_vector( 7 downto 0);
t1_i : in std_logic;
p2_b : inout std_logic_vector( 7 downto 0);
p1_b : inout std_logic_vector( 7 downto 0);
prog_n_o : out std_logic
);
 
end t8048;
 
 
use work.t48_core_comp_pack.t48_core;
use work.t48_core_comp_pack.syn_rom;
use work.t48_core_comp_pack.syn_ram;
 
architecture struct of t8048 is
 
signal t0_s : std_logic;
signal t0_dir_s : std_logic;
signal db_s : std_logic_vector( 7 downto 0);
signal db_dir_s : std_logic;
signal p2_s : std_logic_vector( 7 downto 0);
signal p2_low_imp_s : std_logic;
signal p1_s : std_logic_vector( 7 downto 0);
signal p1_low_imp_s : std_logic;
signal xtal3_s : std_logic;
signal dmem_addr_s : std_logic_vector( 7 downto 0);
signal dmem_we_s : std_logic;
signal dmem_data_from_s : std_logic_vector( 7 downto 0);
signal dmem_data_to_s : std_logic_vector( 7 downto 0);
signal pmem_addr_s : std_logic_vector(11 downto 0);
signal pmem_data_s : std_logic_vector( 7 downto 0);
 
begin
 
t48_core_b : t48_core
generic map (
xtal_div_3_g => 1,
register_mnemonic_g => 1,
include_port1_g => 1,
include_port2_g => 1,
include_bus_g => 1,
include_timer_g => 1,
sample_t1_state_g => 4
)
port map (
xtal_i => xtal_i,
reset_i => reset_n_i,
t0_i => t0_b,
t0_o => t0_s,
t0_dir_o => t0_dir_s,
int_n_i => int_n_i,
ea_i => ea_i,
rd_n_o => rd_n_o,
psen_n_o => psen_n_o,
wr_n_o => wr_n_o,
ale_o => ale_o,
db_i => db_b,
db_o => db_s,
db_dir_o => db_dir_s,
t1_i => t1_i,
p2_i => p2_b,
p2_o => p2_s,
p2_low_imp_o => p2_low_imp_s,
p1_i => p1_b,
p1_o => p1_s,
p1_low_imp_o => p1_low_imp_s,
prog_n_o => prog_n_o,
clk_i => xtal_i,
en_clk_i => xtal3_s,
xtal3_o => xtal3_s,
dmem_addr_o => dmem_addr_s,
dmem_we_o => dmem_we_s,
dmem_data_i => dmem_data_from_s,
dmem_data_o => dmem_data_to_s,
pmem_addr_o => pmem_addr_s,
pmem_data_i => pmem_data_s
);
 
-----------------------------------------------------------------------------
-- Process bidirs
--
-- Purpose:
-- Assign bidirectional signals.
--
bidirs: process (t0_b, t0_s, t0_dir_s,
db_b, db_s, db_dir_s,
p1_b, p1_s, p1_low_imp_s,
p2_b, p2_s, p2_low_imp_s)
 
function open_collector_f(sig : std_logic) return std_logic is
variable sig_v : std_logic;
begin
sig_v := 'Z';
 
if sig = '0' then
sig_v := '0';
end if;
 
return sig_v;
end;
 
begin
-- Test 0 -----------------------------------------------------------------
if t0_dir_s = '1' then
t0_b <= t0_s;
else
t0_b <= 'Z';
end if;
 
-- Data Bus ---------------------------------------------------------------
if db_dir_s = '1' then
db_b <= db_s;
else
db_b <= (others => 'Z');
end if;
 
-- Port 1 -----------------------------------------------------------------
for i in p1_b'range loop
p1_b(i) <= open_collector_f(p1_s(i));
end loop;
-- if p1_low_imp_s = '1' then
-- p1_b <= p1_s;
-- else
-- p1_b <= (others => 'Z');
-- end if;
 
-- Port 2 -----------------------------------------------------------------
for i in p2_b'range loop
p2_b(i) <= open_collector_f(p2_s(i));
end loop;
-- if p2_low_imp_s = '1' then
-- p2_b <= p2_b_s;
-- else
-- p2_b <= (others => 'Z');
-- end if;
 
end process bidirs;
--
-----------------------------------------------------------------------------
 
rom_1k_b : syn_rom
generic map (
address_width_g => 10
)
port map (
clk_i => xtal_i,
rom_addr_i => pmem_addr_s(9 downto 0),
rom_data_o => pmem_data_s
);
 
ram_64_b : syn_ram
generic map (
address_width_g => 6
)
port map (
clk_i => xtal_i,
res_i => reset_n_i,
ram_addr_i => dmem_addr_s(5 downto 0),
ram_data_i => dmem_data_to_s,
ram_we_i => dmem_we_s,
ram_data_o => dmem_data_from_s
);
 
end struct;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.1 2004/03/24 21:32:27 arniml
-- initial check-in
--
-------------------------------------------------------------------------------
/vhdl/system/t8048-c.vhd
0,0 → 1,31
-------------------------------------------------------------------------------
--
-- T8048 Microcontroller System
--
-- $Id: t8048-c.vhd,v 1.1 2004-03-24 21:32:27 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration t8048_struct_c0 of t8048 is
 
for struct
 
for rom_1k_b : syn_rom
use configuration work.syn_rom_lpm_c0;
end for;
 
for ram_64_b : syn_ram
use configuration work.syn_ram_lpm_c0;
end for;
 
for t48_core_b : t48_core
use configuration work.t48_core_struct_c0;
end for;
 
end for;
 
end t8048_struct_c0;
/vhdl/system/syn_rom-e.vhd
0,0 → 1,60
-------------------------------------------------------------------------------
--
-- A synchronous parametrizable ROM.
--
-- $Id: syn_rom-e.vhd,v 1.1 2004-03-24 21:32:27 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity syn_rom is
 
generic (
address_width_g : positive := 10
);
port (
clk_i : in std_logic;
rom_addr_i : in std_logic_vector(address_width_g-1 downto 0);
rom_data_o : out std_logic_vector(7 downto 0)
);
 
end syn_rom;
/vhdl/system/syn_ram-e.vhd
0,0 → 1,70
-------------------------------------------------------------------------------
--
-- A synchronous parametrizable RAM.
--
-- $Id: syn_ram-e.vhd,v 1.1 2004-03-24 21:32:27 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity syn_ram is
 
generic (
address_width_g : positive := 8
);
port (
clk_i : in std_logic;
res_i : in std_logic;
ram_addr_i : in std_logic_vector(address_width_g-1 downto 0);
ram_data_i : in std_logic_vector(7 downto 0);
ram_we_i : in std_logic;
ram_data_o : out std_logic_vector(7 downto 0)
);
 
end syn_ram;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-------------------------------------------------------------------------------
/vhdl/system/syn_rom-lpm-a.vhd
0,0 → 1,102
-------------------------------------------------------------------------------
--
-- A synchronous parametrizable ROM instantiating a standard ROM from
-- the Altera LPM.
--
-- $Id: syn_rom-lpm-a.vhd,v 1.1 2004-03-24 21:32:27 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
architecture lpm of syn_rom is
 
component lpm_rom
generic (
LPM_WIDTH : positive;
LPM_TYPE : string := "LPM_ROM";
LPM_WIDTHAD : positive;
LPM_NUMWORDS : natural := 0;
LPM_FILE : string;
LPM_ADDRESS_CONTROL : string := "REGISTERED";
LPM_OUTDATA : string := "REGISTERED";
LPM_HINT : string := "UNUSED"
);
port (
address : in std_logic_vector(LPM_WIDTHAD-1 downto 0);
inclock : in std_logic;
memenab : in std_logic;
q : out std_logic_vector(LPM_WIDTH-1 downto 0)
);
end component;
 
signal one_s : std_logic;
 
begin
 
one_s <= '1';
 
rom_b : lpm_rom
generic map (
LPM_WIDTH => 8,
LPM_TYPE => "LPM_ROM",
LPM_WIDTHAD => address_width_g,
LPM_NUMWORDS => 2 ** address_width_g,
LPM_FILE => "t48_rom.hex",
LPM_ADDRESS_CONTROL => "REGISTERED",
LPM_OUTDATA => "UNREGISTERED",
LPM_HINT => "UNUSED"
)
port map (
address => rom_addr_i,
inclock => clk_i,
memenab => one_s,
q => rom_data_o
);
 
end lpm;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-------------------------------------------------------------------------------
/vhdl/system/syn_rom-lpm-c.vhd
0,0 → 1,31
-------------------------------------------------------------------------------
--
-- A synchronous parametrizable ROM instantiating a standard ROM from
-- the Altera LPM.
--
-- $Id: syn_rom-lpm-c.vhd,v 1.1 2004-03-24 21:32:27 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration syn_rom_lpm_c0 of syn_rom is
 
for lpm
 
for rom_b : lpm_rom
use configuration work.lpm_rom_c0;
end for;
 
end for;
 
end syn_rom_lpm_c0;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-------------------------------------------------------------------------------
/vhdl/system/syn_ram-lpm-c.vhd
0,0 → 1,31
-------------------------------------------------------------------------------
--
-- A synchronous parametrizable RAM instantiating a standard RAM from
-- the Altera LPM.
--
-- $Id: syn_ram-lpm-c.vhd,v 1.1 2004-03-24 21:32:27 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration syn_ram_lpm_c0 of syn_ram is
 
for lpm
 
for ram_b : lpm_ram_dq
use configuration work.lpm_ram_dq_c0;
end for;
 
end for;
 
end syn_ram_lpm_c0;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-------------------------------------------------------------------------------
/vhdl/dmem_ctrl.vhd
0,0 → 1,214
-------------------------------------------------------------------------------
--
-- The Data Memory control unit.
-- All accesses to the Data Memory are managed here.
--
-- $Id: dmem_ctrl.vhd,v 1.3 2004-04-24 23:44:25 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.dmem_addr_t;
use work.t48_pack.word_t;
use work.dmem_ctrl_pack.dmem_addr_ident_t;
 
entity dmem_ctrl is
 
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- Control Interface ------------------------------------------------------
data_i : in word_t;
write_dmem_addr_i : in boolean;
write_dmem_i : in boolean;
read_dmem_i : in boolean;
addr_type_i : in dmem_addr_ident_t;
bank_select_i : in std_logic;
data_o : out word_t;
-- Data Memory Interface --------------------------------------------------
dmem_data_i : in word_t;
dmem_addr_o : out dmem_addr_t;
dmem_we_o : out std_logic;
dmem_data_o : out word_t
);
 
end dmem_ctrl;
 
 
library ieee;
use ieee.numeric_std.all;
 
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.to_stdLogic;
 
use work.dmem_ctrl_pack.all;
 
architecture rtl of dmem_ctrl is
 
signal dmem_addr_s,
dmem_addr_q : dmem_addr_t;
begin
 
-----------------------------------------------------------------------------
-- Process addr_decode
--
-- Purpose:
-- Decode/multiplex the address information for the Data Memory.
--
addr_decode: process (data_i,
addr_type_i,
bank_select_i,
dmem_addr_q)
variable stack_addr_v : unsigned(5 downto 0);
begin
-- default assignment
dmem_addr_s <= dmem_addr_q;
stack_addr_v := (others => '0');
 
case addr_type_i is
when DM_PLAIN =>
dmem_addr_s <= data_i;
 
when DM_REG =>
dmem_addr_s <= (others => '0');
dmem_addr_s(2 downto 0) <= data_i(2 downto 0);
-- implement bank switching
if bank_select_i = '1' then
-- dmem address 24 - 31: access proper set
dmem_addr_s(4 downto 3) <= "11";
end if;
 
when DM_STACK =>
-- build address from stack pointer
stack_addr_v(3 downto 1) := unsigned(data_i(2 downto 0));
-- dmem address 8 - 23
stack_addr_v := stack_addr_v + 8;
 
dmem_addr_s <= (others => '0');
dmem_addr_s(5 downto 0) <= std_logic_vector(stack_addr_v);
 
when DM_STACK_HIGH =>
dmem_addr_s(0) <= '1';
 
when others =>
-- do nothing
 
-- pragma translate_off
assert false
report "Unknown address type identification for Data Memory controller!"
severity error;
-- pragma translate_on
 
end case;
 
end process addr_decode;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process dmem_addr_reg
--
-- Purpose:
-- Implements the Data Memory Address Register.
-- This register is necessary to hold the address during a write operation
-- as we cannot hold the address in the input register of the
-- synchronous RAM (no clock suppression/gating).
--
dmem_addr_reg: process (res_i, clk_i)
begin
if res_i = res_active_c then
dmem_addr_q <= (others => '0');
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
if write_dmem_addr_i then
dmem_addr_q <= dmem_addr_s;
end if;
 
end if;
 
end if;
 
end process dmem_addr_reg;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Output mapping.
-----------------------------------------------------------------------------
dmem_addr_o <= dmem_addr_s
when write_dmem_addr_i and en_clk_i else
dmem_addr_q;
 
-- data from bus is fed through
dmem_data_o <= data_i;
 
-- data to bus is enabled upon read request
data_o <= dmem_data_i
when read_dmem_i else
(others => bus_idle_level_c);
 
-- write enable to Data Memory is fed through
dmem_we_o <= to_stdLogic(write_dmem_i);
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.2 2004/04/18 18:58:29 arniml
-- clean up sensitivity list
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------
/vhdl/clock_ctrl.vhd
0,0 → 1,394
-------------------------------------------------------------------------------
--
-- The Clock Control unit.
-- Clock States and Machine Cycles are generated here.
--
-- $Id: clock_ctrl.vhd,v 1.4 2004-04-24 23:44:25 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.all;
 
entity clock_ctrl is
 
generic (
-- divide XTAL1 by 3 to derive Clock States
xtal_div_3_g : integer := 1
);
 
port (
clk_i : in std_logic;
xtal_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
xtal3_o : out boolean;
multi_cycle_i : in boolean;
assert_psen_i : in boolean;
assert_prog_i : in boolean;
assert_rd_i : in boolean;
assert_wr_i : in boolean;
mstate_o : out mstate_t;
second_cycle_o : out boolean;
ale_o : out boolean;
psen_o : out boolean;
prog_o : out boolean;
rd_o : out boolean;
wr_o : out boolean
);
 
end clock_ctrl;
 
 
library ieee;
use ieee.numeric_std.all;
 
architecture rtl of clock_ctrl is
 
-- The three XTAL1 cycles.
signal xtal_q : unsigned(1 downto 0);
signal xtal1_s,
xtal2_s,
xtal3_s : boolean;
signal x1_s,
x2_s,
x3_s : std_logic;
 
 
-- The five clock states.
signal mstate_q : mstate_t;
 
signal ale_q : boolean;
signal psen_q : boolean;
signal prog_q : boolean;
signal rd_q : boolean;
signal wr_q : boolean;
 
 
-- The Machine Cycle marker.
signal second_cycle_q : boolean;
signal multi_cycle_q : boolean;
 
begin
 
-----------------------------------------------------------------------------
-- Verify the generics
-----------------------------------------------------------------------------
 
-- pragma translate_off
 
-- XTAL1 divide by 3 --------------------------------------------------------
assert (xtal_div_3_g = 1) or (xtal_div_3_g = 0)
report "xtal_div_3_g must be either 1 or 0!"
severity failure;
 
-- pragma translate_on
 
 
-----------------------------------------------------------------------------
-- Divide XTAL1 by 3 to derive Clock States.
-----------------------------------------------------------------------------
use_xtal_div: if xtal_div_3_g = 1 generate
xtal: process (res_i, xtal_i)
begin
if res_i = res_active_c then
xtal_q <= TO_UNSIGNED(0, 2);
 
elsif xtal_i'event and xtal_i = clk_active_c then
if xtal_q < 2 then
xtal_q <= xtal_q + 1;
else
xtal_q <= TO_UNSIGNED(0, 2);
end if;
 
end if;
 
end process xtal;
 
x1_s <= '1'
when xtal_q = 0 else
'0';
x2_s <= '1'
when xtal_q = 1 else
'0';
x3_s <= '1'
when xtal_q = 2 else
'0';
 
end generate;
 
-----------------------------------------------------------------------------
-- XTAL1 is used directly for Clock States.
-----------------------------------------------------------------------------
no_xtal_div: if xtal_div_3_g = 0 generate
xtal_q <= TO_UNSIGNED(0, 2);
 
x1_s <= '1';
x2_s <= '1';
x3_s <= '1';
 
end generate;
 
-- And finally the boolean flags --------------------------------------------
xtal1_s <= to_boolean(x1_s);
xtal2_s <= to_boolean(x2_s);
xtal3_s <= to_boolean(x3_s);
 
 
-----------------------------------------------------------------------------
-- Process external_signal
--
-- Purpose:
-- Control signals ALE, PSEN, PROG and RD/WR are generated here.
--
external_signals: process (res_i, xtal_i)
begin
if res_i = res_active_c then
ale_q <= false;
psen_q <= false;
prog_q <= false;
rd_q <= false;
wr_q <= false;
 
elsif xtal_i'event and xtal_i = clk_active_c then
 
case mstate_q is
when MSTATE5 =>
-- RD, WR are set at the end of XTAL2 of first machine cycle
if xtal2_s and not second_cycle_q then
if assert_rd_i then
rd_q <= true;
end if;
if assert_wr_i then
wr_q <= true;
end if;
end if;
 
when MSTATE1 =>
if xtal3_s then
psen_q <= false;
end if;
 
when MSTATE2 =>
if xtal2_s then
-- RD, WR are removed at the end of XTAL3 of second machine cycle
rd_q <= false;
wr_q <= false;
-- PROG is removed at the and of XTAL3 of second machine cycle
prog_q <= false;
end if;
 
when MSTATE3 =>
-- ALE is set at the end of XTAL2 of every machine cycle
if xtal2_s then
ale_q <= true;
end if;
 
when MSTATE4 =>
if xtal3_s then
-- PSEN is set at the end of XTAL3
if assert_psen_i then
psen_q <= true;
end if;
 
end if;
 
-- PROG is set at the and of XTAL2
if xtal2_s and multi_cycle_q and not second_cycle_q and
assert_prog_i then
prog_q <= true;
end if;
 
-- ALE is removed at the end of XTAL2 of every machine cycle
if xtal2_s then
ale_q <= false;
end if;
 
when others =>
-- recover when states are out of sync
ale_q <= false;
psen_q <= false;
prog_q <= false;
rd_q <= false;
wr_q <= false;
 
end case;
 
end if;
 
end process external_signals;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process states
--
-- Purpose:
-- The Clock State controller.
--
states: process (res_i, clk_i)
begin
if res_i = res_active_c then
-- Reset machine state to MSTATE3
-- This allows a proper instruction fetch for the first real instruction
-- after reset.
-- The MSTATE3 is part of a virtual NOP that has no MSTATE1 and MSTATE2.
mstate_q <= MSTATE3;
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
case mstate_q is
when MSTATE5 =>
mstate_q <= MSTATE1;
 
when MSTATE1 =>
mstate_q <= MSTATE2;
 
when MSTATE2 =>
mstate_q <= MSTATE3;
 
when MSTATE3 =>
mstate_q <= MSTATE4;
 
when MSTATE4 =>
mstate_q <= MSTATE5;
 
when others =>
-- recover when states are out of sync
mstate_q <= MSTATE1;
 
-- pragma translate_off
assert false
report "Encoding of Clock States failed!"
severity error;
-- pragma translate_on
 
end case;
 
end if;
 
end if;
 
end process states;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process machine_cycle
--
-- Purpose:
-- Keep track of machine cycles.
-- Basically, this means to differ between first and second cycle.
--
machine_cycle: process (res_i, clk_i)
variable state2_v, state5_v : boolean;
begin
if res_i = res_active_c then
multi_cycle_q <= false;
second_cycle_q <= false;
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
state2_v := mstate_q = MSTATE2;
state5_v := mstate_q = MSTATE5;
-- multi cycle information is delivered in State 2 from the decoder
if state2_v and multi_cycle_i then
multi_cycle_q <= true;
end if;
 
-- mark second machine cycle
if multi_cycle_q and state5_v then
second_cycle_q <= true;
end if;
 
-- reset at end of second machine cycle
if state5_v and
(multi_cycle_q and second_cycle_q) then
multi_cycle_q <= false;
second_cycle_q <= false;
end if;
 
end if;
 
end if;
 
end process machine_cycle;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Output assignments
-----------------------------------------------------------------------------
xtal3_o <= xtal3_s;
mstate_o <= mstate_q;
second_cycle_o <= second_cycle_q;
ale_o <= ale_q;
psen_o <= psen_q;
prog_o <= prog_q;
rd_o <= rd_q;
wr_o <= wr_q;
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.3 2004/04/18 18:56:23 arniml
-- reset machine state to MSTATE3 to allow proper instruction fetch
-- after reset
--
-- Revision 1.2 2004/03/28 12:55:06 arniml
-- move code for PROG out of if-branch for xtal3_s
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------
/vhdl/p2.vhd
0,0 → 1,206
-------------------------------------------------------------------------------
--
-- The Port 2 unit.
-- Implements the Port 2 logic.
--
-- $Id: p2.vhd,v 1.4 2004-04-24 23:44:25 arniml Exp $
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_t;
use work.t48_pack.nibble_t;
 
entity p2 is
 
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
write_p2_i : in boolean;
write_exp_i : in boolean;
read_p2_i : in boolean;
read_reg_i : in boolean;
read_exp_i : in boolean;
-- Port 2 Interface -------------------------------------------------------
output_pch_i : in boolean;
output_exp_i : in boolean;
pch_i : in nibble_t;
p2_i : in word_t;
p2_o : out word_t;
p2_low_imp_o : out std_logic
);
 
end p2;
 
 
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
 
architecture rtl of p2 is
 
-- the port output register
signal p2_q : word_t;
 
-- the low impedance marker
signal low_imp_q : std_logic;
 
-- the expander register
signal exp_q : nibble_t;
 
begin
 
-----------------------------------------------------------------------------
-- Process p2_regs
--
-- Purpose:
-- Implements the port output and expander registers.
--
p2_regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
p2_q <= (others => '1');
low_imp_q <= '0';
exp_q <= (others => '0');
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
if write_p2_i then
p2_q <= data_i;
low_imp_q <= '1';
else
low_imp_q <= '0';
end if;
 
if write_exp_i then
exp_q <= data_i(exp_q'range);
end if;
 
end if;
 
end if;
 
end process p2_regs;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process p2_port
--
-- Purpose:
-- Generates the output byte vector for Port 2.
--
p2_port: process (p2_q,
exp_q,
output_exp_i,
pch_i,
output_pch_i)
begin
p2_o <= p2_q;
 
if output_exp_i then
p2_o(nibble_t'range) <= exp_q;
end if;
 
if output_pch_i then
p2_o(nibble_t'range) <= pch_i;
end if;
 
end process p2_port;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process p2_data
--
-- Purpose:
-- Generates the T48 bus data.
--
p2_data: process (read_p2_i,
p2_i,
read_reg_i,
p2_q,
read_exp_i)
begin
data_o <= (others => bus_idle_level_c);
 
if read_p2_i then
data_o <= p2_i;
elsif read_reg_i then
data_o <= p2_q;
elsif read_exp_i then
data_o <= "0000" & p2_i(nibble_t'range);
end if;
 
end process p2_data;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
p2_low_imp_o <= low_imp_q;
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.3 2004/03/29 19:39:58 arniml
-- rename pX_limp to pX_low_imp
--
-- Revision 1.2 2004/03/28 13:11:43 arniml
-- rework Port 2 expander handling
--
-- Revision 1.1 2004/03/23 21:31:53 arniml
-- initial check-in
--
-------------------------------------------------------------------------------
/vhdl/pmem_ctrl.vhd
0,0 → 1,223
-------------------------------------------------------------------------------
--
-- The Program Memory control unit.
-- All operations related to the Program Memory are managed here.
--
-- $Id: pmem_ctrl.vhd,v 1.2 2004-04-24 23:44:25 arniml Exp $
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.pmem_addr_t;
use work.t48_pack.word_t;
use work.pmem_ctrl_pack.pmem_addr_ident_t;
 
entity pmem_ctrl is
 
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
write_pcl_i : in boolean;
read_pcl_i : in boolean;
write_pch_i : in boolean;
read_pch_i : in boolean;
inc_pc_i : in boolean;
write_pmem_addr_i : in boolean;
addr_type_i : in pmem_addr_ident_t;
read_pmem_i : in boolean;
-- Porgram Memroy Interface -----------------------------------------------
pmem_addr_o : out pmem_addr_t;
pmem_data_i : in word_t
);
 
end pmem_ctrl;
 
 
library ieee;
use ieee.numeric_std.all;
 
use work.pmem_ctrl_pack.all;
use work.t48_pack.res_active_c;
use work.t48_pack.clk_active_c;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.pmem_addr_width_c;
use work.t48_pack.dmem_addr_width_c;
use work.t48_pack.page_t;
 
architecture rtl of pmem_ctrl is
 
-- the Program Counter
signal program_counter_q : unsigned(pmem_addr_t'range);
 
-- the Program Memory address
signal pmem_addr_s,
pmem_addr_q : std_logic_vector(pmem_addr_t'range);
 
begin
 
-----------------------------------------------------------------------------
-- Process program_counter
--
-- Purpose:
-- Implements the Program Counter.
--
program_counter: process (res_i, clk_i)
begin
if res_i = res_active_c then
program_counter_q <= (others => '0');
pmem_addr_q <= (others => '0');
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
-- parallel load mode
if write_pcl_i then
program_counter_q(data_i'range) <= UNSIGNED(data_i);
elsif write_pch_i then
program_counter_q(pmem_addr_width_c-1 downto data_i'high+1) <=
UNSIGNED(data_i(pmem_addr_width_c - dmem_addr_width_c - 1 downto 0));
elsif inc_pc_i then
-- increment mode
program_counter_q <= program_counter_q + 1;
end if;
 
-- set pmem address
if write_pmem_addr_i then
pmem_addr_q <= pmem_addr_s;
end if;
 
end if;
 
end if;
 
end process program_counter;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process pmem_addr
--
-- Purpose:
-- Multiplex the Program Memory address.
--
pmem_addr: process (program_counter_q,
addr_type_i,
pmem_addr_q,
data_i)
begin
-- default assignment
pmem_addr_s <= STD_LOGIC_VECTOR(program_counter_q);
case addr_type_i is
when PM_PC =>
-- default is ok
null;
 
when PM_PAGE =>
pmem_addr_s(word_t'range) <= data_i;
-- take page address from program counter
-- => important for JMPP, MOVP!
-- they must wrap to next page when at FF!
 
when PM_PAGE3 =>
pmem_addr_s(word_t'range) <= data_i;
-- page address is explicitely specified
pmem_addr_s(page_t'range) <= "0011";
 
when others =>
null;
 
end case;
 
end process pmem_addr;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process data_output
--
-- Purpose:
-- Multiplex the data bus output.
--
data_output: process (read_pmem_i,
read_pcl_i,
read_pch_i,
pmem_data_i,
program_counter_q)
begin
data_o <= (others => bus_idle_level_c);
 
if read_pmem_i then
data_o <= pmem_data_i;
elsif read_pcl_i then
data_o <= STD_LOGIC_VECTOR(program_counter_q(data_o'range));
elsif read_pch_i then
data_o(3 downto 0) <= STD_LOGIC_VECTOR(program_counter_q(pmem_addr_width_c-1 downto data_o'high+1));
end if;
 
end process data_output;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
pmem_addr_o <= pmem_addr_q;
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.1 2004/03/23 21:31:53 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------
/vhdl/psw.vhd
0,0 → 1,232
-------------------------------------------------------------------------------
--
-- The Program Status Word (PSW).
-- Implements the PSW with its special bits.
--
-- $Id: psw.vhd,v 1.6 2004-04-24 23:44:25 arniml Exp $
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_t;
 
entity psw is
 
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
read_psw_i : in boolean;
read_sp_i : in boolean;
write_psw_i : in boolean;
write_sp_i : in boolean;
-- Decoder Interface ------------------------------------------------------
special_data_i : in std_logic;
inc_stackp_i : in boolean;
dec_stackp_i : in boolean;
write_carry_i : in boolean;
write_aux_carry_i : in boolean;
write_f0_i : in boolean;
write_bs_i : in boolean;
carry_o : out std_logic;
aux_carry_i : in std_logic;
aux_carry_o : out std_logic;
f0_o : out std_logic;
bs_o : out std_logic
);
 
end psw;
 
 
library ieee;
use ieee.numeric_std.all;
 
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.nibble_t;
 
architecture rtl of psw is
 
-- special bit positions in PSW
constant carry_c : natural := 3;
constant aux_carry_c : natural := 2;
constant f0_c : natural := 1;
constant bs_c : natural := 0;
 
-- the PSW register
signal psw_q : nibble_t;
-- the Stack Pointer
signal sp_q : unsigned(2 downto 0);
 
-- pragma translate_off
signal psw_s : word_t;
-- pragma translate_on
 
begin
 
-----------------------------------------------------------------------------
-- Process psw_reg
--
-- Purpose:
-- Implements the PSW register.
--
psw_reg: process (res_i, clk_i)
begin
if res_i = res_active_c then
psw_q <= (others => '0');
sp_q <= (others => '0');
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
-- T48 bus access
if write_psw_i then
psw_q <= data_i(7 downto 4);
end if;
if write_sp_i then
sp_q <= unsigned(data_i(2 downto 0));
end if;
 
-- increment Stack Pointer
if inc_stackp_i then
sp_q <= sp_q + 1;
end if;
-- decrement Stack Pointer
if dec_stackp_i then
sp_q <= sp_q - 1;
end if;
 
-- access to special bits
if write_carry_i then
psw_q(carry_c) <= special_data_i;
end if;
--
if write_aux_carry_i then
psw_q(aux_carry_c) <= aux_carry_i;
end if;
--
if write_f0_i then
psw_q(f0_c) <= special_data_i;
end if;
--
if write_bs_i then
psw_q(bs_c) <= special_data_i;
end if;
 
end if;
 
end if;
 
end process psw_reg;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process data_out
--
-- Purpose:
-- Output multiplexer for T48 Data Bus.
--
data_out: process (read_psw_i,
read_sp_i,
psw_q,
sp_q)
begin
data_o <= (others => bus_idle_level_c);
 
if read_psw_i then
data_o(7 downto 4) <= psw_q;
end if;
 
if read_sp_i then
data_o(3 downto 0) <= '1' & std_logic_vector(sp_q);
end if;
 
end process data_out;
--
-----------------------------------------------------------------------------
 
 
-- pragma translate_off
tb: process (psw_q, sp_q)
begin
psw_s(7 downto 4) <= psw_q;
psw_s(3) <= '1';
psw_s(2 downto 0) <= std_logic_vector(sp_q);
end process tb;
-- pragma translate_on
 
-----------------------------------------------------------------------------
-- Output mapping.
-----------------------------------------------------------------------------
carry_o <= psw_q(carry_c);
aux_carry_o <= psw_q(aux_carry_c);
f0_o <= psw_q(f0_c);
bs_o <= psw_q(bs_c);
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.5 2004/04/24 11:25:39 arniml
-- removed dummy_s - workaround not longer needed for GHDL 0.11.1
--
-- Revision 1.4 2004/04/18 18:59:01 arniml
-- add temporary workaround for GHDL 0.11
--
-- Revision 1.3 2004/04/04 14:15:45 arniml
-- add dump_compare support
--
-- Revision 1.2 2004/03/28 21:28:13 arniml
-- take auxiliary carry from direct ALU connection
--
-- Revision 1.1 2004/03/23 21:31:53 arniml
-- initial check-in
--
-------------------------------------------------------------------------------
/vhdl/alu.vhd
0,0 → 1,443
-------------------------------------------------------------------------------
--
-- The Arithmetic Logic Unit (ALU).
-- It contains the ALU core plus the Accumulator and the Temp Reg.
--
-- $Id: alu.vhd,v 1.8 2004-04-24 23:43:56 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_t;
use work.alu_pack.alu_op_t;
 
entity alu is
 
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
write_accu_i : in boolean;
write_shadow_i : in boolean;
write_temp_reg_i : in boolean;
read_alu_i : in boolean;
-- Decoder Interface ------------------------------------------------------
carry_i : in std_logic;
carry_o : out std_logic;
aux_carry_o : out std_logic;
alu_op_i : in alu_op_t;
use_carry_i : in boolean;
da_high_i : in boolean;
da_overflow_o : out boolean;
accu_low_i : in boolean;
p06_temp_reg_i : in boolean;
p60_temp_reg_i : in boolean
);
 
end alu;
 
 
library ieee;
use ieee.numeric_std.all;
 
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.nibble_t;
use work.alu_pack.all;
 
-- pragma translate_off
use work.t48_tb_pack.tb_accu_s;
-- pragma translate_on
 
architecture rtl of alu is
 
-- the Accumulator and Temp Reg
signal accumulator_q,
accu_shadow_q,
temp_req_q : word_t;
-- inputs to the ALU core
signal in_a_s,
in_b_s : word_t;
-- output of the ALU core
signal data_s : word_t;
 
signal add_result_s : alu_operand_t;
 
begin
 
-----------------------------------------------------------------------------
-- Process working_regs
--
-- Purpose:
-- Implements the working registers:
-- + Accumulator
-- + Temp Reg
--
working_regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
accumulator_q <= (others => '0');
accu_shadow_q <= (others => '0');
temp_req_q <= (others => '0');
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
if write_accu_i then
if accu_low_i then
accumulator_q(nibble_t'range) <= data_i(nibble_t'range);
else
accumulator_q <= data_i;
end if;
end if;
 
if write_shadow_i then
-- write shadow directly from t48 data bus
accu_shadow_q <= data_i;
else
-- default: update shadow Accumulator from real Accumulator
accu_shadow_q <= accumulator_q;
end if;
 
if p06_temp_reg_i then
-- low nibble of DA sequence
temp_req_q <= "00000110";
elsif p60_temp_reg_i then
-- high nibble of DA sequence
temp_req_q <= "01100000";
elsif write_temp_reg_i then
-- normal load from T48 bus
temp_req_q <= data_i;
end if;
 
end if;
 
end if;
 
end process working_regs;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Build the inputs to the ALU core.
-- Input A:
-- Unary operators use only Input A.
-- Is always fed from the shadow Accumulator.
-- Assumption: It never happens that the Accumulator is written and then
-- read for an ALU operation in the next cycle.
-- Its contents can thus be staged through the shadow Accu.
-- Input B:
-- Is always fed from the Temp Reg.
-----------------------------------------------------------------------------
in_a_s <= accu_shadow_q;
in_b_s <= temp_req_q;
 
 
-----------------------------------------------------------------------------
-- Process alu_core
--
-- Purpose:
-- Implements the ALU core.
-- All operations defined in alu_op_t are handled here.
--
alu_core: process (in_a_s,
in_b_s,
alu_op_i,
carry_i,
use_carry_i,
add_result_s)
 
begin
-- default assigments
data_s <= (others => '0');
carry_o <= '0';
 
case alu_op_i is
-- Operation: AND -------------------------------------------------------
when ALU_AND =>
data_s <= in_a_s and in_b_s;
 
-- Operation: OR --------------------------------------------------------
when ALU_OR =>
data_s <= in_a_s or in_b_s;
 
-- Operation: XOR -------------------------------------------------------
when ALU_XOR =>
data_s <= in_a_s xor in_b_s;
 
-- Operation: Add -------------------------------------------------------
when ALU_ADD =>
data_s <= add_result_s(data_s'range);
carry_o <= add_result_s(add_result_s'high);
 
-- Operation: CPL -------------------------------------------------------
when ALU_CPL =>
data_s <= not in_a_s;
 
-- Operation: CLR -------------------------------------------------------
when ALU_CLR =>
data_s <= (others => '0');
 
-- Operation: RL --------------------------------------------------------
when ALU_RL =>
data_s(7 downto 1) <= in_a_s(6 downto 0);
carry_o <= in_a_s(7);
 
if use_carry_i then
data_s(0) <= carry_i;
else
data_s(0) <= in_a_s(7);
end if;
 
-- Operation: RR --------------------------------------------------------
when ALU_RR =>
data_s(6 downto 0) <= in_a_s(7 downto 1);
carry_o <= in_a_s(0);
 
if use_carry_i then
data_s(7) <= carry_i;
else
data_s(7) <= in_a_s(0);
end if;
 
-- Operation: Swap ------------------------------------------------------
when ALU_SWAP =>
data_s(3 downto 0) <= in_a_s(7 downto 4);
data_s(7 downto 4) <= in_a_s(3 downto 0);
 
-- Operation: DEC -------------------------------------------------------
when ALU_DEC =>
data_s <= add_result_s(data_s'range);
 
-- Operation: INC -------------------------------------------------------
when ALU_INC =>
data_s <= add_result_s(data_s'range);
 
-- Operation CONCAT -----------------------------------------------------
when ALU_CONCAT =>
data_s <= in_b_s(7 downto 4) & in_a_s(3 downto 0);
 
-- Operation: NOP -------------------------------------------------------
when ALU_NOP =>
data_s <= in_a_s;
 
when others =>
-- pragma translate_off
assert false
report "Unknown ALU operation selected!"
severity error;
-- pragma translate_on
 
end case;
 
end process alu_core;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process adder
--
-- Purpose:
-- Implements the adder used by several instructions.
-- This way of modelling the adder forces resource sharing of:
-- * ADD
-- * INC
-- * DEC
--
adder: process (in_a_s,
in_b_s,
alu_op_i,
carry_i,
use_carry_i)
 
variable add_a_v, add_b_v : alu_operand_t;
variable c_v : alu_operand_t;
variable result_v : UNSIGNED(alu_operand_t'range);
variable aux_c_v : std_logic_vector(1 downto 0);
 
begin
-- Carry Selection --------------------------------------------------------
c_v := (others => '0');
if use_carry_i and carry_i = '1' then
c_v(0) := '1';
end if;
 
-- Operand Selection ------------------------------------------------------
-- defaults for ADD
add_a_v := '0' & in_a_s;
add_b_v := '0' & in_b_s;
 
case alu_op_i is
when ALU_INC =>
add_b_v := (others => '0');
add_b_v(0) := '1';
when ALU_DEC =>
add_b_v := (others => '1');
when others =>
null;
end case;
 
-- The Adder --------------------------------------------------------------
result_v := UNSIGNED(add_a_v) +
UNSIGNED(add_b_v) +
UNSIGNED(c_v);
 
add_result_s <= std_logic_vector(result_v);
 
-- Auxiliary Carry --------------------------------------------------------
aux_c_v := in_a_s(4) & in_b_s(4);
 
aux_carry_o <= '0';
case aux_c_v is
when "00" | "11" =>
if result_v(4) = '1' then
aux_carry_o <= '1';
end if;
 
when "01" | "10" =>
if result_v(4) = '0' then
aux_carry_o <= '1';
end if;
 
when others =>
null;
 
end case;
 
end process adder;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process da_overflow
--
-- Purpose:
-- Detect overflow situation during DA sequence.
--
da_overflow: process (accu_shadow_q,
da_high_i)
 
variable da_nibble_v : nibble_t;
 
function da_overflow_f(data : in nibble_t) return boolean is
variable overflow_v : boolean;
begin
case data is
when "1010" |
"1011" |
"1100" |
"1101" |
"1110" |
"1111" =>
overflow_v := true;
when others =>
overflow_v := false;
end case;
 
return(overflow_v);
end;
 
begin
if da_high_i then
da_nibble_v := accu_shadow_q(7 downto 4);
else
da_nibble_v := accu_shadow_q(3 downto 0);
end if;
 
da_overflow_o <= da_overflow_f(da_nibble_v);
 
end process da_overflow;
--
-----------------------------------------------------------------------------
 
 
-- pragma translate_off
-----------------------------------------------------------------------------
-- Testbench support.
-----------------------------------------------------------------------------
tb_accu_s <= accumulator_q;
-- pragma translate_on
 
-----------------------------------------------------------------------------
-- Output Multiplexer.
-----------------------------------------------------------------------------
data_o <= data_s
when read_alu_i else
(others => bus_idle_level_c);
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.7 2004/04/07 22:09:03 arniml
-- remove unused signals
--
-- Revision 1.6 2004/04/07 20:56:23 arniml
-- default assignment for aux_carry_o
--
-- Revision 1.5 2004/04/06 20:21:53 arniml
-- fix sensitivity list
--
-- Revision 1.4 2004/04/06 18:10:41 arniml
-- rework adder and force resource sharing between ADD, INC and DEC
--
-- Revision 1.3 2004/04/04 14:18:52 arniml
-- add measures to implement XCHD
--
-- Revision 1.2 2004/03/28 21:08:51 arniml
-- support for DA instruction
--
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
-------------------------------------------------------------------------------
/vhdl/timer.vhd
0,0 → 1,261
-------------------------------------------------------------------------------
--
-- The Timer/Counter unit.
--
-- $Id: timer.vhd,v 1.2 2004-04-15 22:05:13 arniml Exp $
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_t;
use work.t48_pack.mstate_t;
 
entity timer is
 
generic (
-- state in which T1 is sampled (3 or 4)
sample_t1_state_g : integer := 4
);
 
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
t1_i : in std_logic;
clk_mstate_i : in mstate_t;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
read_timer_i : in boolean;
write_timer_i : in boolean;
-- Decoder Interface ------------------------------------------------------
start_t_i : in boolean;
start_cnt_i : in boolean;
stop_tcnt_i : in boolean;
overflow_o : out std_logic
);
 
end timer;
 
 
library ieee;
use ieee.numeric_std.all;
 
use work.t48_pack.all;
 
architecture rtl of timer is
 
-- the 8 bit counter core
signal counter_q : unsigned(word_t'range);
signal overflow_q : boolean;
 
-- increment signal for the counter core
type inc_type_t is (NONE, TIMER, COUNTER);
signal increment_s : boolean;
signal inc_sel_q : inc_type_t;
 
-- T1 edge detector
signal t1_q : std_logic;
signal t1_inc_s : boolean;
 
-- timer prescaler
signal prescaler_q : unsigned(4 downto 0);
signal pre_inc_s : boolean;
 
begin
 
-----------------------------------------------------------------------------
-- Verify the generics
-----------------------------------------------------------------------------
 
-- pragma translate_off
assert (sample_t1_state_g = 3) or (sample_t1_state_g = 4)
report "sample_t1_state_g must be either 3 or 4!"
severity failure;
-- pragma translate_on
 
 
-----------------------------------------------------------------------------
-- Process t1_edge
--
-- Purpose:
-- Implements the edge detector for T1.
--
t1_edge: process (t1_i,
t1_q,
clk_mstate_i)
begin
t1_inc_s <= false;
 
-- sample in state according to generic
-- Old devices: sample at the beginning of state 3
-- New devices: sample in state 4
if (sample_t1_state_g = 3 and clk_mstate_i = MSTATE3) or
(sample_t1_state_g = 4 and clk_mstate_i = MSTATE3) then
-- detect falling edge
if t1_q = '1' and t1_i = '0' then
t1_inc_s <= true;
end if;
end if;
 
end process t1_edge;
--
-----------------------------------------------------------------------------
 
 
pre_inc_s <= clk_mstate_i = MSTATE4 and prescaler_q = 31;
 
 
-----------------------------------------------------------------------------
-- Process inc_sel
--
-- Purpose:
-- Select increment source (timer, counter or none).
--
inc_sel: process (inc_sel_q,
pre_inc_s,
t1_inc_s)
begin
-- default assignment
increment_s <= false;
 
case inc_sel_q is
when NONE =>
increment_s <= false;
when TIMER =>
increment_s <= pre_inc_s;
when COUNTER =>
increment_s <= t1_inc_s;
when others =>
null;
end case;
 
end process inc_sel;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process regs
--
-- Purpose:
-- Implements the counter, the prescaler and other registers.
--
regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
counter_q <= (others => '0');
overflow_q <= false;
t1_q <= '0';
prescaler_q <= (others => '0');
inc_sel_q <= NONE;
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
-- Counter Core and overflow ------------------------------------------
overflow_q <= false;
 
if write_timer_i then
counter_q <= unsigned(data_i);
 
elsif increment_s then
counter_q <= counter_q + 1;
 
if counter_q = 255 then
overflow_q <= true;
end if;
 
end if;
 
-- T1 edge detector ---------------------------------------------------
if (sample_t1_state_g = 3 and clk_mstate_i = MSTATE3) or
(sample_t1_state_g = 4 and clk_mstate_i = MSTATE4) then
t1_q <= t1_i;
end if;
 
-- Prescaler ----------------------------------------------------------
if start_t_i then
prescaler_q <= (others => '0');
 
elsif clk_mstate_i = MSTATE3 then
prescaler_q <= prescaler_q + 1;
 
end if;
 
-- Increment Selector -------------------------------------------------
if start_t_i then
inc_sel_q <= TIMER;
elsif start_cnt_i then
inc_sel_q <= COUNTER;
elsif stop_tcnt_i then
inc_sel_q <= NONE;
end if;
 
end if;
 
end if;
 
end process regs;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
data_o <= std_logic_vector(counter_q)
when read_timer_i else
(others => bus_idle_level_c);
overflow_o <= to_stdLogic(overflow_q);
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.1 2004/03/23 21:31:53 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------
/vhdl/t48_tb_pack-p.vhd
0,0 → 1,22
-------------------------------------------------------------------------------
--
-- $Id: t48_tb_pack-p.vhd,v 1.2 2004-04-14 20:53:54 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
package t48_tb_pack is
 
-- Instruction strobe visibility
signal tb_istrobe_s : std_logic;
 
-- Accumulator visibilty
signal tb_accu_s : std_logic_vector(7 downto 0);
 
end t48_tb_pack;
/vhdl/t48_comp_pack-p.vhd
0,0 → 1,391
-------------------------------------------------------------------------------
--
-- $Id: t48_comp_pack-p.vhd,v 1.6 2004-04-07 22:09:03 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.alu_pack.alu_op_t;
use work.cond_branch_pack.branch_conditions_t;
use work.cond_branch_pack.comp_value_t;
use work.decoder_pack.mnemonic_t;
use work.dmem_ctrl_pack.dmem_addr_ident_t;
use work.pmem_ctrl_pack.pmem_addr_ident_t;
use work.t48_pack.dmem_addr_t;
use work.t48_pack.pmem_addr_t;
use work.t48_pack.mstate_t;
use work.t48_pack.word_t;
use work.t48_pack.nibble_t;
 
package t48_comp_pack is
 
component alu
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
data_o : out word_t;
write_accu_i : in boolean;
write_shadow_i : in boolean;
write_temp_reg_i : in boolean;
read_alu_i : in boolean;
carry_i : in std_logic;
carry_o : out std_logic;
aux_carry_o : out std_logic;
alu_op_i : in alu_op_t;
use_carry_i : in boolean;
da_high_i : in boolean;
da_overflow_o : out boolean;
accu_low_i : in boolean;
p06_temp_reg_i : in boolean;
p60_temp_reg_i : in boolean
);
end component;
 
component bus_mux
port (
alu_data_i : in word_t;
bus_data_i : in word_t;
dec_data_i : in word_t;
dm_data_i : in word_t;
pm_data_i : in word_t;
p1_data_i : in word_t;
p2_data_i : in word_t;
psw_data_i : in word_t;
tim_data_i : in word_t;
data_o : out word_t
);
end component;
 
component clock_ctrl
generic (
xtal_div_3_g : integer := 1
);
port (
clk_i : in std_logic;
xtal_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
xtal3_o : out boolean;
multi_cycle_i : in boolean;
assert_psen_i : in boolean;
assert_prog_i : in boolean;
assert_rd_i : in boolean;
assert_wr_i : in boolean;
mstate_o : out mstate_t;
second_cycle_o : out boolean;
ale_o : out boolean;
psen_o : out boolean;
prog_o : out boolean;
rd_o : out boolean;
wr_o : out boolean
);
end component;
 
component cond_branch
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
compute_take_i : in boolean;
branch_cond_i : in branch_conditions_t;
take_branch_o : out boolean;
accu_i : in word_t;
t0_i : in std_logic;
t1_i : in std_logic;
int_n_i : in std_logic;
f0_i : in std_logic;
f1_i : in std_logic;
tf_i : in std_logic;
carry_i : in std_logic;
comp_value_i : in comp_value_t
);
end component;
 
component db_bus
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
ea_i : in std_logic;
data_i : in word_t;
data_o : out word_t;
write_bus_i : in boolean;
read_bus_i : in boolean;
output_pcl_i : in boolean;
bidir_bus_i : in boolean;
pcl_i : in word_t;
db_i : in word_t;
db_o : out word_t;
db_dir_o : out std_logic
);
end component;
 
component decoder
generic (
register_mnemonic_g : integer := 1
);
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
ea_i : in std_logic;
ale_i : in boolean;
int_n_i : in std_logic;
t0_dir_o : out std_logic;
data_i : in word_t;
data_o : out word_t;
alu_write_accu_o : out boolean;
alu_write_shadow_o : out boolean;
alu_write_temp_reg_o : out boolean;
alu_read_alu_o : out boolean;
bus_write_bus_o : out boolean;
bus_read_bus_o : out boolean;
dm_write_dmem_addr_o : out boolean;
dm_write_dmem_o : out boolean;
dm_read_dmem_o : out boolean;
p1_write_p1_o : out boolean;
p1_read_p1_o : out boolean;
p2_write_p2_o : out boolean;
p2_write_exp_o : out boolean;
p2_read_p2_o : out boolean;
pm_write_pcl_o : out boolean;
pm_read_pcl_o : out boolean;
pm_write_pch_o : out boolean;
pm_read_pch_o : out boolean;
pm_read_pmem_o : out boolean;
psw_read_psw_o : out boolean;
psw_read_sp_o : out boolean;
psw_write_psw_o : out boolean;
psw_write_sp_o : out boolean;
alu_carry_i : in std_logic;
alu_op_o : out alu_op_t;
alu_da_high_o : out boolean;
alu_accu_low_o : out boolean;
alu_da_overflow_i : in boolean;
alu_p06_temp_reg_o : out boolean;
alu_p60_temp_reg_o : out boolean;
alu_use_carry_o : out boolean;
bus_output_pcl_o : out boolean;
bus_bidir_bus_o : out boolean;
clk_multi_cycle_o : out boolean;
clk_assert_psen_o : out boolean;
clk_assert_prog_o : out boolean;
clk_assert_rd_o : out boolean;
clk_assert_wr_o : out boolean;
clk_mstate_i : in mstate_t;
clk_second_cycle_i : in boolean;
cnd_compute_take_o : out boolean;
cnd_branch_cond_o : out branch_conditions_t;
cnd_take_branch_i : in boolean;
cnd_comp_value_o : out comp_value_t;
cnd_f1_o : out std_logic;
cnd_tf_o : out std_logic;
dm_addr_type_o : out dmem_addr_ident_t;
tim_read_timer_o : out boolean;
tim_write_timer_o : out boolean;
tim_start_t_o : out boolean;
tim_start_cnt_o : out boolean;
tim_stop_tcnt_o : out boolean;
p1_read_reg_o : out boolean;
p2_read_reg_o : out boolean;
p2_read_exp_o : out boolean;
p2_output_pch_o : out boolean;
p2_output_exp_o : out boolean;
pm_inc_pc_o : out boolean;
pm_write_pmem_addr_o : out boolean;
pm_addr_type_o : out pmem_addr_ident_t;
psw_special_data_o : out std_logic;
psw_carry_i : in std_logic;
psw_aux_carry_i : in std_logic;
psw_f0_i : in std_logic;
psw_inc_stackp_o : out boolean;
psw_dec_stackp_o : out boolean;
psw_write_carry_o : out boolean;
psw_write_aux_carry_o : out boolean;
psw_write_f0_o : out boolean;
psw_write_bs_o : out boolean;
tim_overflow_i : in boolean
);
end component;
 
component dmem_ctrl
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
write_dmem_addr_i : in boolean;
write_dmem_i : in boolean;
read_dmem_i : in boolean;
addr_type_i : in dmem_addr_ident_t;
bank_select_i : in std_logic;
data_o : out word_t;
dmem_data_i : in word_t;
dmem_addr_o : out dmem_addr_t;
dmem_we_o : out std_logic;
dmem_data_o : out word_t
);
end component;
 
component int
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
clk_mstate_i : in mstate_t;
jtf_executed_i : in boolean;
tim_overflow_i : in boolean;
tf_o : out std_logic;
en_tcnti_i : in boolean;
dis_tcnti_i : in boolean;
int_n_i : in std_logic;
ale_i : in boolean;
last_cycle_i : in boolean;
en_i_i : in boolean;
dis_i_i : in boolean;
ext_int_o : out boolean;
tim_int_o : out boolean;
retr_executed_i : in boolean;
int_executed_i : in boolean;
int_pending_o : out boolean
);
end component;
 
component opc_table
port (
opcode_i : in word_t;
multi_cycle_o : out std_logic;
mnemonic_o : out mnemonic_t
);
end component;
 
component opc_decoder
generic (
register_mnemonic_g : integer := 1
);
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
read_bus_i : in boolean;
inj_int_i : in boolean;
opcode_o : out word_t;
mnemonic_o : out mnemonic_t;
multi_cycle_o : out boolean
);
end component;
 
component timer
generic (
sample_t1_state_g : integer := 4
);
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
t1_i : in std_logic;
clk_mstate_i : in mstate_t;
data_i : in word_t;
data_o : out word_t;
read_timer_i : in boolean;
write_timer_i : in boolean;
start_t_i : in boolean;
start_cnt_i : in boolean;
stop_tcnt_i : in boolean;
overflow_o : out std_logic
);
end component;
 
component p1
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
data_o : out word_t;
write_p1_i : in boolean;
read_p1_i : in boolean;
read_reg_i : in boolean;
p1_i : in word_t;
p1_o : out word_t;
p1_low_imp_o : out std_logic
);
end component;
 
component p2
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
data_o : out word_t;
write_p2_i : in boolean;
write_exp_i : in boolean;
read_p2_i : in boolean;
read_reg_i : in boolean;
read_exp_i : in boolean;
output_pch_i : in boolean;
output_exp_i : in boolean;
pch_i : in nibble_t;
p2_i : in word_t;
p2_o : out word_t;
p2_low_imp_o : out std_logic
);
end component;
 
component pmem_ctrl
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
data_o : out word_t;
write_pcl_i : in boolean;
read_pcl_i : in boolean;
write_pch_i : in boolean;
read_pch_i : in boolean;
inc_pc_i : in boolean;
write_pmem_addr_i : in boolean;
addr_type_i : in pmem_addr_ident_t;
read_pmem_i : in boolean;
pmem_addr_o : out pmem_addr_t;
pmem_data_i : in word_t
);
end component;
 
component psw
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
data_i : in word_t;
data_o : out word_t;
read_psw_i : in boolean;
read_sp_i : in boolean;
write_psw_i : in boolean;
write_sp_i : in boolean;
special_data_i : in std_logic;
inc_stackp_i : in boolean;
dec_stackp_i : in boolean;
write_carry_i : in boolean;
write_aux_carry_i : in boolean;
write_f0_i : in boolean;
write_bs_i : in boolean;
carry_o : out std_logic;
aux_carry_i : in std_logic;
aux_carry_o : out std_logic;
f0_o : out std_logic;
bs_o : out std_logic
);
end component;
 
end t48_comp_pack;
/vhdl/alu_pack-p.vhd
0,0 → 1,46
-------------------------------------------------------------------------------
--
-- $Id: alu_pack-p.vhd,v 1.2 2004-04-04 14:18:53 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_width_c;
 
package alu_pack is
 
-----------------------------------------------------------------------------
-- The ALU operations
-----------------------------------------------------------------------------
type alu_op_t is (ALU_AND, ALU_OR, ALU_XOR,
ALU_CPL, ALU_CLR,
ALU_RL, ALU_RR,
ALU_SWAP,
ALU_DEC, ALU_INC,
ALU_ADD,
ALU_CONCAT,
ALU_NOP);
 
-----------------------------------------------------------------------------
-- The dedicated ALU arithmetic types.
-----------------------------------------------------------------------------
subtype alu_operand_t is std_logic_vector(word_width_c downto 0);
 
end alu_pack;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------
/vhdl/db_bus.vhd
0,0 → 1,148
-------------------------------------------------------------------------------
--
-- The BUS unit.
-- Implements the BUS port logic.
--
-- $Id: db_bus.vhd,v 1.2 2004-04-04 14:15:45 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_t;
 
entity db_bus is
 
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
ea_i : in std_logic;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
write_bus_i : in boolean;
read_bus_i : in boolean;
-- BUS Interface ----------------------------------------------------------
output_pcl_i : in boolean;
bidir_bus_i : in boolean;
pcl_i : in word_t;
db_i : in word_t;
db_o : out word_t;
db_dir_o : out std_logic
);
 
end db_bus;
 
 
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
use work.t48_pack.to_stdLogic;
 
architecture rtl of db_bus is
 
-- the BUS output register
signal bus_q : word_t;
 
-- BUS direction marker
signal db_dir_q : std_logic;
 
begin
 
-----------------------------------------------------------------------------
-- Process bus_regs
--
-- Purpose:
-- Implements the BUS output register.
--
bus_regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
bus_q <= (others => '0');
db_dir_q <= '0';
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
if write_bus_i then
bus_q <= data_i;
 
db_dir_q <= '1';
 
elsif ea_i = '1' or bidir_bus_i then
db_dir_q <= '0';
 
end if;
 
end if;
 
end if;
 
end process bus_regs;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
db_o <= pcl_i
when output_pcl_i else
bus_q;
db_dir_o <= db_dir_q or to_stdLogic(output_pcl_i);
data_o <= (others => bus_idle_level_c)
when not read_bus_i else
db_i;
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
--
-------------------------------------------------------------------------------
/vhdl/p1.vhd
0,0 → 1,138
-------------------------------------------------------------------------------
--
-- The Port 1 unit.
-- Implements the Port 1 logic.
--
-- $Id: p1.vhd,v 1.2 2004-03-29 19:39:58 arniml Exp $
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_t;
 
entity p1 is
 
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
data_o : out word_t;
write_p1_i : in boolean;
read_p1_i : in boolean;
read_reg_i : in boolean;
-- Port 1 Interface -------------------------------------------------------
p1_i : in word_t;
p1_o : out word_t;
p1_low_imp_o : out std_logic
);
 
end p1;
 
 
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.bus_idle_level_c;
 
architecture rtl of p1 is
 
-- the port output register
signal p1_q : word_t;
 
-- the low impedance marker
signal low_imp_q : std_logic;
 
begin
 
-----------------------------------------------------------------------------
-- Process p1_reg
--
-- Purpose:
-- Implements the port output register.
--
p1_reg: process (res_i, clk_i)
begin
if res_i = res_active_c then
p1_q <= (others => '1');
low_imp_q <= '0';
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
if write_p1_i then
p1_q <= data_i;
low_imp_q <= '1';
else
low_imp_q <= '0';
end if;
 
end if;
 
end if;
 
end process p1_reg;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
p1_o <= p1_q;
p1_low_imp_o <= low_imp_q;
data_o <= (others => bus_idle_level_c)
when not read_p1_i else
p1_q
when read_reg_i else
p1_i;
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
-------------------------------------------------------------------------------
/vhdl/t48_core_comp_pack-p.vhd
0,0 → 1,87
-------------------------------------------------------------------------------
--
-- $Id: t48_core_comp_pack-p.vhd,v 1.2 2004-03-29 19:39:58 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
package t48_core_comp_pack is
 
component t48_core
generic (
xtal_div_3_g : integer := 1;
register_mnemonic_g : integer := 1;
include_port1_g : integer := 1;
include_port2_g : integer := 1;
include_bus_g : integer := 1;
include_timer_g : integer := 1;
sample_t1_state_g : integer := 4
);
 
port (
xtal_i : in std_logic;
reset_i : in std_logic;
t0_i : in std_logic;
t0_o : out std_logic;
t0_dir_o : out std_logic;
int_n_i : in std_logic;
ea_i : in std_logic;
rd_n_o : out std_logic;
psen_n_o : out std_logic;
wr_n_o : out std_logic;
ale_o : out std_logic;
db_i : in std_logic_vector( 7 downto 0);
db_o : out std_logic_vector( 7 downto 0);
db_dir_o : out std_logic;
t1_i : in std_logic;
p2_i : in std_logic_vector( 7 downto 0);
p2_o : out std_logic_vector( 7 downto 0);
p2_low_imp_o : out std_logic;
p1_i : in std_logic_vector( 7 downto 0);
p1_o : out std_logic_vector( 7 downto 0);
p1_low_imp_o : out std_logic;
prog_n_o : out std_logic;
clk_i : in std_logic;
en_clk_i : in std_logic;
xtal3_o : out std_logic;
dmem_addr_o : out std_logic_vector( 7 downto 0);
dmem_we_o : out std_logic;
dmem_data_i : in std_logic_vector( 7 downto 0);
dmem_data_o : out std_logic_vector( 7 downto 0);
pmem_addr_o : out std_logic_vector(11 downto 0);
pmem_data_i : in std_logic_vector( 7 downto 0)
);
end component;
 
component syn_rom
generic (
address_width_g : positive := 10
);
port (
clk_i : in std_logic;
rom_addr_i : in std_logic_vector(address_width_g-1 downto 0);
rom_data_o : out std_logic_vector(7 downto 0)
);
end component;
 
component syn_ram
generic (
address_width_g : positive := 8
);
port (
clk_i : in std_logic;
res_i : in std_logic;
ram_addr_i : in std_logic_vector(address_width_g-1 downto 0);
ram_data_i : in std_logic_vector(7 downto 0);
ram_we_i : in std_logic;
ram_data_o : out std_logic_vector(7 downto 0)
);
end component;
 
end t48_core_comp_pack;
/vhdl/decoder_pack-p.vhd
0,0 → 1,84
-------------------------------------------------------------------------------
--
-- $Id: decoder_pack-p.vhd,v 1.2 2004-03-28 13:09:53 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
package decoder_pack is
 
-----------------------------------------------------------------------------
-- The Mnemonics.
-----------------------------------------------------------------------------
type mnemonic_t is (MN_ADD,
MN_ADD_A_DATA,
MN_ANL,
MN_ANL_A_DATA,
MN_ANL_EXT,
MN_CALL,
MN_CLR_A,
MN_CLR_C,
MN_CLR_F,
MN_CPL_A,
MN_CPL_C,
MN_CPL_F,
MN_DA,
MN_DEC,
MN_DIS_EN_I,
MN_DIS_EN_TCNTI,
MN_DJNZ,
MN_ENT0_CLK,
MN_IN,
MN_INC,
MN_INS,
MN_JBB,
MN_JC,
MN_JF,
MN_JMP,
MN_JMPP,
MN_JNI,
MN_JT,
MN_JTF,
MN_JZ,
MN_MOV_A_DATA,
MN_MOV_A_PSW,
MN_MOV_A_RR,
MN_MOV_PSW_A,
MN_MOV_RR,
MN_MOV_RR_DATA,
MN_MOV_T,
MN_MOVD_A_PP,
MN_MOVP,
MN_MOVX,
MN_NOP,
MN_ORL,
MN_ORL_A_DATA,
MN_ORL_EXT,
MN_OUTD_PP_A,
MN_OUTL_EXT,
MN_RET,
MN_RL,
MN_RR,
MN_SEL_MB,
MN_SEL_RB,
MN_STOP_TCNT,
MN_STRT,
MN_SWAP,
MN_XCH,
MN_XRL,
MN_XRL_A_DATA);
 
end decoder_pack;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
-------------------------------------------------------------------------------
/vhdl/opc_table.vhd
0,0 → 1,414
-------------------------------------------------------------------------------
--
-- The Opcode Decoder Table.
-- Decodes the given opcode to instruction mnemonics.
-- Also derives the multicycle information.
--
-- $Id: opc_table.vhd,v 1.2 2004-03-28 13:10:48 arniml Exp $
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_t;
use work.decoder_pack.mnemonic_t;
 
entity opc_table is
 
port (
opcode_i : in word_t;
multi_cycle_o : out std_logic;
mnemonic_o : out mnemonic_t
);
 
end opc_table;
 
 
use work.decoder_pack.all;
 
architecture rtl of opc_table is
 
begin
 
-----------------------------------------------------------------------------
-- Process opc_decode
--
-- Purpose:
-- Decode the opcode to the set of mnemonics.
--
opc_decode: process (opcode_i)
begin
-- default assignment
mnemonic_o <= MN_NOP;
multi_cycle_o <= '0';
 
case opcode_i is
-- Mnemonic ADD ---------------------------------------------------------
when "01101000" | "01101001" | "01101010" | "01101011" | -- ADD A, Rr
"01101100" | "01101101" | "01101110" | "01101111" | --
"01100000" | "01100001" | -- ADD A, @ Rr
"01111000" | "01111001" | "01111010" | "01111011" | -- ADDC A, Rr
"01111100" | "01111101" | "01111110" | "01111111" | --
"01110000" | "01110001" => -- ADDC A, @ Rr
mnemonic_o <= MN_ADD;
 
-- Mnemonic ADD_A_DATA --------------------------------------------------
when "00000011" | -- ADD A, data
"00010011" => -- ADDC A, data
mnemonic_o <= MN_ADD_A_DATA;
multi_cycle_o <= '1';
 
-- Mnemonic ANL ---------------------------------------------------------
when "01011000" | "01011001" | "01011010" | "01011011" | -- ANL A, Rr
"01011100" | "01011101" | "01011110" | "01011111" | --
"01010000" | "01010001" => -- ANL A, @ Rr
mnemonic_o <= MN_ANL;
 
-- Mnemonic ANL_A_DATA --------------------------------------------------
when "01010011" => -- ANL A, data
mnemonic_o <= MN_ANL_A_DATA;
multi_cycle_o <= '1';
 
-- Mnemonic ANL_EXT -----------------------------------------------------
when "10011000" | -- ANL BUS, data
"10011001" | "10011010" => -- ANL PP, data
mnemonic_o <= MN_ANL_EXT;
multi_cycle_o <= '1';
 
-- Mnemonic CALL --------------------------------------------------------
when "00010100" | "00110100" | "01010100" | "01110100" | -- CALL addr
"10010100" | "10110100" | "11010100" | "11110100" => --
mnemonic_o <= MN_CALL;
multi_cycle_o <= '1';
 
-- Mnemonic CLR_A -------------------------------------------------------
when "00100111" => -- CLR A
mnemonic_o <= MN_CLR_A;
 
-- Mnemonic CLR_C -------------------------------------------------------
when "10010111" => -- CLR C
mnemonic_o <= MN_CLR_C;
 
-- Mnemonic CLR_F -------------------------------------------------------
when "10000101" | -- CLR F0
"10100101" =>
mnemonic_o <= MN_CLR_F;
 
-- Mnemonic CPL_A -------------------------------------------------------
when "00110111" => -- CPL A
mnemonic_o <= MN_CPL_A;
 
-- Mnemonic CPL_C -------------------------------------------------------
when "10100111" => -- CPL C
mnemonic_o <= MN_CPL_C;
 
-- Mnemonic CPL_F -------------------------------------------------------
when "10010101" | -- CPL F0
"10110101" => -- CPL F1
mnemonic_o <= MN_CPL_F;
 
-- Mnemonic DA ----------------------------------------------------------
when "01010111" => -- DA D
mnemonic_o <= MN_DA;
 
-- Mnemonic DEC ---------------------------------------------------------
when "11001000" | "11001001" | "11001010" | "11001011" | -- DEC Rr
"11001100" | "11001101" | "11001110" | "11001111" | --
"00000111" => -- DEC A
mnemonic_o <= MN_DEC;
 
-- Mnemonic DIS_EN_I ----------------------------------------------------
when "00010101" | -- DIS I
"00000101" => -- EN I
mnemonic_o <= MN_DIS_EN_I;
 
-- Mnemonic DIS_EN_TCNTI ------------------------------------------------
when "00110101" | -- DIS TCNTI
"00100101" => -- EN TCNTI
mnemonic_o <= MN_DIS_EN_TCNTI;
 
-- Mnemonic DJNZ --------------------------------------------------------
when "11101000" | "11101001" | "11101010" | "11101011" | -- DJNZ Rr, addr
"11101100" | "11101101" | "11101110" | "11101111" => --
mnemonic_o <= MN_DJNZ;
multi_cycle_o <= '1';
 
-- Mnemonic ENT0_CLK ----------------------------------------------------
when "01110101" => -- ENT0 CLK
mnemonic_o <= MN_ENT0_CLK;
 
-- Mnemonic IN ----------------------------------------------------------
when "00001001" | "00001010" => -- IN A, Pp
mnemonic_o <= MN_IN;
multi_cycle_o <= '1';
 
-- Mnemonic INC ---------------------------------------------------------
when "00010111" | -- INC A
"00011000" | "00011001" | "00011010" | "00011011" | -- INC Rr
"00011100" | "00011101" | "00011110" | "00011111" | --
"00010000" | "00010001" => -- INC @ Rr
mnemonic_o <= MN_INC;
 
-- Mnemonic INS ---------------------------------------------------------
when "00001000" => -- INS A, BUS
mnemonic_o <= MN_INS;
multi_cycle_o <= '1';
 
-- Mnemonic JBB ---------------------------------------------------------
when "00010010" | "00110010" | "01010010" | "01110010" | -- JBb addr
"10010010" | "10110010" | "11010010" | "11110010" => --
mnemonic_o <= MN_JBB;
multi_cycle_o <= '1';
 
-- Mnemonic JC ----------------------------------------------------------
when "11110110" | -- JC addr
"11100110" => -- JNC addr
mnemonic_o <= MN_JC;
multi_cycle_o <= '1';
 
-- Mnemonic JF ----------------------------------------------------------
when "10110110" | -- JF0 addr
"01110110" => -- JF1 addr
mnemonic_o <= MN_JF;
multi_cycle_o <= '1';
 
-- Mnemonic JMP ---------------------------------------------------------
when "00000100" | "00100100" | "01000100" | "01100100" | -- JMP addr
"10000100" | "10100100" | "11000100" | "11100100" => --
mnemonic_o <= MN_JMP;
multi_cycle_o <= '1';
 
-- Mnemonic JMPP --------------------------------------------------------
when "10110011" => -- JMPP @ A
mnemonic_o <= MN_JMPP;
multi_cycle_o <= '1';
 
-- Mnemonic JNI ---------------------------------------------------------
when "10000110" => -- JNI addr
mnemonic_o <= MN_JNI;
multi_cycle_o <= '1';
 
-- Mnemonic JT ----------------------------------------------------------
when "00100110" | -- JNT0 addr
"01000110" | -- JNT1 addr
"00110110" | -- JT0 addr
"01010110" => -- JT1 addr
mnemonic_o <= MN_JT;
multi_cycle_o <= '1';
 
-- Mnemonic JTF ---------------------------------------------------------
when "00010110" => -- JTF addr
mnemonic_o <= MN_JTF;
multi_cycle_o <= '1';
 
-- Mnemonic JZ ----------------------------------------------------------
when "10010110" | -- JNZ addr
"11000110" => -- JZ addr
mnemonic_o <= MN_JZ;
multi_cycle_o <= '1';
 
-- Mnemonic MOV_A_DATA --------------------------------------------------
when "00100011" => -- MOV A, data
mnemonic_o <= MN_MOV_A_DATA;
multi_cycle_o <= '1';
 
-- Mnemonic MOV_A_PSW ---------------------------------------------------
when "11000111" => -- MOV A, PSW
mnemonic_o <= MN_MOV_A_PSW;
 
-- Mnemonic MOV_A_RR ----------------------------------------------------
when "11111000" | "11111001" | "11111010" | "11111011" | -- MOV A, Rr
"11111100" | "11111101" | "11111110" | "11111111" | --
"11110000" | "11110001" => -- MOV A, @ Rr
mnemonic_o <= MN_MOV_A_RR;
 
-- Mnemonic MOV_PSW_A ---------------------------------------------------
when "11010111" => -- MOV PSW, A
mnemonic_o <= MN_MOV_PSW_A;
 
-- Mnemonic MOV_RR ------------------------------------------------------
when "10101000" | "10101001" | "10101010" | "10101011" | -- MOV Rr, A
"10101100" | "10101101" | "10101110" | "10101111" | --
"10100000" | "10100001" => -- MOV @ Rr, A
mnemonic_o <= MN_MOV_RR;
 
-- Mnemonic MOV_RR_DATA -------------------------------------------------
when "10111000" | "10111001" | "10111010" | "10111011" | -- MOV Rr, data
"10111100" | "10111101" | "10111110" | "10111111" | --
"10110000" | "10110001" => -- MOV @ Rr, data
mnemonic_o <= MN_MOV_RR_DATA;
multi_cycle_o <= '1';
 
-- Mnemonic MOV_T -------------------------------------------------------
when "01100010" | -- MOV T, A
"01000010" => -- MOV A, T
mnemonic_o <= MN_MOV_T;
 
-- Mnemonic MOVD_A_PP ---------------------------------------------------
when "00001100" | "00001101" | "00001110" | "00001111" => -- MOVD A, Pp
mnemonic_o <= MN_MOVD_A_PP;
multi_cycle_o <= '1';
 
-- Mnemonic MOVP --------------------------------------------------------
when "10100011" | -- MOVP A, @ A
"11100011" => -- MOVP3 A, @ A
mnemonic_o <= MN_MOVP;
multi_cycle_o <= '1';
 
-- Mnemonic MOVX --------------------------------------------------------
when "10000000" | "10000001" | -- MOVX A, @ Rr
"10010000" | "10010001" => -- MOVX @ Rr, A
mnemonic_o <= MN_MOVX;
multi_cycle_o <= '1';
 
-- Mnemonic NOP ---------------------------------------------------------
when "00000000" => -- NOP
mnemonic_o <= MN_NOP;
 
-- Mnemonic ORL ---------------------------------------------------------
when "01001000" | "01001001" | "01001010" | "01001011" | -- ORL A, Rr
"01001100" | "01001101" | "01001110" | "01001111" | --
"01000000" | "01000001" => -- ORL A, @ Rr
mnemonic_o <= MN_ORL;
 
-- Mnemonic ORL_A_DATA --------------------------------------------------
when "01000011" => -- ORL A, data
mnemonic_o <= MN_ORL_A_DATA;
multi_cycle_o <= '1';
 
-- Mnemonic ORL_EXT -----------------------------------------------------
when "10001000" | -- ORL BUS, data
"10001001" | "10001010" => -- ORL Pp, data
mnemonic_o <= MN_ORL_EXT;
multi_cycle_o <= '1';
 
-- Mnemonic OUTD_PP_A ---------------------------------------------------
when "00111100" | "00111101" | "00111110" | "00111111" | -- MOVD Pp, A
"10011100" | "10011101" | "10011110" | "10011111" | -- ANLD PP, A
"10001100" | "10001101" | "10001110" | "10001111" => -- ORLD Pp, A
mnemonic_o <= MN_OUTD_PP_A;
multi_cycle_o <= '1';
 
-- Mnemonic OUTL_EXT ----------------------------------------------------
when "00111001" | "00111010" | -- OUTL Pp, A
"00000010" => -- OUTL BUS, A
mnemonic_o <= MN_OUTL_EXT;
multi_cycle_o <= '1';
 
-- Mnemonic RET ---------------------------------------------------------
when "10000011" | -- RET
"10010011" => -- RETR
mnemonic_o <= MN_RET;
multi_cycle_o <= '1';
 
-- Mnemonic RL ----------------------------------------------------------
when "11100111" | -- RL A
"11110111" => -- RLC A
mnemonic_o <= MN_RL;
 
-- Mnemonic RR ----------------------------------------------------------
when "01110111" | -- RR A
"01100111" => -- RRC A
mnemonic_o <= MN_RR;
 
-- Mnemonic SEL_MB ------------------------------------------------------
when "11100101" | -- SEL MB0
"11110101" => -- SEL MB1
mnemonic_o <= MN_SEL_MB;
 
-- Mnemonic SEL_RB ------------------------------------------------------
when "11000101" | -- SEL RB0
"11010101" => -- SEL RB1
mnemonic_o <= MN_SEL_RB;
 
-- Mnemonic STOP_TCNT ---------------------------------------------------
when "01100101" => -- STOP TCNT
mnemonic_o <= MN_STOP_TCNT;
 
-- Mnemonic START -------------------------------------------------------
when "01000101" | -- STRT CNT
"01010101" => -- STRT T
mnemonic_o <= MN_STRT;
 
-- Mnemonic SWAP --------------------------------------------------------
when "01000111" => -- SWAP A
mnemonic_o <= MN_SWAP;
 
-- Mnemonic XCH ---------------------------------------------------------
when "00101000" | "00101001" | "00101010" | "00101011" | -- XCH A, Rr
"00101100" | "00101101" | "00101110" | "00101111" | --
"00100000" | "00100001" | -- XCH A, @ Rr
"00110000" | "00110001" => -- XCHD A, @ Rr
mnemonic_o <= MN_XCH;
 
-- Mnemonic XRL ---------------------------------------------------------
when "11011000" | "11011001" | "11011010" | "11011011" | -- XRL A, Rr
"11011100" | "11011101" | "11011110" | "11011111" | --
"11010000" | "11010001" => -- XRL A, @ Rr
mnemonic_o <= MN_XRL;
 
-- Mnemonic XRL_A_DATA --------------------------------------------------
when "11010011" => -- XRL A, data
mnemonic_o <= MN_XRL_A_DATA;
multi_cycle_o <= '1';
 
when others =>
-- pragma translate_off
assert now = 0 ns
report "Unknown opcode."
severity warning;
-- pragma translate_on
 
end case;
 
end process opc_decode;
--
-----------------------------------------------------------------------------
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
-- Revision 1.1 2004/03/23 21:31:52 arniml
-- initial check-in
--
-------------------------------------------------------------------------------
/vhdl/clock_ctrl-c.vhd
0,0 → 1,14
-------------------------------------------------------------------------------
--
-- $Id: clock_ctrl-c.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- The clock control unit.
--
-------------------------------------------------------------------------------
 
configuration clock_ctrl_rtl_c0 of clock_ctrl is
 
for rtl
end for;
 
end clock_ctrl_rtl_c0;
/vhdl/p1-c.vhd
0,0 → 1,17
-------------------------------------------------------------------------------
--
-- The Port 1 unit.
-- Implements the Port 1 logic.
--
-- $Id: p1-c.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration p1_rtl_c0 of p1 is
 
for rtl
end for;
 
end p1_rtl_c0;
/vhdl/timer-c.vhd
0,0 → 1,16
-------------------------------------------------------------------------------
--
-- The Timer/Counter unit.
--
-- $Id: timer-c.vhd,v 1.1 2004-03-23 21:31:53 arniml Exp $
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration timer_rtl_c0 of timer is
 
for rtl
end for;
 
end timer_rtl_c0;
/vhdl/p2-c.vhd
0,0 → 1,17
-------------------------------------------------------------------------------
--
-- The Port 2 unit.
-- Implements the Port 2 logic.
--
-- $Id: p2-c.vhd,v 1.1 2004-03-23 21:31:53 arniml Exp $
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration p2_rtl_c0 of p2 is
 
for rtl
end for;
 
end p2_rtl_c0;
/vhdl/dmem_ctrl_pack-p.vhd
0,0 → 1,29
-------------------------------------------------------------------------------
--
-- $Id: dmem_ctrl_pack-p.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
package dmem_ctrl_pack is
 
-----------------------------------------------------------------------------
-- Address Type Identifier
-----------------------------------------------------------------------------
type dmem_addr_ident_t is (DM_PLAIN,
DM_REG,
DM_STACK,
DM_STACK_HIGH);
 
end dmem_ctrl_pack;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
--
-------------------------------------------------------------------------------
/vhdl/pmem_ctrl-c.vhd
0,0 → 1,17
-------------------------------------------------------------------------------
--
-- The Program Memory control unit.
-- All operations related to the Program Memory are managed here.
--
-- $Id: pmem_ctrl-c.vhd,v 1.1 2004-03-23 21:31:53 arniml Exp $
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration pmem_ctrl_rtl_c0 of pmem_ctrl is
 
for rtl
end for;
 
end pmem_ctrl_rtl_c0;
/vhdl/bus_mux-c.vhd
0,0 → 1,19
-------------------------------------------------------------------------------
--
-- The T48 Bus Connector.
-- Multiplexes all drivers of the T48 bus.
--
-- $Id: bus_mux-c.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration bus_mux_rtl_c0 of bus_mux is
 
for rtl
end for;
 
end bus_mux_rtl_c0;
/vhdl/opc_table-c.vhd
0,0 → 1,18
-------------------------------------------------------------------------------
--
-- The Opcode Decoder Table.
-- Decodes the given opcode to instruction mnemonics.
-- Also derives the multicycle information.
--
-- $Id: opc_table-c.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration opc_table_rtl_c0 of opc_table is
 
for rtl
end for;
 
end opc_table_rtl_c0;
/vhdl/pmem_ctrl_pack-p.vhd
0,0 → 1,28
-------------------------------------------------------------------------------
--
-- $Id: pmem_ctrl_pack-p.vhd,v 1.1 2004-03-23 21:31:53 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
package pmem_ctrl_pack is
 
-----------------------------------------------------------------------------
-- Address Type Identifier
-----------------------------------------------------------------------------
type pmem_addr_ident_t is (PM_PC,
PM_PAGE,
PM_PAGE3);
 
end pmem_ctrl_pack;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
--
-------------------------------------------------------------------------------
/vhdl/db_bus-c.vhd
0,0 → 1,19
-------------------------------------------------------------------------------
--
-- The BUS unit.
-- Implements the BUS port logic.
--
-- $Id: db_bus-c.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration db_bus_rtl_c0 of db_bus is
 
for rtl
end for;
 
end db_bus_rtl_c0;
/vhdl/bus_mux.vhd
0,0 → 1,108
-------------------------------------------------------------------------------
--
-- The T48 Bus Connector.
-- Multiplexes all drivers of the T48 bus.
--
-- $Id: bus_mux.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_t;
 
entity bus_mux is
 
port (
alu_data_i : in word_t;
bus_data_i : in word_t;
dec_data_i : in word_t;
dm_data_i : in word_t;
pm_data_i : in word_t;
p1_data_i : in word_t;
p2_data_i : in word_t;
psw_data_i : in word_t;
tim_data_i : in word_t;
data_o : out word_t
);
 
end bus_mux;
 
 
use work.t48_pack.bus_idle_level_c;
 
architecture rtl of bus_mux is
 
begin
 
or_tree: if bus_idle_level_c = '0' generate
data_o <= alu_data_i or
bus_data_i or
dec_data_i or
dm_data_i or
pm_data_i or
p1_data_i or
p2_data_i or
psw_data_i or
tim_data_i;
end generate;
 
and_tree: if bus_idle_level_c = '1' generate
data_o <= alu_data_i and
bus_data_i and
dec_data_i and
dm_data_i and
pm_data_i and
p1_data_i and
p2_data_i and
psw_data_i and
tim_data_i;
end generate;
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
--
-------------------------------------------------------------------------------
/vhdl/decoder-c.vhd
0,0 → 1,28
-------------------------------------------------------------------------------
--
-- The Decoder unit.
-- It decodes the instruction opcodes and executes them.
--
-- $Id: decoder-c.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration decoder_rtl_c0 of decoder is
 
for rtl
 
for opc_decoder_b: opc_decoder
use configuration work.opc_decoder_rtl_c0;
end for;
 
for int_b: int
use configuration work.int_rtl_c0;
end for;
 
end for;
 
end decoder_rtl_c0;
/vhdl/opc_decoder-c.vhd
0,0 → 1,23
-------------------------------------------------------------------------------
--
-- The Opcode Decoder.
-- Derives instruction mnemonics and multicycle information
-- using the OPC table unit.
--
-- $Id: opc_decoder-c.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration opc_decoder_rtl_c0 of opc_decoder is
 
for rtl
 
for opc_table_b: opc_table
use configuration work.opc_table_rtl_c0;
end for;
 
end for;
 
end opc_decoder_rtl_c0;
/vhdl/psw-c.vhd
0,0 → 1,17
-------------------------------------------------------------------------------
--
-- The Program Status Word (PSW).
-- Implements the PSW with its special bits.
--
-- $Id: psw-c.vhd,v 1.1 2004-03-23 21:31:53 arniml Exp $
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration psw_rtl_c0 of psw is
 
for rtl
end for;
 
end psw_rtl_c0;
/vhdl/alu-c.vhd
0,0 → 1,19
-------------------------------------------------------------------------------
--
-- The Arithmetic Logic Unit (ALU).
-- It contains the ALU core plus the Accumulator and the Temp Reg.
--
-- $Id: alu-c.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration alu_rtl_c0 of alu is
 
for rtl
end for;
 
end alu_rtl_c0;
/vhdl/opc_decoder.vhd
0,0 → 1,172
-------------------------------------------------------------------------------
--
-- The Opcode Decoder.
-- Derives instruction mnemonics and multicycle information
-- using the OPC table unit.
--
-- $Id: opc_decoder.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.word_t;
use work.decoder_pack.mnemonic_t;
 
entity opc_decoder is
 
generic (
-- store mnemonic in flip-flops (registered-out)
register_mnemonic_g : integer := 1
);
 
port (
-- Global Interface -------------------------------------------------------
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
-- T48 Bus Interface ------------------------------------------------------
data_i : in word_t;
read_bus_i : in boolean;
-- Decoder Interface ------------------------------------------------------
inj_int_i : in boolean;
opcode_o : out word_t;
mnemonic_o : out mnemonic_t;
multi_cycle_o : out boolean
);
 
end opc_decoder;
 
 
use work.t48_pack.clk_active_c;
use work.t48_pack.res_active_c;
use work.t48_pack.to_boolean;
--use work.decoder_pack.MN_NOP;
use work.decoder_pack.all;
 
use work.t48_comp_pack.opc_table;
 
architecture rtl of opc_decoder is
 
-- the opcode register
signal opcode_q : word_t;
 
-- the mnemonic
signal mnemonic_s,
mnemonic_q : mnemonic_t;
 
signal multi_cycle_s : std_logic;
 
begin
 
-----------------------------------------------------------------------------
-- Verify the generics
-----------------------------------------------------------------------------
 
-- pragma translate_off
 
-- Register Mnemonic --------------------------------------------------------
assert (register_mnemonic_g = 1) or (register_mnemonic_g = 0)
report "register_mnemonic_g must be either 1 or 0!"
severity failure;
 
-- pragma translate_on
 
 
-----------------------------------------------------------------------------
-- Opcode Decoder Table
-----------------------------------------------------------------------------
opc_table_b : opc_table
port map (
opcode_i => opcode_q,
multi_cycle_o => multi_cycle_s,
mnemonic_o => mnemonic_s
);
 
 
-----------------------------------------------------------------------------
-- Process regs
--
-- Purpose:
-- Implements the opcode and mnemonic registers.
--
regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
opcode_q <= (others => '0'); -- NOP
mnemonic_q <= MN_NOP;
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
if read_bus_i then
opcode_q <= data_i;
elsif inj_int_i then
opcode_q <= "00010100";
else
mnemonic_q <= mnemonic_s;
end if;
 
end if;
 
end if;
 
end process regs;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
opcode_o <= opcode_q;
multi_cycle_o <= to_boolean(multi_cycle_s);
mnemonic_o <= mnemonic_q
when register_mnemonic_g = 1 else
mnemonic_s;
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
--
-------------------------------------------------------------------------------
/vhdl/t48_core-c.vhd
0,0 → 1,71
-------------------------------------------------------------------------------
--
-- T48 Microcontroller Core
--
-- $Id: t48_core-c.vhd,v 1.1 2004-03-23 21:31:53 arniml Exp $
--
-------------------------------------------------------------------------------
 
configuration t48_core_struct_c0 of t48_core is
 
for struct
 
for alu_b : alu
use configuration work.alu_rtl_c0;
end for;
 
for bus_mux_b : bus_mux
use configuration work.bus_mux_rtl_c0;
end for;
 
for clock_ctrl_b : clock_ctrl
use configuration work.clock_ctrl_rtl_c0;
end for;
 
for cond_branch_b : cond_branch
use configuration work.cond_branch_rtl_c0;
end for;
 
for use_db_bus
for db_bus_b : db_bus
use configuration work.db_bus_rtl_c0;
end for;
end for;
 
for decoder_b : decoder
use configuration work.decoder_rtl_c0;
end for;
 
for dmem_ctrl_b : dmem_ctrl
use configuration work.dmem_ctrl_rtl_c0;
end for;
 
for use_timer
for timer_b : timer
use configuration work.timer_rtl_c0;
end for;
end for;
 
for use_p1
for p1_b : p1
use configuration work.p1_rtl_c0;
end for;
end for;
 
for use_p2
for p2_b : p2
use configuration work.p2_rtl_c0;
end for;
end for;
 
for pmem_ctrl_b : pmem_ctrl
use configuration work.pmem_ctrl_rtl_c0;
end for;
 
for psw_b : psw
use configuration work.psw_rtl_c0;
end for;
 
end for;
 
end t48_core_struct_c0;
/vhdl/int-c.vhd
0,0 → 1,17
-------------------------------------------------------------------------------
--
-- The Interrupt Controller.
-- It collects the interrupt sources and notifies the decoder.
--
-- $Id: int-c.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration int_rtl_c0 of int is
 
for rtl
end for;
 
end int_rtl_c0;
/vhdl/t48_pack-p.vhd
0,0 → 1,82
-------------------------------------------------------------------------------
--
-- $Id: t48_pack-p.vhd,v 1.1 2004-03-23 21:31:53 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
package t48_pack is
 
-----------------------------------------------------------------------------
-- Global constants
-----------------------------------------------------------------------------
 
-- clock active level
constant clk_active_c : std_logic := '1';
-- reset active level
constant res_active_c : std_logic := '0';
-- idle level on internal data bus
constant bus_idle_level_c : std_logic := '1';
 
-- global data word width
constant word_width_c : natural := 8;
 
-- data memory address width
constant dmem_addr_width_c : natural := 8;
-- program memory address width
constant pmem_addr_width_c : natural := 12;
 
 
-----------------------------------------------------------------------------
-- Global data types
-----------------------------------------------------------------------------
 
-- the global data word width type
subtype word_t is std_logic_vector(word_width_c-1 downto 0);
subtype nibble_t is std_logic_vector(word_width_c/2-1 downto 0);
-- the global data memory address type
subtype dmem_addr_t is std_logic_vector(dmem_addr_width_c-1 downto 0);
-- the global program memory address type
subtype pmem_addr_t is std_logic_vector(pmem_addr_width_c-1 downto 0);
subtype page_t is std_logic_vector(pmem_addr_width_c-1 downto word_width_c);
 
-- the machine states
type mstate_t is (MSTATE1, MSTATE2, MSTATE3, MSTATE4, MSTATE5);
 
 
-----------------------------------------------------------------------------
-- Global functions
-----------------------------------------------------------------------------
 
function to_stdLogic(input: boolean) return std_logic;
function to_boolean(input: std_logic) return boolean;
 
end t48_pack;
 
package body t48_pack is
 
function to_stdLogic(input: boolean) return std_logic is
begin
if input then
return '1';
else
return '0';
end if;
end to_stdLogic;
 
function to_boolean(input: std_logic) return boolean is
begin
if input = '1' then
return true;
else
return false;
end if;
end to_boolean;
 
end t48_pack;
/vhdl/cond_branch-c.vhd
0,0 → 1,19
-------------------------------------------------------------------------------
--
-- The Conditional Branch Logic unit.
-- Decisions whether to take a jump or not are made here.
--
-- $Id: cond_branch-c.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration cond_branch_rtl_c0 of cond_branch is
 
for rtl
end for;
 
end cond_branch_rtl_c0;
/vhdl/dmem_ctrl-c.vhd
0,0 → 1,19
-------------------------------------------------------------------------------
--
-- The Data Memory control unit.
-- All accesses to the Data Memory are managed here.
--
-- $Id: dmem_ctrl-c.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
configuration dmem_ctrl_rtl_c0 of dmem_ctrl is
 
for rtl
end for;
 
end dmem_ctrl_rtl_c0;
/vhdl/int.vhd
0,0 → 1,234
-------------------------------------------------------------------------------
--
-- The Interrupt Controller.
-- It collects the interrupt sources and notifies the decoder.
--
-- $Id: int.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- 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
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- 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
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t48/
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.t48_pack.mstate_t;
 
entity int is
 
port (
clk_i : in std_logic;
res_i : in std_logic;
en_clk_i : in boolean;
clk_mstate_i : in mstate_t;
jtf_executed_i : in boolean;
tim_overflow_i : in boolean;
tf_o : out std_logic;
en_tcnti_i : in boolean;
dis_tcnti_i : in boolean;
int_n_i : in std_logic;
ale_i : in boolean;
last_cycle_i : in boolean;
en_i_i : in boolean;
dis_i_i : in boolean;
ext_int_o : out boolean;
tim_int_o : out boolean;
retr_executed_i : in boolean;
int_executed_i : in boolean;
int_pending_o : out boolean
);
 
end int;
 
 
use work.t48_pack.all;
 
architecture rtl of int is
 
constant tim_int_c : std_logic := '0';
constant ext_int_c : std_logic := '1';
 
type int_state_t is (IDLE, PENDING, INT);
 
signal int_state_s,
int_state_q : int_state_t;
 
signal timer_flag_q : boolean;
signal timer_overflow_q : boolean;
signal timer_int_enable_q : boolean;
signal int_q : boolean;
signal int_enable_q : boolean;
signal ale_q : boolean;
signal int_type_q : std_logic;
signal int_in_progress_q : boolean;
 
begin
 
-----------------------------------------------------------------------------
-- Process nstate
--
-- Purpose:
-- Determines the next state of the Interrupt controller FSM.
--
nstate: process (int_state_q,
int_type_q,
int_in_progress_q,
int_executed_i,
retr_executed_i,
clk_mstate_i,
last_cycle_i)
begin
int_state_s <= int_state_q;
 
case int_state_q is
when IDLE =>
if int_in_progress_q and
last_cycle_i and clk_mstate_i = MSTATE5 then
int_state_s <= PENDING;
end if;
 
when PENDING =>
if int_executed_i then
int_state_s <= INT;
end if;
 
when INT =>
if retr_executed_i then
int_state_s <= IDLE;
end if;
 
when others =>
int_state_s <= IDLE;
 
end case;
 
end process nstate;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Process regs
--
-- Purpose:
-- Implement the various registers.
--
regs: process (res_i, clk_i)
begin
if res_i = res_active_c then
timer_flag_q <= false;
timer_overflow_q <= false;
timer_int_enable_q <= false;
int_q <= false;
int_enable_q <= false;
ale_q <= false;
int_type_q <= '0';
int_state_q <= IDLE;
int_in_progress_q <= false;
 
elsif clk_i'event and clk_i = clk_active_c then
if en_clk_i then
 
ale_q <= ale_i;
int_state_q <= int_state_s;
 
if jtf_executed_i then
timer_flag_q <= false;
elsif tim_overflow_i then
timer_flag_q <= true;
end if;
 
if (int_type_q = tim_int_c and int_executed_i) or
not timer_int_enable_q then
timer_overflow_q <= false;
elsif tim_overflow_i then
timer_overflow_q <= true;
end if;
 
if dis_tcnti_i then
timer_int_enable_q <= false;
elsif en_tcnti_i then
timer_int_enable_q <= true;
end if;
 
if last_cycle_i and
ale_q and not ale_i then
int_q <= not to_boolean(int_n_i);
end if;
 
if dis_i_i then
int_enable_q <= false;
elsif en_i_i then
int_enable_q <= true;
end if;
 
if retr_executed_i then
int_in_progress_q <= false;
elsif (int_q and int_enable_q) or
timer_overflow_q then
int_in_progress_q <= true;
if not int_in_progress_q then
int_type_q <= to_stdLogic(int_q and int_enable_q);
end if;
end if;
 
end if;
 
end if;
 
end process regs;
--
-----------------------------------------------------------------------------
 
 
-----------------------------------------------------------------------------
-- Output Mapping.
-----------------------------------------------------------------------------
tf_o <= to_stdLogic(timer_flag_q);
ext_int_o <= int_type_q = ext_int_c;
tim_int_o <= int_type_q = tim_int_c;
int_pending_o <= int_state_q = PENDING;
 
end rtl;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
--
-------------------------------------------------------------------------------
/vhdl/cond_branch_pack-p.vhd
0,0 → 1,36
-------------------------------------------------------------------------------
--
-- $Id: cond_branch_pack-p.vhd,v 1.1 2004-03-23 21:31:52 arniml Exp $
--
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
--
-- All rights reserved
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
package cond_branch_pack is
 
-----------------------------------------------------------------------------
-- The branch conditions.
-----------------------------------------------------------------------------
type branch_conditions_t is (COND_ON_BIT, COND_Z,
COND_C,
COND_F0, COND_F1,
COND_INT,
COND_T0, COND_T1,
COND_TF);
 
subtype comp_value_t is std_logic_vector(2 downto 0);
 
end cond_branch_pack;
 
 
-------------------------------------------------------------------------------
-- File History:
--
-- $Log: not supported by cvs2svn $
--
-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.