6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Wed Oct 02, 2024 11:14 am

All times are UTC




Post new topic Reply to topic  [ 53 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
PostPosted: Tue Dec 05, 2017 2:03 pm 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
Not my code but:

CLKDIV is a two bit counter, giving it four states. Every four clocks, it inverts the state of CLK8 and starts over.
This gives clk8 a full cycle length of 8 clocks.
4 on, 4 off, 4 on, 4 off etc.

CLK8 <= NOT(CLK8); -- This generates the CLK8 clock, rising and falling every four clocks,
-- giving cycle length of 8 x clk

Edit: Keep in mind that CLKDIV is an integer, not a std_logic_vector.
signal CLKDIV: integer range 0 to 3;


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 06, 2017 4:49 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
Cray Ze wrote:
Not my code but:

CLKDIV is a two bit counter, giving it four states. Every four clocks, it inverts the state of CLK8 and starts over.
This gives clk8 a full cycle length of 8 clocks.
4 on, 4 off, 4 on, 4 off etc.

CLK8 <= NOT(CLK8); -- This generates the CLK8 clock, rising and falling every four clocks,
-- giving cycle length of 8 x clk

Edit: Keep in mind that CLKDIV is an integer, not a std_logic_vector.
signal CLKDIV: integer range 0 to 3;


This is exactly right, this is probably a dumb & wasteful way to do it.
I should be able to achieve the same effect with a 3-bit counter using the highest bit as clk8 as you suggested

Cray Ze wrote:
I haven't had a good look at the above change yet, but before you go to far.

From a signal point of view you can move all the porch cycles to the back porch.
BP would be you current BP + FP values.
FP would become 0

You'll see more optimizations from that point.


I thought the Hsync needed to be after front porch, and before back porch?


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 06, 2017 5:27 am 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
LIV2 wrote:
I thought the Hsync needed to be after front porch, and before back porch?

* In my last post I said "move all the porch cycles to the back porch", while I meant to say "front porch".
But let's forget about porches, read on....


Porch is effectively just black video in most cases, or the blanking signal if your feeding a proper video
DAC (with a blanking pin) rather than a resistor DAC. The sync is a different signal during which porch
is still black video.You could think of the two porches as one, just with a sync signal happening in the middle.

I'll explain why I suggested thinking about the signals, before moving to optimization.
A video signal is cyclical, what you do first or last doesn't matter. It only matters that the
order is kept, and the relation to other signals is kept.
Is a blinking LED blinking 'on' then 'off', or is it blinking 'off' then 'on'

A full line (or column for Vertical) consists of:
Sync -> Back Porch -> Active Video -> Front Porch
OR
Back Porch -> Active Video -> Front Porch -> Sync
OR
Active Video -> Front Porch -> Sync -> Back Porch *** Optimization Hint: Design for this one.
OR
Front Porch -> Sync -> Back Porch -> Active Video

The optimization is to start with full sized counters for the horizontal and vertical frame dimensions.
Enable video when in the active area, set black when outside of it (no need to think about porches).
Apply the sync pulse when the appropriate counter is in the correct range.

as a bonus, bit(2) of the h-counter will provide you with a clk/8 signal for use in your SR loading function.

You currently have something like this in mind:
https://i.stack.imgur.com/tGTx3.png

While designing for this looks a little easier:
https://i.stack.imgur.com/jURiy.jpg

They'll both output the same signal on the VGA port.


Top
 Profile  
Reply with quote  
PostPosted: Fri Dec 08, 2017 5:15 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
Ahh yep I get it now, I’ll rewrite it to work that way which should save me some more macrocells. Thanks


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 30, 2018 10:05 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
Just thought I'd update this since I've made more progress recently.
I should note that I did try various different things to handle porches differently etc but it never made a difference to the macrocell usage etc, I ended up just moving up to a 128 macrocell CPLD which meant I could add a hardware cursor and hardware scroll

The schematics and some photos are attached. the prototype card is a disgusting monstrosity and it took me a full day to solder everything but amazingly it works!
Characters are stored on even addresses, color is stored in odd addresses
The prototype card has IDT7132's instead of 7134s which means it can only do 25 rows as it's a little short on ram. You can see they're stacked here to save me some effort & space.


I've already created a proper PCB for this, when I have the money I'll order it

Here's the current VHDL: https://gist.github.com/LIV2/eac150ffd1 ... 1c12e5c9e4


Attachments:
IMG_9302.JPG
IMG_9302.JPG [ 383.14 KiB | Viewed 5398 times ]
IMG_9300.JPG
IMG_9300.JPG [ 434.41 KiB | Viewed 5398 times ]
IMG_9299.JPG
IMG_9299.JPG [ 164.67 KiB | Viewed 5398 times ]
IMG_9298.JPG
IMG_9298.JPG [ 299.98 KiB | Viewed 5398 times ]
schematic.png
schematic.png [ 799.34 KiB | Viewed 5398 times ]
Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 30, 2018 11:40 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10943
Location: England
Nice!


Top
 Profile  
Reply with quote  
PostPosted: Tue Jul 31, 2018 2:50 am 
Offline

Joined: Sat Dec 30, 2017 3:19 pm
Posts: 116
Location: Detroit, Michigan, USA
Very impressive!


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 16, 2018 1:39 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
Still struggling to get timing just right with this

Since the ROM access time is so slow, this leads each character being displayed 1 character time late which is fine & accounted for in the CPLD
The colour ram is not that slow though so if I load the colour latch at the same time as the shift register this results in the wrong colour being displayed for each colour

I've been stupidly dealing with this by using a 74AC latch with the latch signal generated on the rising edge of the character clock so it's loaded just before MA increments and the RAM has time to output the next byte which looked fine due to the adjustment of my monitor.
After playing with it for a bit I hit the auto adjust button on my monitor and discovered that it had a visible effect of the very edge of the characters to take on the colour of the next character...

I've added another latch now so that the colour data is simply delayed by one character so it matches properly but I now noticed that depending on the adjustment of the monitor you can see a column of pixels in the foreground colour that shouldn't be there between characters; once the auto adjust is complete though it disappears.

Clearly there's some weird timing going on still which is extremely frustrating and demotivating. I would be tempted to think VGA is too much to push through discrete logic but that can't be the case when we have members on this board pushing 640x480 colour graphics.

I'm tempted to replace the discrete logic with another smaller CPLD (I've just about filled the EPM7128) but that idea feels like admitting defeat.


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 16, 2018 5:59 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Quote:
I've added another latch now so that the colour data is simply delayed by one character so it matches properly

