library dp_32; use dp_32.DP32_TYPES.all ; entity DP32 is generic(Tpd : TIME := 1 ns ) ; port(D_BUS : inout BUS_BIT_32 bus ; A_BUS : out BIT_32 ; READ : out BIT ; WRITE : out BIT ; FETCH : out BIT ; READY : in BIT ; Ph1 : in BIT ; Ph2 : in BIT ; RESET : in BIT ) ; end DP32 ; architecture BEHAVIOUR of DP32 is subtype REG_ADDR is NATURAL range 0 to 255 ; type REG_ARRAY is array(REG_ADDR) of BIT_32 ; begin CORE: process variable REG : REG_ARRAY ; variable PC : BIT_32 ; variable CURRENT_INSTR : BIT_32 ; variable OP : BIT_8 ; variable R3,R2,R1 : REG_ADDR ; variable I8 : INTEGER ; variable cc_V,cc_N,cc_Z : BIT ; variable temp_V,temp_N,temp_Z : BIT ; variable DISPLACEMENT : BIT_32 ; variable EFFECTIVE_ADDR : BIT_32 ; alias cm_I : BIT is CURRENT_INSTR(19) ; alias cm_V : BIT is CURRENT_INSTR(18) ; alias cm_N : BIT is CURRENT_INSTR(17) ; alias cm_Z : BIT is CURRENT_INSTR(16) ; procedure MEMORY_READ(ADDR : in BIT_32 ; FETCH_CYCLE : in BOOLEAN ; RESULT : out BIT_32 ) is begin --start bus cycle with address output A_BUS <= ADDR after Tpd ; FETCH <= BOOL_TO_BIT(FETCH_CYCLE) after Tpd ; wait until Ph1 = '1' ; if RESET = '1' then return ; end if ; -- T1 phase READ <= '1' after Tpd ; wait until Ph1 = '1' ; if RESET = '1' then return ; end if ; --T2 phase loop wait until Ph2 = '0' ; if RESET = '1' then return ; end if ; if READY = '1' then RESULT := D_BUS ; exit ; end if ; end loop ; wait until Ph1= '1' ; if RESET = '1' then return ; end if ; --TI phase at end of cycle READ <= '0' after Tpd ; end MEMORY_READ ; procedure MEMORY_WRITE(ADDR : in BIT_32 ; DATA : in BIT_32 ) is begin --start bus cycle with address output A_BUS <= ADDR after Tpd ; FETCH <= '0' after Tpd ; wait until Ph1 = '1' ; if RESET = '1' then return ; end if ; --T1 phase WRITE <= '1' after Tpd ; wait until Ph2 = '1' ; D_BUS <= DATA after Tpd ; wait until Ph1 = '1' ; if RESET = '1' then return ; end if ; --T2 phase loop wait until Ph2 = '0' ; if RESET = '1' then return ; end if ; exit when READY = '1' ; end loop ; wait until Ph1 = '1' ; if RESET = '1' then return ; end if ; --Ti phase at and of cycle WRITE <= '0' after Tpd ; D_BUS <= null after Tpd ; end MEMORY_WRITE ; procedure ADD(RESULT : inout BIT_32 ; OP1 : in INTEGER ; OP2 : in INTEGER ; V,N,Z : out BIT ) is begin --positive overflow if OP2 > 0 and OP1 > INTEGER'low-OP2 then INT_TO_BITS(((INTEGER'low+OP1)+OP2)-INTEGER'high-1,RESULT) ; V := '1' ; --negative overflow elsif OP2 < 0 and OP1 < INTEGER'low-OP2 then INT_TO_BITS(((INTEGER'high+OP1)+OP2)-INTEGER'low+1,RESULT) ; V := '0' ; else INT_TO_BITS(OP1+OP2,RESULT) ; V := '0' ; end if ; N := RESULT(31) ; Z := BOOL_TO_BIT(RESULT = X"0000_0000") ; end ADD ; procedure SUBTRACT(RESULT : inout BIT_32 ; OP1 : in INTEGER ; OP2 : in INTEGER ; V,N,Z : out BIT ) is begin --positive overflow if OP2 < 0 and OP1 > INTEGER'high+OP2 then INT_TO_BITS(((INTEGER'low+OP1)-OP2)-INTEGER'high-1,RESULT) ; V := '1' ; --negative overflow elsif OP2 > 0 and OP1 < INTEGER'low+OP2 then INT_TO_BITS(((INTEGER'high+OP1)-OP2)-INTEGER'low+1,RESULT) ; V := '1' ; else INT_TO_BITS(OP1+OP2,RESULT) ; V := '0' ; end if ; N := RESULT(31) ; Z := BOOL_TO_BIT(RESULT = X"0000_0000") ; end SUBTRACT ; procedure MULTIPLY(RESULT : inout BIT_32 ; OP1 : in INTEGER ; OP2 : in INTEGER ; V,N,Z : out BIT ) is begin --positive overflow if ((OP1>0 and OP2>0) or (OP1<0 and OP2<0)) and (abs OP1 > INTEGER'high / abs OP2) then INT_TO_BITS(INTEGER'high,RESULT) ; V := '1' ; --negative overflow elsif ((OP1>0 and OP2<0) or (OP1<0 and OP2>0)) and ((-abs OP1) < INTEGER'low / abs OP2) then INT_TO_BITS(INTEGER'low,RESULT) ; V := '1' ; else INT_TO_BITS(OP1*OP2,RESULT) ; end if ; N := RESULT(31) ; Z := BOOL_TO_BIT(RESULT = X"0000_0000") ; end MULTIPLY ; procedure DIVIDE(RESULT : inout BIT_32 ; OP1 : in INTEGER ; OP2 : in INTEGER ; V,N,Z : out BIT ) is begin if OP2= 0 then --positive overflow if OP1 >= 0 then INT_TO_BITS(INTEGER'high,RESULT) ; --negative overflow else INT_TO_BITS(INTEGER'low,RESULT) ; end if ; V := '1' ; else INT_TO_BITS(OP1/OP2,RESULT) ; V := '0' ; end if ; N := RESULT(31) ; Z := BOOL_TO_BIT(RESULT = X"0000_0000") ; end DIVIDE ; -- *************** DEBUT DU CODE DU PROCESS begin --check for reset active if RESET = '1' then READ <= '0' after Tpd ; WRITE <= '0' after Tpd ; FETCH <= '0' after Tpd ; D_BUS <= null after Tpd ; PC := X"0000_0000" ; wait until RESET = '0' ; end if ; --fetch next instruction D_BUS <= null ; -- ???? ajout‚ par bibi wait for 1 ns; -- idem MEMORY_READ(PC,TRUE,CURRENT_INSTR) ; if RESET /= '1' then ADD(PC,BITS_TO_INT(PC),1,temp_V,temp_N,temp_Z) ; --decode & execute OP := CURRENT_INSTR(31 downto 24) ; R3 := BITS_TO_NAT(CURRENT_INSTR(23 downto 16)) ; R2 := BITS_TO_NAT(CURRENT_INSTR(15 downto 8)) ; R1 := BITS_TO_NAT(CURRENT_INSTR( 7 downto 0)) ; I8 := BITS_TO_INT(CURRENT_INSTR( 7 downto 0)) ; case OP is when OP_ADD => ADD(REG(R3),BITS_TO_INT(REG(R1)),BITS_TO_INT(REG(R2)),cc_V,cc_N, cc_Z) ; when OP_ADDq => ADD(REG(R3),BITS_TO_INT(REG(R1)),I8,cc_V,cc_N,cc_Z) ; when OP_SUB => SUBTRACT(REG(R3),BITS_TO_INT(REG(R1)),BITS_TO_INT(REG(R2)),cc_V, cc_N,cc_Z) ; when OP_SUBq => SUBTRACT(REG(R3),BITS_TO_INT(REG(R1)),I8,cc_V,cc_N,cc_Z) ; when OP_MUL => MULTIPLY(REG(R3),BITS_TO_INT(REG(R1)),BITS_TO_INT(REG(R2)),cc_V, cc_N,cc_Z) ; when OP_MULq => MULTIPLY(REG(R3),BITS_TO_INT(REG(R1)),I8,cc_V,cc_N,cc_Z) ; when OP_DIV => DIVIDE(REG(R3),BITS_TO_INT(REG(R1)),BITS_TO_INT(REG(R2)),cc_V, cc_N,cc_Z) ; when OP_DIVq => DIVIDE(REG(R3),BITS_TO_INT(REG(R1)),I8,cc_V,cc_N,cc_Z) ; when OP_Land => REG(R3) := REG(R1) and REG(R2) ; cc_Z := BOOL_TO_BIT(REG(R3) = X"0000_0000") ; when OP_Lor => REG(R3) := REG(R1) or REG(R2) ; cc_Z := BOOL_TO_BIT(REG(R3) = X"0000_0000") ; when OP_Lxor => REG(R3) := REG(R1) xor REG(R2) ; cc_Z := BOOL_TO_BIT(REG(R3) = X"0000_0000") ; when OP_Lmask => REG(R3) := REG(R1) and not REG(R2) ; cc_Z := BOOL_TO_BIT(REG(R3) = X"0000_0000") ; when OP_Ld => MEMORY_READ(PC,TRUE,DISPLACEMENT) ; if RESET /= '1' then ADD(PC,BITS_TO_INT(PC),1,temp_V,temp_N,temp_Z) ; ADD(EFFECTIVE_ADDR,BITS_TO_INT(REG(R1)), BITS_TO_INT(DISPLACEMENT),temp_V,temp_N,temp_Z) ; MEMORY_READ(EFFECTIVE_ADDR,FALSE,REG(R3)) ; end if ; when OP_Ldq => ADD(EFFECTIVE_ADDR,BITS_TO_INT(REG(R1)),I8,temp_V,temp_N,temp_Z); MEMORY_READ(EFFECTIVE_ADDR,FALSE,REG(R3)) ; when OP_St => MEMORY_READ(EFFECTIVE_ADDR,TRUE,DISPLACEMENT) ; if RESET /= '1' then ADD(PC,BITS_TO_INT(PC),1,temp_V,temp_N,temp_Z) ; ADD(EFFECTIVE_ADDR,BITS_TO_INT(REG(R1)), BITS_TO_INT(DISPLACEMENT),temp_V,temp_N,temp_Z) ; MEMORY_WRITE(EFFECTIVE_ADDR,REG(R3)) ; end if ; when OP_Stq => ADD(EFFECTIVE_ADDR,BITS_TO_INT(REG(R1)),I8,temp_V,temp_N,temp_Z); MEMORY_WRITE(EFFECTIVE_ADDR,REG(R3)) ; when OP_Br => MEMORY_READ(PC,TRUE,DISPLACEMENT) ; if RESET /= '1' then ADD(PC,BITS_TO_INT(PC),1,temp_V,temp_N,temp_Z) ; ADD(EFFECTIVE_ADDR,BITS_TO_INT(PC),BITS_TO_INT(DISPLACEMENT), temp_V,temp_N,temp_Z) ; if ((cm_V and cc_V) or (cm_N and cc_N) or (cm_Z and cc_Z)) = cm_I then PC := EFFECTIVE_ADDR ; end if ; end if ; when OP_Bi => MEMORY_READ(PC,TRUE,DISPLACEMENT) ; if RESET /= '1' then ADD(PC,BITS_TO_INT(PC),1,temp_V,temp_N,temp_Z) ; ADD(EFFECTIVE_ADDR,BITS_TO_INT(REG(R1)), BITS_TO_INT(DISPLACEMENT),temp_V,temp_N,temp_Z) ; if ((cm_V and cc_V) or (cm_N and cc_N) or (cm_Z and cc_Z)) = cm_I then PC := EFFECTIVE_ADDR ; end if ; end if ; when OP_Brq => ADD(EFFECTIVE_ADDR,BITS_TO_INT(PC),I8,temp_V,temp_N,temp_Z) ; if ((cm_V and cc_V) or (cm_N and cc_N) or (cm_Z and cc_Z)) = cm_I then PC := EFFECTIVE_ADDR ; end if ; when OP_Biq => ADD(EFFECTIVE_ADDR,BITS_TO_INT(REG(R1)),I8,temp_V,temp_N,temp_Z); if ((cm_V and cc_V) or (cm_N and cc_N) or (cm_Z and cc_Z)) = cm_I then PC := EFFECTIVE_ADDR ; end if ; when others => assert FALSE report "illegal instruction" severity WARNING ; end case ; end if ; end process ; end BEHAVIOUR ;