Latest Status Update:

Sunday 24 April -

Project log added

PROJECT INDEX

Most recent update (holdups)

I have put this on the back burner for now as I make a fuser for making PCB's with the Toner Transfer method as I need to make PCB's to prototype with. I am almost finished the fuser hardware and I will upload it a separate project soon.

I am now doing the VHDL with a Altera CPLD (EPM240) and I will order a lager version (EPM570). It took a bit to get used to the Altera IDE as there are no constraints files like in Xilinx.

Details

What I currently have in mind is a Z80 @ 20MHz running the target code, an atMEGA (atMEGA1284 to start with) @20 or 25MHz doing all I/O interfacing and assisting with VGA generation and a CPLD clocking out the pixels to a VGA port @ 50 MHz. The SRAM will probably have to run at 100MHz to be shared between these functions.

To accomplish this, I need to learn the following skills -

Proposed major parts are -

The problems I have encountered so far are -

Difficulty finding parts with 0.1 inch pin spacing. I am reverting to using SMD devices on breakout boards. This has created additional problems as I can't find the correct breakout boards for VQFP chips with different pinouts.

Difficulty finding suitable CPLD devices that will work with the 5 Volt Vcc of the CPU. I have so far settled for a 5 Volt 'tolerant' CPLD but it lacks GPIO pins and wont be suitable for the end design unless I use a number of them.

I have had many setbacks with the Toner Transfer Method of PCB manufacture. After buying another laser printer some of the issues have resolved but I am back to square one again. I am using the Pulsar Toner Transfer Sheets and Toner Reactive Foil. My fuser (laminator) has been modified to increase the temperature but the hysteresis of the thermostat is too wide and the feed motor is too fast to maintain temperature on larger boards. I expect I will put a micro-controller into it to regulate the speed and temperature.

Another problem I anticipate is that this circuit is not going to work on bread board because of the high frequency signals. I will probably have to make a modular system with PCB's much like the Arduino 'Shield' system to prototype it as I go, and hence the need for in house PCB manufacture.

The anticipated sub projects are -

Here are some pics of the development tool I am working with -

This is a development board that I bought on ebay. It is for an atMEGA664. The atMEGA1284 has the same pinout. I had to modify the Arduino IDE to use the 1284. I will use it with the Arduino IDE for low speed proof of concept work using sketch and the USB port. When I am ready to start the VGA side of things I will switch to AVR Studio and program it with the USBasp pictured. The files that came with it had a trojen in some files and changes to the core Arduino java file so started with a new copy of the IDE and made the changes needed. They're not hard to do, just text files, you don't even need to re-compile as the tool-chain already supports the atMEGA1284.

This is a XC9572XL CPLD breakout board. It has a 50MHz active crystal on board. The Xilinx programmer works with the Xilinx ISE for loading the VHDL into the chip.

This is an "open bench logic sniffer" that I use to see what's wrong when my VHDL doesn't do what I expect it to do. It scans at 200MHz and is rather cheap. It matches this project well.

Here the CPLD board is connected to a Papilio One LogicStart MegaWing. I am just using it for the VGA socket.

Here is a test pattern being generated by the CPLD as a proof of concept for the VGA timing.

Here is where I am up to. Getting everything to DIP so that I can work on a breadboard.

Just a quick update (02/01/2015) I am waiting for shorting links or jumpers so that I can plug a shield with SRAM on top of the XC9572XL module.

The links arrived.

I moded the CPLD board so that it passes out 5 Volts instead of 1.8 Volts so that I can power the SRAM.

Here is the shield thingy made on strip board. It will accept chips / breakout boards of different widths so I can use it with the atMEGA1284 later on.

And the bottom (messy soldering).

It's messy but I hope it works. I really didn't expect this to run on a bread board with 40 ns access times. Now there is only one wire in a signal path, the rest are the shorting links.

Here are the components apart.

And assembled.

I re-wrote the constraints file to suite the new pinout and tested it with the old VHDL that doesn't use the SRAM and that is working.

Now I have to write some new VHDL and I will post the results when that stage is done.

Here's the old VHLD.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;


-- VGA standard 800x600 50MHz
-- VGA actual   400x300 25MHz
-- RAM 120,000  120,000 Bytes at 1 Byte per pixel
-- pixels       400 x 300
-- chr  8 x  8   50 x  37.5
-- chr 16 x 16   25 x  18.75

-- #### HORIZONTAL ####
-- signal  value    units   provisor     domain              time               domain
-- h_active  800   pixels   @ 50 MHz     0000 - 0799    16.000 uS    0.000 - 15.980 uS
-- h_back     64   pixels   @ 50 MHz     0800 - 0863     1.280 uS   16.000 - 17.260 uS
-- h_sync    120   pixels   @ 50 MHz     0864 - 0983     2.400 uS   17.280 - 19.660 uS
-- h_front    56   pixels   @ 50 MHz     0984 - 1039     1.120 uS   19.680 - 20.580 uS

