Video artifacts present in scan doubled video

I uploaded a video to youtube that shows some video artifacts happening with the scan doubled video.

The entire video shakes as if interlaced, but it’s not. Original res 320×200(15.7khz), doubled to 640×400.(~31khz)

There is a colored wavy pattern across the white sections.

Video showing artifacts

On a monitor directly attached to the amiga, the screen is very stable, crisp, and nice looking. :)

 

Removed the black bar, amiga VSC is starting to work much better

Here’s a screen shot of the amiga vsc in action.  As you can see, there’s been much improvement from the last session.

Even though I am now passing the amiga’s VSYNC through the FPGA to the monitor, I wasn’t resetting my Y coordinate in my hvsync generator module. What this meant was that the module thought it was blanking when it wasn’t — spitting out a scrolling black bar.  On receipt of a VSYNC from the amiga, I now adjust the Y coordinate appropriately. (set it to 435, for what it’s worth)

 

 

Getting closer….

So a few versions later, trying some different failed attempts, I am finally starting to get a little closer.  Here’s the best video I’ve got so far, but my image is still scrolling.

If I can fix the scrolling issue, which I suppose is related to VSYNC, then maybe things might be looking better.

The things that give me hope are:

  • Size is basically correct, taking up the whole output screen.
  • Colors all look right
  • Text is basically readable
  • Some artifacts around the edges of the graphics, but nothing too horrible

Yay! Initial shots from the VSC!

So I got everything hooked up tonight, and the good news is that I have definitely made some progress!

It appears to work, although the video is currently scrolling with multiple video problems, but I definitely have something to work with!

finally got some work into the VSC

Ok, so I’ve finally got some work done on this tonight.

I’ve decided to go to a 4-line buffer system because it’s a more round number than 3 — makes everything easier to deal with.

I’ve gotten rid of the dram controller, and all associated circuitry. Create (4) dual-port rams, instantiated my amiga video acquisition module.

Good progress tonight. Still have to create the write FSM for grabbing the data from the amiga module and writing it into the correct line buffer. Should be easy but at 1:33am local time, I’ve got to sleep.

I wanted to keep the work modularized and so I needed what I believe is called a (one-hot?) decoder — which takes a single write enable signal, and a 2-bit select signal for the write bank, and then outputs four separate signals so that only one of the signals is enabled at a time. All are sitting on standby, but only one line buffer will only be written to, every 320 pixels. All are being fed an x-coordinate for a write address.

 

I haven’t had a chance to simulate this, but I think it’ll work.  Here’s my code:

module wren_decoder(
select,
bank_wrens,
master_wren
);</code>

input [1:0] select;
input master_wren;
output reg [3:0] bank_wrens ;

always @ (select or master_wren)
begin
if (master_wren) begin
case (select)
2'd0 : bank_wrens = 4'b0001;
2'd1 : bank_wrens = 4'b0010;
2'd2 : bank_wrens = 4'b0100;
2'd3 : bank_wrens = 4'b1000;
endcase
end
else begin

bank_wrens = 4'b0000;

end

end

endmodule

If master_wren is disabled, then all four rams see wr_enable disabled.

If master_wren is enabled, then based on the bank selection, the correct ram is enabled for writing.

Each ram gets their wr_enable signal tied to bank_wrens[0], bank_wrens[1], and so on......

Look ok?

 

switching design from DRAM to ALTRAMs

So as my last couple posts alluded to, I’ve been having problems with my DRAM-based design.

My controller isn’t dual-port.

And I’ve been trying to wrap my head around a time-slot method for arbitration.  And optimizing memory controllers.

Then it struck me — my incoming and outgoing data rate access to the memory is exactly the same.  Because my output is twice the resolution, but half the frequency, the per-frame time is the same for 640×400 @ 32khz as for 320×200 @ 15.7khz.

So if the data rates are the same, what’s stopping me from just putting a little buffer in-line, and forgetting all this complicated DRAM access time issues?

I ran it past my super smart friend Brian, and he’s thinks it’s a fine idea.  He recommended perhaps a three line buffer, using separate rams for each line, cycling through each buffer for each incoming/outgoing line.

I’m convinced that the simplest solution is always the best solution which leaves less room for error.

I’m excited about having a new way of moving forward on this. I’ve been stagnant for a couple weeks but that is changing soon enough.

 

on memory controller optimization

So I’ve been trying to optimize a freeware memory controller for my particular memory chip.

