📄 pc_inc_spec.vhd
字号:
--------------------------------------------------
-- Model : 8051 Behavioral Model,
-- VHDL Entity mc8051.pc_inc.interface
--
-- Author : Michael Mayer (mrmayer@computer.org),
-- Dr. Hardy J. Pottinger,
-- Department of Electrical Engineering
-- University of Missouri - Rolla
--
-- Created at : 10/24/98 13:58:45
--
LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
LIBRARY mc8051 ;
USE mc8051.synth_pack.all;
ENTITY pc_inc IS
PORT(
cycle_states : IN std_logic_vector( 3 DOWNTO 0 ) ;
force_lcall : IN std_logic ;
int_clk : IN std_logic ;
int_rst : IN std_logic ;
ir : IN std_logic_vector( 7 DOWNTO 0 ) ;
new_ir : IN std_logic ;
pc : IN std_logic_vector( 15 DOWNTO 0 ) ;
last_cycle : OUT std_logic ;
pdat_loc : OUT std_logic_vector( 15 DOWNTO 0 ) ;
wr_pc : OUT std_logic ;
new_pc : INOUT std_logic_vector( 15 DOWNTO 0 )
);
-- Declarations
END pc_inc ;
--
-- VHDL Architecture mc8051.pc_inc.spec
--
-- Created:
-- by - mrmayer.UNKNOWN (eceultra7.ece.umr.edu)
-- at - 12:36:08 08/29/98
--
-- Generated by Mentor Graphics' Renoir(TM) 3.0 (Build 110)
--
architecture spec of pc_inc is
TYPE four_bit0 IS RANGE 0 TO 3;
TYPE four_bit1 IS RANGE 1 TO 4;
SUBTYPE bits2 IS unsigned(1 DOWNTO 0);
TYPE lookup_entry_type IS RECORD
numb_bytes : four_bit0; -- number of bytes
numb_cycles : four_bit1; -- number of cycles
END RECORD lookup_entry_type;
FUNCTION conv_int_to_bits2 (arg : four_bit1) RETURN bits2 IS
VARIABLE output : bits2;
BEGIN
CASE arg IS
WHEN 1 => output := "00";
WHEN 2 => output := "01";
WHEN 3 => output := "10";
WHEN 4 => output := "11";
WHEN OTHERS => output := "00";
END CASE;
RETURN output;
END FUNCTION conv_int_to_bits2;
TYPE lookup_table_type IS ARRAY(0 TO 127) OF lookup_entry_type;
-- the following lookup table has the number of bytes and cycles for each
-- opcode. The are organized as follows (all in hex):
-- n0-n5 => opcodes (2n)*10 + 0 - (2n)*10 + 5
-- n6 => opcodes (2n)*10 + 6 - (2n)*10 + 7
-- n7 => opcodes (2n)*10 + 8 - (2n)*10 + F
-- n8-nD => opcodes (2n+1)*10 + 0 - (2n+1)*10 + 5
-- nE => opcodes (2n+1)*10 + 6 - (2n+1)*10 + 7
-- nF => opcodes (2n+1)*10 + 8 - (2n+1)*10 + F
CONSTANT lookup_table : lookup_table_type := (
16#00# => (1,1), 16#01# => (2,2), 16#02# => (3,2), 16#03# => (1,1),
16#04# => (1,1), 16#05# => (2,1), 16#06# => (1,1), 16#07# => (1,1),
16#08# => (3,2), 16#09# => (2,2), 16#0A# => (3,2), 16#0B# => (1,1),
16#0C# => (1,1), 16#0D# => (2,1), 16#0E# => (1,1), 16#0F# => (1,1),
16#10# => (3,2), 16#11# => (2,2), 16#12# => (1,2), 16#13# => (1,1),
16#14# => (2,1), 16#15# => (2,1), 16#16# => (1,1), 16#17# => (1,1),
16#18# => (3,2), 16#19# => (2,2), 16#1A# => (1,2), 16#1B# => (1,1),
16#1C# => (2,1), 16#1D# => (2,1), 16#1E# => (1,1), 16#1F# => (1,1),
16#20# => (2,2), 16#21# => (2,2), 16#22# => (2,1), 16#23# => (3,2),
16#24# => (2,1), 16#25# => (2,1), 16#26# => (1,1), 16#27# => (1,1),
16#28# => (2,2), 16#29# => (2,2), 16#2A# => (2,1), 16#2B# => (3,2),
16#2C# => (2,1), 16#2D# => (2,1), 16#2E# => (1,1), 16#2F# => (1,1),
16#30# => (2,2), 16#31# => (2,2), 16#32# => (2,1), 16#33# => (3,2),
16#34# => (2,1), 16#35# => (2,1), 16#36# => (1,1), 16#37# => (1,1),
16#38# => (2,2), 16#39# => (2,2), 16#3A# => (2,2), 16#3B# => (1,2),
16#3C# => (2,1), 16#3D# => (3,2), 16#3E# => (2,1), 16#3F# => (2,1),
16#40# => (2,2), 16#41# => (2,2), 16#42# => (2,2), 16#43# => (1,2),
16#44# => (1,4), 16#45# => (3,2), 16#46# => (2,2), 16#47# => (2,2),
16#48# => (3,2), 16#49# => (2,2), 16#4A# => (2,2), 16#4B# => (1,2),
16#4C# => (2,1), 16#4D# => (2,1), 16#4E# => (1,1), 16#4F# => (1,1),
16#50# => (2,2), 16#51# => (2,2), 16#52# => (2,1), 16#53# => (1,2),
16#54# => (1,4), 16#55# => (1,1), 16#56# => (2,2), 16#57# => (2,2),
16#58# => (2,2), 16#59# => (2,2), 16#5A# => (2,1), 16#5B# => (2,1),
16#5C# => (3,2), 16#5D# => (3,2), 16#5E# => (3,2), 16#5F# => (3,2),
16#60# => (2,2), 16#61# => (2,2), 16#62# => (2,1), 16#63# => (1,1),
16#64# => (1,1), 16#65# => (2,1), 16#66# => (1,1), 16#67# => (1,1),
16#68# => (2,2), 16#69# => (2,2), 16#6A# => (2,1), 16#6B# => (1,1),
16#6C# => (1,1), 16#6D# => (3,2), 16#6E# => (1,1), 16#6F# => (2,2),
16#70# => (1,2), 16#71# => (2,2), 16#72# => (1,2), 16#73# => (1,2),
16#74# => (1,1), 16#75# => (2,1), 16#76# => (1,1), 16#77# => (1,1),
16#78# => (1,2), 16#79# => (2,2), 16#7A# => (1,2), 16#7B# => (1,2),
16#7C# => (1,1), 16#7D# => (2,1), 16#7E# => (1,1), 16#7F# => (1,1)
);
SIGNAL pc_plus0, pc_plus1, pc_plus2, pc_plus3 : unsigned(15 DOWNTO 0)
:= (OTHERS => '0');
SIGNAL cycle_counter : unsigned(1 DOWNTO 0);
SIGNAL number_of_bytes : four_bit0; -- number of bytes
SIGNAL number_of_cycles : four_bit1; -- number of cycles
SIGNAL last_cycle_internal : std_logic;
SIGNAL reset_state : std_logic;
BEGIN
reset_state <= '1' WHEN int_rst = '1' ELSE
'0' WHEN cycle_states = s6p2 ELSE
reset_state;
pc_plus0 <= unsigned(pc) WHEN rising_edge(new_ir) ELSE pc_plus0;
pc_plus1 <= pc_plus0 + 1;
pc_plus2 <= pc_plus1 + 1;
pc_plus3 <= pc_plus2 + 1;
-- perfom the table lookup to drive number of bytes & cycles
-- (this should be replaced by a ROM
-- and latches, where new_ir would be the enable)
table_lookup : PROCESS (new_ir) IS
VARIABLE lsb_3 : std_logic_vector(2 DOWNTO 0);
VARIABLE index_val : unsigned(6 DOWNTO 0);
BEGIN
IF rising_edge(new_ir) THEN
IF ir(3) = '1' THEN
lsb_3 := "111";
ELSIF ir(2 DOWNTO 1) = "11" THEN
lsb_3 := "110";
ELSE
lsb_3 := ir(2 DOWNTO 0);
END IF;
index_val := unsigned(ir(7 DOWNTO 5) & ir(3) & lsb_3);
number_of_bytes <= lookup_table(to_integer(index_val)).numb_bytes;
number_of_cycles <= lookup_table(to_integer(index_val)).numb_cycles;
END IF;
END PROCESS table_lookup;
-- define a counter which resets on new_ir, and increments
-- with int_clk whenever cycle_state = s6p2.
set_cycle_counter : PROCESS (int_clk, reset_state) IS
BEGIN
IF (reset_state = '1') THEN
-- asynchronous reset
cycle_counter <= "00";
ELSIF falling_edge(int_clk) AND cycle_states = s6p2 THEN
IF last_cycle_internal = '1' THEN
-- synchronous reset
cycle_counter <= "00";
ELSE
-- synchronous increment
CASE cycle_counter IS
WHEN "00" => cycle_counter <= "01";
WHEN "01" => cycle_counter <= "10";
WHEN "10" => cycle_counter <= "11";
WHEN "11" => cycle_counter <= "11";
WHEN OTHERS => cycle_counter <= "00";
REPORT "BAD CYCLE COUNTER in pc_incrementer";
-- this last entry could probably wrap around to "00"
END CASE;
END IF;
END IF;
END PROCESS set_cycle_counter;
-- output the last_cycle (combinational logic)
last_cycle_internal <= '1' WHEN cycle_counter = conv_int_to_bits2(number_of_cycles) ELSE
'0';
last_cycle <= last_cycle_internal;
-- output the new pc on the first cycle at s1p2
-- (this process is combinational logic & trisate)
output_new_pc : PROCESS (int_clk, reset_state, force_lcall, cycle_counter,
cycle_states, number_of_bytes, pc_plus0,
pc_plus1, pc_plus2, pc_plus3) IS
BEGIN
IF reset_state = '0' AND force_lcall = '0' AND
cycle_counter = "00" AND cycle_states = s1p2 THEN
-- the above conditions correspond to an enable on the tristate
CASE number_of_bytes IS
WHEN 0 => new_pc <= std_logic_vector(pc_plus0);
WHEN 1 => new_pc <= std_logic_vector(pc_plus1);
WHEN 2 => new_pc <= std_logic_vector(pc_plus2);
WHEN 3 => new_pc <= std_logic_vector(pc_plus3);
END CASE;
wr_pc <= '1';
ELSE
new_pc <= (OTHERS => 'Z'); -- tristate
wr_pc <= 'L';
END IF;
END PROCESS output_new_pc;
-- process to drive the pdata location (pdat_loc)
-- this process has combination logic, and
-- a set of flip-flops for pdat_loc.
-- the enable for the flip flops is a complicated expression for
-- all of the if statements, while the input to the ff's is
-- multiplexed or selected from the four possible values.
drive_pdat_loc : PROCESS (int_clk, reset_state) IS
VARIABLE first_half, second_half : BOOLEAN;
BEGIN
CASE cycle_states IS
WHEN s1p1 | s1p2 | s2p1 | s2p2 | s3p1 | s3p2 =>
first_half := TRUE;
second_half := FALSE;
WHEN s4p1 | s4p2 | s5p1 | s5p2 | s6p1 | s6p2 =>
first_half := FALSE;
second_half := TRUE;
WHEN OTHERS =>
first_half := FALSE;
second_half := FALSE;
END CASE;
IF reset_state = '1' THEN
pdat_loc <= (OTHERS => '0');
ELSIF last_cycle_internal = '1' AND second_half THEN
-- output the new pc
pdat_loc <= pc;
ELSIF cycle_counter = "00" THEN
IF first_half THEN
pdat_loc <= std_logic_vector(pc_plus1);
ELSIF second_half THEN
IF std_match(ir,"100-0011") THEN -- check for the MOVC instruction
pdat_loc <= new_pc;
ELSIF number_of_bytes >= 2 THEN
pdat_loc <= std_logic_vector(pc_plus2);
END IF;
END IF;
ELSIF cycle_counter = "01" THEN
IF number_of_bytes >= 3 THEN
pdat_loc <= std_logic_vector(pc_plus3);
END IF;
END IF;
END PROCESS drive_pdat_loc;
END ARCHITECTURE spec;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -