From: aleksa on
I have two CPUs (master and slave) and a Spartan II FPGA.

CPUs communicate using FPGA.

Inside the FPGA there is a READY flag which:
- master can reset to '0';
- slave can set to '1' or to the state of another flag;
- also, hardware RESET can reset it to '0', but that never happens;

So, READY should be implemented as a FDRSE.

At the time of first writing of VHDL code, I didn't think
*how* ISE will implement the READY flag, and I wrote this:

if rising_edge(CLK) then
if WR3/=WR2 or RESET='1' then READY <= '0'; -- master/reset
elsif ACTION='1' then -- slave
if ACTIONCODE="00" then READY <= '1';
elsif ACTIONCODE="01" then READY <= ACTIONBIT;
end if;
end if;
end if;

ISE implemented a FDRE and routed Q output
back to D input (not directly, of course).

In real world that didn't work.
I wrote a test prog that has failed after several seconds.
READY was set to '1' when it should have stayed '0'.

Later, I re-wrote it to look more like the FDRSE template:

READY_RES <= '1' when (WR3/=WR2 or RESET='1') else '0';
READY_SET <= '1' when (ACTION='1' and ACTIONCODE="00") else '0';
READY_CE <= '1' when (ACTION='1' and ACTIONCODE="01") else '0';

if rising_edge(CLK) then
if READY_RES='1' then READY <= '0';
elsif READY_SET='1' then READY <= '1';
elsif READY_CE='1' then READY <= ACTIONBIT;
end if;
end if;

And that worked. ISE has implemented a FDRSE and
that test prog never failed.

All signals are synchro to CLK, and the design is constrained.

Why did the first example fail?

BTW, just to be safe, I've later instantiated the FDRSE.


Master has its own clock and to cross clock domains, I do this:

if rising_edge(MASTERCLK) then
WR0 <= not WR0;
end if;

if rising_edge(CLK) then
WR3 <= WR2; WR2 <= WR1; WR1 <= WR0; -- right to left
end if;

CLK is 40 MHz.


From: Andy on
How are you synchronizing action, actioncode and actionbit?

Andy
From: aleksa on
Slave CPU ('C51) is connected to FPGA with 3 pins:
SCLK, SCODE1 and SCODE0.

SCLK and SCODE1 are inputs to FPGA.
SCODE0 is bi-dir.

C51 can:
- send data to FPGA (SHIFTIN);
- recv data from FPGA (SHIFTOUT);
- make FPGA execute something (EXECUTE).

C51 first places code in SCODE1-0 then clocks with SCLK:
0x SHIFTIN
10 EXECUTE
11 SHIFTOUT

SCLK and SCODE1 are synchronized to CLK:
if rising_edge(CLK) then
SCLK3 <= SCLK2; SCLK2 <= SCLK1; SCLK1 <= SCLK;
SCODE1C <= SCODE1B; SCODE1B <= SCODE1A; SCODE1A <= SCODE1;
end if;

Since SCODE0 is bi-dir, I track changes of SCODE1:
if rising_edge(CLK) then
if SCODE1C/=SCODE1B then -- change?
SCODE <= SCODE1 & SCODE0; -- register SCODE1-0
end if;
end if;

SCODE0 <= SHIFTOUT(7) when SCODE="11" else 'Z';

FPGA acts on rising edge of (sampled) C51 clock:
-- rising slave CLK
RSCLK <= '1' when (SCLK3='0' and SCLK2='1') else '0';

> How are you synchronizing action, actioncode and actionbit?

C51 places '0' on SCODE1 and that makes SCODE0 input.
Then it sends data on SCODE0 to FPGA, with SCLK as clock:
if rising_edge(CLK) then
if RSCLK='1' and SCODE="0-" then SHIFTIN <= SCODE0 & SHIFTIN(12 downto 1); end if;
end if;

The data C51 has transmitted is now in SHIFTIN register:
Action, actioncode and actionbit are bitfields (aliases) of SHIFTIN.

Next, C51 puts "10" on SCODE1-0 (EXECUTE) and clocks with SCLK:
-- from my first post, changed a bit:
if rising_edge(CLK) then
if WR3/=WR2 or RESET='1' then READY <= '0'; -- master/reset
elsif RSCLK='1' and SCODE="10" and SHIFTIN(12)='0' then -- slave, execute action
if SHIFTIN(11 downto 10)="00" then READY <= '1';
elsif SHIFTIN(11 downto 10)="01" then READY <= SHIFTIN(9);
end if;
end if;
end if;


From: aleksa on
I just found out that even the FDRSE
version doesn't work on the long run.

That test prog works for about
10sec with FDRE, or
20min with FDRSE, than fails.


From: KJ on
On Dec 2, 6:06 pm, "aleksa" <aleks...(a)gmail.com> wrote:
> I just found out that even the FDRSE
> version doesn't work on the long run.
>
> That test prog works for about
> 10sec with FDRE, or
> 20min with FDRSE, than fails.

What Andy was alluding to is that you have a timing problem. Less
likely causes (but not totally improbable) of intermittent operation
are:
- power supply issues
- Flaky parts
- Non rad-hard parts operating near rad
....etc...

Your most likely candidate though is a timing problem, so assume you
have one...if it helps, pretend some slug wrote the code and you're
the hired gun coming in to save the day. Some of your comments are
contradictory (only one clock, but there are multiple things being
clocked, there are multiple clocks) and without seeing the design will
be tough to diagnose out here so here are the things to check out.

1. Verify that the timing report for Fmax is greater than the actual
clock frequency.
2. Verify that the setup time requirement listed in the timing report
for each input is actually being met in the real system.
3. Have the timing analyzer analyze all clock domain crossings or look
at the final implementation for clock domain crossings...if you've
gotten to this step, then this is likely your problem so turn a very
critical eye to everything. Some questions to ponder (can also be
pondered by looking at the source code)

- If multiple bits get moved from one domain to another (maybe the two
bits of 'ACTIONCODE' as an example) what one *other* signal is there
that tells you that it is OK to sample these signals and that they are
guaranteed valid? ALL clock domain crossings must consist of a single
'command/valid' signal and then the data payload that is being
transferred. Either that or it must go through a dual clock fifo.

- Does every clock domain crossing meet that requirement?

- Did you verify that the requirement is met by viewing the final
implementation?

Kevin Jennings