<> <> <<>> DIRECTORY Core, CoreClasses, CoreOps, LogicUtils, Ports, Rope, Rosemary; XilinxPrimitives: CEDAR PROGRAM IMPORTS CoreClasses, CoreOps, LogicUtils, Ports = BEGIN OPEN LogicUtils; XilinxFlipFlopRoseClass: Rope.ROPE = RoseClass["XilinxFlipFlop", XilinxFFInit, XilinxFFSimple, TRUE]; XilinxFlipFlop: PUBLIC PROC RETURNS [ct: Core.CellType] = { name: Rope.ROPE = "DFF"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ CoreClasses.CreateUnspecified[CoreOps.CreateWire[LIST[ CoreOps.CreateWire[name: "D"], CoreOps.CreateWire[name: "Q"], CoreOps.CreateWire[name: "CK"], CoreOps.CreateWire[name: "ar"], CoreOps.CreateWire[name: "ap"]]], name]; SimulateGate[ct, XilinxFlipFlopRoseClass]; Ports.InitPorts[ct, l, none, "D", "CK", "ar", "ap"]; Ports.InitPorts[ct, l, drive, "Q"]; CacheStore[name, ct]; }; XilinxFFRef: TYPE = REF XilinxFFRec; XilinxFFRec: TYPE = RECORD [ ffD, ffQ, ffClock, ffR, ffP: NAT _ LAST[NAT], master, slave: Ports.Level]; XilinxFFInit: Rosemary.InitProc = { state: XilinxFFRef _ IF oldStateAny=NIL THEN NEW[XilinxFFRec] ELSE NARROW[oldStateAny]; state.master _ state.slave _ L; [state.ffD, state.ffQ, state.ffClock, state.ffR, state.ffP] _ Ports.PortIndexes[cellType.public, "D", "Q", "CK", "ar", "ap"]; p[state.ffQ].l _ L; stateAny _ state; }; XilinxFFSimple: Rosemary.EvalProc = { state: XilinxFFRef _ NARROW[stateAny]; SELECT TRUE FROM p[state.ffR].l=L AND p[state.ffP].l=L => IF ~clockEval THEN SELECT p[state.ffClock].l FROM -- normal mode of operation L => state.master _ p[state.ffD].l; -- load master bit H => state.slave _ state.master; -- load slave bit ENDCASE => state.slave _ state.master _ X; -- random clock p[state.ffR].l=H => state.slave _ state.master _ L; -- asynchronous reset p[state.ffP].l=H => state.slave _ state.master _ H; -- asynchronous preset ENDCASE => state.slave _ state.master _ X; -- mushy reset p[state.ffQ].l _ state.slave; }; <> <> <<>> FlipFlopRoseClass: Rope.ROPE = RoseClass["FlipFlop", FFInit, FFSimple, TRUE]; FlipFlop: PUBLIC PROC [metaStableResistant: BOOL _ FALSE] RETURNS [ct: Core.CellType] = { name: Rope.ROPE = IF metaStableResistant THEN "FlipFlopMR" ELSE "FlipFlop"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ IF metaStableResistant THEN SCBlock[Extract["ffMR.sch"]] ELSE MakeSC["ff"]; SimulateGate[ct, FlipFlopRoseClass]; Ports.InitPorts[ct, l, none, "D", "CK"]; Ports.InitPorts[ct, l, drive, "Q", "NQ"]; CacheStore[name, ct]; }; FFRef: TYPE = REF FFRec; FFRec: TYPE = RECORD [ ffD, ffQ, ffNQ, ffClock: NAT _ LAST[NAT], master, slave: Ports.Level]; FFInit: Rosemary.InitProc = { state: FFRef _ IF oldStateAny=NIL THEN NEW[FFRec] ELSE NARROW[oldStateAny]; state.master _ state.slave _ L; [state.ffD, state.ffQ, state.ffNQ, state.ffClock] _ Ports.PortIndexes[cellType.public, "D", "Q", "NQ", "CK"]; p[state.ffQ].l _ p[state.ffNQ].l _ L; stateAny _ state; }; FFSimple: Rosemary.EvalProc = { <<-- of course state.master is the inverse of the physical master level in the current CMosB implementation, but nobody has access to the real value, so let's keep things simple...>> state: FFRef _ NARROW[stateAny]; IF ~clockEval THEN SELECT p[state.ffClock].l FROM L => state.master _ p[state.ffD].l; -- load master bit H => state.slave _ state.master; -- load slave bit ENDCASE => state.slave _ state.master _ X; -- random clock p[state.ffQ].l _ state.slave; p[state.ffNQ].l _ Ports.NotL[state.slave]; }; END.