Cool project! And I guess it's the '273 register which you added to do the delay and make things match, as you say. Generally you have one character whose color and pixel data have been loaded in the '273 and the shift register, and you have another character whose color and pixel data is waiting to go in the '273 and the shift register. So, you've set up the pipeline appropriately. The green dots (below) indicate the character that's waiting (its color data and pixel data).
Attachment:
CPLD Driven color VGA.png
CPLD Driven color VGA.png [ 246.79 KiB | Viewed 5231 times ]

When the pipeline advances you'll want the '273 and the shift register to load simultaneously, and I assume that's what you're doing (I admit I haven't read all the preceding posts). And, after the two registers load, the shift register does a series of shifts (I assume it's 7 shifts, making the character 8 pixels wide). So, the pattern for the shift reg is load shift shift shift shift shift shift shift [and so on]. But here's the thing. For a good looking display you need the timing of those eight events to be entirely regular... which is almost impossible with a '165 shift register but quite easy with a '166 shift register. That's because the load input on a '165 takes effect immediately, and thus the timing of the load signal is critical. But on a '166 the load input doesn't take effect immediately -- it simply alters the function of the next clock edge (when it arrives) from shift to load. Thus on a '166 shift timing and load timing are one and the same. The load is synchronous.

Having swapped the '165 for a '166, you may find it convenient to also swap the '273 for a '377. With such an arrangement both chips' clock inputs can be driven by the 8x clock (the pixel clock, at 8 times the character rate). Also, once per character when the pipeline is about to advance, a brief (ie, one pixel time) active-low pulse is applied to both the load input of the '166 and the enable input of the '377. Thus the '377 does a "load idle idle idle (etc)" pattern while the '166 is doing its "load shift shift shift (etc)" pattern, and the two chips are operating from identical signals.

Finally, because of delays resulting from the XOR and the mux you may find it beneficial to insert a register between the output of the '157 mux and the resistors etc of the output circuit. That register, too, would be clocked by the pixel clock. I hope the explanations are clear, or at least not too bad. Sorry to recommend so many changes but I think the payoff will be a great looking display.

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Last edited by Dr Jefyll on Fri Aug 17, 2018 2:03 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 16, 2018 6:29 am 
Offline
User avatar

Joined: Fri Nov 09, 2012 5:54 pm
Posts: 1429
Thanks Jeff, you already got the problems covered. :)

That 74157 multiplexer controlled by the 7486 XOR gate gives us some propagation delay,
and I think this won't look good in the RGB output signal.

I'm also suggesting to insert a 74574 latch or such (clocked with the dot clock) at the 74157 outputs.
If the outputs of the latch won't give you enough current, add a buffer too.

Dennis Kuschel did a TTL based VGA graphic unit some time ago, and the circuitry at the RGB output had looked like this:

Attachment:
kuschel_vga.png
kuschel_vga.png [ 36.72 KiB | Viewed 5224 times ]


Top
 Profile  
Reply with quote  
PostPosted: Fri Aug 17, 2018 6:15 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
Wow thanks!
That makes perfect sense, without synchronous registers & synchronous load the shift register and the latch will never meet up correctly

