-- Original file is copyright by Grant Searle 2014 -- Grant Searle's "multicomp" page at http://searle.hostei.com/grant/Multicomp/index.html -- -- Changes to this code by Doug Gilliland 2019 -- 16K (internal) RAM version -- library ieee; use ieee.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; entity Microcomputer is port( n_reset : in std_logic; clk : in std_logic; -- swap around in and out to make loopback work -- RXD is RXD on serial chip and TXD is TXD on serial chip -- Swap Pin Assignment, so FPGA rxd connects to PL2303 tx. -- -- swap around in and out to make loopback work -- RXD is RXD on serial chip and TXD is TXD on serial chip -- RXD : out std_logic; -- TXD : in std_logic; -- PL2303 RXD - RXD - rxd - pin 86 - out std_logic; -- PL2303 TXD - TXD - txd - pin 87 - in std_logic; -- circuit diagram has rxd pin 86 -- circuit diagram has txd pin 87 -- As PL2303 is not supported on Win 10 use one of the VGA pins and another serial ro USB. txd : in std_logic; rxd : out std_logic; rts : out std_logic; -- 16 bit video videoR0 : out std_logic; videoR1 : out std_logic; videoR2 : out std_logic; videoR3 : out std_logic; videoR4 : out std_logic; videoG0 : out std_logic; videoG1 : out std_logic; videoG2 : out std_logic; videoG3 : out std_logic; videoG4 : out std_logic; videoG5 : out std_logic; videoB0 : out std_logic; videoB1 : out std_logic; videoB2 : out std_logic; videoB3 : out std_logic; videoB4 : out std_logic; hSync : out std_logic; vSync : out std_logic; switch0 : in std_logic; switch1 : in std_logic; switch2 : in std_logic; -- LED uses same pins as 7seg LED1 : out std_logic; LED2 : out std_logic; LED3 : out std_logic; LED4 : out std_logic; -- LED uses same pins as 7seg LEDSEGA : out std_logic; LEDSEGB : out std_logic; LEDSEGC : out std_logic; LEDSEGD : out std_logic; LEDSEGE : out std_logic; LEDSEGF : out std_logic; LEDSEGG : out std_logic; LEDSEGH : out std_logic; -- 7 seg digit select. DSEN1 : out std_logic; DSEN2 : out std_logic; DSEN3 : out std_logic; DSEN4 : out std_logic; ps2Clk : inout std_logic; ps2Data : inout std_logic ); end Microcomputer; architecture struct of Microcomputer is signal n_WR : std_logic; signal n_RD : std_logic; signal cpuAddress : std_logic_vector(15 downto 0); signal cpuDataOut : std_logic_vector(7 downto 0); signal cpuDataIn : std_logic_vector(7 downto 0); signal basRomData : std_logic_vector(7 downto 0); signal interface1DataOut : std_logic_vector(7 downto 0); signal aciaData : std_logic_vector(7 downto 0); signal internalRam1DataOut : std_logic_vector(7 downto 0); signal n_memWR : std_logic :='1'; signal n_memRD : std_logic :='1'; signal n_basRomCS : std_logic :='1'; signal n_videoInterfaceCS : std_logic :='1'; signal n_aciaCS : std_logic :='1'; signal n_internalRamCS : std_logic :='1'; signal n_IOCS : std_logic :='1'; signal n_IOCS_Write : std_logic :='1'; signal n_IOCS_Read : std_logic :='1'; signal n_IOCS_addr : std_logic :='1'; signal serialClkCount : std_logic_vector(15 downto 0); signal serialClkCount_d : std_logic_vector(15 downto 0); signal serialClkEn : std_logic; signal serialClock : std_logic; signal cpuClkCount : std_logic_vector(5 downto 0); signal cpuClock : std_logic; signal sdClock : std_logic; signal sdClkCount : std_logic_vector(5 downto 0); signal latchedBits : std_logic_vector(7 downto 0); signal switchesRead : std_logic_vector(7 downto 0); signal txdBuff : std_logic; signal funKeys : std_logic_vector(12 downto 0); signal fKey1 : std_logic; signal fKey2 : std_logic; begin -- ____________________________________________________________________________________ -- Card has 16 bits of RGB digital data -- Drive the least significant bits with 0's since Multi-Comp only has 6 bits of RGB digital data -- use these for debug <= '0'; videoR0 <= '0'; videoR1 <= '0'; videoR2 <= '0'; videoG0 <= '0'; videoG1 <= '0'; videoG2 <= '0'; videoG3 <= '0'; videoB0 <= '0'; videoB1 <= '0'; videoB2 <= '0'; -- set_location_assignment PIN_84 -to n_reset -- set_location_assignment PIN_88 -to switch0 -- set_location_assignment PIN_91 -to switch1 -- set_location_assignment PIN_90 -to switch2 -- left to right -- LED4 LED2 ? ? POWER -- LED1 <= latchedBits(0); -- LED2 <= fKey1; -- LED3 <= txdBuff; -- LED4 <= rxd; -- txd <= txdBuff; -- LED3 <= txdBuff; -- LED4 <= rxd; -- LED4 <= n_reset; -- set_location_assignment PIN_133 -to DSEN1 -- set_location_assignment PIN_135 -to DSEN2 -- set_location_assignment PIN_136 -to DSEN3 -- set_location_assignment PIN_137 -to DSEN4 -- set_location_assignment PIN_127 -to AD_CLK -- set_location_assignment PIN_129 -to AD_CS -- set_location_assignment PIN_128 -to AD_DAT -- set_location_assignment PIN_85 -to BEEP -- set_location_assignment PIN_24 -to CLK_IN -- set_location_assignment PIN_133 -to DIG[1] -- set_location_assignment PIN_135 -to DIG[2] -- set_location_assignment PIN_136 -to DIG[3] -- set_location_assignment PIN_137 -to DIG[4] -- set_location_assignment PIN_10 -to FLASH_CLK -- set_location_assignment PIN_11 -to FLASH_CS -- set_location_assignment PIN_7 -to FLASH_DI -- set_location_assignment PIN_23 -to FLASH_DO -- set_location_assignment PIN_132 -to IRDA -- set_location_assignment PIN_90 -to KEY[0] -- set_location_assignment PIN_91 -to KEY[1] -- set_location_assignment PIN_88 -to KEY[2] -- set_location_assignment PIN_89 -to KEY[3] -- set_location_assignment PIN_99 -to PS2CLK -- set_location_assignment PIN_98 -to PS2DAT -- set_location_assignment PIN_86 -to RXD -- set_location_assignment PIN_87 -to TXD --set_location_assignment PIN_133 -to DIG[1] --set_location_assignment PIN_135 -to DIG[2] --set_location_assignment PIN_136 -to DIG[3] --set_location_assignment PIN_137 -to DIG[4] -- LEDS A B C D -- button a b c d -- 0 -- button a lights A -- button b lights D -- button c lights C -- button d lights B -- left to right -- buttons SW4 SW3 SW2 SW1 -- buttons [KEY(3)] [KEY(0)] [KEY(1)] [KEY(2)] -- LEDS D5 D4 D3 D2 D1 -- LEDS SEG(3) SEG(2) SEG(6) SEG(7) PWR -- DIG "0111" "1101" "1011" "1110" -- DP "0111" "1011" "1110" -- error -- : "1101" -- : in middle -- SEG(3)<= KEY(3); -- left button light left LED -- SEG(2)<= KEY(0); -- -- SEG(6)<= KEY(1); -- -- SEG(7)<= KEY(2); -- right button lights right LED --7seg digit [] [] [] [] -- DSEN1 <= fkey1; DSEN2 <= not fkey1; DSEN3 <= '1'; DSEN4 <= '1'; -- ZRTech board:- -- pin -- a, b, c, d, e, f, g, h -- 1, 2, 4, 8, 16, 32, 64,128 --pin:143,144, 1,141,142,138, 2, 3 -- a -- f b -- g -- e c -- d dp -- -- LED: --PIN: 141 1 2 3 -- * * * * --SEG: d c g pwr -- -- 8 4 64 128 -- 85 BP1 - buzzer -- 86 rxd -- 87 txd -- TXD -TXT:PL2303 -- RXD -RXD:PL2303 --# end ENTITY(Microcomputer) --# ------------------------- --set_location_assignment PIN_133 -to DSEN1 --set_location_assignment PIN_135 -to DSEN2 --set_location_assignment PIN_136 -to DSEN3 --set_location_assignment PIN_137 -to DSEN4 --set_location_assignment PIN_143 -to LEDSEGA --set_location_assignment PIN_144 -to LEDSEGB --set_location_assignment PIN_1 -to LEDSEGC --set_location_assignment PIN_141 -to LEDSEGD --set_location_assignment PIN_142 -to LEDSEGE --set_location_assignment PIN_138 -to LEDSEGF --set_location_assignment PIN_2 -to LEDSEGG --set_location_assignment PIN_3 -to LEDSEGH LEDSEGA <= not latchedBits(0); LEDSEGB <= not latchedBits(1); LEDSEGC <= not latchedBits(2); LEDSEGD <= not latchedBits(3); LEDSEGE <= not latchedBits(4); LEDSEGF <= not latchedBits(5); LEDSEGG <= not latchedBits(6); LEDSEGH <= not latchedBits(7); -- rxd <= txdBuff; n_IOCS_Write <= n_memWR or n_IOCS; n_IOCS_Read <= not n_memWR or n_IOCS; switchesRead(0) <= switch0; switchesRead(1) <= switch1; switchesRead(2) <= switch2; switchesRead(3) <= '0'; switchesRead(4) <= '0'; switchesRead(5) <= '0'; switchesRead(6) <= '0'; switchesRead(7) <= '0'; -- ____________________________________________________________________________________ -- CPU CHOICE GOES HERE cpu1 : entity work.cpu09 port map( clk => not(cpuClock), rst => not n_reset, rw => n_WR, addr => cpuAddress, data_in => cpuDataIn, data_out => cpuDataOut, halt => '0', hold => '0', irq => '0', firq => '0', nmi => '0' ); -- ____________________________________________________________________________________ -- ROM GOES HERE rom1 : entity work.M6809_EXT_BASIC_ROM -- 8KB BASIC port map( address => cpuAddress(12 downto 0), clock => clk, q => basRomData ); -- ____________________________________________________________________________________ -- RAM GOES HERE -- ram1: entity work.InternalRam16K ram1: entity work.IntRAM16K port map ( address => cpuAddress(13 downto 0), clock => clk, data => cpuDataOut, wren => not(n_memWR or n_internalRamCS), q => internalRam1DataOut ); -- ____________________________________________________________________________________ -- Display GOES HERE io1 : entity work.SBCTextDisplayRGB port map ( n_reset => n_reset, clk => clk, -- RGB CompVideo signals hSync => hSync, vSync => vSync, -- Only 6 bits used, -- videoR0 => videoR3, videoR1 => videoR4, videoG0 => videoG4, videoG1 => videoG5, videoB0 => videoB3, videoB1 => videoB4, n_wr => n_videoInterfaceCS or cpuClock or n_WR, n_rd => n_videoInterfaceCS or cpuClock or (not n_WR), regSel => cpuAddress(0), dataIn => cpuDataOut, dataOut => interface1DataOut, ps2Clk => ps2Clk, ps2Data => ps2Data, FNkeys => funKeys ); FNKey1Toggle: entity work.Toggle_On_FN_Key port map ( FNKey => funKeys(1), clock => clk, n_res => n_reset, latchFNKey => fKey1 ); FNKey2Toggle: entity work.Toggle_On_FN_Key port map ( FNKey => funKeys(2), clock => clk, n_res => n_reset, latchFNKey => fKey2 ); UART : entity work.bufferedUART port map( clk => clk, n_wr => n_aciaCS or cpuClock or n_WR, n_rd => n_aciaCS or cpuClock or (not n_WR), -- n_int => n_int1, regSel => cpuAddress(0), dataIn => cpuDataOut, dataOut => aciaData, rxClkEn => serialClkEn, txClkEn => serialClkEn, -- PL2303 RXD is input -- -- rxd => rxd, -- txd => txdBuff, txd => rxd, rxd => txd, n_cts => '0', n_dcd => '0', n_rts => rts ); io3: entity work.OutLatch port map ( dataIn8 => cpuDataOut, clock => clk, load => n_IOCS_Write, clear => n_reset, latchOut => latchedBits ); -- ____________________________________________________________________________________ -- MEMORY READ/WRITE LOGIC GOES HERE -- n_memRD <= not(cpuClock) nand ( n_WR); n_memWR <= not(cpuClock) nand (not n_WR); -- ____________________________________________________________________________________ -- CHIP SELECTS GO HERE -- memory map -- RAM 0x0000 - 0x3FFF -- ROM 0xE000 - 0xFFFF -- fKey1 selects UART or Screen. -- terminal 0xFFD0/1 - 0xFFD2/3 "1111 1111 1101 000" -- IOCS 0xFFD4 -- terminal 0xFFD0/1 - 0xFFD2/3 "1111 1111 1101 000" -- n_basRomCS <= '0' when cpuAddress(15 downto 13) = "111" else '1'; --8K at top of memory -- n_videoInterfaceCS <= '0' when (( cpuAddress(15 downto 1) = "111111111101000" and fKey1 = '0') or (cpuAddress(15 downto 1) = "111111111101001" and fKey1 = '1')) else '1'; -- n_aciaCS <= '0' when (( cpuAddress(15 downto 1) = "111111111101001" and fKey1 = '0') or (cpuAddress(15 downto 1) = "111111111101000" and fKey1 = '1')) else '1'; -- n_IOCS <= '0' when cpuAddress(15 downto 0) = "1111111111010100" else '1'; -- 1 byte FFD4 (65492 dec) n_internalRamCS <= '0' when cpuAddress(15 downto 14) = "00" else '1'; n_basRomCS <= '0' when cpuAddress(15 downto 13) = "111" else '1'; --8K at top of memory -- n_IOCS_addr 0 when FFDx n_IOCS_addr <= '0' when cpuAddress(15 downto 4) = "111111111101" else '1'; --0xFFD n_videoInterfaceCS <= '0' when ( n_IOCS_addr = '0' and ( ( cpuAddress(3 downto 1) = "000" and fKey1 = '0') or (cpuAddress(3 downto 1) = "001" and fKey1 = '1') ) ) else '1'; n_aciaCS <= '0' when ( n_IOCS_addr = '0' and ( ( cpuAddress(3 downto 1) = "001" and fKey1 = '0') or (cpuAddress(3 downto 1) = "000" and fKey1 = '1') ) ) else '1'; n_IOCS <= '0' when ( n_IOCS_addr = '0' and cpuAddress(3 downto 0) = "0100" ) else '1'; -- 1 byte FFD4 (65492 dec) -- ____________________________________________________________________________________ -- BUS ISOLATION GOES HERE -- Order matters since SRAM overlaps I/O chip selects cpuDataIn <= interface1DataOut when n_videoInterfaceCS = '0' else aciaData when n_aciaCS = '0' else switchesRead when n_IOCS_Read = '0' else basRomData when n_basRomCS = '0' else internalRam1DataOut when n_internalRamCS = '0' else -- basRomData when n_basRomCS = '0' else x"FF"; -- ____________________________________________________________________________________ -- SYSTEM CLOCKS GO HERE clk_gen: process (clk) begin if rising_edge(clk) then -- if cpuClkCount < 1 then -- 4 = 10MHz, 3 = 12.5MHz, 2=16.6MHz, 1=25MHz -- if cpuClkCount < 8 then -- 4 = 10MHz, 3 = 12.5MHz, 2=16.6MHz, 1=25MHz if cpuClkCount < 1 then -- 4 = 10MHz, 3 = 12.5MHz, 2=16.6MHz, 1=25MHz cpuClkCount <= cpuClkCount + 1; else cpuClkCount <= (others=>'0'); end if; cpuClock <= cpuClkCount(0); end if; end process; sdclk_gen: process (clk) begin if rising_edge(clk) then if sdClkCount < 49 then -- 1MHz sdClkCount <= sdClkCount + 1; else sdClkCount <= (others=>'0'); end if; if sdClkCount < 25 then sdClock <= '0'; else sdClock <= '1'; end if; end if; end process; -- ____________________________________________________________________________________ -- Baud Rate Clock Signals -- Serial clock DDS -- 50MHz master input clock: -- f = (increment x 50,000,000) / 65,536 = 16X baud rate -- Baud Increment -- 115200 2416 -- 38400 805 -- 19200 403 -- 9600 201 -- 4800 101 -- 2400 50 baud_div: process (serialClkCount_d, serialClkCount) begin if fKey2 = '0' then serialClkCount_d <= serialClkCount + 2416; -- 115,200 baud else serialClkCount_d <= serialClkCount + 6; -- 300 baud end if; end process; --Single clock wide baud rate enable baud_clk: process(clk) begin if rising_edge(clk) then serialClkCount <= serialClkCount_d; if serialClkCount(15) = '0' and serialClkCount_d(15) = '1' then serialClkEn <= '1'; else serialClkEn <= '0'; end if; end if; end process; end;