-- Signal                  Freq       Period     Rises after       Duration
-- clk        50,000,000     Hz        20 nS           10 nS          10 nS
-- hc(0)      25,000,000     Hz        40 nS           20 nS          20 nS
-- hc(1)      12,500,000     Hz        80 nS           40 nS          40 nS
-- hc(2)       6,250,000     Hz       160 nS           80 nS          80 nS
-- hc(3)       3,125,000     Hz       320 nS          180 nS         180 nS
-- hc(4)       1,563,500     Hz       640 ns          320 nS         320 nS
-- hc(5)         781,250     Hz     1.280 uS          640 nS         640 nS
-- hc(6)         390,625     Hz     2.560 uS        1.280 uS       1.280 uS
-- hc(7)         195,312.50  Hz     5.120 uS        2.560 uS       2.560 uS
-- hc(8)          97,656.25  Hz    10.240 uS        5.120 uS       5.120 uS
-- hc(9)          48,828.125 Hz    20.480 uS       10.240 uS      10.240 uS
-- hc(10)         24,   ...  Hz    40.960 uS       20.480 uS      20.480 uS


-- #### VERTICAL ####
-- signal     duration       range                    range start            range ends after
-- v_active  600 lines  000 -  599                              0    512        +64   +16  +4+2+1
-- v_back     23 lines  600 -  622   512        +64   +16+8          512        +64+32   +8+4+2
-- v_sync      6 lines  623 -  628   512        +64+32   +8+4+2+1    512        +64+32+16  +4
-- v_front    37 lines  629 -  665   512        +64+32+16  +4  +1    512+128          +16+8     +1

-- signal   rises after
-- h_sync                    any h signal that doesn't repeat in one scanline should be ok
-- vc(0)        1 line 
-- vc(1)        2 lines
-- vc(2)        4 lines
-- vc(3)        8 lines
-- vc(4)       16 lines
-- vc(5)       32 lines
-- vc(6)       64 lines
-- vc(7)      128 lines
-- vc(9)      256 lines
-- vc(10)     512 lines


-- ok now some notes
-- the original vga spec is for 1040 clock cycles per h_line
-- which means the h_count will be 11 bit h_count(10 downto 0)
-- there are 666 lines to a frame 9 bit   v_count(9 doen to 0)
-- h_active = 800 clocks = 512 + 256 + 32 - 1

entity XC9572XL is --VGA800x600-50MHz is

    Port (
         CLK      :  in STD_LOGIC;
           H_SYNC   : out STD_LOGIC;
           V_SYNC   : out STD_LOGIC;
           RED      : out STD_LOGIC;
           GRN      : out STD_LOGIC;
           BLU      : out STD_LOGIC;
--          C_ACTIVE : out STD_LOGIC;
--          C_SYNC   : out STD_LOGIC;
         LED1     : out STD_LOGIC;
         LED2     : out STD_LOGIC;
         LED3     : out STD_LOGIC;
         LED4     : out STD_LOGIC   
         );
            
end XC9572XL;--VGA800x600-50MHz;

architecture Behavioral of XC9572XL is--VGA800x600-50MHz is

--signal nclk       : STD_LOGIC;

signal h_counter  : STD_LOGIC_VECTOR (10 downto 0) := "11111111111";
signal h_active   : STD_LOGIC;
signal v_counter  : STD_LOGIC_VECTOR (10 downto 0) := "11111111111";
signal v_active   : STD_LOGIC;

signal f_counter  : STD_LOGIC_VECTOR (4 downto 0) := "00000";
signal dot_x      : STD_LOGIC_VECTOR (5 downto 0) := "000001";
signal dot_x_dir  : STD_lOGIC := '1';
signal dot_y      : STD_LOGIC_VECTOR (5 downto 0) := "000000";
signal dot_y_dir  : STD_LOGIC := '1';
signal dot_flag   : STD_LOGIC;
signal edge_flag  : STD_LOGIC;

signal h_highlight : STD_LOGIC;
signal v_highlight : STD_LOGIC;

signal chrr        : STD_LOGIC_VECTOR (7 downto 0);
signal px          : STD_LOGIC;

--signal h_sync_reg : STD_LOGIC;
--signal h_actv_reg : STD_LOGIC;
--signal v_sync_reg : STD_LOGIC;
--signal v_actv_reg : STD_LOGIC;

begin

-- update horizontal counter and flags
process (CLK)--, h_counter, v_counter)
begin
if rising_edge(CLK) then
    h_counter <= h_counter + 1; -- start of horizontal code
    if (h_counter = 0) then -- start of horizontal active period
        h_active <= '1';
    end if;


    if (h_counter > 390 and h_counter < 408) then -- debugging block
        h_highlight <= '1';
