DIRECTORY CoreCreate, IO, Logic, LogicUtils, Ports, Rosemary; LogicCounterImpl: CEDAR PROGRAM IMPORTS CoreCreate, IO, LogicUtils, Ports EXPORTS Logic = BEGIN OPEN LogicUtils, CoreCreate; CounterState: TYPE ~ REF CounterStateRec; CounterStateRec: TYPE ~ RECORD [ cin, cout, load, input, output, noutput, ck: NAT _ LAST[NAT], -- all counters count: NAT _ LAST[NAT], -- up only bin, bout, up, down: NAT _ LAST[NAT], -- up/down only master, slave: Ports.LevelSequence ]; CounterCLG: PUBLIC PROC [n: NAT] RETURNS [ct: CellType] = { 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 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[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]; }; CounterUpRoseClass: ROPE = RoseClass["CounterUp", CounterUpInit, CounterUpSimple, TRUE]; CounterUp: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { fullName: ROPE = IO.PutFR["CounterUp b=%g", IO.int[b]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; IF b=0 THEN Error["Please provide the number of bits for the up counter"]; IF b=1 THEN Error["Sorry, but a counter must have more than one bit"]; ct _ Extract["CounterUp.sch", LIST[["nBits", b]]]; SimulateMacro[ct, CounterUpRoseClass]; Ports.InitPorts[ct, l, none, "CK", "Cin", "Load", "Count"]; Ports.InitPorts[ct, l, drive, "Cout"]; Ports.InitPorts[ct, ls, none, "Input"]; Ports.InitPorts[ct, ls, drive, "Output", "nOutput"]; CacheStore[fullName, ct]; }; CounterUpInit: Rosemary.InitProc ~ { state: CounterState _ IF oldStateAny=NIL THEN NEW[CounterStateRec] ELSE NARROW[oldStateAny]; b: NAT; [state.cin, state.cout, state.load, state.count, state.input, state.output, state.noutput, state.ck] _ Ports.PortIndexes[cellType.public, "Cin", "Cout", "Load", "Count", "Input", "Output", "nOutput", "CK"]; b _ p[state.input].ls.size; -- find out number of bits in counter state.master _ NEW[Ports.LevelSequenceRec[b]]; Ports.SetLS[state.master, X]; state.slave _ NEW[Ports.LevelSequenceRec[b]]; Ports.SetLS[state.slave, X]; Ports.SetLS[p[state.output].ls, X]; Ports.SetLS[p[state.noutput].ls, X]; p[state.cout].l _ X; stateAny _ state; }; CounterUpSimple: Rosemary.EvalProc ~ { state: CounterState _ NARROW [stateAny]; tmp: Ports.Level; -- working storage IF ~clockEval THEN SELECT p[state.ck].l FROM L => { -- copy X, input, slave or slave+1 to master count: Ports.Level = Ports.AndL[p[state.count].l, p[state.cin].l]; SELECT TRUE FROM p[state.load].l=X => Ports.SetLS[state.master, X]; -- unknown p[state.load].l=H => Ports.CopyLS[p[state.input].ls, state.master]; -- load count=X => Ports.SetLS[state.master, X]; -- unknown count=H => { -- need to count up by 1 tmp _ H; FOR i: NAT DECREASING IN [0..state.master.size) DO -- increment [tmp, state.master[i]] _ Ports.SumL[state.slave[i], L, tmp]; ENDLOOP; }; ENDCASE => Ports.CopyLS[state.slave, state.master]; -- loop back }; H => { -- copy master to slave Ports.CopyLS[state.master, state.slave]; }; ENDCASE => { -- clock is unknown, all becomes unknown Ports.SetLS[state.master, X]; Ports.SetLS[state.slave, X]; }; Ports.CopyLS[state.slave, p[state.output].ls]; Ports.NotLS[state.slave, p[state.noutput].ls]; tmp _ p[state.cin].l; -- compute cout FOR i: NAT IN [0..state.slave.size) DO tmp _ Ports.AndL[state.slave[i], tmp]; ENDLOOP; p[state.cout].l _ tmp; }; CounterUpDownRoseClass: ROPE = RoseClass["CounterUpDown", CounterUpDownInit, CounterUpDownSimple, TRUE]; CounterUpDown: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { fullName: ROPE = IO.PutFR["CounterUpDown b=%g", IO.int[b]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; IF b=0 THEN Error["Please provide the number of bits for the up counter"]; IF b=1 THEN Error["Sorry, but a counter must have more than one bit"]; ct _ Extract["CounterUpDown.sch", LIST[["nBits", b]]]; SimulateMacro[ct, CounterUpDownRoseClass]; Ports.InitPorts[ct, l, none, "CK", "Cin", "Bin", "Load", "Up", "Down"]; Ports.InitPorts[ct, l, drive, "Cout", "Bout"]; Ports.InitPorts[ct, ls, none, "Input"]; Ports.InitPorts[ct, ls, drive, "Output", "nOutput"]; CacheStore[fullName, ct]; }; CounterUpDownInit: Rosemary.InitProc ~ { state: CounterState _ IF oldStateAny=NIL THEN NEW[CounterStateRec] ELSE NARROW[oldStateAny]; b: NAT; [state.cin, state.cout, state.bin, state.bout, state.up, state.down, state.load, state.input, state.output, state.noutput, state.ck] _ Ports.PortIndexes[cellType.public, "Cin", "Cout", "Bin", "Bout", "Up", "Down", "Load", "Input", "Output", "nOutput", "CK"]; b _ p[state.input].ls.size; -- find out number of bits in counter state.master _ NEW[Ports.LevelSequenceRec[b]]; Ports.SetLS[state.master, X]; state.slave _ NEW[Ports.LevelSequenceRec[b]]; Ports.SetLS[state.slave, X]; Ports.SetLS[p[state.output].ls, X]; Ports.SetLS[p[state.noutput].ls, X]; p[state.cout].l _ X; p[state.bout].l _ X; stateAny _ state; }; CounterUpDownSimple: Rosemary.EvalProc ~ { state: CounterState _ NARROW [stateAny]; tmp: Ports.Level; -- working storage IF ~clockEval THEN SELECT p[state.ck].l FROM L => { -- copy X, input, slave or slave+1 or slave-1 to master up: Ports.Level = Ports.AndL[p[state.up].l, p[state.cin].l]; down: Ports.Level = Ports.AndL[p[state.down].l, p[state.bin].l]; SELECT TRUE FROM p[state.load].l=X => Ports.SetLS[state.master, X]; -- unknown p[state.load].l=H => Ports.CopyLS[p[state.input].ls, state.master]; -- load up=X OR down=X => Ports.SetLS[state.master, X]; -- unknown up=down => Ports.CopyLS[state.slave, state.master]; -- loop back up=H => { -- need to count up tmp _ H; FOR i: NAT DECREASING IN [0..state.master.size) DO -- increment [tmp, state.master[i]] _ Ports.SumL[state.slave[i], L, tmp]; ENDLOOP; }; down=H => { -- need to count down: x-1 = ~(~x+1); tmp _ H; FOR i: NAT DECREASING IN [0..state.master.size) DO -- increment [tmp, state.master[i]] _ Ports.SumL[Ports.NotL[state.slave[i]], L, tmp]; state.master[i] _ Ports.NotL[state.master[i]]; ENDLOOP; }; ENDCASE => ERROR; -- cannot happen }; H => { -- copy master to slave Ports.CopyLS[state.master, state.slave]; }; ENDCASE => { -- clock is unknown, all becomes unknown Ports.SetLS[state.master, X]; Ports.SetLS[state.slave, X]; }; Ports.CopyLS[state.slave, p[state.output].ls]; Ports.NotLS[state.slave, p[state.noutput].ls]; tmp _ p[state.cin].l; FOR i: NAT IN [0..state.slave.size) DO tmp _ Ports.AndL[state.slave[i], tmp]; ENDLOOP; p[state.cout].l _ tmp; tmp _ Ports.NotL[p[state.bin].l]; FOR i: NAT IN [0..state.slave.size) DO tmp _ Ports.OrL[state.slave[i], tmp]; ENDLOOP; p[state.bout].l _ Ports.NotL[tmp]; }; Counter: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { insts: CellInstances _ NIL; fullName: ROPE = IO.PutFR["ObsoleteCounter b=%g", IO.int[b]]; Obsolete["counter.icon is obsolete, use counterUp or counterUpDown"]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; IF b=0 THEN Error["Please provide the number of bits for the counter"]; IF b=1 THEN Error["Sorry, but a counter must have more than one bit"]; FOR i: NAT IN [0..b) DO insts _ CONS[ Instance[SCBlock[Extract["counter1B.sch"]], -- designed by Alfred ["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: "Counter", public: Wires["Vdd", "Gnd", "s0", "s1", "Cin", "Cout", "CK", Seq["Input", b], Seq["Output", b]], onlyInternal: Wires[Seq["carry", b-1]], instances: insts]; CacheStore[fullName, ct]; }; ShiftRegName: ROPE = "ShiftReg"; ShiftReg: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { insts: CellInstances _ NIL; fake: Wire _ Seq["fake", b]; fullName: ROPE = IO.PutFR["ObsoleteShiftReg b=%g", IO.int[b]]; Obsolete["shiftReg.icon is obsolete, use shReg instead"]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; IF b=0 THEN Error["Please provide the number of bits for the shift register"]; IF b=1 THEN Error["A shift register must have more than one bit"]; FOR i: NAT IN [0..b) DO insts _ CONS[ Instance[SCBlock[Extract["ff4.sch"]], ["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: "ShiftReg", public: Wires["Vdd", "Gnd", "s0", "s1", "CK", "inL", "inR", Seq["Input", b], Seq["Output", b]], onlyInternal: Wires[fake], instances: insts]; CacheStore[fullName, ct]; }; END. ~LogicCounterImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last Edited by: Louis Monier September 30, 1987 7:09:28 pm PDT Bertrand Serlet April 10, 1987 3:03:04 am PDT Jean-Marc Frailong October 21, 1987 5:14:08 pm PDT Barth, October 22, 1986 11:48:51 am PDT Counters Shared types cin, cout, load, count, input, output, noutput, ck: NAT _ LAST[NAT], -- port indices Lookahead carry/borrow evaluator (used through schematics only) 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. This loop does all except for the last stage Handle last stage, always has 2 inputs. A special trick removes the carry input Up counter Public => Cin, Cout, Load, Count, Input[b], Output[b], nOutput[b] Generate an up-only counter with carry lookahead logic -- Evaluate new internal (master/slave) state -- Pass internal state to the output port -- Compute Cout Up/Down counter Public => Cin, Cout, Bin, Bout, Load, Up, Down, Input[b], Output[b], nOutput[b] Generate an up-only counter with carry lookahead logic -- Evaluate new internal (master/slave) state -- Pass internal state to the output port -- Compute Cout -- Compute Bout Code for obsolete icons, should be removed ASAP Counter - Superseded by CounterUp & CounterUpDown ShiftReg - Superseded by ShReg (straight schematics) Κ >– "cedar" style˜codešœ™Kšœ Οmœ1™K™-K™2K™'K™—KšΟk œ žœ%˜=K˜•StartOfExpansion[]šΠblœžœž˜Kšžœ žœ˜)Kšžœ˜ Kšœžœžœ˜$—head™L™ Kšœžœžœ˜)šœžœžœ˜ Kšœ4žœžœžœΟc™TKšœ-žœžœžœ ˜MKšœžœžœžœ  ˜"Kšœžœžœžœ ˜5Kšœ"˜"Kšœ˜—šœ?™?š Οn œžœžœžœžœ˜;KšœU™UKšœΚ™ΚKšœ žœžœžœ  ˜KšœO™OK™6Kšœ žœžœžœ ˜;K˜Kšžœžœžœžœ˜Kšžœžœ?˜JKšžœžœ;˜FKšœ"žœ˜6Kšœ*˜*KšœG˜GKšœ.˜.Kšœ\˜\Kšœ˜Kšœ˜K˜—š‘œ˜(Kš œžœ žœžœžœžœžœ˜\Kšœžœ˜Kšœ‚˜‚Kšœ %˜AKšœžœ:˜LKšœžœ9˜JKšœ#˜#Kšœ$˜$Kšœ˜Kšœ˜Kšœ˜˜K˜——š‘œ˜*Kšœžœ ˜(Kšœ ˜$Kš -™-šžœ žœ˜šžœž˜šœ 7˜>Kšœ<˜Kšœ9˜9K˜Kšžœžœžœžœ˜KšžœžœC˜NKšžœžœ7˜Bšžœžœžœž˜šœžœ˜ šœ&˜&Kšœžœžœžœ˜5Kšœžœžœžœ˜7Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ+˜+—Kšœ˜—Kšžœ˜—šœ˜Kšœ`˜`Kšœ˜Kšœ˜—Kšœ˜Kšœ˜———K˜Kšžœ˜—…—*$<ΰ