port (
clk : in std_logic;
res_n : in std_logic;
+ pc_type : in std_logic; --'0' pcl, '1' pch
dbus_we_n : in std_logic;
abus_we_n : in std_logic;
dbus_oe_n : in std_logic;
abus_oe_n : in std_logic;
addr_inc_n : in std_logic;
- add_carry : in std_logic;
- inc_carry : out std_logic;
+ addr_dec_n : in std_logic;
+ add_carry : out std_logic;
+ rel_we_n : in std_logic;
+ rel_calc_n : in std_logic;
+ rel_prev : out std_logic;
int_d_bus : inout std_logic_vector (dsize - 1 downto 0);
int_a_bus : inout std_logic_vector (dsize - 1 downto 0)
);
architecture rtl of pc is
+component dff
+ generic (
+ dsize : integer := 8
+ );
+ port (
+ clk : in std_logic;
+ we_n : in std_logic;
+ oe_n : in std_logic;
+ d : in std_logic_vector (dsize - 1 downto 0);
+ q : out std_logic_vector (dsize - 1 downto 0)
+ );
+end component;
+
signal val : std_logic_vector (dsize - 1 downto 0);
+signal rel : std_logic_vector (dsize - 1 downto 0);
begin
- int_a_bus <= (val + add_carry) when
- (abus_oe_n = '0' and add_carry = '1') else
- val when
- (abus_oe_n = '0' and add_carry /= '1') else
+ ---increment & page moved case.
+ int_a_bus <= val + 1 when (abus_oe_n = '0'
+ and pc_type = '1' and addr_inc_n = '0') else
+ val when (abus_oe_n = '0') else
(others => 'Z');
- int_d_bus <= (val + add_carry) when
- (dbus_oe_n = '0' and add_carry = '1') else
- val when
- (dbus_oe_n = '0' and add_carry /= '1') else
+
+ ---increment & page moved case.
+ int_d_bus <= val + 1 when (dbus_oe_n = '0'
+ and pc_type = '1' and addr_inc_n = '0') else
+ val when (dbus_oe_n = '0') else
(others => 'Z');
set_p : process (clk, res_n)
variable add_val : std_logic_vector(dsize downto 0);
+ variable dec_val : std_logic_vector(dsize downto 0);
begin
if (clk'event and clk = '1') then
+
if (addr_inc_n = '0' and abus_we_n = '0') then
--case increment & address set
--for jmp op, abs xy not page crossing case.
add_val := ('0' & int_a_bus) + 1;
- inc_carry <= add_val(dsize);
val <= add_val(dsize - 1 downto 0);
+ add_carry <= add_val(dsize);
+ rel_prev <= '0';
elsif (addr_inc_n = '0') then
add_val := ('0' & val) + 1;
- inc_carry <= add_val(dsize);
+ val <= add_val(dsize - 1 downto 0);
+ add_carry <= add_val(dsize);
+ rel_prev <= '0';
+ elsif (addr_dec_n = '0') then
+ dec_val := ('0' & val) - 1;
+ val <= dec_val(dsize - 1 downto 0);
+ add_carry <= '0';
+ rel_prev <= '0';
+ elsif (rel_calc_n = '0') then
+ add_val := ('0' & val) + ('0' & rel);
+ --relative addressing mode is signed operation.
+ if (rel(7) = '0') then
+ --add positive
+ add_carry <= add_val(dsize);
+ rel_prev <= '1';
+ else
+ --add negative
+ add_carry <= '0';
+ if (add_val(7) = '1') then
+ --negative value > goto preveous page.
+ rel_prev <= '1';
+ else
+ rel_prev <= '0';
+ end if;
+ end if;
val <= add_val(dsize - 1 downto 0);
elsif (abus_we_n = '0') then
val <= int_a_bus;
+ add_carry <= '0';
+ rel_prev <= '0';
elsif (dbus_we_n = '0') then
val <= int_d_bus;
+ add_carry <= '0';
+ rel_prev <= '0';
+ else
+ rel_prev <= '0';
+ add_carry <= '0';
end if;
elsif (res_n'event and res_n = '0') then
val <= conv_std_logic_vector(reset_addr, dsize);
end if;
end process;
+
+ rel_dff : dff generic map (dsize)
+ port map(clk, rel_we_n, '0', int_d_bus, rel);
end rtl;
----------------------------------------
status_reg : inout std_logic_vector (dsize - 1 downto 0);
inst_we_n : out std_logic;
ad_oe_n : out std_logic;
+ pcl_inc_n : out std_logic;
pcl_d_we_n : out std_logic;
pcl_a_we_n : out std_logic;
pcl_d_oe_n : out std_logic;
pcl_a_oe_n : out std_logic;
+ pcl_rel_we_n : out std_logic;
+ pcl_rel_calc_n : out std_logic;
pch_d_we_n : out std_logic;
pch_a_we_n : out std_logic;
pch_d_oe_n : out std_logic;
pch_a_oe_n : out std_logic;
- pc_inc_n : out std_logic;
+ rel_pg_crs_n : in std_logic;
dbuf_int_oe_n : out std_logic;
dl_al_we_n : out std_logic;
dl_ah_we_n : out std_logic;
pcl_a_oe_n <= '0';
pch_a_oe_n <= '0';
inst_we_n <= '0';
- pc_inc_n <= '0';
+ pcl_inc_n <= '0';
--disable the last opration pins.
x_oe_n <= '1';
dbuf_int_oe_n <= '1';
pch_d_we_n <= '1';
pcl_a_we_n <= '1';
+ pcl_rel_we_n <= '1';
+ pcl_rel_calc_n <= '1';
dl_al_we_n <= '1';
dl_al_oe_n <= '1';
dl_ah_oe_n <= '1';
begin
pcl_a_oe_n <= '1';
pch_a_oe_n <= '1';
- pc_inc_n <= '1';
+ pcl_inc_n <= '1';
next_cycle <= T0;
end procedure;
d_print("immediate");
pcl_a_oe_n <= '0';
pch_a_oe_n <= '0';
- pc_inc_n <= '0';
+ pcl_inc_n <= '0';
--send data from data bus buffer.
--receiver is instruction dependent.
dbuf_int_oe_n <= '0';
--fetch next opcode (abs low).
pcl_a_oe_n <= '0';
pch_a_oe_n <= '0';
- pc_inc_n <= '0';
+ pcl_inc_n <= '0';
--latch abs low data.
dbuf_int_oe_n <= '0';
dl_al_we_n <= '0';
dl_al_we_n <= '1';
--latch abs hi data.
- pc_inc_n <= '0';
+ pcl_inc_n <= '0';
pcl_a_oe_n <= '0';
pch_a_oe_n <= '0';
dbuf_int_oe_n <= '0';
procedure abs_latch_out is
begin
--d_print("abs 4");
- pc_inc_n <= '1';
+ pcl_inc_n <= '1';
pcl_a_oe_n <= '1';
pch_a_oe_n <= '1';
dl_ah_we_n <= '1';
--fetch opcode.
pcl_a_oe_n <= '0';
pch_a_oe_n <= '0';
- pc_inc_n <= '0';
+ pcl_inc_n <= '0';
dbuf_int_oe_n <= '0';
--latch adl
dl_al_we_n <= '0';
d_print("jsr 3");
pcl_a_oe_n <= '1';
pch_a_oe_n <= '1';
- pc_inc_n <= '1';
+ pcl_inc_n <= '1';
dbuf_int_oe_n <= '1';
dl_al_we_n <= '1';
--fetch next opcode (abs low).
pcl_a_oe_n <= '0';
pch_a_oe_n <= '0';
- pc_inc_n <= '0';
+ pcl_inc_n <= '0';
--latch abs low data.
dbuf_int_oe_n <= '0';
dl_al_we_n <= '0';
pcl_a_we_n <= '0';
pch_a_we_n <= '0';
inst_we_n <= '0';
- pc_inc_n <= '0';
+ pcl_inc_n <= '0';
next_cycle <= T1;
end if;
if exec_cycle = T1 then
pcl_a_oe_n <= '1';
pch_a_oe_n <= '1';
- pc_inc_n <= '1';
+ pcl_inc_n <= '1';
--pop stack (decrement only)
sp_pop_n <= '0';
d_print("rts 6");
--increment pc.
- pc_inc_n <= '0';
+ pcl_inc_n <= '0';
next_cycle <= T0;
end if; --if exec_cycle = T1 then
d_print("bmi");
elsif instruction = conv_std_logic_vector(16#d0#, dsize) then
d_print("bne");
+ if exec_cycle = T1 then
+ stat_dec_oe_n <= '0';
+ pcl_inc_n <= '0';
+ if status_reg(st_Z) /= '1' then
+ d_print("get rel");
+
+ pcl_a_oe_n <= '0';
+ pch_a_oe_n <= '0';
+ dbuf_int_oe_n <= '0';
+ --latch rel value.
+ pcl_rel_we_n <= '0';
+ next_cycle <= T2;
+ else
+ d_print("no branch");
+ next_cycle <= T0;
+ end if;
+ elsif exec_cycle = T2 then
+ d_print("rel ea");
+ pcl_inc_n <= '1';
+ pcl_a_oe_n <= '0';
+ pch_a_oe_n <= '0';
+ dbuf_int_oe_n <= '1';
+ pcl_rel_we_n <= '1';
+
+ --calcurate relative addr.
+ pcl_rel_calc_n <= '0';
+ next_cycle <= T3;
+ elsif exec_cycle = T3 then
+ --pcl_a_oe_n <= '0';
+ --pch_a_oe_n <= '0';
+ pcl_rel_calc_n <= '1';
+
+ if rel_pg_crs_n = '0' then
+ --page crossed. start from fetch.
+ next_cycle <= T0;
+ else
+ --no page boundary.
+ --fetch cycle is done.
+ fetch_inst;
+ next_cycle <= T1;
+ end if;
+ end if;
+
elsif instruction = conv_std_logic_vector(16#10#, dsize) then
d_print("bpl");
elsif instruction = conv_std_logic_vector(16#50#, dsize) then
pcl_a_we_n <= '1';
pcl_d_oe_n <= '1';
pcl_a_oe_n <= '1';
+ pcl_rel_we_n <= '1';
+ pcl_rel_calc_n <= '1';
pch_d_we_n <= '1';
pch_a_we_n <= '1';
pch_d_oe_n <= '1';
pch_a_oe_n <= '1';
- pc_inc_n <= '1';
+ pcl_inc_n <= '1';
inst_we_n <= '1';
dbuf_int_oe_n <= '1';
dl_al_we_n <= '1';
port (
clk : in std_logic;
res_n : in std_logic;
+ pc_type : in std_logic;
dbus_we_n : in std_logic;
abus_we_n : in std_logic;
dbus_oe_n : in std_logic;
abus_oe_n : in std_logic;
addr_inc_n : in std_logic;
- add_carry : in std_logic;
- inc_carry : out std_logic;
+ addr_dec_n : in std_logic;
+ add_carry : out std_logic;
+ rel_we_n : in std_logic;
+ rel_calc_n : in std_logic;
+ rel_prev : out std_logic;
int_d_bus : inout std_logic_vector (dsize - 1 downto 0);
int_a_bus : inout std_logic_vector (dsize - 1 downto 0)
);
status_reg : inout std_logic_vector (dsize - 1 downto 0);
inst_we_n : out std_logic;
ad_oe_n : out std_logic;
+ pcl_inc_n : out std_logic;
pcl_d_we_n : out std_logic;
pcl_a_we_n : out std_logic;
pcl_d_oe_n : out std_logic;
pcl_a_oe_n : out std_logic;
+ pcl_rel_we_n : out std_logic;
+ pcl_rel_calc_n : out std_logic;
pch_d_we_n : out std_logic;
pch_a_we_n : out std_logic;
pch_d_oe_n : out std_logic;
pch_a_oe_n : out std_logic;
- pc_inc_n : out std_logic;
+ rel_pg_crs_n : in std_logic;
dbuf_int_oe_n : out std_logic;
dl_al_we_n : out std_logic;
dl_ah_we_n : out std_logic;
signal set_clk : std_logic;
signal trigger_clk : std_logic;
+ signal pcl_inc_n : std_logic;
signal pcl_d_we_n : std_logic;
signal pcl_a_we_n : std_logic;
signal pcl_d_oe_n : std_logic;
signal pcl_a_oe_n : std_logic;
+ signal pcl_rel_we_n : std_logic;
+ signal pcl_rel_calc_n : std_logic;
signal pch_d_we_n : std_logic;
signal pch_a_we_n : std_logic;
signal pch_d_oe_n : std_logic;
signal pch_a_oe_n : std_logic;
- signal pc_inc_n : std_logic;
signal pc_cry : std_logic;
signal pc_cry_n : std_logic;
signal dum_terminate : std_logic := 'Z';
+ signal pc_rel_prev : std_logic;
+ signal pc_rel_prev_n : std_logic;
+ signal rel_pg_crs_n : std_logic;
signal inst_we_n : std_logic;
signal dbuf_r_nw : std_logic;
status_reg,
inst_we_n,
ad_oe_n,
+ pcl_inc_n,
pcl_d_we_n,
pcl_a_we_n,
pcl_d_oe_n,
pcl_a_oe_n,
+ pcl_rel_we_n,
+ pcl_rel_calc_n,
pch_d_we_n,
pch_a_we_n,
pch_d_oe_n,
pch_a_oe_n,
- pc_inc_n,
+ rel_pg_crs_n,
dbuf_int_oe_n,
dl_al_we_n,
dl_ah_we_n,
internal_dbus, ea_base_l, ea_base_h);
pc_l : pc generic map (dsize, 16#00#)
- port map(trigger_clk, rst_n,
+ port map(trigger_clk, rst_n, '0',
pcl_d_we_n, pcl_a_we_n, pcl_d_oe_n, pcl_a_oe_n,
- pc_inc_n, '0', pc_cry, internal_dbus, internal_abus_l);
+ pcl_inc_n, '1', pc_cry,
+ pcl_rel_we_n, pcl_rel_calc_n, pc_rel_prev,
+ internal_dbus, internal_abus_l);
pc_h : pc generic map (dsize, 16#80#)
- port map(trigger_clk, rst_n,
+ port map(trigger_clk, rst_n, '1',
pch_d_we_n, pch_a_we_n, pch_d_oe_n, pch_a_oe_n,
- pc_cry_n, pc_cry, dum_terminate, internal_dbus, internal_abus_h);
+ pc_cry_n, pc_rel_prev_n, dum_terminate,
+ '1', '1', dum_terminate,
+ internal_dbus, internal_abus_h);
instruction_register : dff generic map (dsize)
port map(trigger_clk, inst_we_n, '0', d_io, instruction);
phi2 <= not input_clk;
set_clk <= input_clk;
trigger_clk <= not input_clk;
+
pc_cry_n <= not pc_cry;
+ pc_rel_prev_n <= not pc_rel_prev;
r_nw <= dbuf_r_nw;
+ --branch instruction page crossed?
+ rel_pg_crs_n <= pc_cry nand pc_rel_prev;
+
--adh output is controlled by decoder.
adh_buffer : tsb generic map (dsize)
port map (ad_oe_n, internal_abus_h, addr(asize - 1 downto dsize));