Process variable setup times and propogations

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View

    Reposting: Sorry for the earlier mess. The Xilinx newsgroup portal
apparently chewed my origional posting!

Greetings folks,

    I am having a strange time with some code I recently wrote to implement
a UART - the code seems to be working fine now, but a problem cropped up
that is baffling me. This design is being synthesized in Xilinx ISE 5.1
and implemented into a Spartan-II XD2S50 device. I'm on something of a
learning curve with things right now so please go easy on me! :D

............
    when 10 => -- Stop Bit
    BitPos := 11; -- next is holding pattern for breaks
    if(FIFOhead = 3) then
        FIFOhead := 0; -- wrap around
    else
        FIFOhead := FIFOhead + 1;
    end if;

    FIFO(FIFOhead)(8) <= RxD; -- stash the break bit
    FIFO(FIFOhead)(7 downto 0) <= RReg; -- stash the received data
............

    The two FIFO array assignment statements at the bottom are the
predominant problem.... The object is to assign the break bit to the 9th
bit of the array of 9-bit words (indexed by the process variable
'FIFOhead'), and then assign the databyte to the lower part. As written
and synthesized, the above writes ONLY the received byte and NOT the
break bit. If the statements are exchanged, the opposite happens. In
short, only the SECOND assignment appears to be executing properly. If a
'dummy' statement is inserted, so the code looks like:

............
    end if;
    FIFO(FIFOhead)(7 downto 0) <= RReg; -- DUMMY
    FIFO(FIFOhead)(8) <= RxD; -- stash the break bit
    FIFO(FIFOhead)(7 downto 0) <= RReg; -- stash the received data
............

    then both assignments work properly. There appears to be some amount of
latency inherent in updating the variable before it can be used as an
index, but why? And what is the proper way to detect or circumvent this
problem? This fix seems to work just fine, but I fear this problem may
explain similarly strange behavior in other sections of code.

    If this IS a latency problem, how should I go about detecting these
sort of things in my design to ensure all code is relatively
bulletproof? All of the VHDL texts I have here really only cover
language theory and simulation synthesis, not things like proper timing
and floorplanning of the design into a physical device. What's the best
way to work on filling in my learning gaps in this area? Thanks in
advance for any insight!

-- Matt


Re: Process variable setup times and propogations



Quoted text here. Click to load it


The change you show should not have made any difference.
Post the  complete process. Something else is going on.

Try changing  if(FIFOhead  = 3) to
               if(FIFOhead >= 3)


  -- Mike Treseler


Re: UART -- Process variable setup times and propogations

Quoted text here. Click to load it
process. Something else is going on.

    Thanks for the reply, Mike - here's the whole reciever UART process I'm
currently synth'ing... I started with a basic UART design from freecores.org and
wound up rewriting a bunch of it in order to process things like break
conditions and the like, as well as adding in the small FIFO to help with
handling data flow. As written below, the UART seems to function pretty much
normally when synthesized into the chip. However, beyond the problem I
origionally mentioned (the FIFOhead not seeming to update right away) this UART
also seems to have the quirk of occasionally letting two of the same received
byte slip thru when data is constantly streaming in.

    Unfortunatly this system contains two seperate clocks - one which is devided
down to run the UART at standard baud rates, and another which drives the main
chunk of the system which reads the recived bytes from the UART. It seems that
on occasion (and this is verifiable on a logic analyzer) the clocks seem to line
up such that status data is not read correctly, and the UART is somehow being
read twice in quick succession.

    Do I need to include a higher-level syncronization method to ensure the two
clocks don't cause issues when inevitably lining up such that one is reading
data controlled by the other, whilst the data is in the middle of a transition?

    I've played with a couple possible solutions, but nothing seems to work with
the double-reads. This seems like a nice simple recieving UART, but I'm stumped.
Any ideas?

Regards,
-- Matt

................
entity RxUnit is
   port (
      Clk    : in  Std_Logic;  -- system clock signal
      Reset  : in  Std_Logic;  -- Reset input
      Enable : in  Std_Logic;  -- Enable input
      ReadA  : in  Std_logic;  -- Async Read Received Byte
      RxD    : in  Std_Logic;  -- RS-232 data input
      RxAv   : out Std_Logic;  -- Byte available
      DataO  : out Std_Logic_Vector(7 downto 0); -- Byte received
    Break  : out Std_Logic;  -- Break Detected
    Debug  : out Std_Logic); -- debug
end entity;

architecture Behaviour of RxUnit is
   signal RReg    : Std_Logic_Vector(7 downto 0); -- receive register
   signal ReadS    : Std_Logic;    -- Synchronised load signal

   component synchroniser is
   port (
      C1 : in Std_Logic;     -- Asynchronous signal
      C :  in Std_Logic;     -- Clock
      O :  out Std_logic);-- Synchronised signal
   end component;

   -- the FIFO
   type FIFOarraytype is array (integer range 0 to 4) of std_logic_vector(8
downto 0);
   signal FIFO:FIFOarraytype;

