URL
https://opencores.org/ocsvn/light52/light52/trunk
Subversion Repositories light52
Compare Revisions
- This comparison shows the changes necessary to convert path
/light52/trunk
- from Rev 16 to Rev 17
- ↔ Reverse comparison
Rev 16 → Rev 17
/vhdl/light52_cpu.vhdl
136,8 → 136,11
|
entity light52_cpu is |
generic ( |
-- Do not map unused BRAM onto XRAM space. |
USE_BRAM_FOR_XRAM : boolean := false; |
-- Implement DA and XCHD instructions by default. |
IMPLEMENT_BCD_INSTRUCTIONS : boolean := false; |
-- Use a combinational (dedicated) multiplier by default. |
SEQUENTIAL_MULTIPLIER : boolean := false |
); |
port( |
228,17 → 231,27
|
---- Interrupt handling -------------------------------------------------------- |
|
-- IRQ inputs ANDed to IE mask bits |
-- IRQ inputs ANDed to IE mask bits. |
signal irq_masked_inputs : std_logic_vector(4 downto 0); |
-- IRQ inputs ANDed to IE mask bits ANDed to IP mask bits. |
signal irq_masked_inputs_hp : std_logic_vector(4 downto 0); |
-- Level of highest-level active IRQ input. 0 is highest, 4 lowest, 7 is none. |
signal irq_level_inputs : unsigned(2 downto 0); |
-- Level of IRQ being serviced. 7 if none. Set by IRQ, reset to 7 by RETI. |
signal irq_level_current : unsigned(2 downto 0); |
-- Low 6 bits of IRQ service address. |
signal irq_vector : unsigned(5 downto 0); |
signal irq_active : std_logic; -- IRQ pending service |
signal load_ie : std_logic; -- IE register load enable |
signal irq_restore_level : std_logic; -- Restore irq_level_current to 7 (RETI) |
signal load_ip : std_logic; -- IP register load enable |
-- Restore irq priority level (as per RETI execution). |
signal irq_restore_level : std_logic; |
-- High wwhen the active IRQ is allowed by the priority rules. |
signal irq_active_allowed : std_logic; |
-- High when serving a LOw Priority interrupt. |
signal irq_serving_lop : std_logic; |
-- High when serving a HIgh Priority interrupt. |
signal irq_serving_hip : std_logic; |
-- High when the active interrupt line is a HIgh Priority interrupt. |
signal irq_active_hip : std_logic; |
|
---- CPU programmer's model registers ------------------------------------------ |
|
252,7 → 265,9
signal SP_reg : t_byte; -- SP |
signal SP_next : t_byte; -- Next value for SP |
signal IE_reg : t_byte; -- IE |
signal IP_reg : t_byte; -- IP |
|
|
signal alu_p : std_logic; -- P flag (from ALU) |
signal DPTR_reg : t_address; -- DPTR |
|
897,6 → 912,27
|
--## 2.- Interrupt handling #################################################### |
|
|
-- IP SFR is implemented as a regular SFR as per the MC51 architecture. |
load_ip <= '1' when sfr_addr_internal=SFR_ADDR_IP and sfr_we_internal='1' |
else '0'; |
|
IP_register: |
process(clk) |
begin |
if clk'event and clk='1' then |
if reset='1' then |
IP_reg <= (others => '0'); |
else |
if load_ip='1' then |
IP_reg <= alu_result; |
end if; |
end if; |
end if; |
end process IP_register; |
|
|
-- IE SFR is implemented as a regular SFR as per the MC51 architecture. |
load_ie <= '1' when sfr_addr_internal=SFR_ADDR_IE and sfr_we_internal='1' |
else '0'; |
|
920,8 → 956,15
|
-- Mask the irq inputs with IE register bits... |
irq_masked_inputs <= irq_source and std_logic_vector(IE_reg(4 downto 0)); |
-- ...separate the highpriority interrupt inputs by masking with IP register... |
irq_masked_inputs_hp <= irq_masked_inputs and std_logic_vector(IP_reg(4 downto 0)); |
-- ...and encode the highest priority active input |
irq_level_inputs <= |
"000" when irq_masked_inputs_hp(0)='1' else |
"001" when irq_masked_inputs_hp(1)='1' else |
"010" when irq_masked_inputs_hp(2)='1' else |
"011" when irq_masked_inputs_hp(3)='1' else |
"100" when irq_masked_inputs_hp(4)='1' else |
"000" when irq_masked_inputs(0)='1' else |
"001" when irq_masked_inputs(1)='1' else |
"010" when irq_masked_inputs(2)='1' else |
928,36 → 971,61
"011" when irq_masked_inputs(3)='1' else |
"100" when irq_masked_inputs(4)='1' else |
"111"; |
|
irq_active_hip <= '1' when irq_masked_inputs_hp/="00000" else '0'; |
|
-- An active, enabled interrupt will be serviced only if... |
irq_active_allowed <= '1' when |
-- ...other high-priority interrupt is NOT being serviced... |
irq_serving_hip='0' and |
-- ...and either the incoming interrupt is high-priority... |
(irq_active_hip='1' or |
-- -- ...or no interrupt is being serviced at all; |
(irq_active_hip='0' and irq_serving_lop='0')) |
-- otherwise the interrupt is not allowed to proceed. |
else '0'; |
|
-- We have a pending irq if interrupts are enabled... |
irq_active <= '1' when IE_reg(7)='1' and |
-- ...and the active irq has higher priority than any |
-- ongoing irq routine. |
(irq_level_inputs < irq_level_current) |
else '0'; |
-- ...and some interrupt source is active... |
irq_level_inputs/="111" and |
-- ...and the active interrupt is allowed by the priority |
-- rules... |
irq_active_allowed='1' |
-- ...otherwise the interrupt is ignored. |
else '0'; |
|
irq_registered_priority_encoder: |
process(clk) |
begin |
if clk'event and clk='1' then |
if reset='1' or irq_restore_level='1' then |
-- After reset, irq level is 7, which means all irqs are accepted. |
-- Note that valid levels are 0 to 4 and the lower the number, |
-- the higher the priority. |
-- The level is restored to 7 by the RETI instruction too. |
irq_level_current <= "111"; |
else |
if reset='1' then |
-- After reset, no interrupt of either priority level is being |
-- serviced. |
irq_serving_hip <= '0'; |
irq_serving_lop <= '0'; |
elsif irq_restore_level='1' then |
-- RETI executed: if high-priority level was active... |
if irq_serving_hip='1' then |
-- ...disable it, reverting to the previous priority level... |
irq_serving_hip <= '0'; |
else |
-- otherwise disable the low priority level. |
irq_serving_lop <= '0'; |
end if; |
else |
-- Evaluate and register the interrupt priority in the same state |
-- the irq is to be acknowledged. |
if ps=fetch_1 and irq_active='1' then |
irq_level_current <= irq_level_inputs; |
irq_serving_hip <= irq_active_hip; |
irq_serving_lop <= irq_serving_lop or (not irq_active_hip); |
-- This irq vector is going to be used in state irq_2. |
irq_vector <= irq_level_inputs & "011"; |
end if; |
end if; |
end if; |
end process irq_registered_priority_encoder; |
|
-- This irq vector is going to be used in state irq_2. |
irq_vector <= irq_level_current & "011"; |
|
|
--## 3.- Combined register bank & decoding table ############################### |
1617,6 → 1685,7
DPTR_reg(15 downto 8) when SFR_ADDR_DPH, |
DPTR_reg( 7 downto 0) when SFR_ADDR_DPL, |
IE_reg when SFR_ADDR_IE, |
IP_reg when SFR_ADDR_IP, |
unsigned(sfr_rd) when others; |
|
-- Registering the SFR read mux gives the SFR block the same timing behavior as |
/vhdl/light52_pkg.vhdl
37,7 → 37,7
|
subtype t_byte is unsigned(7 downto 0); |
|
-- These include only the CPU SFRs (B,ACC,PSW,DPH,DPL,SP,IE) |
-- These include only the CPU SFRs (B,ACC,PSW,DPH,DPL,SP,IE,IP) |
constant SFR_ADDR_ACC : t_byte := X"E0"; |
constant SFR_ADDR_PSW : t_byte := X"D0"; |
constant SFR_ADDR_B : t_byte := X"F0"; |
45,6 → 45,7
constant SFR_ADDR_DPH : t_byte := X"83"; |
constant SFR_ADDR_DPL : t_byte := X"82"; |
constant SFR_ADDR_IE : t_byte := X"A8"; |
constant SFR_ADDR_IP : t_byte := X"B8"; |
|
|
---- Configuration constants --------------------------------------------------- |
/vhdl/light52_mcu.vhdl
262,8 → 262,8
sfr_we => sfr_we |
); |
|
-- FIXME uart irq is unconnected! |
irq_source <= "000" & timer_irq & ext_irq; |
-- Connect peripheral IRQ inputs to the CPU. |
irq_source <= uart_irq & "00" & timer_irq & ext_irq; |
|
---- SFR input mux ------------------------------------------------------------- |
|