-- ######################################################################## -- # Main Memory -- ######################################################################## -- Main memory is dual-ported 16x1024. The initial values included here -- are the actual program and data. ifelse(MEMORY_SIZE, 256, [ xpubramA0: RAMB4_S16_S16 generic map (include(xpu0.inc)) port map (ADDRA => xpuADDRA(7 downto 0), DIA => xpuDINA, DOA => xpuDOUTA, WEA => '0', CLKA => xpuCLOCK, RSTA => '0', ENA => '1', ADDRB => xpuADDRB(7 downto 0), DIB => xpuDINB, DOB => xpuDOUTB, WEB => xpuWEB, CLKB => xpuCLOCK, RSTB => '0', ENB => '1'); ]) ifelse(MEMORY_SIZE, 1024, [ ifelse(WORD_SIZE, 16, [ define(ram44, [ xpubramA$1: RAMB4_S4_S4 generic map ($2) port map (ADDRA => xpuADDRA(9 downto 0), DIA => xpuDINA( eval(4 * $1 + 3) downto eval(4 * $1 + 0)), DOA => xpuDOUTA(eval(4 * $1 + 3) downto eval(4 * $1 + 0)), WEA => '0', CLKA => xpuCLOCK, RSTA => '0', ENA => '1', ADDRB => xpuADDRB(9 downto 0), DIB => xpuDINB( eval(4 * $1 + 3) downto eval(4 * $1 + 0)), DOB => xpuDOUTB(eval(4 * $1 + 3) downto eval(4 * $1 + 0)), WEB => xpuWEB, CLKB => xpuCLOCK, RSTB => '0', ENB => '1'); ]) ]) ifelse(WORD_SIZE, 32, [ define(ram44, [ xpubramA$1: RAMB4_S4_S8 generic map ($2) port map (ADDRA => xpuADDRA(9 downto 0), DIA => xpuDINA( eval(4 * $1 + 3) downto eval(4 * $1 + 0)), DOA => xpuDOUTA(eval(4 * $1 + 3) downto eval(4 * $1 + 0)), WEA => '0', CLKA => xpuCLOCK, RSTA => '0', ENA => '1', ADDRB => xpuADDRB(9 downto 1), DIB(7 downto 4) => xpuDINB( eval(4 * $1 + 19) downto eval(4 * $1 + 16)), DIB(3 downto 0) => xpuDINB( eval(4 * $1 + 3) downto eval(4 * $1 + 0)), DOB(7 downto 4) => xpuDOUTB( eval(4 * $1 + 19) downto eval(4 * $1 + 16)), DOB(3 downto 0) => xpuDOUTB( eval(4 * $1 + 3) downto eval(4 * $1 + 0)), WEB => xpuWEB, CLKB => xpuCLOCK, RSTB => '0', ENB => '1'); ]) ]) ram44(0, [include(xpu0.inc)]) ram44(1, [include(xpu1.inc)]) ram44(2, [include(xpu2.inc)]) ram44(3, [include(xpu3.inc)]) ]) xpuADDRA <= xpunPC; xpuADDRB <= xpunST0(9 downto 0); xpuWEB <= xpuDECALU AND xpuDOUTA(5); xpuDINB <= xpuST1; -- ######################################################################## -- # Decode -- ######################################################################## xpuInsn <= xpuDOUTA; xpuDECALUg <= NOT xpuDOUTA(15) AND NOT xpuDOUTA(14); -- 00 decalug: buf port map(I => xpuDECALUg, O => xpuDECALU); xpuDECIMMg <= NOT xpuDOUTA(15) AND xpuDOUTA(14); -- 01 decimmg: buf port map(I => xpuDECIMMg, O => xpuDECIMM); xpuDECCALLg <= xpuDOUTA(15) AND xpuDOUTA(14); -- 11 callg: buf port map(I => xpuDECCALLg, O => xpuDECCALL); xpuDECRETURNg <= NOT xpuDOUTA(15) AND NOT xpuDOUTA(14) AND xpuDOUTA(3); returng: buf port map(I => xpuDECRETURNg, O => xpuDECRETURN); xpuDECWRITE <= xpuDOUTA(2); process (xpuDOUTA) begin case xpuDOUTA(15 downto 14) is when "00" => xpuDECALUOP <= xpuDOUTA(9 downto 7); xpuDECLOGOP <= xpuDOUTA(13 downto 10); when "01" => xpuDECALUOP <= "101"; xpuDECLOGOP <= "XXXX"; when others => xpuDECALUOP <= "001"; if (xpuDOUTA(10) = '0') then xpuDECLOGOP <= "0011"; -- ST0 else xpuDECLOGOP <= "0101"; -- ST1 end if; end case; end process; -- define(orbits, [ ifelse($1, 0, [ xpuST0(0) ], [ xpuST0($1) OR orbits(eval($1 - 1))])]) process (xpuINSN, xpuST0) begin xpuPRED0 <= orbits(HIBIT); if (xpuST0(HIBIT) = '0') then if (xpuPRED0 = '0') then xpuPRED <= xpuINSN(12); else xpuPRED <= xpuINSN(13); end if; else xpuPRED <= xpuINSN(11); end if; end process; -- ######################################################################## -- # Call-Return Stack -- ######################################################################## -- The Call-Return Stack (CSR) lives in a special 16x10 RAM. -- vanilla ncsp <= csp; [ncsp] <= [ncsp] + 1 -- goto ncsp <= csp; [ncsp] <= N -- call ncsp <= csp+1; [ncsp] <= N -- return ncsp <= csp-1; [ncsp] <= [ncsp] + 1 define(xcsr, [ xpunPCR($1) <= xpunPC($1) AND NOT xpuRESET; xpucs$1: RAM16X1D port map ( WE => '1', D => xpunPCR($1), WCLK => xpuCLOCK, A0 => xpunCSP(0), -- write address A1 => xpunCSP(1), A2 => xpunCSP(2), A3 => xpunCSP(3), DPRA0 => xpunCSP(0), DPRA1 => xpunCSP(1), DPRA2 => xpunCSP(2), DPRA3 => xpunCSP(3), DPO => xpuPC($1) );]) xcsr(0) xcsr(1) xcsr(2) xcsr(3) xcsr(4) xcsr(5) xcsr(6) xcsr(7) xcsr(8) xcsr(9) process begin wait until xpuCLOCK'event and xpuCLOCK = '1'; xpuCSP <= xpunCSP; end process; ifelse(A,A,[ process (xpuCSP, xpuDECRETURN, xpuDECCALL) begin xpuCSPd(1) <= xpuDECRETURN; xpuCSPd(0) <= xpuCSPd(1) OR (xpuDECCALL); end process; xpunCSP <= xpuCSP + (xpuCSPd(1) & xpuCSPd(1) & xpuCSPd(1) & xpuCSPd(0)); ],[ -- call -> increment -- return -> decrement -- otherwise same xpuDECRETURN <= xpuDECALU AND xpuDOUTA(3); process (xpuCSP, xpuDECRETURN, xpuDECCALL) begin if (xpuDECCALL = '1') then xpunCSP <= xpuCSP + 1; elsif (xpuDECRETURN = '1') then xpunCSP <= xpuCSP - 1; else xpunCSP <= xpuCSP; end if; end process; ]) xpuiPC <= xpuPC + 1; process (xpuRESET, xpuPC, xpuDOUTA) begin if ((xpuDOUTA(15) = '1') and (xpuPRED = '1')) then xpunPC <= xpuDOUTA(9 downto 0); else ifelse(PC_MODE, INC, [ xpunPC <= xpuiPC; ]) ifelse(PC_MODE, LFSR, [ ifelse(MEMORY_SIZE, 256, [ xpunPC(7 downto 0) <= xpuPC(6 downto 0) & (NOT (xpuPC(7) XOR xpuPC(5) XOR xpuPC(4) XOR xpuPC(3))); ]) ifelse(MEMORY_SIZE, 1024, [ xpunPC(9 downto 0) <= xpuPC(8 downto 0) & (NOT (xpuPC(9) XOR xpuPC(6))); ]) ]) end if; end process; -- ######################################################################## -- # Data Stack -- ######################################################################## xpuDWE <= xpuDECIMM OR (xpuDECALU AND xpuDECWRITE); define(xdsr, [ xpucd$1: RAM16X1D port map ( WE => xpuDWE, D => xpuST0($1), WCLK => xpuCLOCK, A0 => xpunSP(0), -- write address A1 => xpunSP(1), A2 => xpunSP(2), A3 => xpunSP(3), DPRA0 => xpuSP(0), -- read address DPRA1 => xpuSP(1), DPRA2 => xpuSP(2), DPRA3 => xpuSP(3), DPO => xpuST1($1) );]) define(xdsrs, [ ifelse($1, -1, [ ], [ xdsr($1) xdsrs(eval($1 - 1))])]) xdsrs(HIBIT) process begin wait until xpuCLOCK'event and xpuCLOCK = '1'; xpuST0 <= xpunST0; xpuSP <= xpunSP; end process; process (xpuDECALU, xpuSP) begin if (xpuDECALU = '1') then xpuSPd <= xpuInsn(1 downto 0); elsif (xpuINSN(15) = '1') then xpuSPd <= xpuINSN(10) & xpuINSN(10); else xpuSPd <= "0" & xpuDECIMM; end if; end process; xpunSP <= xpuSP + (xpuSPd(1) & xpuSPd(1) & xpuSPd(1) & xpuSPd(0)); -- 16-bit adder with 16-bit out (cpuADDERS) and carry out (cpuADDERC) ifelse(WORD_SIZE, 16, [ process (xpuST0, xpuST1) begin xpuSUM <= ('0' & xpuST0) + ('0' & xpuST1); xpuADDERS <= xpuSUM(15 downto 0); xpuADDERC <= xpuSUM(16); end process; ]) ifelse(WORD_SIZE, 32, [ process (xpuST0, xpuST1) begin xpuSUM0 <= ('0' & xpuST0(15 downto 0)) + ('0' & xpuST1(15 downto 0)); xpuSUM1 <= ('0' & xpuST0(31 downto 16)) + ('0' & xpuST1(31 downto 16)) + xpuSUM0(16); xpuADDERS <= xpuSUM1(15 downto 0) & xpuSUM0(15 downto 0); xpuADDERC <= xpuSUM1(16); end process; ]) -- logical operation is handled by a 4-way mux, repeated per-bit define(xpulogbit, [[ process (xpuDECLOGOP, xpuST0, xpuST1) begin if (xpuST0($1) = '0') then if (xpuST1($1) = '0') then xpuLogic($1) <= xpuDECLOGOP(3); -- A=0, B=0, bit#3 else xpuLogic($1) <= xpuDECLOGOP(2); -- A=0, B=1, bit#2 end if; else if (xpuST1($1) = '0') then xpuLogic($1) <= xpuDECLOGOP(1); -- A=1, B=0, bit#1 else xpuLogic($1) <= xpuDECLOGOP(0); -- A=1, B=1, bit#0 end if; end if; end process; ]]) define(xpulogbits, [ ifelse($1, -1, [ ], [ xpulogbit($1) xpulogbits(eval($1 - 1))])]) xpulogbits(HIBIT) process (xpuDOUTA, xpuDECIMM, xpuST0, xpuADDERS, xpuADDERC, xpuLogic) begin -- if (xpuDOUTA(15) = '0') then case (xpuDECALUOP) is when "000" => xpunST0 <= XPUADDERS; when "001" => xpunST0 <= xpuLogic; when "010" => xpunST0 <= '0' & xpuST0(HIBIT downto 1); when "011" => xpunST0 <= ifelse(WORD_SIZE, 16, [ xpuADDERC & "XXXXXXXXXXXXXXX"; ],[ xpuADDERC & "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; ]) when "100" => xpunST0 <= xpuDOUTB; ifelse(WORD_SIZE, 16, [ when "101" => xpunST0 <= xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13 downto 0); ], [ when "101" => xpunST0 <= xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13) & xpuDOUTA(13 downto 0); ]) when others => xpunST0 <= xpuIODin; end case; -- else -- if (xpuINSN(10) = '0') then -- xpunST0 <= xpuST0; -- else -- xpunST0 <= xpuST1; -- end if; -- end if; end process; xpuIOAddr <= xpuST0; xpuIODout <= xpuST1; xpuIOWrite <= xpuDECALU AND xpuINSN(6); xpuIORead <= xpuDECALUOP(2) and xpuDECALUOP(1); -- remove xpuSP from status -- dont care for xpuIOread0, xpuIOread1 -- remove xpu->cpu monitors -- xpuDECALUOP: 17.2 -- try xpuDECLOGOP 17.3