XilinxPrimitives.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
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;
};
Edge-Triggered Flip-Flop (one input, one clock, complementary outputs)
Hacked from Logic to initialize state to low. Note that all flops in a VM will have this behaviour!
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];
};
Edge-Triggered Flip-Flop (with data enable)
Hacked from Logic to initialize state to low. Note that all flops in a VM will have this behaviour!
FlipFlopEnableRoseClass: Rope.ROPE = RoseClass["FlipFlopEnable", FFenInit, FFenSimple, TRUE];
FlipFlopEnable:
PUBLIC
PROC
RETURNS [ct: Core.CellType] = {
name: Rope.ROPE = "FlipFlopEnable";
ct ← CacheFetch[name];
IF ct#NIL THEN RETURN[ct];
ct ← MakeSC["ffEn"];
SimulateGate[ct, FlipFlopEnableRoseClass];
Ports.InitPorts[ct, l, none, "D", "CK", "en", "nEn"]; Ports.InitPorts[ct, l, drive, "Q", "NQ"];
CacheStore[name, ct];
};
FFenRef: TYPE = REF FFenRec;
FFenRec:
TYPE =
RECORD [
ffD, ffQ, ffNQ, ffClock, ffen, ffnEn: NAT ← LAST[NAT],
master, slave: Ports.Level];
FFenInit: Rosemary.InitProc = {
state: FFenRef ← IF oldStateAny=NIL THEN NEW[FFenRec] ELSE NARROW[oldStateAny];
state.master ← state.slave ← L;
[state.ffD, state.ffQ, state.ffNQ, state.ffClock, state.ffen, state.ffnEn, ] ← Ports.PortIndexes[cellType.public, "D", "Q", "NQ", "CK", "en", "nEn"];
p[state.ffQ].l ← p[state.ffNQ].l ← L;
stateAny ← state;
};
FFenSimple: 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: FFenRef ← NARROW[stateAny];
IF ~clockEval
THEN
SELECT p[state.ffClock].l
FROM
L => state.master ← Ports.OrL[
-- load master bit
Ports.AndL[p[state.ffD].l, p[state.ffen].l],
Ports.AndL[state.slave, p[state.ffnEn].l]
];
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.