begin

   -- Synchronise Read on Clk
   SyncLoad : Synchroniser port map (ReadA, Clk, ReadS);
   --Busy <= LoadS or TBufL;

   -- Rx Process
   RxProc : process(Clk,Reset,Enable,RxD,ReadS)
   variable BitPos : INTEGER range 0 to 11;   -- Position of the bit in the frame
   variable SampleCnt : INTEGER range 0 to 3; -- Count from 0 to 3 in each bit
   variable FIFOhead, FIFOtail : INTEGER range 0 to 4; -- FIFO head and tail

   begin
      if Reset = '0' then -- Reset
         --RRegL <= '0';
       --RRegLcache <= '0';
         BitPos := 0;
       FIFOhead := 0;
       FIFOtail := 0;
      elsif Rising_Edge(Clk) then
    
        DataO <= FIFO(FIFOtail)(7 downto 0); -- always output whatever is on the FIFO
tail
        Debug <= FIFO(FIFOtail)(0); -- a signal to the outside world for debugging on
logic analyzer
        Break <= FIFO(FIFOtail)(8);

        if (ReadS = '1' and FIFOhead /= FIFOtail) then -- advance FIFO on read edge
             if(FIFOtail = 3) then
                FIFOtail := 0;
            else
                FIFOtail := FIFOtail + 1;
            end if;
        else    
                Debug <= '0';
        end if;
    
    if(FIFOhead /= FIFOtail) then -- there is stuff in the FIFO
             RxAv <= '1';  -- Indicate there is data avaliable to be read
    else
            RxAv <= '0';
    end if;

         if Enable = '1' then
            case BitPos is
               when 0 => -- idle
                  if RxD = '0' then -- Start Bit
                     SampleCnt := 0;
                     BitPos := 1;
                  end if;
               when 10 => -- Stop Bit
                  BitPos := 11;    -- next is holding pattern for breaks
              if(FIFOhead = 3) then
                 FIFOhead := 0; -- wrap around
               else
                 FIFOhead := FIFOhead + 1;
              end if;
              FIFO(FIFOhead)(7 downto 0) <= RReg; -- DUMMY 'WAIT'
              FIFO(FIFOhead)(8) <= RxD; -- stash the break bit
              FIFO(FIFOhead)(7 downto 0) <= RReg; -- stash the recieved data

            when 11 => -- Holding pattern for break release (so only one break is
recieved)
                  if(RxD = '1') then
                  BitPos := 0;
              end if;
               when others =>
                  if SampleCnt = 1 then -- Sample RxD on 1
                     RReg(BitPos-2) <= RxD; -- Deserialisation
                  end if;
                  if SampleCnt = 3 then -- Increment BitPos on 3
                     BitPos := BitPos + 1;
                  end if;
            end case;
            if SampleCnt = 3 then
               SampleCnt := 0;
            else
               sampleCnt := SampleCnt + 1;
            end if;

         end if;
      end if;
   end process;
end Behaviour;
.............



Re: UART -- Process variable setup times and propogations
If, as you say, one of the clocks is derived from the other, then they
have a fixed delay or phase relationship, and you should not have a problem.
If, however, these two clocks are incoherent, you have a real tricky
problem on your hands, and ignoring that will just get you deeper and
deeper into trouble.
Keep the design synchronous. Double-synchronize to reduce metastability
problems. Flip-flops are almost free these days.

Peter Alfke, Xilinx
============
Matt wrote:
Quoted text here. Click to load it
process. Something else is going on.
Quoted text here. Click to load it
and
Quoted text here. Click to load it
devided
Quoted text here. Click to load it
line
Quoted text here. Click to load it
the two
Quoted text here. Click to load it
work with
Quoted text here. Click to load it
stumped.
Quoted text here. Click to load it
frame
Quoted text here. Click to load it
is on the FIFO tail
Quoted text here. Click to load it
for debugging on
Quoted text here. Click to load it
on read edge
Quoted text here. Click to load it
recieved data
Quoted text here. Click to load it
one break is
Quoted text here. Click to load it

Re: UART -- Process variable setup times and propogations



Quoted text here. Click to load it

Quirks like this smell like a synchronization problem.
Consider using the synchronous template for all synth code.

Quoted text here. Click to load it

You have identified and verified a synchronization problem.


Quoted text here. Click to load it

No. Use only only the faster clock as a clock.
Inputs including former clocks are all synched
with two dflops and become inputs that
never appear in a sensitivity list.

Quoted text here. Click to load it

Change to

  RxProc : process(Clk,Reset)

and watch the other inputs events synchronously.


  -- Mike Treseler



Re: Process variable setup times and propogations
On Wed, 02 Jul 2003 13:38:32 -0700, Mike Treseler

Quoted text here. Click to load it

I agree, something else may be going on.

Be aware that if :
a) this is all within a single process, and
b) Fifohead is a signal not a variable, the assignment of the new value
to Fifohead is postponed to the end of the process (or explicit Wait)
thus Fifohead will have the old value at the point of the assignments to
Fifio(Fifohead).  This MUST be the case to avoid race conditions within
clocked processes, as a little thought will show.

Quoted text here. Click to load it
Another potential problem can arise, where the fields within a
std_logic_vector are addressed by variables and must synthesise to an
assignment to the whole vector.
For that reason, an assignment to the whole vector is to be preferred.

Quoted text here. Click to load it

However, since you use numeric constants 8, 7 downto 0 here, I don't
THINK this is the problem, unless it is a tools bug.

- Brian

Site Timeline