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]; }; 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. φLogicCounterImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last Edited by: Louis Monier January 8, 1987 1:45:05 pm PST Jean-Marc Frailong March 26, 1987 5:29:45 pm PST Barth, October 22, 1986 11:48:51 am PDT Counter - This type of counter is obsolete and should be rewritten/deleted CounterUp - Two flavors, ripple (slow) and lookahead (fast) Public: Cin, Cout, Load, Count, Input[b], Output[b], nOutput[b] Two types of CounterUp maye be generated: ripple and lookahead. Ripple is smaller, but much slower (refer to curves in documentation). Lookahead is faster, and should barely make it to 40MHz for 32 bits. It might be necessary in the future to add a new flavor, pipelined counters. Extract the cell with the "drive" context variable set to NEW [NAT _ drive]. Avoids perturbing the LogicUtils context for nothing... Ripple counter up generator. Bits are generated in pairs (slightly faster and smaller), and an odd bit is added as MSB if needed. 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. The construction is not recursive because orphan bits raise trouble in the recursive structure. Internal instances are named to help troubleshooting. This loop does all except for the last stage Handle last stage, always has 2 inputs. A special trick removes the carry input Lookahead counter up generator. A carry propagation tree is generated by CLP and assembled here. CounterUpName: ROPE = "CounterUp"; CounterUp: PUBLIC PROC [b: NAT, type: CounterType] RETURNS [ct: CellType] = { CounterType: TYPE ~ {ripple, lookahead, best}; ctCell: CellType _ LogicUtils.Extract["counterUp1B.sch", TRUE]; ctCtrl: CellType; insts: CellInstances; input, output, nOutput, carry, cout: Wire; 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"]; Sisyph.Store[LogicUtils.GetLogicContext[], "publicD", NEW[NAT_IF b<4 THEN 1 ELSE b/4]]; ctCtrl _ LogicUtils.Extract["counterUp1BCtrl.sch"]; insts _ LIST[Instance[ctCtrl]]; input _ Seq["Input", b]; output _ Seq["Output", b]; nOutput _ Seq["nOutput", b]; carry _ Seq["carry", b]; cout _ CoreOps.SetShortWireName[carry[0], "Cout"]; FOR i: NAT IN [0..b) DO insts _ CONS[ Instance[ctCell, ["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"]], insts]; ENDLOOP; ct _ Cell[ name: CounterUpName, public: Wires["Vdd", "Gnd", "CK", "Load", "Count", "Cin", cout, input, output, nOutput], onlyInternal: Wires["load", "count", "en", "nEn", carry ], instances: insts]; }; TestCounterUp: PROC [b: NAT] RETURNS [ct: CellType] = { ctCell: CellType _ LogicUtils.SCBlock[LogicUtils.Extract["counterUp1B.sch", TRUE]]; ctCtrl: CellType; insts: CellInstances; input, output, nOutput, carry, cout: Wire; 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"]; Sisyph.Store[LogicUtils.cx, "publicD", NEW[NAT_IF b<4 THEN 1 ELSE b/4]]; ctCtrl _ LogicUtils.Extract["counterUp1BCtrl.sch"]; insts _ LIST[Instance[ctCtrl]]; input _ Seq["Input", b]; output _ Seq["Output", b]; nOutput _ Seq["nOutput", b]; carry _ Seq["carry", b]; cout _ CoreOps.SetShortWireName[carry[0], "Cout"]; FOR i: NAT IN [0..b) DO insts _ CONS[ Instance[ctCell, ["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"]], insts]; ENDLOOP; ct _ Cell[ name: CounterUpName, public: Wires["Vdd", "Gnd", "CK", "Load", "Count", "Cin", cout, input, output, nOutput], onlyInternal: Wires["load", "count", "freeze", carry ], instances: insts]; }; Left-ShiftReg ShiftReg [] _ Counter[2]; [] _ ShiftReg[2]; Κ Ξ– "cedar" style˜codešœ™Kšœ Οmœ1™šœžœ˜ šœ˜Kšœ,˜,Kšœ/˜/Kšœ1˜1Kšœ žœ žœžœ˜6Kšœ˜KšœI˜I—Kšœ˜—Kšžœ˜—Kšžœžœ2˜?šžœ‘7˜>K˜(šœžœ˜ šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜KšœI˜I—Kšœ˜—Kšœ˜—šœ ˜ Kšœžœžœ ˜0KšœY˜YKšœ5˜5Kšœ˜—Kšœ˜—šŸœžœžœžœ˜0KšŸœM™SKšœπ™πšœ žœžœžœ ˜$Kšœ(‘ ˜HKšœ)‘ ˜I—Kšœ=‘˜OKšœžœ˜Kš œ žœžœžœžœ˜Kšœ‘˜0Kšœ‘˜3Kšœ žœžœ‘$˜;Kšœ˜Kšœ˜Kšœ#˜#š žœžœžœžœ‘-˜[K™,Kšœžœ‘˜5Kšœ‘˜4Kšœ3‘˜CKšœ žœžœ‘˜Mšžœžœžœ ž˜Kšœžœ‘˜*šžœžœ‘8˜Pšœžœ˜ šœ ˜ Kšœ˜KšœžœT˜]Kšœžœžœ žœ˜4—Kšœ˜—Kšœ˜—šžœ‘+˜2šœžœ˜ šœ ˜ Kšœ˜KšœžœŠ˜“Kšœžœžœ žœ˜4—Kšœ˜—Kšœ˜—Kšžœ˜—Kšœ žœ ‘!˜:Kšžœ˜—KšœO™Ošžœ žœ‘˜/šœžœ˜ šœ1˜1Kšœ˜Kšœ˜Kšœ˜Kšœ#˜#—Kšœ˜——šžœ‘˜#šœžœ˜ šœ1˜1Kšœ˜Kšœ˜Kšœ˜Kšœ#˜#—Kšœ˜——šœ ˜ Kšœžœžœ ˜$KšœC˜CKšœ"˜"Kšœ˜—Kšœ˜—šŸœžœžœžœ˜p