Before writing any software for Y Ddraig the CPLD will need to be programmed. The CPLD being used here is a Xilinx XC95108 and it is responsible for the address decoding for the peripherals and will eventually be used for controlling the DRAM but that isn’t going to be used in the inital stages of getting the computer up and running.
The clock signal for the 68000 is generated by CPLD so the first step is to create a clock signal for the 68000. The 10Mhz output clock is derived from the 40Mhz clock input to the CPLD.
architecture Behavioral of Clock is signal clk_divider : std_logic_vector(1 downto 0) := (others => '0'); begin process(clk) begin if (rising_edge(clk)) then clk_divider <= clk_divider + 1; end if; end process; clk10 <= clk_divider(1); end Behavioral;
The memory map that is going to be used for Y Ddraig is as follows:
|Device||Start Address||End Address|
On startup the 68000 fetches two long word vectors from address 0x000000 for the stack pointer and start address for the code. As the ROM is set at address 0xF80000 this has to map the first four reads to the ROM.
This is handled by a 74LS164 8 bit shift register (U11) which sets the bootrom signal low for the first 4 address accesses (/AS) and then the bootrom signal is high until the next reset.
With this information the address decoding module is defined as follows:
entity AddressDecode is Port ( a : in STD_LOGIC_VECTOR (23 downto 8); clk : in STD_LOGIC; as : in STD_LOGIC; bootrom : in STD_LOGIC; reset : in STD_LOGIC; dtack : out STD_LOGIC; cs_rom : out STD_LOGIC; cs_sram : out STD_LOGIC; cs_duart : out STD_LOGIC; cs_pit : out STD_LOGIC; cs_kbd : out STD_LOGIC; cs_rtc : out STD_LOGIC; cs_ym2151 : out STD_LOGIC; cs_eth : out STD_LOGIC; cs_vdp : out STD_LOGIC; cs_ide : out STD_LOGIC); end AddressDecode;
ROM access is selected when the bootrom signal is 0 or the address range is in the ROM area. RAM access is similarly defined except that it expects the bootrom signal to be 1.
Peripheral access defined in 256 byte address blocks in the defined address ranges.
-- $F80000 - $FFFFFF cs_rom <= '0' WHEN as = '0' AND (bootrom = '0' OR std_match(a, "11111-----------")) ELSE '1'; -- $000000 - $0FFFFF cs_sram <= '0' WHEN as = '0' AND bootrom = '1' AND std_match(a, "0000------------") ELSE '1'; -- $F7F000 - $F7F0FF cs_duart <= '0' WHEN as = '0' AND std_match(a, "1111011111110000") ELSE '1'; -- $F7F100 - $F7F1FF cs_ym2151 <= '0' WHEN as = '0' AND std_match(a, "1111011111110001") ELSE '1'; -- $F7F200 - $F7F2FF cs_pit <= '0' WHEN as = '0' AND std_match(a, "1111011111110010") ELSE '1'; -- $F7F300 - $F7F3FF cs_kbd <= '0' WHEN as = '0' AND std_match(a, "1111011111110011") ELSE '1'; -- $F7F400 - $F7F4FF cs_ide <= '0' WHEN as = '0' AND std_match(a, "1111011111110100") ELSE '1'; -- $F7F500 - $F7F5FF cs_eth <= '0' WHEN as = '0' AND std_match(a, "1111011111110101") ELSE '1'; -- $F7F600 - $F7F6FF cs_rtc <= '0' WHEN as = '0' AND std_match(a, "1111011111110110") ELSE '1'; -- $F7F700 - $F7F7FF cs_vdp <= '0' WHEN as = '0' AND std_match(a, "1111011111111111") ELSE '1';
For some of the peripherals the DTACK signal is automatically handled. These include the ROM (in hardware), the DUART and The PIT. For the others then the DTACK signal must be generated.
The DTACK generator:
signal dtack_s : std_logic_vector(3 downto 0); process (clk, reset, as) begin if (reset = '0' or as = '1') then dtack_s <= (others => '0'); elsif (rising_edge(clk)) then if (dtack_s < "1111") then dtack_s <= dtack_s + 1; end if; end if; end process;
Check if we need to generate the DTACK signal:
-- Check the chip select signals to see if one is low ack <= cs_sram AND cs_kbd AND cs_rtc AND cs_ym2151 AND cs_vdp AND cs_eth; -- Generate the DTACK dtack <= '0' WHEN ack = '0' AND dtack_s > "0101" ELSE '1';
This should provide the address decoding needed to be able be able to start writing some code to test the hardware is working as expected.