??? 04/18/07 00:37 Read: times Msg Score: +2 +2 Good Answer/Helpful |
#137391 - latches in FPGAs Responding to: ???'s previous message |
How would you instantiate a latch that works, in the general case, as an address latch for use with 805x's? It turns out that all of the currently-available Xilinx devices, both FPGA and CPLD, support transparent latches. By this I mean that the storage element in the macrocell/slice is automagically configured as a D flip-flop or a transparent latch depending on how you write your code. The usual code correctly infers a transparent latch: latch : process (le, d) is begin if (le = '1') then q <= d; end if; end process latch;I confirmed this using both the FPGA editor and looking at the synthesis schematics (both RTL and technology). It gets even better. I tried all sorts of things to see if I could get the tools to build a latch out of gates, with zero success. For everything I could think of, XST inferred a transparent latch and used the slice primitive. First thing I did was put le as a chip input and the tools correctly inferred a BUFG which feed the slice storage element's CK input; the D input properly drove the latch's D input. Next, I tried gating the clock input with a comparator: complatch : process (le, addr, d) is begin if (le = '1') and (addr = X"8000") then q <= d; end if; end process complatch;and the tools correctly identified le as the global clock signal. The (addr = X"8000") was correctly identified and used as the latch's clock enable. Finally, I tried gating the latch enable with some other register: ile <= '1' when (le = '1') and (somereg = '1') else '0'; gatedlatch : process (ile, addr, d) is begin if (ile = '1') and (addr = X"8000") then q <= d; end if; end process gatedlatch;and this time XST told me that it couldn't determine which of the signals driving ile was the real clock signal and told me to put the CLOCK_SIGNAL attribute on the proper signal. But it still created ile properly (ANDing the two results) and fed that into a primitive latch's CK input, and again (addr = X"8000") was used as the latch clock enable. Note, though, that the gated clock was put onto regular routing resources and as such could exhibit large skew if fed to more than one slice. Placing the CLOCK_SIGNAL attribute on the le signal made the "don't know which is the clock" complaints go away; however, ile was put onto a global low-skew line. Also, the mapper threw up a physical design rule warning about Gated Clocks, since indeed that's still the case. So one of the reasons for the recommendation that one avoid describing latches for FPGAs -- that the synthesis tool will build the latch out of combinatorial logic -- is clearly just wrong, at least with Xilinx parts (I suspect the same results for Altera and Lattice, but users of those devices should verify). The other reason for the no-latch rule is that static timing analysis is problematic with a transparent latch. Of course there are setup time issues around the dropping edge of the latch enable (when the latch goes from transparent to latched). You also have the problem of analyzing the time from the latch output to a destination register. What's the delay? There's the case when the latch is transparent and when the latch is not, so what's the starting point? What happens when the enable is asynchronous to the destination register's clock? And so forth. The point is that static timing analysisis very simple for synchronous registered designs. What's the clock period? what's the delay from register A to register B? does the delay exceed the clock period? Yes, you lose; no, you win. Repeat for all registers in the design. However, it is not at all simple when you throw transparent latches into the mix, so it's up to the engineer to do the due diligence to ensure that the design will work. So, to interface an 8051 to an FPGA, do it in the usual way: describe a transparent latch using ALE to grab the low-order address bits off of P0 in the usual way. Then use the rising edge of WR\ as the register clock and store data from P0 when the address decodes. And ruefully note the latch warning from the synthesis tool. addrlatch : process (ale, p0) is begin latch : if (ale = '1') then addrlo = p0; end if latch; end process addrlatch; regwrite : process (wr_l) is begin if rising_edge(wr_l) then isRegA : if ((p2 & addrlo) = X"8000") then regA <= p0; end if isRegA; isRegB : if ((p2 & addrlo) = X"A000") then regB <= p0; end if isRegB; end if; // rising_edge end process regwrite; regread : process (p2, addrlo, rd_l, regA, regB) is begin if (rd_l = '0') then decode : case (p2 & addrlo) is when X"8000" => ip0 <= regA; when X"A000" => ip0 <= regB; when others => ip0 <= X"00"; end case decode; end if; // rd_l = '0' end process regread; p0 <= ip0 when rd_l = '0' else (others => 'Z'); Hope this is useful ... -a |