CounterCLG:
PUBLIC
PROC [n:
NAT]
RETURNS [ct: CellType] = {
Public => PIn[n], nCOut[n], CIn, COut (of the counter. CIn must also enable counting)
Carry lookahead propagation for a counter. Merges by steps of 2 and inverts at each stage. CIn is used only to enable COut: the partial carries are computed independently from Cin. The construction is not recursive because orphan bits raise trouble in the recursive structure. Internal instances are named to help troubleshooting.
clpCell2: ARRAY BOOL OF CellType; -- indexed by PIn polarity
clpCell1: CellType; -- for orphan bits
insts: CellInstances ← NIL;
internals: LIST OF WR ← NIL;
publicPIn, publicCOut: Wire; -- the public wires
pIn, cOut, pOut, cIn: Wire; -- wires between stages
polarity: BOOL; -- polarity of PIn for current stage (TRUE means positive)
fullName: ROPE = IO.PutFR["CounterCLG n=%g", IO.int[n]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
polarity ← TRUE; -- top-level PIn is in positive logic
clpCell1 ← Extract["counterCLPX1.sch"]; -- for orphan bits
clpCell2[FALSE] ← Extract["counterCLP2N.sch"]; -- stages with negative PIn, CIn
clpCell2[TRUE] ← Extract["counterCLP2P.sch"]; -- stages with positive PIn, CIn
publicPIn ← Seq["PIn", n];
publicCOut ← Seq["nCOut", n];
pOut ← publicPIn; cIn ← publicCOut;
FOR size:
NAT ← n, (size+1)/2
WHILE size>2
DO
-- for each stage, size = nbr of stage inputs
This loop does all except for the last stage
blocks: NAT = (size+1)/2; -- CLP cells for this stage
pIn ← pOut; cOut ← cIn; -- transfer from lower stage
pOut ← Seq[size: blocks]; cIn ← Seq[size: blocks]; -- to next stage
internals ← CONS [pOut, CONS [cIn, internals]]; -- add "outputs" to internals
FOR i:
NAT
IN [0..blocks)
DO
source: NAT = 2*i; -- index into pIn, cOut
IF source=size-1
THEN {
-- special case, 1 single bit, always LSB, may be orphan
insts ←
CONS[
InstanceList[
type: clpCell1,
pas: LIST [["PIn", pIn[source]], ["COut", cOut[source]], ["POut", pOut[i]], ["CIn", cIn[i]]],
name: IO.PutFR["%g/%g", IO.int[i], IO.int[blocks]]],
insts];
}
ELSE {
-- 2 input CLP, may be negative or positive
insts ←
CONS[
InstanceList[
type: clpCell2[polarity],
pas: LIST [["PIn0", pIn[source]], ["PIn1", pIn[source+1]], ["COut0", cOut[source]], ["COut1", cOut[source+1]], ["POut", pOut[i]], ["CIn", cIn[i]]],
name: IO.PutFR["%g/%g", IO.int[i], IO.int[blocks]]],
insts];
};
ENDLOOP;
polarity ← NOT polarity; -- invert polarity for next stage
ENDLOOP;
Handle last stage, always has 2 inputs. A special trick removes the carry input
IF polarity
THEN
-- last stage: positive inputs
insts ←
CONS[
Instance[Extract["counterCLP2PL.sch"],
["Force", "Vdd"],
["PIn", pOut],
["COut", cIn],
["CIn", "CIn"], ["COutX", "COut"]],
insts]
ELSE
-- last stage: negative inputs
insts ←
CONS[
Instance[Extract["counterCLP2NL.sch"],
["Force", "Gnd"],
["PIn", pOut],
["COut", cIn],
["CIn", "CIn"], ["COutX", "COut"]],
insts];
ct ← Cell[
name: IO.PutFR["CLP%g", IO.int[n]],
public: Wires["Vdd", "Gnd", publicPIn, publicCOut, "COut", "CIn"],
onlyInternal: WireList[internals],
instances: insts];
CacheStore[fullName, ct];
};