Skip to content

Instantly share code, notes, and snippets.

@jkominek
Last active June 25, 2024 14:37
Show Gist options
  • Save jkominek/46a75b27dead6661b912381269a04b1a to your computer and use it in GitHub Desktop.
Save jkominek/46a75b27dead6661b912381269a04b1a to your computer and use it in GitHub Desktop.
really dumb code for converting a PAL file into verilog
#!/usr/bin/env python3
import sys
import re
palfile = [ x.strip() for x in open(sys.argv[1]).readlines() ]
part = palfile[0]
reference = palfile[1]
checksum = palfile[2]
description = palfile[3]
pins = palfile[4].split() + palfile[5].split()
def decomposepin(pin):
if pin.startswith("/"):
return (pin[1:], True)
else:
return (pin, False)
def composepin(pin, al):
if al:
return pin+"_n"
else:
return pin
def verilogsafe(s):
return re.sub("\W","_", s)
pins_by_name = { }
for (pin, id) in zip(pins, range(1, 100)):
name, al = decomposepin(pin)
pins_by_name[name] = { "id": id,
"name": name,
"al": al }
signals = { }
current = None
for line in palfile[7:]:
l = re.sub("\s+;.+", "", line)
if "=" in l:
# starting a new signal
m = re.match("\s*(\S+)\s*=\s*(.+)", l)
current, al = decomposepin(m.group(1))
signals.setdefault(current, { "al": al,
"eq": [ ] })["eq"].append(m.group(2))
if l.startswith("+"):
if current is None:
raise Exception("no in-progress signal")
# continuing the same signal
signals[current]["eq"].append(l[1:].strip())
for pinname in pins_by_name:
if pinname in signals:
pins_by_name[pinname]['dir'] = 'output'
else:
pins_by_name[pinname]['dir'] = 'input'
vpins = [ ]
for pinname in sorted(pins_by_name, key=lambda p: pins_by_name[p]['id']):
if pinname in ('GND', 'VCC'):
continue
pininf = pins_by_name[pinname]
name = pinname
if pininf['al']:
name += "_n"
vpins.append(f"{pininf['dir']} {verilogsafe(name)}")
vpins = ", ".join(vpins)
print(f"module {verilogsafe(reference)}({vpins});")
for pinname in sorted(pins_by_name, key=lambda p: pins_by_name[p]['id']):
pininf = pins_by_name[pinname]
print(f"// {pininf['id']:2d} {'/' if pininf['al'] else ''}{pininf['name']}")
print()
def fixupterm(term):
rawvariables = [ x.strip() for x in term.split("*") ]
variables = [ ]
for var in rawvariables:
name, al = decomposepin(var)
if pins_by_name[name]['al'] == al:
# polarity match
variables.append(composepin(verilogsafe(name), pins_by_name[name]['al']))
else:
# mismatch
variables.append("~"+composepin(verilogsafe(name), pins_by_name[name]['al']))
return "("+(" & ".join(variables))+")"
for name in signals:
siginf = signals[name]
pininf = pins_by_name[name]
body = signals[name]['eq']
body = " | ".join([ fixupterm(x) for x in body ])
if pininf['al'] == siginf['al']:
# polarity matches
print(f"assign {composepin(name, pininf['al'])} = {body};")
else:
# polarity mismatch
print(f"assign {composepin(name, pininf['al'])} = ~({body});")
print()
print("endmodule")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment