Interfacing externally clocked data to an FPGA (Spartan 3)
CASTalk.com Forum Index CASTalk.com
Discussion of DSP, FPGA, storage and embedded system.
 
 FAQFAQ   MemberlistMemberlist     RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
Google
 
Web castalk.com
Interfacing externally clocked data to an FPGA (Spartan 3)

 
Post new topic   Reply to topic    CASTalk.com Forum Index -> FPGA
Author Message
Bart
Guest





Posted: Fri Dec 16, 2005 9:15 am    Post subject: Interfacing externally clocked data to an FPGA (Spartan 3) Reply with quote

Hi,

First time poster here. I'm using Xilinx's cheap Spartan 3 Starter Kit
Board to create a simple VGA "controller" (framebuffer output) that I
want to interface to 8051 and Z80 systems I've constructed myself
(breadboard projects.)

I'm having serious trouble implementing writes to the on-board SRAM
because there appears to be some sort of conflict with the display
refresh which causes data to occasionally be misplaced in the frame
buffer (several dozen pixels per frame.)

After a couple weeks (!!) of debugging and experimentation (too much
stuff to list in this first post), I believe I've narrowed the problem
down to one of the following issues:

1. Writes are supposed to pre-empt reads in my VHDL state machine.
Perhaps there is some sort of conflict. If there is, it is not obvious.
My state machine is pretty tight and unless the toolchain is
synthesizing glitchy logic, there should be no problem.

2. Data is input from the external CPU (Z80 or 8051) via a simple 5-bit
port: 3 bits of color data, an address pointer reset bit, and a clock
bit. The Z80 will write a 0 and then a 1 to the clock bit and on the
rising edge of this pin, the FPGA is to latch the data and initiate a
write. It appears that the transition from low-to-high may be
problematic for the FPGA or once a write is complete, the internal
signal is not deasserted quickly enough (but this really shouldn't
cause any problems -- it would just write over and over again to the
same spot.)

I've tried to sync the input pin clock to the FPGA's 50MHz clock (which
my state machines run off of) but no luck there.

3. My 2-cycle write sequence to SRAM might be wrong. But I doubt it
because I've verified it against working code and I've synthesized
simpler circuits which prove that RAM is being read and written
correctly.


I've tried a number of things including adding a pin to disable the
display (thus stopping all reads) which the Z80 can control. Even when
the display is off and I write to the FPGA, these bad pixels appear.
It's not physical noise, that's almost for sure. The pixels are always
colored the same as in the image -- in fact, they're often missing from
the image and moved somewhere else.


Here's some of the relevant VHDL (I hope the formatting is preserved,
I'm using Google Groups):