I've ordered a couple of '377s,'166's and a couple of '574s though they're going to take a while to get here.


Top
 Profile  
Reply with quote  
PostPosted: Fri Aug 17, 2018 3:37 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
You're welcome -- and I'll look forward to hearing further updates. :)

I hope when you ordered the parts you included some fast logic such as 74AC or 74AHC for the signal paths that are critical. The path that has the most to accomplish between pixel-clocks is the path through that XOR gate. Ideally the '166, the XOR, the '157 and the new output reg should all be fast parts, but you can maybe relax that requirement, depending on the pixel-clock frequency.

BTW, a '163 counter can be used as a 4-bit synchronous-load register if you simply let the load function override the count function. Using a '163 as the new output reg might save some space for you, as it's only a 16-pin device. The '173 is another 16-pin option.

Edit: OTOH, if you use an 8-bit reg you can use one of the extra sections to condition the other input of the XOR gate, which might be important.

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 18, 2018 8:46 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
The '157 and '86 at least are already AC, I just neglected to update the schematic on that so by the looks of it.

I was silly enough to order HC versions of the '377, '166 and '574, looking now I can't find anything in DIP except for the 574 but I can probably stick some SOICs upside down on the protoboard and solder wires to it. Thanks for the tip re: synch counters as a latch I'll use it!

In the meantime I've tested the theory by replacing all the external logic with another CPLD and it looks perfect (but it's a bit of a waste of a CPLD!) so I can't wait to get the new ICs

The external logic is currently implemented as
Code:
library ieee;
use ieee.std_logic_1164.all;

entity vgalogic is

   port
    (
        clk      : in std_logic;
        color_d   : in std_logic_vector (7 downto 0);
        char_d   : in std_logic_vector (7 downto 0);
        viden    : in std_logic;
        cursor   : in std_logic;
        latch    : in std_logic;
        out_R    : out std_logic;
        out_G    : out std_logic;
        out_B    : out std_logic;
        out_I    : out std_logic
    );

end entity;

architecture rtl of vgalogic is

signal shift_register: std_logic_vector(7 downto 0) := (others => '0');
signal muxsel: std_logic;
signal muxd: std_logic_vector (3 downto 0);
signal color_latch1: std_logic_vector (7 downto 0);
signal pixel: std_logic := '0';


begin
   muxsel <= (pixel xor cursor);
   process (clk)
    begin
      if (rising_edge(clk)) then
        if (latch = '1') then
           color_latch1 <= color_d;
         else
           color_latch1 <= color_latch1;
         end if;
      end if;
    end process;


    process(muxsel)
    begin
    if (muxsel = '1') then
        muxd (3 downto 0) <= color_latch1 (3 downto 0);
    else
        muxd (3 downto 0) <= color_latch1 (7 downto 4);
    end if;
    end process;

    process (clk)
    begin
        if (rising_edge(clk)) then
            if (latch = '1') then
                shift_register <= char_d;
            else
                shift_register (7 downto 1) <= shift_register (6 downto 0);
                shift_register (0) <= '0';
            end if;
        end if;
    end process;
    pixel <= shift_register(7);

    process (clk)
    begin
    if (rising_edge(clk)) then
        if viden = '0' then
            OUT_I <= muxd(3);
            OUT_R <= muxd(2);
            OUT_G <= muxd(1);
            OUT_B <= muxd(0);
        else
            OUT_I <= '0';
            OUT_R <= '0';
            OUT_G <= '0';
            OUT_B <= '0';
        end if;
    end if;
    end process;
end rtl;


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 18, 2018 9:54 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
LIV2 wrote:
Thanks for the tip re: synch counters as a latch I'll use it!

It does save some space. But are you sure you don't need some extra flipflop sections (as you'd get with a 20-pin device such as '574)? Just checking -- I haven't carefully examined what you're doing. I already mentioned in the edit added to my last post that the signal called Cursor (which drives pin 12 of the XOR) had better be run through a flipflop. But maybe you've managed the same thing using a flipflop inside the CPLD. If so, that flipflop should ideally use the pixel clock (but only enabled 1 out of 8 times, like what the '377 is doing).

Looking again, I notice the same concern applies re the signal called Blank, too (which drives pin 15 of the '157).

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 18, 2018 12:37 pm 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
Ahh yep sorry I missed that, CURSOR isn't running through a flip-flop inside the cpld, BLANK (aka viden) is described as follows
Code:
VID_ENABLE:
process(clk,V_BLANK,H_BLANK)
begin
    if falling_edge(clk) then
        if (V_BLANK NOR H_BLANK) then
            viden <= '0';
        else
            viden <= '1';
        end if;
    end if;
end process;


Which I know understand isn't suitable, this needs to be latched at the same time the shift register and colour latch do. same with the cursor
I could do that in the CPLD but the timing would be slightly different to the output '547 so I may as well pass them through the same latch as the video output.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 53 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: