Friday, May 6, 2011

Ashes to Ashes

There's nothing in the Stratix III datasheet about ring oscillators, but the clock tree (of the C2) is supposed to handle speeds up to 730 MHz.

Spent a little time reading a thread on the Altera forum about ring oscillators. The posters recommend using an LCELL primitive and the assignment editor to control placement. Routing variation is still an issue, but they say that if all cells are in the same logic array block, and the RO is driving a register in that block, then the routing should stay consistent.

So, what I'm thinking now is that a pseudo dual-edged FF could be implemented in the same block as the ring oscillator, and configured in a T flip-flop configuration, so that its output would have the same frequency as the ring oscillator. Then the output of this PDEFF register could be sent to the destination logic (such as the carry-save counter) to hopefully well isolate the placement/routing within the RO block from that of the destination logic.

Another idea: Merge the ring oscillator with the PDEDFF, by using a slightly delayed version of the TFF output as the TFF clock. The advantage here is that we make sure that the ring oscillator does not run any faster than the PDEDFF can handle.

OK, I drew that circuit and simplified it. Basically it is just two T flip-flops (rising-edge triggered and falling-edge triggered) with their outputs XOR'ed together, and the output of that XOR (delayed slightly by a buffer, say) is used is the clock of both flip-flops.

I'm going to try building that now, as a schematic. I found the Technology Map Viewer is helpful to see exactly how the design compiles into cells. Here's what I came up with, after realizing I needed LCELL on both the rising and falling edge triggered T flip-flops (originally I didn't have an LCELL after the NOT):


Unfortunately, the Technology Map viewer reveals that Quartus is reorganizing the logic in some unexpected way. To get more control, I am redoing the design in VHDL as follows:

library ieee;
use ieee.std_logic_1164.all;
use work.rtl_attributes.all; -- Borrowed from the IEEE 1076.6 (2004) spec. Needed for KEEP attribute.


entity pde_tff_ro2 is

port ( clk_out : out std_logic );

end entity pde_tff_ro2;

architecture impl of pde_tff_ro2 is

signal int_clk : std_logic; -- Internal clock signal.
signal int_clk_d1 : std_logic; -- Internal clock signal, delayed by 1 LUT propagation delay.

signal rq,fq : std_logic; -- Rising- and falling-edge TFF outputs.

-- Prevent certain key signals from being optimized away.

attribute KEEP of int_clk : signal is True;
attribute KEEP of int_clk_d1 : signal is True;
attribute KEEP of clk_out : signal is True;

begin

int_clk <= rq xor fq; -- Exclusive OR of rising & falling edge TFF outputs.
int_clk_d1 <= int_clk; -- Hoping this inserts an extra LCELL due to KEEP attribute.
clk_out <= int_clk; -- Output gets another copy of the internal clock.

-- Rising-edge-triggered toggle flip-flop.

re_tff: process is begin
wait until rising_edge(int_clk_d1);
rq <= not rq;
end process;

-- Falling-edge-triggered toggle flip-flop.

fe_tff: process is begin
wait until falling_edge(int_clk_d1);
fq <= not fq;
end process;

end architecture impl;

OK, that seems to give me the design I want:


This image is from the Technology Map Viewer. The double-boxed elements are LUTs and the registers are individual flip-flops in the LABs.

I need to look at the design in the Chip Planner as well, to make sure all the LUTs are being placed in the same LAB. They seem to be, except that post-fitting it looks like the internal clock is being routed through a CLKCTRL module...

This could be good or bad. It is good in that it reduces skew (uses low-skew interconnect resources), but bad in that it can increase delay to get down there and back. So it may reduce the RO frequency.

I should perhaps use an ALTCLKCTRL megafunction to do regional clock generation from the main output of this module... Anyway, let's worry about that later.

DERP, I just realized that without an external kick, this clock will never get started because it will never generate its own edges. So, I need to design a start-up circuit for it.

OK, I tried to fix that problem by just gating the int_clk with an AND gate controlled by a slider switch, but still no dice.

It occurs to me that, even with the kicker to get it started, this design is perhaps fatally delicate, in that if it ever settles down, it will never spontaneously start going again.

I tried various ways to fix the problem, but no dice. I think I'm going to back off from this whole register-based oscillator idea, and just revert to doing an ordinary ring oscillator.

Before I left, I did that, and it worked (with the PDEDFF-based carry-save counter); the half-cycle period is about 1.7 ns.

No comments:

Post a Comment