(Please note how I am clearing the sram_do_write signal -- I think this
may be part of the problem but there's no easy way to rectify it.)

process(input)
begin
if input(4)'event and input(4) = '1' then
if input(3) = '1' then -- reset address
write_addr <= "000000000000000000";
else
sram_data_write(2 downto 0) <= input(2 downto 0);
sram_write_addr <= write_addr;
write_addr <= write_addr + 1;
sram_do_write <= '1';
end if;
end if;

if sram_state = SRAM_WRITE then
sram_do_write <= '0';
end if;
end process;


--
-- SRAM State Machine
--
process(clk_50mhz, sram_do_write, sram_do_read, sram_write_addr,
sram_read_addr)
begin
sram_oe <= '0';

if clk_50mhz'event and clk_50mhz = '1' then
case sram_state is
when SRAM_WAITING =>
sram_read_done <= '0';
sram_write_done <= '0';
if sram_do_write = '1' then -- write requested
sram_addr <= sram_write_addr;
sram_ce <= '0';
sram_we <= '0';
sram_io_t <= '0';

sram_state <= SRAM_WRITE;
elsif sram_do_read = '1' and sram_do_write = '0' then -- read
requested
--
-- Address in sram_addr and data will be read to
-- sram_data_read.
--
sram_addr <= sram_read_addr;
sram_ce <= '0';
sram_we <= '1';
sram_io_t <= '1';

sram_state <= SRAM_READ;
else
sram_ce <= '1';
sram_io_t <= '1';
end if;
when SRAM_READ =>
sram_ce <= '1';
sram_we <= '1';
sram_io_t <= '0';

sram_data_read_buf <= sram_data_read;
sram_read_done <= '1'; -- finished reading
sram_state <= SRAM_WAITING;
when SRAM_WRITE =>
sram_ce <= '1';
sram_we <= '1';
sram_io_t <= '0';

sram_write_done <= '1';
sram_state <= SRAM_WAITING;
end case;
end if;
end process;


Any suggestions would be greatly appreciated!
Back to top
Antti Lukats
Guest





Posted: Fri Dec 16, 2005 9:15 am    Post subject: Re: Interfacing externally clocked data to an FPGA (Spartan Reply with quote

"Bart" <bart_trzynadlowski@yahoo.com> schrieb im Newsbeitrag
news:1134717308.862664.31090@o13g2000cwo.googlegroups.com...
Quote:
Hi,

First time poster here. I'm using Xilinx's cheap Spartan 3 Starter Kit
Board to create a simple VGA "controller" (framebuffer output) that I
want to interface to 8051 and Z80 systems I've constructed myself
(breadboard projects.)

[snip]


generic advice, if in such trouble as you are then it is usually VERY
helpful to "look" into the FPGA, so get the ChipScope eval, add the ILA to
some of the signals and look whats actually happening.

you can use one DCM to get say 150MHz and use that ILA clock so you would
see several samplings per each system clock sample

Antti
Back to top
johnp
Guest





Posted: Fri Dec 16, 2005 5:16 pm    Post subject: Re: Interfacing externally clocked data to an FPGA (Spartan Reply with quote

Bart -

Have you checked the quality of the input(4) signal? If it is slow or
has noise, glitches, etc the ram write address could get incremented
multiple times for each write operation.

Also, you mentioned trying to synchronize the sram_do_write signal
to the 50MHz clock - you must do that! Otherwise, you've got an async
signal feeding into your state machine - just a matter of time before
it screws up.

Hope this helps!

John Providenza
Back to top
Kolja Sulimma
Guest





Posted: Sat Dec 17, 2005 12:17 am    Post subject: Re: Interfacing externally clocked data to an FPGA (Spartan Reply with quote

I would suggest to try to get a simplified system to run at first.
Use internal SRAM as frame buffer. This will not be enough for full
screen, but that does not matter at first, considering the magnitude of
your difficultied.

The internal SRAM is dual ported so you can write with one state machine
and read with another, using different clocks. If you still see
problems, it is very likely that the quality of the input signal is the
problem.

If not, you have a problem with synchronization or SRAM access. Try to
think of a design change that can separate the two.

Kolja
Back to top
Bart
Guest





Posted: Sat Dec 17, 2005 1:15 am    Post subject: Re: Interfacing externally clocked data to an FPGA (Spartan Reply with quote

John and Kolja: The quality of the input signal is something I
suspected initially but I ruled out any major interference problems
early on. Here's my line of thinking:

- The bad pixels are always the same color as the image data. Corrupted
colors do not occur. If I create a white background with a blue box in
the center, there will be some white pixels scattered inside the box
and blue pixels scattered around outside.

- Each time the input is clocked (by the external Z80), the internal
write pointer is incremented. If there were any glitches on this line,
the image would be offset and for my test cases (boxes and such), it
would be very noticable.

What I initially wanted to do to fix the problem is write some code
like this:

if clk_50mhz'event and clk_50mhz = '1' then -- main clock
if input_clk_prev = '0' and input_clk = '1' then
-- input clock detected. sample the data
end if;
input_clk_prev <= input_clk;
end if;

It didn't work. Although it may have sort of helped solve the problem,
what was happening is that it was triggering much more often than it
should, causing the write pointer to increment incorrectly and thus
garbling up the image.

I did a test where I had an 8051 send a set number of clock pulses to
the FPGA and I displayed the number on the LEDs. It was always correct.
When I used the above code, it would be off by 1 every now and then.

johnp wrote:
Quote:
Also, you mentioned trying to synchronize the sram_do_write signal
to the 50MHz clock - you must do that! Otherwise, you've got an async
signal feeding into your state machine - just a matter of time before
it screws up.

This is probably the issue. Last night, I may have fixed it. What's
unusual is that I had tried similar code before to synchronize the
signal and it failed to make a difference.

I'll try to show you what I did. I don't have my code with me at the
moment so this is going off of memory. Any thoughts on whether this is
a sound method? Is it too much of a kludge?

process(input, clk_50mhz)
begin
if input(4)'event and input(4) = '1' then -- input(4) is input CLK
do_write <= NOT do_write;
end if;

if clk_50mhz'event and clk_50mhz = '1' then
if do_write_prev /= do_write then
sram_do_write <= '1';
end if;

if sram_state = SRAM_WRITE then
sram_do_write <= '0';
end if;

do_write_prev <= do_write;
end if;
end process;

The idea is that I monitor do_write and when it changes, I signal
sram_do_write in sync with the FPGA master clock.

Oddly enough, I tried code almost exactly like this earlier (both in
this process and in the SRAM state machine) and it never worked! I was
using a XOR to detect a change (if the XOR result was 1, a change
occured) -- would that make a difference? To me, it seems the two are
functionally equivalent.

Thanks for the input so far!
Back to top
johnp
Guest





Posted: Sat Dec 17, 2005 7:18 am    Post subject: Re: Interfacing externally clocked data to an FPGA (Spartan Reply with quote

Bart -

I suspect the problem is that you are supplying no setup/hold time
on the sram address bus. Also, no hold time on the data bus:
sram_addr <= sram_write_addr;
sram_ce <= '0';
sram_we <= '0';
sram_io_t <= '0';

Try using a 3 clock cycle sequence to write the rams:
a) assert the correct address
b) assert data, CE, and WE
c) remove CE and WE

If your ram is fast enough, you can shorten the to 2 clock cycles by
using
a negedge clock to assert/remove WE.

Good luck!

John Providenza
Back to top
Guest






Posted: Fri Dec 23, 2005 5:15 pm    Post subject: Re: Interfacing externally clocked data to an FPGA (Spartan Reply with quote

Hi,
Your problem is here:
if clk_50mhz'event and clk_50mhz = '1' then -- main clock
if input_clk_prev = '0' and input_clk = '1' then
-- input clock detected. sample the data
end if;
input_clk_prev <= input_clk;
end if;

They should change to the following code:
if clk_50mhz'event and clk_50mhz = '1' then -- main clock
if input_clk_prev_R = '0' and input_clk_R = '1' then
-- input clock detected. sample the data
end if;
input_clk_R <= input_clk;
input_clk_prev_R <= input_clk_R;
end if;

Never use any asynchronous input signal in your design directly.

All asynchronous input signals must be registered and their registered
data can be used in your design.

Weng




You must use 50MHz clock to latch them, then their latched registered
values should replace the above two data.

....
elsif(
Back to top
 
Post new topic   Reply to topic    CASTalk.com Forum Index -> FPGA All times are GMT
Page 1 of 1

 
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 vote in polls in this forum




VoIP Electronics Powered by phpBB