<> <> <> <> <> <<>> DIRECTORY CoreCreate, CoreOps, IO, Logic, LogicUtils, Static, Sisyph; LogicCounterImpl: CEDAR PROGRAM IMPORTS CoreCreate, CoreOps, IO, Logic, LogicUtils, Static, Sisyph EXPORTS Logic = BEGIN OPEN Logic, CoreCreate; <> CounterName: ROPE = "Counter"; Counter: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { counter1B: CellType _ LogicUtils.Extract["counter1B.sch", TRUE]; -- designed by Alfred insts: CellInstances _ NIL; IF b=0 THEN LogicUtils.Error["Please provide the number of bits for the counter"]; IF b=1 THEN LogicUtils.Error["Sorry, but a counter must have more than one bit"]; FOR i: NAT IN [0..b) DO insts _ CONS[ Instance[counter1B, ["dataIn", Index["Input", i]], ["Output", Index["Output", i]], ["carryIn", IF i=b-1 THEN "Cin" ELSE Index["carry", i]], ["carryOut", IF i=0 THEN "Cout" ELSE Index["carry", i-1]], ["nCount", "s1"], ["LoadOrDown", "s0"]], insts]; ENDLOOP; ct _ Cell[ name: CounterName, public: Wires["Vdd", "Gnd", "s0", "s1", "Cin", "Cout", "CK", Seq["Input", b], Seq["Output", b]], onlyInternal: Wires[Seq["carry", b-1]], instances: insts]; }; <> CounterUp: PUBLIC PROC [b: NAT, type: CounterType] RETURNS [ct: CellType] = { <> <> BufferCell: PROC [name: ROPE, drive: NAT] RETURNS [ct: CellType] ~ { <> cx: Sisyph.Context _ Sisyph.Copy[LogicUtils.GetLogicContext[]]; Sisyph.Store[cx, "drive", NEW[NAT _ drive]]; ct _ Sisyph.ES[name, cx]; }; RippleCounterUp: PROC [b: NAT] RETURNS [ct: CellType] = { <> ctCell2: CellType = LogicUtils.Extract["counterUp2B.sch", TRUE]; -- for each pair of bits ctCell1: CellType = LogicUtils.Extract["counterUp1B.sch", TRUE]; -- termination for odd b insts: CellInstances; input, output, nOutput, carry, cout: Wire; pairs: NAT = b/2; -- number of full bit pairs odd: NAT = b-2*pairs; -- 1 if b is odd, 0 if b is even input _ Seq["Input", b]; output _ Seq["Output", b]; nOutput _ Seq["nOutput", b]; carry _ Seq["carry", b/2]; insts _ LIST [Instance[BufferCell["counterUpCtrl.sch", (b+3)/4]]]; -- driver cell FOR i: NAT IN [0..pairs) DO -- setup the cell pairs bit: NAT _ 2*i+odd; -- index of high-order bit of current pair insts _ CONS[ Instance[ctCell2, ["QL", output[bit+1]], ["QH", output[bit]], ["nQL", nOutput[bit+1]], ["nQH", nOutput[bit]], ["inputL", input[bit+1]], ["inputH", input[bit]], ["carryIn", IF i=pairs-1 THEN "Cin" ELSE carry[i+1]], ["carryOut", carry[i]], ["load", "load"], ["count", "count"], ["nLoad", "nLoad"], ["CK", "CK"]], insts]; ENDLOOP; IF odd=0 THEN cout _ CoreOps.SetShortWireName[carry[0], "Cout"] ELSE { -- need to add special 1-bit cell as MSB of the counter cout _ CoreOps.CreateWire[name: "Cout"]; insts _ CONS[ Instance[ctCell1, ["Q", output[0]], ["nQ", nOutput[0]], ["input", input[0]], ["carryIn", carry[0]], ["carryOut", cout], ["load", "load"], ["count", "count"], ["nLoad", "nLoad"], ["CK", "CK"]], insts]; }; ct _ Cell[ name: IO.PutFR["RippleCounterUp%g", IO.int[b]], public: Wires["Vdd", "Gnd", "CK", "Load", "Count", "Cin", cout, input, output, nOutput], onlyInternal: Wires[carry, "load", "nLoad", "count"], instances: insts]; }; ClpBy2: PROC [n: NAT] RETURNS [ct: CellType] = { <> <> clpCell2: ARRAY BOOL OF CellType _ [ LogicUtils.Extract["counterCLP2N.sch"], -- stages with negative PIn, CIn LogicUtils.Extract["counterCLP2P.sch"]]; -- stages with positive PIn, CIn clpCell1: CellType _ LogicUtils.Extract["counterCLPX1.sch"]; -- 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 _ TRUE; -- polarity of PIn for current stage 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 <> 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; <> IF polarity THEN -- last stage: positive inputs insts _ CONS[ Instance[LogicUtils.Extract["counterCLP2PL.sch"], ["Force", "Vdd"], ["PIn", pOut], ["COut", cIn], ["CIn", "CIn"], ["COutX", "COut"]], insts] ELSE -- last stage: negative inputs insts _ CONS[ Instance[LogicUtils.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]; }; LookaheadCounterUp: PROC [b: NAT] RETURNS [ct: CellType] ~ { <> ctBit: CellType = LogicUtils.Extract["counterUp1B2.sch", TRUE]; -- basic counter bit, inverted Cin insts: CellInstances; input, output, nOutput, ncarry: Wire; input _ Seq["Input", b]; output _ Seq["Output", b]; nOutput _ Seq["nOutput", b]; ncarry _ Seq["ncarry", b]; insts _ LIST [Instance[BufferCell["counterUpCtrl2.sch", (b+3)/4]]]; -- driver cell FOR i: NAT IN [0..b) DO -- collect elementary bits insts _ CONS[ Instance[ctBit, ["Q", output[i]], ["nQ", nOutput[i]], ["input", input[i]], ["ncin", ncarry[i]], ["load", "load"], ["ncount", "ncount"], ["nLoad", "nLoad"], ["CK", "CK"]], insts]; ENDLOOP; insts _ CONS[ -- add the carry lookahead logic Instance[ClpBy2[b], ["PIn", output], ["nCOut", ncarry], ["COut", "Cout"], ["CIn", "Cin"]], insts]; ct _ Cell[ name: IO.PutFR["FastCounterUp%g", IO.int[b]], public: Wires["Vdd", "Gnd", "CK", "Load", "Count", "Cin", "Cout", input, output, nOutput], onlyInternal: Wires[ncarry, "load", "nLoad", "ncount"], instances: insts]; }; IF b=0 THEN LogicUtils.Error["Please provide the number of bits for the up counter"]; IF b=1 THEN LogicUtils.Error["Sorry, but a counter must have more than one bit"]; ct _ IF type=ripple THEN RippleCounterUp[b] ELSE LookaheadCounterUp[b]; }; <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<["Q", output[i]], >> <<["nQ", nOutput[i]], >> <<["input", input[i]], >> <<["carryIn", IF i=b-1 THEN "Cin" ELSE carry[i+1]], >> <<["carryOut", carry[i]], >> <<["load", "load"], ["count", "count"], ["en", "en"], ["nEn", "nEn"], ["CK", "CK"]], >> <> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<["Q", output[i]], >> <<["nQ", nOutput[i]], >> <<["input", input[i]], >> <<["carryIn", IF i=b-1 THEN "Cin" ELSE carry[i+1]], >> <<["carryOut", carry[i]], >> <<["load", "load"], ["count", "count"], ["freeze", "freeze"], ["CK", "CK"]], >> <> <> <> <> <> <> <> <<};>> <> ShRegName: ROPE = "ShReg"; ShRegLeft: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { shCell: CellType _ LogicUtils.Extract["shReg1B.sch", TRUE]; shCtrl: CellType; insts: CellInstances; output, outMSB: Wire; IF b=0 THEN LogicUtils.Error["Please provide the number of bits for the shift register"]; IF b=1 THEN LogicUtils.Error["A shift register must have more than one bit"]; Sisyph.Store[LogicUtils.GetLogicContext[], "publicD", NEW[NAT_IF b<4 THEN 1 ELSE b/4]]; shCtrl _ LogicUtils.Extract["shRegCtrl.sch"]; insts _ LIST[Instance[shCtrl]]; output _ Seq["Output", b]; outMSB _ CoreOps.SetShortWireName[output[0], "outMSB"]; FOR i: NAT IN [0..b) DO insts _ CONS[ Instance[shCell, ["Q", output[i]], ["prev", IF i=b-1 THEN "inLSB" ELSE output[i+1]], ["nQ", Index["nOutput", i]], ["input", Index["Input", i]], ["load", "load"], ["shift", "shift"], ["en", "en"], ["nEn", "nEn"], ["CK", "CK"]], insts]; ENDLOOP; ct _ Cell[ name: ShiftRegName, public: Wires["Vdd", "Gnd", "CK", "Load", "Shift", "inLSB", outMSB, Seq["Input", b], output, Seq["nOutput", b]], onlyInternal: Wires["load", "shift", "en", "nEn"], instances: insts]; }; <> ShiftRegName: ROPE = "ShiftReg"; ShiftReg: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ff: CellType _ FF4[]; insts: CellInstances _ NIL; fake: Wire _ Static.UnconnectedOK[Seq["fake", b]]; IF b=0 THEN LogicUtils.Error["Please provide the number of bits for the shift register"]; IF b=1 THEN LogicUtils.Error["A shift register must have more than one bit"]; FOR i: NAT IN [0..b) DO insts _ CONS[ Instance[ff, ["D0", IF i=0 THEN "inR" ELSE Index["Output", i-1]], ["D1", IF i=b-1 THEN "inL" ELSE Index["Output", i+1]], ["D2", Index["Output", i]], ["D3", Index["Input", i]], ["Q", Index["Output", i]], ["NQ", Index[fake, i]], ["s0", "s0"], ["s1", "s0"], ["s2", "s1"]], insts]; ENDLOOP; ct _ Cell[ name: ShiftRegName, public: Wires["Vdd", "Gnd", "s0", "s1", "CK", "inL", "inR", Seq["Input", b], Seq["Output", b]], onlyInternal: Wires[fake], instances: insts]; }; END. <<>> <<[] _ Counter[2];>> <<[] _ ShiftReg[2];>>