--    end if;
--    if (h_counter = 407) then
   else
        h_highlight <= '0';
    end if;



    if (h_counter = 800) then -- end of horizontal active period
        h_active <= '0';
    end if;
    if (h_counter = 856) then -- start of horizontal sync
        H_SYNC <= '0';
    end if;
    if (h_counter = 976) then -- end of horizontal sync
        H_SYNC <= '1';

        v_counter <= v_counter + 1; -- start of vertical code
        if (v_counter = 0) then -- start of vertical active period
            v_active <= '1';
        end if;


        if (v_counter = 291) then -- debugging block
            v_highlight <= '1';
        end if;
        if (v_counter = 307) then
            v_highlight <= '0';
        end if;


        if (v_counter = 600) then -- end of vertical active period
            v_active <= '0';
        end if;
        if (v_counter = 637) then  -- start of vertical sync
            V_SYNC <= '1';
        end if;
        if (v_counter = 643) then -- end of vertical sync
            V_SYNC <= '0';
        end if;
        if(v_counter = 666) then -- end of vertical frame
            v_counter <= "11111111111";
            f_counter <= f_counter + 1;
            if (f_counter = "11111") then
                if (dot_x = 0) then
                    dot_x_dir <= '1';
                end if;
                if (dot_x = 48) then
                    dot_x_dir <= '0';
                end if;
                if(dot_y = 0) then
                    dot_y_dir <= '1';
                end if;
                if (dot_y = 35) then
                    dot_y_dir <= '0';
                end if;
                if(dot_x_dir = '1') then
                    dot_x <= dot_x + 1;
                else
                    dot_x <= dot_x - 1;
                end if;
                if(dot_y_dir = '1') then
                    dot_y <= dot_y + 1;
                else
                    dot_y <= dot_y -1;
                end if;
            end if;
        end if;
    end if; -- end of vertical code
    
    if(h_active = '1' AND v_active = '1' AND (h_counter = 1 OR h_counter = 800 OR v_counter = 1 OR v_counter = 600)) then
      edge_flag <= '1';
    else edge_flag <= '0';
    end if;

    if (h_counter = 1040) then -- end of horizontal line
        h_counter <= "11111111111"; 
    end if; -- end of horizontal code

    if ((h_counter(9 downto 4) = dot_x(5 downto 0)) AND (v_counter(9 downto 4) = dot_y(5 downto 0))) then
        dot_flag <= '1';
    else
        dot_flag <= '0';
    end if;
    --dot_flag <= '1';

end if;

end process;

--process (nclk)
--begin
--if rising_edge(CLK) then
--    h_counter <= h_counter + 1; -- start of horizontal code
--end if;
--end process;

--nclk <= not CLK;

--with v_counter (3 downto 1) select chrr <= 
--  "00000000" when "000",
--  "00111110" when "001",
--  "01100110" when "010",
--  "01100110" when "011",
--  "00111110" when "100",
--  "01100110" when "101",
--  "01100110" when "110",
--  "00111110" when "111",
--  "00000000" when others;
  
with v_counter (3 downto 1) select chrr <= 
  "11111111" when "000",
  "10000001" when "001",
  "10000001" when "010",
  "10000001" when "011",
  "10000001" when "100",
  "10000001" when "101",
  "10000001" when "110",
  "11111111" when "111",

  "00000000" when others;

with h_counter (3 downto 1) select px <=
  chrr(0) when "000",
  chrr(1) when "001",
  chrr(2) when "010",
  chrr(3) when "011",
  chrr(4) when "100",
  chrr(5) when "101",
  chrr(6) when "110",
  chrr(7) when "111",
  '0'     when others;

--LED1 <= '1';
--LED2 <= not '1';
--LED3 <= '0';
--LED4 <= not '0';

RED <= ((px XOR dot_flag) AND h_active AND v_active AND (h_counter(4) XOR (v_highlight AND h_highlight) XOR v_counter(4)));
GRN <= ((px XOR dot_flag) AND h_active AND v_active AND (h_counter(5) XOR (v_highlight AND h_highlight) XOR v_counter(4)));
BLU <= ((px XOR dot_flag) AND h_active AND v_active AND (h_counter(6) XOR (v_highlight AND h_highlight) XOR v_counter(4)));


--H_ACTIVE <= h_actv_reg;
--H_SYNC   <= h_sync_reg;
--V_ACTIVE <= v_actv_reg;
--V_SYNC   <= v_sync_reg;
--C_ACTIVE <= h_actv_reg AND v_actv_reg;
--C_SYNC   <= h_sync_reg XOR v_sync_reg;




end Behavioral;

Damn! No markup for VHDL!

Anyway, I am doing this as an exercise in learning VHDL. The Xilinx XC9572XL simply doesn't have enough pins, there are only about three or four left after the SRAM and VGA are accounted for.

This chip has enough logic to do one line at a time under the control of an ATmega. The larger XC95144XL could probably do the full frame without any assistance.

I will order a XC95144XL in a QFP100 package. I really didn't want to use any 'hard to solder' chips.

Perhaps I should think about using a wide bus 'level translator' for the Z80 and then just use all 3.3 Volt chips for everything else. Then I can use a much larger FPGA and do lots of nice things with the video.

I'm a bit lost at the moment with which way to go. It's difficult to mix an old 5 Volts CPU with modern chips.