Line 72... |
Line 72... |
-- Revision History
|
-- Revision History
|
-- Author Date Change
|
-- Author Date Change
|
------------------ -------- ---------------------------------------------------
|
------------------ -------- ---------------------------------------------------
|
-- Seth Henry 07/19/06 Design Start
|
-- Seth Henry 07/19/06 Design Start
|
-- Seth Henry 01/18/11 Fixed BTT instruction to match V8
|
-- Seth Henry 01/18/11 Fixed BTT instruction to match V8
|
|
-- Seth Henry 07/22/11 Fixed interrupt transition logic to avoid data
|
|
-- corruption issues.
|
|
-- Seth Henry 07/26/11 Optimized logic in ALU, stack pointer, and data path
|
|
-- sections.
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_unsigned.all;
|
use ieee.std_logic_unsigned.all;
|
use ieee.std_logic_arith.all;
|
use ieee.std_logic_arith.all;
|
Line 222... |
Line 226... |
Halt_Enabled_fn: if( Enable_CPU_Halt )generate
|
Halt_Enabled_fn: if( Enable_CPU_Halt )generate
|
Halt <= CPU_Halt;
|
Halt <= CPU_Halt;
|
end generate;
|
end generate;
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- ALU (Arithmetic / Logic Unit
|
-- ALU (Arithmetic / Logic Unit)
|
-- Notes:
|
-- Notes:
|
-- 1) Infers a multiplier in Xilinx/Altera parts - should be checked in others
|
-- 1) Infers a multiplier in Xilinx/Altera parts - should be checked in others
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
Open8_ALU : block is
|
Open8_ALU : block is
|
|
|
-- Preinitialization is for simulation only - check actual reset conditions
|
-- Preinitialization is for simulation only - check actual reset conditions
|
signal Regfile_D, Regfile : REGFILE_TYPE := (others => (others => '0') );
|
signal Regfile : REGFILE_TYPE := (others => (others => '0') );
|
signal Flags_D, Flags : FLAG_TYPE := (others => '0');
|
signal Flags : FLAG_TYPE := (others => '0');
|
signal Mult : ADDRESS_TYPE := (others => '0');
|
signal Mult : ADDRESS_TYPE := (others => '0');
|
|
|
signal Sum : std_logic_vector(8 downto 0) := (others => '0');
|
|
signal Addend_A, Addend_B : DATA_TYPE := (others => '0');
|
|
signal Carry : std_logic := '0';
|
|
|
|
begin
|
begin
|
|
|
ALU_Regs <= Regfile;
|
ALU_Regs <= Regfile;
|
ALU_Flags <= Flags;
|
ALU_Flags <= Flags;
|
|
|
ALU_proc: process( ALU_Ctrl, Regfile, Flags, Mult, Sum )
|
-- We need to infer a hardware multipler, so we create a special clocked
|
|
-- process with no reset or clock enable
|
|
Multiplier: process( Clock )
|
|
begin
|
|
if( rising_edge(Clock) )then
|
|
Mult <= Regfile(0) *
|
|
Regfile(conv_integer(ALU_Ctrl.Reg));
|
|
end if;
|
|
end process;
|
|
|
|
ALU: process( Reset, Clock )
|
|
variable Sum : std_logic_vector(8 downto 0) := "000000000";
|
variable Index : integer range 0 to 7 := 0;
|
variable Index : integer range 0 to 7 := 0;
|
variable Temp : std_logic_vector(8 downto 0);
|
variable Temp : std_logic_vector(8 downto 0);
|
begin
|
begin
|
Regfile_D <= Regfile;
|
if( Reset = Reset_Level )then
|
Flags_D <= Flags;
|
for i in 0 to 7 loop
|
Addend_A <= x"00";
|
Regfile(i) <= (others => '0');
|
Addend_B <= x"00";
|
end loop;
|
Carry <= '0';
|
Flags <= x"00";
|
|
elsif( rising_edge(Clock) )then
|
Temp := (others => '0');
|
Temp := (others => '0');
|
Index := conv_integer(ALU_Ctrl.Reg);
|
Index := conv_integer(ALU_Ctrl.Reg);
|
|
if( Halt = '0' )then
|
case ALU_Ctrl.Oper is
|
case ALU_Ctrl.Oper is
|
when ALU_INC | ALU_UPP => -- Rn = Rn + 1 : Flags N,C,Z
|
when ALU_INC | ALU_UPP => -- Rn = Rn + 1 : Flags N,C,Z
|
Addend_A <= x"01";
|
Sum := ("0" & x"01") +
|
Addend_B <= Regfile(Index);
|
("0" & Regfile(Index));
|
Flags_D(FL_CARRY) <= Sum(8);
|
Flags(FL_CARRY) <= Sum(8);
|
Regfile_D(Index) <= Sum(7 downto 0);
|
Regfile(Index) <= Sum(7 downto 0);
|
-- ALU_INC and ALU_UPP are essentially the same, except that ALU_UPP
|
-- ALU_INC and ALU_UPP are essentially the same, except that ALU_UPP
|
-- doesn't set the N or Z flags. Note that the MSB can be used to
|
-- doesn't set the N or Z flags. Note that the MSB can be used to
|
-- distinguish between the two ALU modes.
|
-- distinguish between the two ALU modes.
|
if( ALU_Ctrl.Oper(4) = '0' )then
|
if( ALU_Ctrl.Oper(4) = '0' )then
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Sum(7 downto 0) = 0 )then
|
if( Sum(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO)<= '1';
|
end if;
|
end if;
|
Flags_D(FL_NEG) <= Sum(7);
|
Flags(FL_NEG) <= Sum(7);
|
end if;
|
end if;
|
|
|
when ALU_UPP2 => -- Rn = Rn + C
|
when ALU_UPP2 => -- Rn = Rn + C
|
Addend_A <= x"00";
|
Sum := ("0" & x"00") +
|
Addend_B <= Regfile(Index);
|
("0" & Regfile(Index)) +
|
Carry <= Flags(FL_CARRY);
|
Flags(FL_CARRY);
|
Flags_D(FL_CARRY) <= Sum(8);
|
Flags(FL_CARRY) <= Sum(8);
|
Regfile_D(Index) <= Sum(7 downto 0);
|
Regfile(Index) <= Sum(7 downto 0);
|
|
|
when ALU_ADC => -- R0 = R0 + Rn + C : Flags N,C,Z
|
when ALU_ADC => -- R0 = R0 + Rn + C : Flags N,C,Z
|
Addend_A <= Regfile(0);
|
Sum := ("0" & Regfile(0)) +
|
Addend_B <= Regfile(Index);
|
("0" & Regfile(Index)) +
|
Carry <= Flags(FL_CARRY);
|
Flags(FL_CARRY);
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Sum(7 downto 0) = 0 )then
|
if( Sum(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_CARRY) <= Sum(8);
|
Flags(FL_CARRY) <= Sum(8);
|
Flags_D(FL_NEG) <= Sum(7);
|
Flags(FL_NEG) <= Sum(7);
|
Regfile_D(0) <= Sum(7 downto 0);
|
Regfile(0) <= Sum(7 downto 0);
|
|
|
when ALU_TX0 => -- R0 = Rn : Flags N,Z
|
when ALU_TX0 => -- R0 = Rn : Flags N,Z
|
Temp := "0" & Regfile(Index);
|
Temp := "0" & Regfile(Index);
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Temp(7 downto 0) = 0 )then
|
if( Temp(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_NEG) <= Temp(7);
|
Flags(FL_NEG) <= Temp(7);
|
Regfile_D(0) <= Temp(7 downto 0);
|
Regfile(0) <= Temp(7 downto 0);
|
|
|
when ALU_OR => -- R0 = R0 | Rn : Flags N,Z
|
when ALU_OR => -- R0 = R0 | Rn : Flags N,Z
|
Temp(7 downto 0) := Regfile(0) or Regfile(Index);
|
Temp(7 downto 0) := Regfile(0) or Regfile(Index);
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Temp(7 downto 0) = 0 )then
|
if( Temp(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_NEG) <= Temp(7);
|
Flags(FL_NEG) <= Temp(7);
|
Regfile_D(0) <= Temp(7 downto 0);
|
Regfile(0) <= Temp(7 downto 0);
|
|
|
when ALU_AND => -- R0 = R0 & Rn : Flags N,Z
|
when ALU_AND => -- R0 = R0 & Rn : Flags N,Z
|
Temp(7 downto 0) := Regfile(0) and Regfile(Index);
|
Temp(7 downto 0) := Regfile(0) and Regfile(Index);
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Temp(7 downto 0) = 0 )then
|
if( Temp(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_NEG) <= Temp(7);
|
Flags(FL_NEG) <= Temp(7);
|
Regfile_D(0) <= Temp(7 downto 0);
|
Regfile(0) <= Temp(7 downto 0);
|
|
|
when ALU_XOR => -- R0 = R0 ^ Rn : Flags N,Z
|
when ALU_XOR => -- R0 = R0 ^ Rn : Flags N,Z
|
Temp(7 downto 0) := Regfile(0) xor Regfile(Index);
|
Temp(7 downto 0) := Regfile(0) xor Regfile(Index);
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Temp(7 downto 0) = 0 )then
|
if( Temp(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_NEG) <= Temp(7);
|
Flags(FL_NEG) <= Temp(7);
|
Regfile_D(0) <= Temp(7 downto 0);
|
Regfile(0) <= Temp(7 downto 0);
|
|
|
when ALU_ROL => -- Rn = Rn<<1,C : Flags N,C,Z
|
when ALU_ROL => -- Rn = Rn<<1,C : Flags N,C,Z
|
Temp := Regfile(Index) & Flags(FL_CARRY);
|
Temp := Regfile(Index) & Flags(FL_CARRY);
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Temp(7 downto 0) = 0 )then
|
if( Temp(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_CARRY) <= Temp(8);
|
Flags(FL_CARRY) <= Temp(8);
|
Flags_D(FL_NEG) <= Temp(7);
|
Flags(FL_NEG) <= Temp(7);
|
Regfile_D(Index) <= Temp(7 downto 0);
|
Regfile(Index) <= Temp(7 downto 0);
|
|
|
when ALU_ROR => -- Rn = C,Rn>>1 : Flags N,C,Z
|
when ALU_ROR => -- Rn = C,Rn>>1 : Flags N,C,Z
|
Temp := Regfile(Index)(0) & Flags(FL_CARRY) &
|
Temp := Regfile(Index)(0) & Flags(FL_CARRY) &
|
Regfile(Index)(7 downto 1);
|
Regfile(Index)(7 downto 1);
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Temp(7 downto 0) = 0 )then
|
if( Temp(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_CARRY) <= Temp(8);
|
Flags(FL_CARRY) <= Temp(8);
|
Flags_D(FL_NEG) <= Temp(7);
|
Flags(FL_NEG) <= Temp(7);
|
Regfile_D(Index) <= Temp(7 downto 0);
|
Regfile(Index) <= Temp(7 downto 0);
|
|
|
when ALU_DEC => -- Rn = Rn - 1 : Flags N,C,Z
|
when ALU_DEC => -- Rn = Rn - 1 : Flags N,C,Z
|
Addend_A <= Regfile(Index);
|
Sum := ("0" & Regfile(Index)) +
|
Addend_B <= x"FF";
|
("0" & x"FF");
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Sum(7 downto 0) = 0 )then
|
if( Sum(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_CARRY) <= Sum(8);
|
Flags(FL_CARRY) <= Sum(8);
|
Flags_D(FL_NEG) <= Sum(7);
|
Flags(FL_NEG) <= Sum(7);
|
Regfile_D(Index) <= Sum(7 downto 0);
|
Regfile(Index) <= Sum(7 downto 0);
|
|
|
when ALU_SBC => -- Rn = R0 - Rn - C : Flags N,C,Z
|
when ALU_SBC => -- Rn = R0 - Rn - C : Flags N,C,Z
|
Addend_A <= Regfile(0);
|
Sum := ("0" & Regfile(0)) +
|
Addend_B <= not Regfile(Index);
|
("0" & (not Regfile(Index))) +
|
Carry <= Flags(FL_CARRY);
|
Flags(FL_CARRY);
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Sum(7 downto 0) = 0 )then
|
if( Sum(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_CARRY) <= Sum(8);
|
Flags(FL_CARRY) <= Sum(8);
|
Flags_D(FL_NEG) <= Sum(7);
|
Flags(FL_NEG) <= Sum(7);
|
Regfile_D(0) <= Sum(7 downto 0);
|
Regfile(0) <= Sum(7 downto 0);
|
|
|
when ALU_ADD => -- R0 = R0 + Rn : Flags N,C,Z
|
when ALU_ADD => -- R0 = R0 + Rn : Flags N,C,Z
|
Addend_A <= Regfile(0);
|
Sum := ("0" & Regfile(0)) +
|
Addend_B <= Regfile(Index);
|
("0" & Regfile(Index));
|
Flags_D(FL_CARRY) <= Sum(8);
|
Flags(FL_CARRY) <= Sum(8);
|
Regfile_D(0) <= Sum(7 downto 0);
|
Regfile(0) <= Sum(7 downto 0);
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Sum(7 downto 0) = 0 )then
|
if( Sum(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_NEG) <= Sum(7);
|
Flags(FL_NEG) <= Sum(7);
|
|
|
when ALU_STP => -- Sets bit(n) in the Flags register
|
when ALU_STP => -- Sets bit(n) in the Flags register
|
Flags_D(Index) <= '1';
|
Flags(Index) <= '1';
|
|
|
when ALU_BTT => -- Z = !R0(N), N = R0(7)
|
when ALU_BTT => -- Z = !R0(N), N = R0(7)
|
Flags_D(FL_ZERO) <= not Regfile(0)(Index);
|
Flags(FL_ZERO) <= not Regfile(0)(Index);
|
Flags_D(FL_NEG) <= Regfile(0)(7);
|
Flags(FL_NEG) <= Regfile(0)(7);
|
-- Temp := "0" & Regfile(Index);
|
|
-- Flags_D(FL_ZERO) <= '0';
|
|
-- if( Temp(7 downto 0) = 0 )then
|
|
-- Flags_D(FL_ZERO) <= '1';
|
|
-- end if;
|
|
-- Flags_D(FL_NEG) <= Temp(7);
|
|
|
|
when ALU_CLP => -- Clears bit(n) in the Flags register
|
when ALU_CLP => -- Clears bit(n) in the Flags register
|
Flags_D(Index) <= '0';
|
Flags(Index) <= '0';
|
|
|
when ALU_T0X => -- Rn = R0 : Flags N,Z
|
when ALU_T0X => -- Rn = R0 : Flags N,Z
|
Temp := "0" & Regfile(0);
|
Temp := "0" & Regfile(0);
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Temp(7 downto 0) = 0 )then
|
if( Temp(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_NEG) <= Temp(7);
|
Flags(FL_NEG) <= Temp(7);
|
Regfile_D(Index) <= Temp(7 downto 0);
|
Regfile(Index) <= Temp(7 downto 0);
|
|
|
when ALU_CMP => -- Sets Flags on R0 - Rn : Flags N,C,Z
|
when ALU_CMP => -- Sets Flags on R0 - Rn : Flags N,C,Z
|
Addend_A <= Regfile(0);
|
Sum := ("0" & Regfile(0)) +
|
Addend_B <= not Regfile(Index);
|
("0" & (not Regfile(Index))) +
|
Carry <= '1';
|
'1';
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Sum(7 downto 0) = 0 )then
|
if( Sum(7 downto 0) = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_CARRY) <= Sum(8);
|
Flags(FL_CARRY) <= Sum(8);
|
Flags_D(FL_NEG) <= Sum(7);
|
Flags(FL_NEG) <= Sum(7);
|
|
|
when ALU_MUL => -- Stage 1 of 2 {R1:R0} = R0 * Rn : Flags Z
|
when ALU_MUL => -- Stage 1 of 2 {R1:R0} = R0 * Rn : Flags Z
|
Regfile_D(0) <= Mult(7 downto 0);
|
Regfile(0) <= Mult(7 downto 0);
|
Regfile_D(1) <= Mult(15 downto 8);
|
Regfile(1) <= Mult(15 downto 8);
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( Mult = 0 )then
|
if( Mult = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
|
|
when ALU_LDI | ALU_POP => -- Rn <= Data : Flags N,Z
|
when ALU_LDI | ALU_POP => -- Rn <= Data : Flags N,Z
|
-- The POP instruction doesn't alter the flags, so we need to check
|
-- The POP instruction doesn't alter the flags, so we need to check
|
if( ALU_Ctrl.Oper = ALU_LDI )then
|
if( ALU_Ctrl.Oper = ALU_LDI )then
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( ALU_Ctrl.Data = 0 )then
|
if( ALU_Ctrl.Data = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_NEG) <= ALU_Ctrl.Data(7);
|
Flags(FL_NEG) <= ALU_Ctrl.Data(7);
|
end if;
|
end if;
|
Regfile_D(Index) <= ALU_Ctrl.Data;
|
Regfile(Index) <= ALU_Ctrl.Data;
|
|
|
when ALU_LDX => -- R0 <= Data : Flags N,Z
|
when ALU_LDX => -- R0 <= Data : Flags N,Z
|
Flags_D(FL_ZERO) <= '0';
|
Flags(FL_ZERO) <= '0';
|
if( ALU_Ctrl.Data = 0 )then
|
if( ALU_Ctrl.Data = 0 )then
|
Flags_D(FL_ZERO) <= '1';
|
Flags(FL_ZERO) <= '1';
|
end if;
|
end if;
|
Flags_D(FL_NEG) <= ALU_Ctrl.Data(7);
|
Flags(FL_NEG) <= ALU_Ctrl.Data(7);
|
Regfile_D(0) <= ALU_Ctrl.Data;
|
Regfile(0) <= ALU_Ctrl.Data;
|
|
|
when ALU_RFLG =>
|
when ALU_RFLG =>
|
Flags_D <= ALU_Ctrl.Data;
|
Flags <= ALU_Ctrl.Data;
|
|
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
end process;
|
|
|
|
-- 8-bit Adder with carry
|
|
Sum <= ("0" & Addend_A) + ("0" & Addend_B) + Carry;
|
|
|
|
-- We need to infer a hardware multipler, so we create a special clocked
|
|
-- process with no reset or clock enable
|
|
M_Reg: process( Clock )
|
|
begin
|
|
if( rising_edge(Clock) )then
|
|
Mult <= Regfile(0) *
|
|
Regfile(conv_integer(ALU_Ctrl.Reg));
|
|
end if;
|
|
end process;
|
|
|
|
S_Regs: process( Reset, Clock )
|
|
begin
|
|
if( Reset = Reset_Level )then
|
|
for i in 0 to 7 loop
|
|
Regfile(i) <= (others => '0');
|
|
end loop;
|
|
Flags <= x"00";
|
|
elsif( rising_edge(Clock) )then
|
|
if( Halt = '0' )then
|
|
Regfile <= Regfile_D;
|
|
Flags <= Flags_D;
|
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
end block;
|
end block;
|
Line 490... |
Line 467... |
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
Open8_PC : block is
|
Open8_PC : block is
|
-- Preinitialization is for simulation only - check actual reset conditions
|
-- Preinitialization is for simulation only - check actual reset conditions
|
signal PC_Q : ADDRESS_TYPE := (others => '0');
|
signal PC_Q : ADDRESS_TYPE := (others => '0');
|
signal Rewind_1_2n : std_logic := '0';
|
|
begin
|
begin
|
|
|
PC <= PC_Q;
|
PC <= PC_Q;
|
|
|
-- This sets the carry input on the "rewind" adder. If the rewind command is
|
Program_Counter: process( Reset, Clock )
|
-- PC_REV2, then we clear the carry. Otherwise, we leave it high.
|
|
Rewind_PC_Calc: process( PC_Ctrl )
|
|
begin
|
|
Rewind_1_2n <= '1';
|
|
if( PC_Ctrl.Oper = PC_REV2 )then
|
|
Rewind_1_2n <= '0';
|
|
end if;
|
|
end process;
|
|
|
|
Program_Counter: process( Reset, Clock, Halt, PC_Ctrl, PC_Q, Rewind_1_2n )
|
|
variable PC_Offset_SX : ADDRESS_TYPE := x"0000";
|
variable PC_Offset_SX : ADDRESS_TYPE := x"0000";
|
begin
|
begin
|
PC_Offset_SX(15 downto 8):= (others => PC_Ctrl.Offset(7));
|
|
PC_Offset_SX(7 downto 0) := PC_Ctrl.Offset;
|
|
if( Reset = Reset_Level )then
|
if( Reset = Reset_Level )then
|
PC_Q <= Program_Start_Addr;
|
PC_Q <= Program_Start_Addr;
|
elsif( rising_edge(Clock) )then
|
elsif( rising_edge(Clock) )then
|
|
PC_Offset_SX(15 downto 8):= (others => PC_Ctrl.Offset(7));
|
|
PC_Offset_SX(7 downto 0) := PC_Ctrl.Offset;
|
if( Halt = '0' )then
|
if( Halt = '0' )then
|
case PC_Ctrl.Oper is
|
case PC_Ctrl.Oper is
|
when PC_IDLE =>
|
when PC_IDLE =>
|
null;
|
null;
|
when PC_REV1 | PC_REV2 =>
|
when PC_REV1 =>
|
PC_Q <= PC_Q - 2 + Rewind_1_2n;
|
PC_Q <= PC_Q - 1;
|
|
when PC_REV2 =>
|
|
PC_Q <= PC_Q - 2;
|
when PC_INCR =>
|
when PC_INCR =>
|
PC_Q <= PC_Q + PC_Offset_SX - 2;
|
PC_Q <= PC_Q + PC_Offset_SX - 2;
|
when PC_LOAD =>
|
when PC_LOAD =>
|
PC_Q <= PC_Ctrl.Addr;
|
PC_Q <= PC_Ctrl.Addr;
|
end case;
|
end case;
|
Line 560... |
Line 528... |
end process;
|
end process;
|
|
|
end block;
|
end block;
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
-- Address Source Mux
|
|
-------------------------------------------------------------------------------
|
|
|
|
Open8_AS : block is
|
|
begin
|
|
|
|
Address_Select: process( AS_Ctrl, PC, SP, IMM, ISR )
|
|
begin
|
|
Address <= (others => '0');
|
|
case AS_Ctrl.Src is
|
|
when ADDR_PC =>
|
|
Address <= PC;
|
|
when ADDR_SP =>
|
|
Address <= SP;
|
|
when ADDR_IMM =>
|
|
Address <= IMM;
|
|
when ADDR_ISR =>
|
|
Address <= ISR;
|
|
end case;
|
|
end process;
|
|
|
|
end block;
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- (Write) Data Path
|
|
-------------------------------------------------------------------------------
|
|
|
|
Open8_DP : block is
|
|
begin
|
|
|
|
Data_Path: process( Reset, Clock )
|
|
begin
|
|
if( Reset = Reset_Level )then
|
|
Wr_Data <= (others => '0');
|
|
Wr_Enable <= '0';
|
|
Rd_Enable <= '1';
|
|
elsif( rising_edge(Clock) )then
|
|
if( Halt = '0' )then
|
|
Wr_Enable <= '0';
|
|
Rd_Enable <= '1';
|
|
case DP_Ctrl.Src is
|
|
when DATA_IDLE =>
|
|
null;
|
|
when DATA_REG =>
|
|
Wr_Enable <= '1';
|
|
Rd_Enable <= '0';
|
|
Wr_Data <= ALU_Regs(conv_integer(DP_Ctrl.Reg));
|
|
when DATA_FLAG =>
|
|
Wr_Enable <= '1';
|
|
Rd_Enable <= '0';
|
|
Wr_Data <= ALU_Flags;
|
|
when DATA_PC =>
|
|
Wr_Enable <= '1';
|
|
Rd_Enable <= '0';
|
|
Wr_Data <= PC(15 downto 8);
|
|
if( DP_Ctrl.Reg = ACCUM )then
|
|
Wr_Data <= PC(7 downto 0);
|
|
end if;
|
|
when others => null;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
end block;
|
|
|
|
-------------------------------------------------------------------------------
|
-- Interrupt Controller
|
-- Interrupt Controller
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
Open8_INT : block is
|
Open8_INT : block is
|
|
|
Line 1331... |
Line 1366... |
-- operation due to the current instruction
|
-- operation due to the current instruction
|
ALU_Ctrl.Oper <= ALU_IDLE;
|
ALU_Ctrl.Oper <= ALU_IDLE;
|
Cache_Ctrl <= CACHE_IDLE;
|
Cache_Ctrl <= CACHE_IDLE;
|
SP_Ctrl.Oper <= SP_IDLE;
|
SP_Ctrl.Oper <= SP_IDLE;
|
DP_Ctrl.Src <= DATA_IDLE; -- JSH 7/20
|
DP_Ctrl.Src <= DATA_IDLE; -- JSH 7/20
|
|
INT_Ctrl.Soft_Ints <= (others => '0'); -- JSH 7/22
|
-- Rewind the PC by 3 to compensate for the pipeline registers
|
-- Rewind the PC by 3 to compensate for the pipeline registers
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= x"FF";
|
PC_Ctrl.Offset <= x"FF";
|
CPU_Next_State <= ISR_C1;
|
CPU_Next_State <= ISR_C1;
|
|
|
Line 1415... |
Line 1451... |
SP_Ctrl.Addr <= Stack_Start_Addr;
|
SP_Ctrl.Addr <= Stack_Start_Addr;
|
end generate;
|
end generate;
|
|
|
end block;
|
end block;
|
|
|
-------------------------------------------------------------------------------
|
|
-- Address Source Mux
|
|
-------------------------------------------------------------------------------
|
|
|
|
Open8_AS : block is
|
|
begin
|
|
|
|
Address_Select: process( AS_Ctrl, PC, SP, IMM, ISR )
|
|
variable PC_Mux, SP_Mux : ADDRESS_TYPE;
|
|
variable IMM_Mux, ISR_Mux: ADDRESS_TYPE;
|
|
begin
|
|
PC_Mux := (others => '0');
|
|
SP_Mux := (others => '0');
|
|
IMM_Mux := (others => '0');
|
|
ISR_Mux := (others => '0');
|
|
|
|
case AS_Ctrl.Src is
|
|
when ADDR_PC =>
|
|
PC_Mux := PC;
|
|
when ADDR_SP =>
|
|
SP_Mux := SP;
|
|
when ADDR_IMM =>
|
|
IMM_Mux := IMM;
|
|
when ADDR_ISR =>
|
|
ISR_Mux := ISR;
|
|
end case;
|
|
|
|
for i in 0 to 15 loop
|
|
Address(i) <= PC_Mux(i) or SP_Mux(i) or IMM_Mux(i) or
|
|
ISR_Mux(i);
|
|
end loop;
|
|
end process;
|
|
|
|
end block;
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- (Write) Data Path
|
|
-------------------------------------------------------------------------------
|
|
|
|
Open8_DP : block is
|
|
signal Wr_Data_D : DATA_TYPE := (others => '0');
|
|
signal Wr_Enable_D : std_logic := '0';
|
|
begin
|
|
|
|
Data_Select: process( DP_Ctrl, ALU_Regs, ALU_Flags, PC )
|
|
variable Reg_Mux, PC_Mux : DATA_TYPE;
|
|
variable Flag_Mux : DATA_TYPE;
|
|
begin
|
|
Reg_Mux := (others => '0');
|
|
Flag_Mux := (others => '0');
|
|
PC_Mux := (others => '0');
|
|
Wr_Enable_D <= '0';
|
|
|
|
case DP_Ctrl.Src is
|
|
when DATA_IDLE =>
|
|
null;
|
|
when DATA_REG =>
|
|
Reg_Mux := ALU_Regs(conv_integer(DP_Ctrl.Reg));
|
|
Wr_Enable_D <= '1';
|
|
when DATA_FLAG =>
|
|
Flag_Mux := ALU_Flags;
|
|
Wr_Enable_D <= '1';
|
|
when DATA_PC =>
|
|
Wr_Enable_D <= '1';
|
|
if( DP_Ctrl.Reg = ACCUM )then
|
|
PC_Mux := PC(7 downto 0);
|
|
else
|
|
PC_Mux := PC(15 downto 8);
|
|
end if;
|
|
end case;
|
|
|
|
for i in 0 to 7 loop
|
|
Wr_Data_D(i) <= Reg_Mux(i) or Flag_Mux(i) or PC_Mux(i);
|
|
end loop;
|
|
end process;
|
|
|
|
S_Regs: process( Reset, Clock )
|
|
begin
|
|
if( Reset = Reset_Level )then
|
|
Wr_Data <= (others => '0');
|
|
Wr_Enable <= '0';
|
|
Rd_Enable <= '1';
|
|
elsif( rising_edge(Clock) )then
|
|
if( Halt = '0' )then
|
|
Wr_Data <= Wr_Data_D;
|
|
Wr_Enable <= Wr_Enable_D;
|
|
Rd_Enable <= not Wr_Enable_D;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
end block;
|
|
|
|
end rtl;
|
end rtl;
|
|
|
No newline at end of file
|
No newline at end of file
|