446 lines
11 KiB
Lua
446 lines
11 KiB
Lua
--[[
|
|
Memory Gates
|
|
]]
|
|
|
|
GateActions("Memory")
|
|
|
|
GateActions["latch"] = {
|
|
name = "Latch (Edge triggered)",
|
|
inputs = { "Data", "Clk" },
|
|
output = function(gate, Data, Clk)
|
|
local clk = (Clk > 0)
|
|
if (gate.PrevValue ~= clk) then
|
|
gate.PrevValue = clk
|
|
if (clk) then
|
|
gate.LatchStore = Data
|
|
end
|
|
end
|
|
return gate.LatchStore or 0
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = 0
|
|
gate.PrevValue = nil
|
|
end,
|
|
label = function(Out, Data, Clk)
|
|
return "Latch Data:"..Data.." Clock:"..Clk.." = "..Out
|
|
end
|
|
}
|
|
|
|
GateActions["dlatch"] = {
|
|
name = "D-Latch",
|
|
inputs = { "Data", "Clk" },
|
|
output = function(gate, Data, Clk)
|
|
if (Clk > 0) then
|
|
gate.LatchStore = Data
|
|
end
|
|
return gate.LatchStore or 0
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = 0
|
|
end,
|
|
label = function(Out, Data, Clk)
|
|
return "D-Latch Data:"..Data.." Clock:"..Clk.." = "..Out
|
|
end
|
|
}
|
|
|
|
GateActions["srlatch"] = {
|
|
name = "SR-Latch",
|
|
inputs = { "S", "R" },
|
|
output = function(gate, S, R)
|
|
if (S > 0) and (R <= 0) then
|
|
gate.LatchStore = 1
|
|
elseif (S <= 0) and (R > 0) then
|
|
gate.LatchStore = 0
|
|
end
|
|
return gate.LatchStore
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = 0
|
|
end,
|
|
label = function(Out, S, R)
|
|
return "S:"..S.." R:"..R.." == "..Out
|
|
end
|
|
}
|
|
|
|
GateActions["rslatch"] = {
|
|
name = "RS-Latch",
|
|
inputs = { "S", "R" },
|
|
output = function(gate, S, R)
|
|
if (S > 0) and (R < 1) then
|
|
gate.LatchStore = 1
|
|
elseif (R > 0) then
|
|
gate.LatchStore = 0
|
|
end
|
|
return gate.LatchStore
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = 0
|
|
end,
|
|
label = function(Out, S, R)
|
|
return "S:"..S.." R:"..R.." == "..Out
|
|
end
|
|
}
|
|
|
|
GateActions["toggle"] = {
|
|
name = "Toggle (Edge triggered)",
|
|
inputs = { "Clk", "OnValue", "OffValue" },
|
|
output = function(gate, Clk, OnValue, OffValue)
|
|
local clk = (Clk > 0)
|
|
if (gate.PrevValue ~= clk) then
|
|
gate.PrevValue = clk
|
|
if (clk) then
|
|
gate.LatchStore = (not gate.LatchStore)
|
|
end
|
|
end
|
|
|
|
if (gate.LatchStore) then return OnValue end
|
|
return OffValue
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = false
|
|
gate.PrevValue = nil
|
|
end,
|
|
label = function(Out, Clk, OnValue, OffValue)
|
|
return "Off:"..OffValue.." On:"..OnValue.." Clock:"..Clk.." = "..Out
|
|
end
|
|
}
|
|
|
|
GateActions["wom4"] = {
|
|
name = "Write Only Memory(4 store)",
|
|
inputs = { "Clk", "AddrWrite", "Data" },
|
|
output = function( gate, Clk, AddrWrite, Data )
|
|
AddrWrite = math.floor(tonumber(AddrWrite))
|
|
if ( Clk > 0 ) then
|
|
if ( AddrWrite >= 0 ) and ( AddrWrite < 4 ) then
|
|
gate.LatchStore[AddrWrite] = Data
|
|
end
|
|
end
|
|
return 0
|
|
end,
|
|
reset = function( gate )
|
|
gate.LatchStore = {}
|
|
for i = 0, 3 do
|
|
gate.LatchStore[i] = 0
|
|
end
|
|
end,
|
|
label = function()
|
|
return "Write Only Memory - 4 store"
|
|
end
|
|
}
|
|
|
|
GateActions["ram8"] = {
|
|
name = "RAM(8 store)",
|
|
inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" },
|
|
output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset )
|
|
if (Reset > 0) then
|
|
gate.LatchStore = {}
|
|
end
|
|
|
|
AddrRead = math.floor(tonumber(AddrRead))
|
|
AddrWrite = math.floor(tonumber(AddrWrite))
|
|
|
|
if (Clk > 0) then
|
|
if (AddrWrite >= 0) and (AddrWrite < 8) then
|
|
gate.LatchStore[AddrWrite] = Data
|
|
end
|
|
end
|
|
|
|
if (AddrRead < 0) or (AddrRead >= 8) then return 0 end
|
|
|
|
return gate.LatchStore[AddrRead] or 0
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = {}
|
|
end,
|
|
label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset)
|
|
return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset..
|
|
"\nReadAddr:"..AddrRead.." = "..Out
|
|
end,
|
|
ReadCell = function(dummy,gate,Address)
|
|
if (Address < 0) || (Address >= 8) then
|
|
return 0
|
|
else
|
|
return gate.LatchStore[Address] or 0
|
|
end
|
|
end,
|
|
WriteCell = function(dummy,gate,Address,value)
|
|
if (Address < 0) || (Address >= 8) then
|
|
return false
|
|
else
|
|
gate.LatchStore[Address] = value
|
|
return true
|
|
end
|
|
end
|
|
}
|
|
|
|
GateActions["ram64"] = {
|
|
name = "RAM(64 store)",
|
|
inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" },
|
|
output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset )
|
|
if (Reset > 0) then
|
|
gate.LatchStore = {}
|
|
end
|
|
|
|
AddrRead = math.floor(tonumber(AddrRead))
|
|
AddrWrite = math.floor(tonumber(AddrWrite))
|
|
if (Clk > 0) then
|
|
if (AddrWrite < 64) then
|
|
gate.LatchStore[AddrWrite] = Data
|
|
end
|
|
end
|
|
return gate.LatchStore[AddrRead] or 0
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = {}
|
|
end,
|
|
label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset)
|
|
return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset..
|
|
"\nReadAddr:"..AddrRead.." = "..Out
|
|
end,
|
|
ReadCell = function(dummy,gate,Address)
|
|
if (Address < 0) || (Address >= 64) then
|
|
return 0
|
|
else
|
|
return gate.LatchStore[Address] or 0
|
|
end
|
|
end,
|
|
WriteCell = function(dummy,gate,Address,value)
|
|
if (Address < 0) || (Address >= 64) then
|
|
return false
|
|
else
|
|
gate.LatchStore[Address] = value
|
|
return true
|
|
end
|
|
end
|
|
}
|
|
|
|
GateActions["ram1k"] = {
|
|
name = "RAM(1kb)",
|
|
inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" },
|
|
output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset )
|
|
if (Reset > 0) then
|
|
gate.LatchStore = {}
|
|
end
|
|
|
|
AddrRead = math.floor(tonumber(AddrRead))
|
|
AddrWrite = math.floor(tonumber(AddrWrite))
|
|
if (Clk > 0) then
|
|
if (AddrWrite < 1024) then
|
|
gate.LatchStore[AddrWrite] = Data
|
|
end
|
|
end
|
|
return gate.LatchStore[AddrRead] or 0
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = {}
|
|
end,
|
|
label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset )
|
|
return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset..
|
|
"\nReadAddr:"..AddrRead.." = "..Out
|
|
end,
|
|
ReadCell = function(dummy,gate,Address)
|
|
if (Address < 0) || (Address >= 1024) then
|
|
return 0
|
|
else
|
|
return gate.LatchStore[Address] or 0
|
|
end
|
|
end,
|
|
WriteCell = function(dummy,gate,Address,value)
|
|
if (Address < 0) || (Address >= 1024) then
|
|
return false
|
|
else
|
|
gate.LatchStore[Address] = value
|
|
return true
|
|
end
|
|
end
|
|
}
|
|
|
|
GateActions["ram32k"] = {
|
|
name = "RAM(32kb)",
|
|
inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" },
|
|
output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset )
|
|
if (Reset > 0) then
|
|
gate.LatchStore = {}
|
|
end
|
|
|
|
AddrRead = math.floor(tonumber(AddrRead))
|
|
AddrWrite = math.floor(tonumber(AddrWrite))
|
|
if (Clk > 0) then
|
|
if (AddrWrite < 32768) then
|
|
gate.LatchStore[AddrWrite] = Data
|
|
end
|
|
end
|
|
return gate.LatchStore[AddrRead] or 0
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = {}
|
|
end,
|
|
label = function(Out, Clk, AddrRead, AddrWrite, Data, Reset )
|
|
return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset..
|
|
"\nReadAddr:"..AddrRead.." = "..Out
|
|
end,
|
|
ReadCell = function(dummy,gate,Address)
|
|
if (Address < 0) || (Address >= 32768) then
|
|
return 0
|
|
else
|
|
return gate.LatchStore[Address] or 0
|
|
end
|
|
end,
|
|
WriteCell = function(dummy,gate,Address,value)
|
|
if (Address < 0) || (Address >= 32768) then
|
|
return false
|
|
else
|
|
gate.LatchStore[Address] = value
|
|
return true
|
|
end
|
|
end
|
|
}
|
|
|
|
GateActions["ram128k"] = {
|
|
name = "RAM(128kb)",
|
|
inputs = { "Clk", "AddrRead", "AddrWrite", "Data", "Reset" },
|
|
output = function(gate, Clk, AddrRead, AddrWrite, Data, Reset )
|
|
if (Reset > 0) then
|
|
gate.LatchStore = {}
|
|
end
|
|
|
|
AddrRead = math.floor(tonumber(AddrRead))
|
|
AddrWrite = math.floor(tonumber(AddrWrite))
|
|
if (Clk > 0) then
|
|
if (AddrWrite < 131072) then
|
|
gate.LatchStore[AddrWrite] = Data
|
|
end
|
|
end
|
|
return gate.LatchStore[AddrRead] or 0
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = {}
|
|
end,
|
|
label = function(Out, Clk, AddrRead, AddrWrite, Data)
|
|
return "WriteAddr:"..AddrWrite.." Data:"..Data.." Clock:"..Clk..
|
|
"\nReadAddr:"..AddrRead.." = "..Out
|
|
end,
|
|
ReadCell = function(dummy,gate,Address)
|
|
if (Address < 0) || (Address >= 131072) then
|
|
return 0
|
|
else
|
|
return gate.LatchStore[Address] or 0
|
|
end
|
|
end,
|
|
WriteCell = function(dummy,gate,Address,value)
|
|
if (Address < 0) || (Address >= 131072) then
|
|
return false
|
|
else
|
|
gate.LatchStore[Address] = value
|
|
return true
|
|
end
|
|
end
|
|
}
|
|
|
|
GateActions["ram64x64"] = {
|
|
name = "RAM(64x64 store)",
|
|
inputs = { "Clk", "AddrReadX", "AddrReadY", "AddrWriteX", "AddrWriteY", "Data", "Reset" },
|
|
output = function(gate, Clk, AddrReadX, AddrReadY, AddrWriteX, AddrWriteY, Data, Reset )
|
|
if (Reset > 0) then
|
|
gate.LatchStore = {}
|
|
end
|
|
|
|
AddrReadX = math.floor(tonumber(AddrReadX))
|
|
AddrReadY = math.floor(tonumber(AddrReadY))
|
|
AddrWriteX = math.floor(tonumber(AddrWriteX))
|
|
AddrWriteY = math.floor(tonumber(AddrWriteY))
|
|
if (Clk > 0) then
|
|
if (AddrWriteX >= 0) and (AddrWriteX < 64) or (AddrWriteY >= 0) and (AddrWriteY < 64) then
|
|
gate.LatchStore[AddrWriteX + AddrWriteY*64] = Data
|
|
end
|
|
end
|
|
|
|
if (AddrReadX < 0) or (AddrReadX >= 64) or (AddrReadY < 0) or (AddrReadY >= 64) then
|
|
return 0
|
|
end
|
|
|
|
return gate.LatchStore[AddrReadX + AddrReadY*64] or 0
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = {}
|
|
end,
|
|
label = function(Out, Clk, AddrReadX, AddrReadY, AddrWriteX, AddrWriteY, Data, Reset)
|
|
return "WriteAddr:"..AddrWriteX..", "..AddrWriteY.." Data:"..Data.." Clock:"..Clk.." Reset:"..Reset..
|
|
"\nReadAddr:"..AddrReadX..", "..AddrReadY.." = "..Out
|
|
end,
|
|
ReadCell = function(dummy,gate,Address)
|
|
if (Address < 0) || (Address >= 4096) then
|
|
return 0
|
|
else
|
|
return gate.LatchStore[Address] or 0
|
|
end
|
|
end,
|
|
WriteCell = function(dummy,gate,Address,value)
|
|
if (Address < 0) || (Address >= 4096) then
|
|
return false
|
|
else
|
|
gate.LatchStore[Address] = value
|
|
return true
|
|
end
|
|
end
|
|
}
|
|
|
|
GateActions["udcounter"] = {
|
|
name = "Up/Down Counter",
|
|
inputs = { "Increment", "Decrement", "Clk", "Reset"},
|
|
output = function(gate, Inc, Dec, Clk, Reset)
|
|
local lInc = (Inc > 0)
|
|
local lDec = (Dec > 0)
|
|
local lClk = (Clk > 0)
|
|
local lReset = (Reset > 0)
|
|
if ((gate.PrevInc ~= lInc || gate.PrevDec ~= lDec || gate.PrevClk ~= lClk) && lClk) then
|
|
if (lInc) and (!lDec) and (!lReset) then
|
|
gate.countStore = (gate.countStore or 0) + 1
|
|
elseif (!lInc) and (lDec) and (!lReset) then
|
|
gate.countStore = (gate.countStore or 0) - 1
|
|
end
|
|
gate.PrevInc = lInc
|
|
gate.PrevDec = lDec
|
|
gate.PrevClk = lClk
|
|
end
|
|
if (lReset) then
|
|
gate.countStore = 0
|
|
end
|
|
return gate.countStore
|
|
end,
|
|
label = function(Out, Inc, Dec, Clk, Reset)
|
|
return "Increment:"..Inc.." Decrement:"..Dec.." Clk:"..Clk.." Reset:"..Reset.." = "..Out
|
|
end
|
|
}
|
|
|
|
GateActions["togglewhile"] = {
|
|
name = "Toggle While(Edge triggered)",
|
|
inputs = { "Clk", "OnValue", "OffValue", "While" },
|
|
output = function(gate, Clk, OnValue, OffValue, While)
|
|
local clk = (Clk > 0)
|
|
|
|
if (While <= 0) then
|
|
clk = false
|
|
gate.LatchStore = false
|
|
end
|
|
|
|
if (gate.PrevValue ~= clk) then
|
|
gate.PrevValue = clk
|
|
if (clk) then
|
|
gate.LatchStore = (not gate.LatchStore)
|
|
end
|
|
end
|
|
|
|
if (gate.LatchStore) then return OnValue end
|
|
return OffValue
|
|
end,
|
|
reset = function(gate)
|
|
gate.LatchStore = 0
|
|
gate.PrevValue = nil
|
|
end,
|
|
label = function(Out, Clk, OnValue, OffValue, While)
|
|
return "Off:"..OffValue.." On:"..OnValue.." Clock:"..Clk.." While:"..While.." = "..Out
|
|
end
|
|
}
|
|
|
|
GateActions()
|