DecoderBody:
PROC [a, s:
NAT]
RETURNS [ct: CellType] ~ {
nor: CellType ← Logic.Nor[a+1]; -- one more input for nEn
norInput, nAd, nnAd, select: Wire;
insts: CellInstances ← NIL;
norInput ← FindWire[nor.public, "I"];
nAd ← Seq["nAd", a];
nnAd ← Seq["nnAd", a];
select ← Seq["Select", s];
-- one (a+1)-input nor per output
FOR i:
NAT
IN [0..s)
DO
pas: LIST OF PA ← LIST[["X", select[i]], [norInput[a], "nEn"]];
-- recognize the input "i"
FOR in:
NAT
IN [0..a)
DO
pas ← CONS[[norInput[in], IF BitOps.EBFW[i, in, a] THEN nAd[in] ELSE nnAd[in]], pas];
ENDLOOP;
insts ← CONS[InstanceList[nor, pas], insts];
ENDLOOP;
ct ← Cell[name: "DecoderBody",
public: Wires["Vdd", "Gnd", nAd, nnAd, select, "nEn"],
instances: insts];
};
Decoder:
PUBLIC
PROC [a:
NAT, s:
NAT ← 0]
RETURNS [ct: CellType] = {
address, nAd, nnAd, select: Wire;
insts: CellInstances ← NIL;
fullName: ROPE;
IF a=0 THEN Error["Please provide parameter(s) for decoder with enable"];
IF s>BitOps.TwoToThe[a] THEN Error["s too large in decoder"];
IF s=0 THEN s ← BitOps.TwoToThe[a];
fullName ← IO.PutFR["Decoder a=%g s=%g", IO.int[a], IO.int[s]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
address ← Seq["Address", a];
nAd ← Seq["nAd", a];
nnAd ← Seq["nnAd", a];
select ← Seq["Select", s];
insts ← CONS[Instance[DecoderBuffer[a], ["I", address], ["nX", nAd], ["X", nnAd] ], insts];
insts ← CONS[Instance[Logic.InvDriver[s], ["I", "Enable"], ["X", "nEn"] ], insts];
insts ← CONS[Instance[DecoderBody[a, s], ["Select", select], ["nAd", nAd], ["nnAd", nnAd], ["nEn", "nEn"] ], insts];
ct ← Cell[name: "Decoder",
public: Wires["Vdd", "Gnd", address, select, "Enable"],
onlyInternal: Wires[nAd, nnAd, "nEn"],
instances: insts];
SimulateMacro[ct, DecoderRoseClass];
Ports.InitPorts[ct, l, none, "Enable"];
Ports.InitPorts[ct, ls, none, "Address"]; Ports.InitPorts[ct, ls, drive, "Select"];
CacheStore[fullName, ct];
};