I’m running into this situation where the DRAM to ALTRAM copy takes upwards of 24us per line. But I only have a total of 32us per line. So my “free” memory time is limited to about 8us.  I was _really_ trying to get the copy down pretty low so the “rest” of the memory time could be spent writing from the amiga to the dram.

I’m running into weird problems though. First off, sometimes the copy exceeds the time per horizontal line, and I can’t figure out wtf that is. It’s not so simple that it’s a simple bank change or something that causes a little extra delay.

Furthermore, everything seems to be working. No graphics flaws that I can see. I would expect to see randomly repeated rows or something.

I took the controller from 133mhz to 166mhz, and I see some improvement there.  The controller does not wait tRCD when it can, but waits tRC all the time. I tried changing the value to the tRCD from the datasheet, and that does really speed things up, but anytime there is a bank change, then there’s an associated error.

I’m beginning to think that the highest payoff in optimizing the controller is the burst size, because there seems to be much overhead with each read request. When you are running at 166mhz, data is coming in pretty damn fast from the memory, and each added 16bits width comes in at the clock rate. Since your overhead would be fixed, doubling the amount of data received would allow for more efficient transfer.

The controller has a fixed burst size of 2 — and I’ll need to modify controller a fair bit to support it.  What especially makes my job harder is that the order of the data changes based on the most significant portions of the column address. So accesses to a CA of 00xxxx- has order 0-1-2-3, but CA of 11xxxx- has order 3-0-1-2. It just makes things harder than just tacking the received data on the end. :)

 

maybe a big problem, memory arbitration on FPGAs

So far, I’ve been using a user-selectable mux, with a physical switch, to control which process is connected to the single-port memory controller.

If the switch is in one position, you can upload via USB a properly formatted image.  In the other position, the display FSM is active, and it is reading from the memory and displaying it on the output video port.

But since I’m transitioning to a model where I have simultaneous input from the amiga, while outputting to the monitor — things are going to have to get more complicated.

Finding working, easy to use, free memory controllers for FPGAs is tough. A lot of the stuff on OpenCores sucks, and even when they work, there is zero documentation, and reliability is shaky. Sure there are commercial cores.

My memory controller is a freeware wishbone slave. I know I need some type of arbitration, but I’m not even convinced yet that there is enough time (bandwidth?) to allow everyone to properly interleave the access they need. It’s also weird, in that, we read from the memory much faster than we write. Which means that we in essence do unnecessary reads. Do we do some type of per-line synchronization? Can I get away with some other type of scheme?

I’ll take any hints from people who have experience with this stuff.

Important information:

Arriving video information from the amiga comes at a 7.14mhz pixel clock speed, getting 12 bits (16 bits packed) every 140ns.  This translates to about 14 megabytes per second. Wow!

Output video is a 25mhz pixel clock, with 12 bits (16 packed) leaving every 40ns. This translates to about 50 megabytes per second.

It’s approximately a 4:1 ratio of reads from memory (aka output to monitor) to writes (aka input from amiga)

My memory is running at 133mhz, and is 16-bit wide.  The controller is setup to do a burst size of 2. I think I can access 32 bits every 30ns with a 100mhz user clock best case. So I’m getting at least an effective 1 gigbit / second throughput. This doesn’t include writing it into secondary memory (block ram, etc).

 

my level converter board with lcx245′s

I put this together last night. It takes the amiga 5v video signals in on the right hand side and then outputs 3.3v to IDC40-pin connector that connects to the FPGA board.

Once I build my header cables, they will plug directly into the solderless board on the right hand side.

In case anyone is wondering, none of the standard pre-stripped jumper lengths fit directly across the board, so I moved the 245′s further away to accommodate the lengths that worked.

 

 

 

more ordering of parts, soldered pins for lcx245 parts

So I was looking everywhere for a female-female header cable that has the right number of pins, to basically interface the Denise IC DIP Clip to my level converting solderless breadboard.  I couldn’t seem to find them, although I can’t believe they aren’t more popular.

However, I stumbled on Pololu, who I knew I’d be ordering from one of these days.  They have wires with precrimped terminals, and the associated housings to make your own custom header cables. I think this is perfect.  I’ll have one side be male to plug into the solderless breadboard, and the other side female to interface with the DIP Clip. Should be a pretty clean solution.

My LCX245 board needed the pins soldered on, so I did that yesterday, and tested each of them with a multimeter to make sure it was successful. I need to get a lamp magnifier, as I could use the help when soldering.

I’ve got more Verilog work to do, although I think I’ve got the majority of the high level design stuff done. Finally the hardware pieces and parts are coming together so I get this thing actually interfaced with my amiga.