|
楼主 |
发表于 2013-6-28 00:05:36
|
显示全部楼层
回复 3# scion
intel cad history
IntelCADPaperFinal2.pdf
(891.83 KB, 下载次数: 22 )
intel 386 VHDL behavior model ??
==
-------------------------------------------------------------------------------- ---- Intel 80386 VHDL model ---- Copyright (C) Convergent, Inc. 1988 ---- ---- File: i80386.vhd ---- Revision: E0.1 ---- Date Created: 6-12-1988 ---- Author: Mark Dakur ---- Function: This VHDL model emulates the Intel 80386 32-bit CPU ---- to the instruction and bus timing level. ---- Generics: Debug 1=Enable Reporting of Model Status. ---- 0=None (Default) ---- Inst ---- Performance ---- Speed ---- Target Simulator: ViewSim ---- ---- Reference Material: Intel Data Book, 80386-20, Oct., 1987 ---- Intel 80386 Programmers Reference, 1986 ---- 80386 Technical Reference, Edmund Strauss, 1987 ---- ---- Verification: No ---- Validation: No ---- Certification: No ---- ---- Behavioral models have two main parts: a package declaration and its ---- corresponding package body, and an entity declaration and its ---- corresponding architecture body. The package declaration and ---- package body define subprograms used by the behavioral model; ---- the entity declaration and architecture body define the behavior ---- of the model. ---- This file contains the entity declaration and architecture. ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Specification ---- ---- 1.0 Introduction ---- 2.0 Description ---- ---- The i80386 consists of 6 functional units defined as follows: ---- ---- 1) Bus Interface Unit {BIunit} ---- Accepts internal requests for code fetches from the CPunit and -- -- data transfers from the Eunit and prioritizes the requests. ---- It is the interface to the external pins (ports) of the package. ---- ---- 2) Code Prefetch Unit {CPunit} ---- Performs the program look ahead function. When the BIunit is not ---- performing bus cycles to execute an instruction, it uses the BIunit ---- to to fetch sequentially along the instruction byte stream. These ---- prefetched instructions are stored in the 16-byte Code Queue to ---- await processing by the IDunit. ---- ---- 3) Instruction Decode Unit {IDunit} ---- a) Instructions Supported: ---- 1) nop ---- 2) mov eax,"immediate 32 bit data" ---- 3) mov ebx,"immediate 32 bit data" ---- 4) mov eax,[ebx] ---- 5) mov [ebx],eax ---- 6) in al,"byte address" ---- 7) out "byte address",al ---- 8) inc eax ---- 9) inc ebx ---- 10) jmp "label" (relative nears and shorts) ---- ---- 4) Execution Unit {Eunit} ---- a) Control Unit {Cunit} ---- b) Data Unit {Dunit} ---- c) Protection Test Unit {PTunit} ---- ---- 5) Segmentation Unit {Sunit} ---- ---- 6) Paging Unit {Punit} ---- a) Page Translator Unit {PTunit} ---- i) Translation Lookaside Buffer {TLB} ---- a) Page Directory ---- b) Page Table ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Revision History ---- ---- Revision ---- Level Date Engineer Description ---- -------- ------- --------------- --------------------------------------- ---- E0.1 6-12-88 Dakur First Release ------------------------------------------------------------------------------------------------------------------------------------------------------------------ Entity declaration for i80386:---- The following entity declaration begins the definition of the-- behavioral model of the i80386. It declares the model's name-- and its IO signals, or ports. This declaration defines the-- model's interface with enclosing designs; it defines the part-- of the model that is externally visible. Following this-- entity declaration is its corresponding architecture body;-- the architecture body defines the behavior of the model.-------------------------------------------------------------------------PACKAGE i80386 isFUNCTION tohex (CONSTANT value, Bytes: IN INTEGER) RETURN integer;END i80386ACKAGE BODY i80386 isFUNCTION tohex (CONSTANT value, Bytes: IN INTEGER) RETURN integer IS VARIABLE dWord: vlbit_1d(31 downto 0); VARIABLE Byte: vlbit_1d(31 downto 0); VARIABLE Count: INTEGER;BEGIN Count := 1; dWord := vlbit_vector(value); Convert: WHILE Count <= Bytes LOOP CASE integer(Bytes) is WHEN 4 => CASE Count is WHEN 1 => Byte := X"000000" & dWord(31 downto 24); WHEN 2 => Byte := X"000000" & dWord(23 downto 16); WHEN 3 => Byte := X"000000" & dWord(15 downto 8); WHEN 4 => Byte := X"000000" & dWord(7 downto 0); WHEN OTHERS => NULL; END CASE; WHEN 2 => CASE Count is WHEN 1 => Byte := X"000000" & dWord(15 downto 8); WHEN 2 => Byte := X"000000" & dWord(7 downto 0); WHEN OTHERS => NULL; END CASE; WHEN 1 => Byte := X"000000" & dWord(7 downto 0); WHEN OTHERS => NULL; END CASE; Count := Count + 1; CASE integer(Byte(7 downto 4)) is WHEN 15 => put("F"); WHEN 14 => put("E"); WHEN 13 => put("D"); WHEN 12 => put("C"); WHEN 11 => put("B"); WHEN 10 => put("A"); WHEN 9 => put("9"); WHEN 8 => put("8"); WHEN 7 => put("7"); WHEN 6 => put("6"); WHEN 5 => put("5"); WHEN 4 => put("4"); WHEN 3 => put("3"); WHEN 2 => put("2"); WHEN 1 => put("1"); WHEN 0 => put("0"); WHEN OTHERS => put("X"); END CASE; CASE integer(Byte(3 downto 0)) is WHEN 15 => put("F"); WHEN 14 => put("E"); WHEN 13 => put("D"); WHEN 12 => put("C"); WHEN 11 => put("B"); WHEN 10 => put("A"); WHEN 9 => put("9"); WHEN 8 => put("8"); WHEN 7 => put("7"); WHEN 6 => put("6"); WHEN 5 => put("5"); WHEN 4 => put("4"); WHEN 3 => put("3"); WHEN 2 => put("2"); WHEN 1 => put("1"); WHEN 0 => put("0"); WHEN OTHERS => put("X"); END CASE; END LOOP Convert; put("h"); RETURN 1;END tohex;END i80386;USE work.i80386.tohex;entity i80386 is GENERIC (CONSTANT Debug: BOOLEAN := FALSE; CONSTANT Inst: BOOLEAN := FALSE; CONSTANT Performance: INTEGER := 1; CONSTANT Speed: INTEGER := 32);-- USE: Pass a value to the above generics from attributes attached to the 80386 symbol-- on the schematic.-- Description: Debug; A value of integer 1 (one) means that the model will output-- status information as simulation progresses. The default if no attribute exists is-- FALSE, or no status reported.-- Inst; A value of interger 1 (one) means that the model will output-- instructions. The Debug generic overides this one.-- Performance; 0=min, 1=typ, 2=max-- Speed; Processor speed choices, values are: 0=16MHz, 1=20MHz, 2=25MHZ, 3=30MHz port (BE_n: out vlbit_1d(3 downto 0) := B"0000"; Address: out vlbit_1d(31 downto 2) := B"111111111111111111111111111111"; W_R_n: out vlbit := '0'; D_C_n: out vlbit := '1'; M_IO_n: out vlbit := '0'; LOCK_n, ADS_n: out vlbit := '1'; HLDA: out vlbit := '0'; Data: inout vlbit_1d(31 downto 0) := X"ZZZZZZZZ"; CLK2: in vlbit := '0'; NA_n, BS16_n: in vlbit := '1'; READY_n, HOLD, PERQ: in vlbit := '0'; BUSY_n, ERROR_n: in vlbit := '1'; INTR: in vlbit := '0'; NMI, RESET: in vlbit := '0');-- THE ORDER OF THE PORTS IS IMPORTANT FOR COMPATIBILITY WITH THE "INORDER"-- ATTRIBUTE ON THE SYMBOL FOR THIS MODEL.end i80386;-------------------------------------------------------------------------------------------------------------------------------------------------- Architecture Body of i80386:---- The following architecture body defines the behavior of the i80386-- model. It consists of a set of process statements and other-- concurrent statements. These statements are all invoked when-- simulation begins, and continue to execute concurrently throughout-- simulation. The statements communicate via the internal signals-- declared at the top of the architecture body. Each statement either-- checks the validity of input signals, or modifies the values of-- output signals or internal signals in response to changes on input-- signals or internal signals.-------------------------------------------------------------------------architecture behavior of i80386 is-- Internal Signals-- These information paths allow for communication between Concurent-- Process Blocks within the model. All signals that are defined here have-- global visibility. Signals, variables and constants defined within process-- blocks have local visibility within that process ONLY. SIGNAL CLK: vlbit := '1'; -- 80386 internal clock=CLK2 / 2 SIGNAL StateNA: vlbit := '1'; SIGNAL StateBS16: vlbit := '1'; SIGNAL RequestPending: vlbit := '1'; CONSTANT Pending: vlbit := '1'; CONSTANT NotPending: vlbit := '0'; SIGNAL NonAligned: vlbit := '0'; SIGNAL ReadRequest: vlbit := '1'; SIGNAL MemoryFetch: vlbit := '1'; SIGNAL CodeFetch: vlbit := '1'; SIGNAL ByteEnable: vlbit_1d(3 downto 0) := X"0"; SIGNAL DataWidth: vlbit_1d(31 downto 0) := X"00000002"; CONSTANT WidthByte: INTEGER := 0; -- Byte CONSTANT WidthWord: INTEGER := 1; -- Word (2 bytes) CONSTANT WidthDword: INTEGER := 2; -- Dword (4 bytes) SIGNAL dWord: vlbit_1d(31 downto 0) := X"00000000"; SIGNAL State: vlbit_1d(31 downto 0) := X"00000000"; -- State Register, Initialized to StateTi CONSTANT StateTi: INTEGER := 0; -- Reset State CONSTANT StateT1: INTEGER := 1; -- First state of a non-pipelined bus cycle CONSTANT StateT2: INTEGER := 2; -- State where NA_n is false (non-pipelined) CONSTANT StateT1P: INTEGER := 3; -- First state of a pipelined bus cycle CONSTANT StateTh: INTEGER := 4; -- Hold acknowledge state CONSTANT StateT2P: INTEGER := 5; -- Subsequent state of a pipelined bus cycle CONSTANT StateT2I: INTEGER := 6; -- Subsequent state of a potential pipelined -- bus cycle. -- The constants are indexes into the vector State where each constant represents 1 bit of the vector.-- Internal User Registers--- General Purpose Data and Address SIGNAL EAX: vlbit_1d(31 DOWNTO 0); SIGNAL EDX: vlbit_1d(31 DOWNTO 0); SIGNAL ECX: vlbit_1d(31 DOWNTO 0); SIGNAL EBX: vlbit_1d(31 DOWNTO 0); SIGNAL EBP: vlbit_1d(31 DOWNTO 0); SIGNAL ESI: vlbit_1d(31 DOWNTO 0); SIGNAL EDI: vlbit_1d(31 DOWNTO 0); SIGNAL ESP: vlbit_1d(31 DOWNTO 0);-- NOTE: Create a proceedure that can be called with the appropriate mnemonic-- to access the appropriate register. Futher work must be done to implement-- the 16-bit and 8-bit versions of these registers.--- Segment Selectors SIGNAL CS: vlbit_1d(15 DOWNTO 0); -- Code Segment SIGNAL SS: vlbit_1d(15 DOWNTO 0); -- Stack Segment SIGNAL DS: vlbit_1d(15 DOWNTO 0); -- Data Segment Module A SIGNAL ES: vlbit_1d(15 DOWNTO 0); -- Data Segment Structure 1 SIGNAL FSS: vlbit_1d(15 DOWNTO 0); -- Data Segment Structure 2 SIGNAL GS: vlbit_1d(15 DOWNTO 0); -- Data Segment Structure 3--- Segment Descripters--- These register are associated with each Segment Selector Register and are--- not visible to the programmer.--- Instruction Pointer and Flags SIGNAL rEIP: vlbit_1d(31 downto 0) := X"FFFFFFF0";-- Must create a proceedure to access by mnemonic the IP within the EIP register. SIGNAL rEFLAGS: vlbit_1d(31 downto 0) := B"XXXXXXXXXXXXXXXX0XXXXXXXXX0X0X1X"; CONSTANT VM: INTEGER := 0; CONSTANT RF: INTEGER := 0; CONSTANT NT: INTEGER := 0; CONSTANT IOPL: INTEGER := 0; CONSTANT xOF: INTEGER := 0; CONSTANT DF: INTEGER := 0; CONSTANT xIF: INTEGER := 0; CONSTANT TF: INTEGER := 0; CONSTANT SF: INTEGER := 0; CONSTANT ZF: INTEGER := 0; CONSTANT AF: INTEGER := 4; CONSTANT PF: INTEGER := 2; CONSTANT CF: INTEGER := 0;--- Machine Control SIGNAL rCR0: vlbit_1d(31 downto 0) := X"00000000"; SIGNAL rCR1: vlbit_1d(31 downto 0) := X"00000000"; SIGNAL rCR2: vlbit_1d(31 downto 0) := X"00000000"; -- Page Directory Base Register SIGNAL rCR3: vlbit_1d(31 downto 0) := X"00000000";--- System Address (Memory Mapping Management) -- Global Descripter Table Pointer SIGNAL rGDTbase: vlbit_1d(31 downto 0) := X"00000000"; SIGNAL rGDTlimit: vlbit_1d(15 downto 0) := X"0000"; SIGNAL rGDTselector: vlbit_1d(15 downto 0) := X"0000"; -- Local Descripter Table Pointer SIGNAL rLDTbase: vlbit_1d(31 downto 0) := X"00000000"; SIGNAL rLDTlimit: vlbit_1d(15 downto 0) := X"0000"; SIGNAL rLDTselector: vlbit_1d(15 downto 0) := X"0000"; -- Interrupt Descripter Table Pointer SIGNAL rIDTbase: vlbit_1d(31 downto 0) := X"00000000"; SIGNAL rIDTlimit: vlbit_1d(15 downto 0) := X"0000"; SIGNAL rIDTselector: vlbit_1d(15 downto 0) := X"0000"; -- Task State Segment Descripter Table Pointer SIGNAL rTSSbase: vlbit_1d(31 downto 0) := X"00000000"; SIGNAL rTSSlimit: vlbit_1d(15 downto 0) := X"0000"; SIGNAL rTSSselector: vlbit_1d(15 downto 0) := X"0000"; -- Page Table Register Files-- SIGNAL rfPageDir: vlbit_2d(0 to 1024,31 downto 0);-- SIGNAL rfPageTable: vlbit_2d(0 to 1024,31 downto 0);--- Debug--- Test-- 80386 Instruction Set (Supported by this model)--- Instruction Prefixes CONSTANT REP: INTEGER := 16#F3#; CONSTANT REPNE: INTEGER := 16#F2#; CONSTANT LOCK: INTEGER := 16#F0#;--- Segment Override Prefixes CONSTANT CSsop: INTEGER := 16#2E#; CONSTANT SSsop: INTEGER := 16#36#; CONSTANT DSsop: INTEGER := 16#3E#; CONSTANT ESsop: INTEGER := 16#26#; CONSTANT FSsop: INTEGER := 16#64#; CONSTANT GSsop: INTEGER := 16#65#; CONSTANT OPsop: INTEGER := 16#66#; CONSTANT ADsop: INTEGER := 16#67#;--- Data Transfer CONSTANT MOV_al_b: INTEGER := 16#B0#; CONSTANT MOV_eax_dw: INTEGER := 16#B8#; -- mov eax,0000A5A5h CONSTANT MOV_ebx_dw: INTEGER := 16#BB#; -- mov ebx,0FFFFFFF0h CONSTANT MOV_ebx_eax: INTEGER := 16#89#; -- mov [ebx],eax {89,03} CONSTANT MOV_eax_ebx: INTEGER := 16#8B#; -- mov eax,[ebx] {8B,03} CONSTANT IN_al: INTEGER := 16#E4#; CONSTANT OUT_al: INTEGER := 16#E6#;--- Arithmetic CONSTANT ADD_al_b: INTEGER := 16#04#; CONSTANT ADD_ax_w: INTEGER := 16#05#;--- Shift/Rotate CONSTANT ROL_eax_b: INTEGER := 16#D1#; -- rol eax,1 {D1,C0} CONSTANT ROL_al_1: INTEGER := 16#D0#; CONSTANT ROL_al_n: INTEGER := 16#C0#;--- String Manipulation CONSTANT INC_eax: INTEGER := 16#40#; CONSTANT INC_ebx: INTEGER := 16#43#;--- Bit Manipulation--- Control Transfer CONSTANT JMP_rel_short: INTEGER := 16#EB#; CONSTANT JMP_rel_near: INTEGER := 16#E9#; CONSTANT JMP_intseg_immed: INTEGER := 16#EA#;--- High Level Language Support--- Operating System Support--- Processor Control CONSTANT HLT: INTEGER := 16#F4#; CONSTANT WAITx: INTEGER := 16#9B#; CONSTANT NOP: INTEGER := 16#90#; BEGIN-- Begin Fault Detection Section Faults: PROCESS BEGIN WAIT UNTIL now > 1; assert not bitunknown(CLK2) report "Clock {i}: CLK2 (pin F12) is undefined" severity FAILURE; assert not bitunknown(READY_n) report "Control {i}: READY (pin G13) is undefined" severity FAILURE; END PROCESS Faults;-- End Fault Detection Section-- Begin Behavioral Blocks -- Port Signals Status Reports Begin CLK2status: PROCESS -- Function: The first time (after the loading the network) -- the simulation is run, this process will report -- status of the 80386's CLK2 input from the network. VARIABLE StartTime: INTEGER; VARIABLE Pwidth: INTEGER; VARIABLE freq: INTEGER; BEGIN WAIT UNTIL prising(CLK2); StartTime := now; WAIT UNTIL prising(CLK2); Pwidth := (now - StartTime); freq := 10000000 / Pwidth; put("CLK2 Pulse Width is=",Pwidth); putline(" in 10ths of nS"); put("CLK2 Frequency is=",freq); putline("kHZ"); WAIT; end PROCESS CLK2status; -- Port Signals Status Reports End -- Internal Control Logic Processes Begin GenCLK: PROCESS begin -- CLK is the 80386's internal clock an is 1/2 of CLK2 wait until prising(CLK2); CLK <= not CLK; end PROCESS GenCLK; Initialize: PROCESS BEGIN EAX <= X"00000000"; rEFLAGS <= X"00000002"; rEIP <= X"FFFFFFF0"; rIDTbase <= X"00000000"; rIDTlimit <= X"03FF"; State <= vlbit_vector(StateTi); IF Debug THEN putline("DEBUG: State=RESET"); END IF; WAIT UNTIL pfalling(RESET); -- De-assert the drivers IF Debug THEN putline("DEBUG: 80386 was successfully Reset."); END IF; EAX <= X"ZZZZZZZZ"; rEFLAGS <= X"ZZZZZZZZ"; rEIP <= X"ZZZZZZZZ"; rIDTbase <= X"ZZZZZZZZ"; rIDTlimit <= X"ZZZZ"; State <= X"ZZZZZZZZ"; RequestPending <= 'Z'; WAIT UNTIL prising(RESET); end PROCESS Initialize; TstateMachine: PROCESS VARIABLE nState: vlbit_1d(31 downto 0) := X"00000000"; BEGIN WAIT UNTIL pfalling(CLK); CASE integer(State) is WHEN StateTi => IF Debug THEN put("DEBUG: 80386 is in State Ti"); END IF; IF RESET = '0' and RequestPending = Pending THEN nState := vlbit_vector(StateT1); IF Debug THEN putline(", Moving to StateT1"); END IF; ELSIF RESET = '0' and HOLD = '1' THEN nState := vlbit_vector(StateTh); IF Debug THEN putline(", Moving to StateTh"); END IF; ELSE nState := vlbit_vector(StateTi); IF Debug THEN IF RESET = '1' THEN putline(", Due to RESET = Asserted"); ELSE putline(", Due to NO Requests Pending"); END IF; END IF; END IF; WHEN StateT1 => IF Debug THEN putline("DEBUG: 80386 is in State T1, Moving to StateT2"); END IF; nState := vlbit_vector(StateT2); WHEN StateT2 => IF Debug THEN putline("DEBUG: 80386 is in State T2"); END IF; IF READY_n = '0' and HOLD ='0' and RequestPending = Pending THEN nState := vlbit_vector(StateT1); ELSIF READY_N = '1' and NA_n = '1' THEN NULL; ELSIF (RequestPending = Pending or HOLD = '1') and (READY_N = '1' and NA_n = '0') THEN nState := vlbit_vector(StateT2I); ELSIF RequestPending = Pending and HOLD = '0' and READY_N = '1' and NA_n = '0' THEN nState := vlbit_vector(StateT2P); ELSIF RequestPending = NotPending and HOLD = '0' and READY_N = '0' THEN nState := vlbit_vector(StateTi); ELSIF HOLD = '1' and READY_N = '1' THEN nState := vlbit_vector(StateTh); END IF; WHEN StateT1P => IF Debug THEN putline("DEBUG: 80386 is in State T1P"); END IF; IF NA_n = '0' and HOLD = '0' and RequestPending = Pending THEN nState := vlbit_vector(StateT2P); ELSIF NA_n = '0' and (HOLD = '1' or RequestPending = NotPending) THEN nState := vlbit_vector(StateT2I); ELSIF NA_n = '1' THEN nState := vlbit_vector(StateT2); END IF; WHEN StateTh => IF Debug THEN putline("DEBUG: 80386 is in State Th"); END IF; IF HOLD = '1' THEN NULL; ELSIF HOLD = '0' and RequestPending = Pending THEN nState := vlbit_vector(StateT1); ELSIF HOLD = '0' and RequestPending = NotPending THEN nState := vlbit_vector(StateTi); END IF; WHEN StateT2P => IF Debug THEN putline("DEBUG: 80386 is in State T2P"); END IF; IF READY_n = '0' THEN nState := vlbit_vector(StateT1P); END IF; WHEN StateT2I => IF Debug THEN putline("DEBUG: 80386 is in State T2I"); END IF; IF READY_n = '1' and (RequestPending = NotPending or HOLD = '1') THEN NULL; ELSIF READY_n = '1' and RequestPending = Pending and HOLD = '0' THEN nState := vlbit_vector(StateT2P); ELSIF READY_n = '0' and HOLD = '1' THEN nState := vlbit_vector(StateTh); ELSIF READY_n = '0' and HOLD = '0' and RequestPending = Pending THEN nState := vlbit_vector(StateT1); ELSIF READY_n = '0' and HOLD = '0' and RequestPending = NotPending THEN nState := vlbit_vector(StateTi); END IF; WHEN OTHERS => putline("MODEL ERROR: Invalid State=",State); END CASE; State <= nState; -- This is where the next State is actually assigned. end PROCESS TstateMachine; -- Internal Control Logic Processes End -- Instruction Pre-Fetch, Decode and Execution Unit Begin InstDecode: PROCESS VARIABLE InstQueue: vlbit_2d(1 to 16,7 downto 0); VARIABLE InstQueueRd_Addr: INTEGER := 1; -- Address used by the decode unit to read the queue. VARIABLE InstQueueWr_Addr: INTEGER := 1; -- Address used by the Pre-fetch unit to fill the queue. VARIABLE InstQueueLimit: INTEGER := 16; -- Maximum length of the Queue. VARIABLE InstAddrPointer: INTEGER := 0; -- Allways points to the current instruction's Address. VARIABLE PhyAddrPointer: INTEGER := 0; -- Allways points to the Systems Physical Address. VARIABLE Extended: BOOLEAN := FALSE; -- True if an extended op-code prefix was detected. VARIABLE More: BOOLEAN := FALSE; -- True if instruction was decoded correctly and -- another read is needed for data. VARIABLE Flush: BOOLEAN := FALSE; -- True if JMP was executed, flush the Queue. VARIABLE First: BOOLEAN := TRUE; -- First time thru. VARIABLE Byte: vlbit_1d(7 downto 0); VARIABLE lWord: vlbit_1d(15 downto 0); VARIABLE uWord: vlbit_1d(15 downto 0); VARIABLE fWord: vlbit_1d(31 downto 0); VARIABLE Dummy: INTEGER; BEGIN IF First THEN PhyAddrPointer := integer(rEIP); InstAddrPointer := PhyAddrPointer; First := FALSE; END IF; RequestPending <= Pending; ReadRequest <= Pending; MemoryFetch <= Pending; CodeFetch <= Pending; IF Debug THEN put("DEBUG: Fetching 1st Word @ Addr=");Dummy := tohex(PhyAddrPointer,4);putline(""); END IF; WAIT UNTIL pfalling(READY_n); RequestPending <= NotPending; WAIT UNTIL pfalling(CLK); InstQueue(InstQueueWr_Addr) := Data(7 downto 0); InstQueueWr_Addr := InstQueueWr_Addr + 1; InstQueue(InstQueueWr_Addr) := Data(15 downto 8); InstQueueWr_Addr := InstQueueWr_Addr + 1; IF StateBS16 = '1' THEN -- A dWord code fetch InstQueue(InstQueueWr_Addr) := Data(23 downto 16); InstQueueWr_Addr := InstQueueWr_Addr + 1; InstQueue(InstQueueWr_Addr) := Data(31 downto 24); InstQueueWr_Addr := InstQueueWr_Addr + 1; PhyAddrPointer := PhyAddrPointer + 4; -- Point to next dWord since BS16- = 1 ELSE PhyAddrPointer := PhyAddrPointer + 2; -- Point to next word since BS16- = 0 IF Debug THEN put("DEBUG: Fetching 2nd Word @ Addr=");Dummy := tohex(PhyAddrPointer,4);putline(""); END IF; rEIP <= vlbit_vector(PhyAddrPointer); WAIT UNTIL prising(CLK); RequestPending <= Pending; WAIT UNTIL pfalling(READY_n); RequestPending <= NotPending; WAIT UNTIL pfalling(CLK); InstQueue(InstQueueWr_Addr) := Data(7 downto 0); InstQueueWr_Addr := InstQueueWr_Addr + 1; InstQueue(InstQueueWr_Addr) := Data(15 downto 8); InstQueueWr_Addr := InstQueueWr_Addr + 1; PhyAddrPointer := PhyAddrPointer + 2; -- Point to next word since BS16- = 0 END IF; Decode: WHILE InstQueueRd_Addr < InstQueueWr_Addr LOOP IF DEBUG THEN putline("DEBUG: InstQueueRd_Addr=",InstQueueRd_Addr); putline("DEBUG: InstQueueWr_Addr=",InstQueueWr_Addr); putline("DEBUG: InstQueueLimit=",InstQueueLimit); put("DEBUG: InstAddrPointer=");Dummy := tohex(InstAddrPointer,4);putline(""); put("DEBUG: PhyAddrPointer=");Dummy := tohex(PhyAddrPointer,4);putline(""); putline("DEBUG: Extended=",Extended); putline("DEBUG: Flush=",Flush); putline("DEBUG: More=",More); put("DEBUG: InstQueue( 1)=");Dummy := tohex(integer(InstQueue(1)),1);putline(""); put("DEBUG: InstQueue( 2)=");Dummy := tohex(integer(InstQueue(2)),1);putline(""); put("DEBUG: InstQueue( 3)=");Dummy := tohex(integer(InstQueue(3)),1);putline(""); put("DEBUG: InstQueue( 4)=");Dummy := tohex(integer(InstQueue(4)),1);putline(""); put("DEBUG: InstQueue( 5)=");Dummy := tohex(integer(InstQueue(5)),1);putline(""); put("DEBUG: InstQueue( 6)=");Dummy := tohex(integer(InstQueue(6)),1);putline(""); put("DEBUG: InstQueue( 7)=");Dummy := tohex(integer(InstQueue(7)),1);putline(""); put("DEBUG: InstQueue( 8)=");Dummy := tohex(integer(InstQueue(8)),1);putline(""); put("DEBUG: InstQueue( 9)=");Dummy := tohex(integer(InstQueue(9)),1);putline(""); put("DEBUG: InstQueue(10)=");Dummy := tohex(integer(InstQueue(10)),1);putline(""); put("DEBUG: InstQueue(11)=");Dummy := tohex(integer(InstQueue(11)),1);putline(""); put("DEBUG: InstQueue(12)=");Dummy := tohex(integer(InstQueue(12)),1);putline(""); put("DEBUG: InstQueue(13)=");Dummy := tohex(integer(InstQueue(13)),1);putline(""); put("DEBUG: InstQueue(14)=");Dummy := tohex(integer(InstQueue(14)),1);putline(""); put("DEBUG: InstQueue(15)=");Dummy := tohex(integer(InstQueue(15)),1);putline(""); put("DEBUG: InstQueue(16)=");Dummy := tohex(integer(InstQueue(16)),1);putline(""); END IF; CASE integer(InstQueue(InstQueueRd_Addr)) is WHEN NOP => InstAddrPointer := InstAddrPointer + 1; InstQueueRd_Addr := InstQueueRd_Addr + 1; Flush := FALSE; More := FALSE; IF Debug OR Inst THEN putline("DEBUG: Executing NOP"); END IF; WHEN OPsop => InstAddrPointer := InstAddrPointer + 1; InstQueueRd_Addr := InstQueueRd_Addr + 1; Extended := TRUE; Flush := FALSE; More := FALSE; IF Debug OR Inst THEN put("DEBUG: Extended Op-Code Read:");Dummy := tohex(OPsop,1);putline(""); END IF; WHEN JMP_rel_short => IF (InstQueueWr_Addr - InstQueueRd_Addr) >= 3 THEN IF Debug OR Inst THEN put("DEBUG: Executing JMP-Rel-Short from:");Dummy := tohex(InstAddrPointer,4); END IF; IF InstQueue(InstQueueRd_Addr+1,7) = '1' THEN -- Negative Offset PhyAddrPointer := InstAddrPointer + 1 - (16#FF# - integer(extendum(InstQueue(InstQueueRd_Addr+1),32))); InstAddrPointer := PhyAddrPointer; IF Debug OR Inst THEN put(" (-)To:");Dummy := tohex(PhyAddrPointer,4);putline(""); END IF; ELSE -- Positive Offset PhyAddrPointer := InstAddrPointer + 2 + integer(extendum(InstQueue(InstQueueRd_Addr+1),32)); InstAddrPointer := PhyAddrPointer; IF Debug OR Inst THEN put(" (+)To:");Dummy := tohex(PhyAddrPointer,4);putline(""); END IF; END IF; Flush := TRUE; More := FALSE; ELSE Flush := FALSE; More := TRUE; END IF; WHEN JMP_rel_near => IF (InstQueueWr_Addr - InstQueueRd_Addr) >= 5 THEN IF Debug OR Inst THEN put("DEBUG: Executing JMP-Rel-Near from:");Dummy := tohex(InstAddrPointer,4); END IF; PhyAddrPointer := InstAddrPointer + 5 + integer(extendum(InstQueue(InstQueueRd_Addr+1),32)); InstAddrPointer := PhyAddrPointer; IF Debug OR Inst THEN put(" To:");Dummy := tohex(PhyAddrPointer,4);putline(""); END IF; Flush := TRUE; More := FALSE; ELSE Flush := FALSE; More := TRUE; END IF; WHEN JMP_intseg_immed =>-- To be Implemented (mad/8-23-1988) IF Debug OR Inst THEN putline("DEBUG: {TBD} Executing JMP-IntSeg-Immed from:",InstAddrPointer); END IF; InstAddrPointer := InstAddrPointer + 1; InstQueueRd_Addr := InstQueueRd_Addr + 1; Flush := FALSE; More := FALSE; WHEN MOV_al_b =>-- To be Implemented (mad/8-23-1988) IF Debug OR Inst THEN putline("DEBUG: {TBD} Executing MOV-al<-byte"); END IF; InstAddrPointer := InstAddrPointer + 1; InstQueueRd_Addr := InstQueueRd_Addr + 1; Flush := FALSE; More := FALSE; WHEN MOV_eax_dw => IF (InstQueueWr_Addr - InstQueueRd_Addr) >= 5 THEN IF Debug OR Inst THEN put("DEBUG: Executing MOV-eax<-dw"); END IF; -- Note Word position is swaped EAX <= InstQueue(InstQueueRd_Addr+4) & InstQueue(InstQueueRd_Addr+3) & InstQueue(InstQueueRd_Addr+2) & InstQueue(InstQueueRd_Addr+1); WAIT FOR 1; IF Debug OR Inst THEN put(" of:");Dummy := tohex(integer(EAX),4);putline(""); END IF; More := FALSE; Flush := FALSE; InstAddrPointer := InstAddrPointer + 5; InstQueueRd_Addr := InstQueueRd_Addr + 5; ELSE Flush := FALSE; More := TRUE; IF Debug THEN putline("DEBUG: Executing MOV-eax<-dw but ..."); putline("DEBUG: all of the immediate data is not in queue."); END IF; END IF; WHEN MOV_ebx_dw => IF (InstQueueWr_Addr - InstQueueRd_Addr) >= 5 THEN IF Debug OR Inst THEN put("DEBUG: Executing MOV-ebx<-dw"); END IF; -- Note Word position is swaped EBX <= InstQueue(InstQueueRd_Addr+4) & InstQueue(InstQueueRd_Addr+3) & InstQueue(InstQueueRd_Addr+2) & InstQueue(InstQueueRd_Addr+1); WAIT FOR 1; IF Debug OR Inst THEN put(" of:");Dummy := tohex(integer(EBX),4);putline(""); END IF; More := FALSE; Flush := FALSE; InstAddrPointer := InstAddrPointer + 5; InstQueueRd_Addr := InstQueueRd_Addr + 5; ELSE Flush := FALSE; More := TRUE; IF Debug THEN putline("DEBUG: Executing MOV-ebx<-dw but ..."); putline("DEBUG: all of the immediate data is not in queue."); END IF; END IF; WHEN MOV_eax_ebx => -- Read at [ebx] to eax register IF (InstQueueWr_Addr - InstQueueRd_Addr) >= 2 THEN IF Debug OR Inst THEN put("DEBUG: Executing MOV-eax,[ebx]"); END IF; IF Debug OR Inst THEN put(" at address:");Dummy := tohex(integer(EBX),4);putline(""); END IF; rEIP <= EBX; RequestPending <= Pending; ReadRequest <= Pending; MemoryFetch <= Pending; CodeFetch <= NotPending; WAIT UNTIL pfalling(READY_n); RequestPending <= NotPending; WAIT UNTIL pfalling(CLK); uWord := Data(15 downto 0); IF StateBS16 = '1' THEN lWord := Data(31 downto 16); ELSE rEIP <= vlbit_vector(integer(rEIP) + 2); WAIT FOR 1; IF Debug THEN put("DEBUG: Reading Second Word at Addr=");Dummy := tohex(integer(rEIP),4);putline(""); END IF; WAIT UNTIL prising(CLK); RequestPending <= Pending; WAIT UNTIL pfalling(READY_n); RequestPending <= NotPending; WAIT UNTIL pfalling(CLK); lWord := Data(15 downto 0); END IF; EAX <= uWord & lWord; WAIT FOR 1; IF Debug OR Inst THEN put("DEBUG: Data=");Dummy := tohex(integer(EAX),4);putline(""); END IF; More := FALSE; Flush := FALSE; InstAddrPointer := InstAddrPointer + 2; InstQueueRd_Addr := InstQueueRd_Addr + 2; ELSE Flush := FALSE; More := TRUE; END IF; WHEN MOV_ebx_eax => -- Write at [ebx] from eax register IF (InstQueueWr_Addr - InstQueueRd_Addr) >= 2 THEN IF Debug OR Inst THEN put("DEBUG: Executing MOV-[ebx],eax"); END IF; IF Debug OR Inst THEN put(" at address:");Dummy := tohex(integer(EBX),4);putline(""); END IF; rEIP <= EBX; lWord := EAX(15 downto 0); uWord := EAX(31 downto 16); IF Debug OR Inst THEN put("DEBUG: Data=");Dummy := tohex(integer(EAX),4);putline(""); END IF; RequestPending <= Pending; ReadRequest <= NotPending; MemoryFetch <= Pending; CodeFetch <= NotPending; IF Debug THEN put("DEBUG: Writing First Word at Addr=");Dummy := tohex(integer(EBX),4);putline(""); END IF; WAIT UNTIL (integer(State) = StateT1 OR integer(State) = StateT1P); WAIT UNTIL prising(CLK); Data <= (uWord & lWord) after 480; WAIT UNTIL pfalling(READY_n); RequestPending <= NotPending; WAIT UNTIL prising(CLK); Data <= X"ZZZZZZZZ" after 480; WAIT FOR 1; IF StateBS16 = '0' THEN IF Debug THEN put("DEBUG: Writing Second Word at Addr=");Dummy := tohex(integer(EBX),4);putline(""); END IF; rEIP <= vlbit_vector(integer(rEIP) + 2); RequestPending <= Pending; ReadRequest <= NotPending; MemoryFetch <= Pending; CodeFetch <= NotPending; WAIT UNTIL (integer(State) = StateT1 OR integer(State) = StateT1P); WAIT UNTIL prising(CLK); Data <= (uWord & lWord) after 480; WAIT UNTIL pfalling(READY_n); RequestPending <= NotPending; WAIT UNTIL prising(CLK); Data <= X"ZZZZZZZZ" after 480; WAIT FOR 1; END IF; More := FALSE; Flush := FALSE; InstAddrPointer := InstAddrPointer + 2; InstQueueRd_Addr := InstQueueRd_Addr + 2; ELSE Flush := FALSE; More := TRUE; END IF; WHEN IN_al => IF (InstQueueWr_Addr - InstQueueRd_Addr) >= 2 THEN IF Debug OR Inst THEN put("DEBUG: Executing IN-al"); END IF; rEIP <= extendum(InstQueue(InstQueueRd_Addr+1),32); WAIT FOR 1; IF Debug OR Inst THEN put(" from:");Dummy := tohex(integer(rEIP),4); END IF; RequestPending <= Pending; ReadRequest <= Pending; MemoryFetch <= NotPending; CodeFetch <= NotPending; WAIT UNTIL pfalling(READY_n); RequestPending <= NotPending; WAIT UNTIL pfalling(CLK); EAX(7 downto 0) <= Data(7 downto 0); WAIT FOR 1; IF Debug OR Inst THEN put(" Data=");Dummy := tohex(integer(EAX(7 downto 0)),1);putline(""); END IF; InstAddrPointer := InstAddrPointer + 2; InstQueueRd_Addr := InstQueueRd_Addr + 2; Flush := FALSE; More := FALSE; ELSE Flush := FALSE; More := TRUE; IF Debug THEN putline("DEBUG: Executing IN-al but ..."); putline("DEBUG: the immediate Address is not in queue."); END IF; END IF; WHEN OUT_al => IF (InstQueueWr_Addr - InstQueueRd_Addr) >= 2 THEN IF Debug OR Inst THEN put("DEBUG: Executing OUT-al"); END IF; rEIP <= extendum(InstQueue(InstQueueRd_Addr+1),32); WAIT FOR 1; IF Debug OR Inst THEN put(" to:");Dummy := tohex(integer(rEIP),4); END IF; RequestPending <= Pending; ReadRequest <= NotPending; MemoryFetch <= NotPending; CodeFetch <= NotPending; IF Debug OR Inst THEN put(" Data=");Dummy := tohex(integer(EAX(7 downto 0)),1);putline(""); END IF; WAIT UNTIL (integer(State) = StateT1 OR integer(State) = StateT1P); WAIT UNTIL prising(CLK); fWord := X"ZZZZZZ" & EAX(7 downto 0); Data <= fWord after 480; WAIT UNTIL pfalling(READY_n); RequestPending <= NotPending; WAIT UNTIL prising(CLK); Data <= X"ZZZZZZZZ" after 480; WAIT FOR 1; InstAddrPointer := InstAddrPointer + 2; InstQueueRd_Addr := InstQueueRd_Addr + 2; Flush := FALSE; More := FALSE; ELSE Flush := FALSE; More := TRUE; IF Debug THEN putline("DEBUG: Executing OUT-al but ..."); putline("DEBUG: the immediate Address is not in queue."); END IF; END IF; WHEN ADD_al_b =>-- To be Implemented (mad/8-23-1988) IF Debug OR Inst THEN putline("DEBUG: {TBD} Executing ADD-al to byte:"); END IF; InstAddrPointer := InstAddrPointer + 1; InstQueueRd_Addr := InstQueueRd_Addr + 1; Flush := FALSE; More := FALSE; WHEN ADD_ax_w =>-- To be Implemented (mad/8-23-1988) IF Debug OR Inst THEN putline("DEBUG: {TBD} Executing ADD-ax to word:"); END IF; InstAddrPointer := InstAddrPointer + 1; InstQueueRd_Addr := InstQueueRd_Addr + 1; Flush := FALSE; More := FALSE; WHEN ROL_al_1 =>-- To be Implemented (mad/8-23-1988) IF Debug OR Inst THEN putline("DEBUG: {TBD} Executing ROL-al left one bit"); END IF; InstAddrPointer := InstAddrPointer + 2; InstQueueRd_Addr := InstQueueRd_Addr + 2; Flush := FALSE; More := FALSE; WHEN ROL_al_n =>-- To be Implemented (mad/8-23-1988) IF Debug OR Inst THEN putline("DEBUG: {TBD} Executing ROL-al by:"); END IF; InstAddrPointer := InstAddrPointer + 2; InstQueueRd_Addr := InstQueueRd_Addr + 2; Flush := FALSE; More := FALSE; WHEN INC_eax => EAX <= vlbit_vector(integer(EAX) + 1); WAIT FOR 1; IF Debug OR Inst THEN put("DEBUG: Executing INC-eax by 1 to:");Dummy := tohex(integer(EAX),4);putline(""); END IF; InstAddrPointer := InstAddrPointer + 1; InstQueueRd_Addr := InstQueueRd_Addr + 1; Flush := FALSE; More := FALSE; WHEN INC_ebx => EBX <= vlbit_vector(integer(EBX) + 1); WAIT FOR 1; IF Debug OR Inst THEN put("DEBUG: Executing INC-ebx by 1 to:");Dummy := tohex(integer(EBX),4);putline(""); END IF; InstAddrPointer := InstAddrPointer + 1; InstQueueRd_Addr := InstQueueRd_Addr + 1; Flush := FALSE; More := FALSE; WHEN OTHERS => put("ERROR: Invalid Instruction=");Dummy := tohex(integer(InstQueue(InstQueueRd_Addr)),1);putline(""); InstAddrPointer := InstAddrPointer + 1; InstQueueRd_Addr := InstQueueRd_Addr + 1; Flush := FALSE; More := FALSE; END CASE; EXIT WHEN ((InstQueueLimit - InstQueueRd_Addr) < 4) OR Flush OR More; END LOOP Decode; IF Flush THEN InstQueueRd_Addr := 1; InstQueueWr_Addr := 1; fWord := vlbit_vector(InstAddrPointer); IF fWord(0) = '1' THEN InstQueueRd_Addr := InstQueueRd_Addr + integer(extendum(fWord(1 downto 0),32)); END IF; IF Debug THEN putline("DEBUG: Flushing Instruction Queue"); END IF; END IF; IF (InstQueueLimit - InstQueueRd_Addr) < 3 THEN -- The queue is about to be bounded. -- This section implements the circular queue. IF Debug THEN putline("DEBUG: Instruction Queue Length Execeeded"); putline("DEBUG: Implementing Circular Queue"); END IF; InstQueueWr_Addr := 1; Circular: WHILE InstQueueRd_Addr <= InstQueueLimit LOOP InstQueue(InstQueueWr_Addr) := InstQueue(InstQueueRd_Addr); InstQueueRd_Addr := InstQueueRd_Addr + 1; InstQueueWr_Addr := InstQueueWr_Addr + 1; END LOOP Circular; InstQueueRd_Addr := 1; END IF; IF Debug THEN putline("DEBUG: Request Pending, filling Queue at:",InstQueueWr_Addr); END IF; rEIP <= vlbit_vector(PhyAddrPointer); WAIT UNTIL prising(CLK); end PROCESS InstDecode; -- Instruction Pre-Fetch, Decode and Execution Unit Begin -- ByteEnables Begin GenByteEnables: PROCESS (rEIP) BEGIN CASE integer(DataWidth) is WHEN WidthByte => CASE integer(rEIP(1 downto 0)) is -- A[1:0] WHEN 0 => ByteEnable <= B"1110"; WHEN 1 => ByteEnable <= B"1101"; WHEN 2 => ByteEnable <= B"1011"; WHEN 3 => ByteEnable <= B"0111"; WHEN OTHERS => NULL; END CASE; WHEN WidthWord => CASE integer(rEIP(1 downto 0)) is -- A[1:0] WHEN 0 => ByteEnable <= B"1100"; NonAligned <= NotPending; WHEN 1 => ByteEnable <= B"1001"; NonAligned <= NotPending; WHEN 2 => ByteEnable <= B"0011"; NonAligned <= NotPending; WHEN 3 => IF Debug THEN putline("DEBUG: Non-Aligned Word"); END IF; ByteEnable <= B"0111"; NonAligned <= Pending; WHEN OTHERS => NULL; END CASE; WHEN WidthDword => CASE integer(rEIP(1 downto 0)) is -- A[1:0] WHEN 0 => ByteEnable <= B"0000"; NonAligned <= NotPending; WHEN 1 => IF Debug THEN putline("DEBUG: Non-Aligned Dword"); END IF; ByteEnable <= B"0001"; NonAligned <= Pending; WHEN 2 => IF Debug THEN putline("DEBUG: Non-Aligned Dword"); END IF; NonAligned <= Pending; ByteEnable <= B"0011"; WHEN 3 => IF Debug THEN putline("DEBUG: Non-Aligned Dword"); END IF; NonAligned <= Pending; ByteEnable <= B"0111"; WHEN OTHERS => NULL; END CASE; WHEN OTHERS => putline("MODEL ERROR: Data Path Width Fault: DataWidth"); putline("MODEL ERROR: Width Selected was:",integer(DataWidth)); END CASE; end PROCESS GenByteEnables; -- ByteEnables End -- Bus Interface Unit Begin GenBusIntf: PROCESS (State) BEGIN CASE integer(State) is WHEN StateT1 | StateT2P => Address <= rEIP(31 downto 2) after 40ns; IF Debug THEN-- putline("DEBUG: Next Address=",rEIP); END IF; BE_n <= ByteEnable after 30ns; M_IO_n <= MemoryFetch; IF ReadRequest = Pending THEN W_R_n <= '0' after 30ns; ELSE W_R_n <= '1' after 30ns; END IF; IF CodeFetch = Pending THEN D_C_n <= '0' after 30ns; ELSE D_C_n <= '1' after 30ns; END IF; WHEN OTHERS => NULL; END CASE; CASE integer(State) is WHEN StateT1 => ADS_n <= '0' after 25ns; WHEN StateT2 => ADS_n <= '1' after 25ns; WHEN StateT1P => ADS_n <= '1' after 25ns; WHEN StateT2P => ADS_n <= '0' after 25ns; WHEN OTHERS => NULL; END CASE; end PROCESS GenBusIntf; BS16: PROCESS BEGIN WAIT UNTIL integer(State) = StateT2 OR integer(State) = StateT1P; WHILE integer(State) = StateT2 OR integer(State) = StateT1P LOOP WAIT UNTIL prising(CLK); StateBS16 <= BS16_n; IF BS16_n = '0' THEN DataWidth <= vlbit_vector(Widthword); -- WidthByte, WidthWord, WidthDword ELSE DataWidth <= vlbit_vector(WidthDword); END IF; END LOOP; end PROCESS BS16; NA: PROCESS BEGIN WAIT UNTIL integer(State) = StateT2 OR integer(State) = StateT1P; WAIT UNTIL prising(CLK); StateNA <= NA_n; end PROCESS NA; -- Bus Interface Unit End-- End Behavioral Blocksend behavior; |
|