Last active
September 21, 2019 06:46
-
-
Save urbanij/c8fa0bb54ad13e1d53547b735c0e11c6 to your computer and use it in GitHub Desktop.
Lookup Table generator for 7-segment display (specifically for the 6 on-board on the Terasic DE10-Lite dev. board)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
# | |
# ========================================================== | |
# LUT 7-segment generator | |
# for the Univeristy project G-Pong | |
# Fall 2018 -- Digital Design class | |
# | |
# Francesco Urbani | |
# Date: Fri Nov 30 10:38:59 CET 2018 | |
# | |
# usage: | |
# input : $ python lut_7_seg_generator.py generate-all | |
# or | |
# $ python lut_7_seg_generator.py [MAX_SCORE] [ORIENTATION] [ALIGNMENT] | |
# e.g. | |
# $ python lut_7_seg_generator.py 23 up right | |
# | |
# | |
# ouput : 4 files called {module_name}.v in current directory if generate-all | |
# otherwise just a file. | |
# ========================================================== | |
import sys | |
import os | |
import math | |
import time | |
import datetime | |
try: | |
import tqdm | |
except Exception as e: | |
print("Installing tqdm...") | |
os.system("pip install tqdm") | |
def print_error_msg(): | |
print("usage: python lut_7_seg_generator.py generate-all") | |
print("") | |
print("or: python lut_7_seg_generator.py [MAX_SCORE] [ORIENTATION] [ALIGNMENT]") | |
print(" MAX_SCORE: highest displayable score") | |
print(" ORIENTATION: up/down") | |
print(" ALIGNMENT: left/right") | |
print("") | |
# print("----------------------------") | |
if sys.platform[:3] != "win": # for unix | |
unix_date_format = os.popen('date').read()[:-1] # unix time stamp | |
else: # for shitty windows machines | |
unix_date_format = str(datetime.datetime.utcfromtimestamp(time.time()).replace(tzinfo=datetime.timezone.utc)) | |
# map of the 7-segment display. | |
# Terasic DE10-Lite has six 7-segment displays common anode (active low) | |
# the 7th bit represent the point | |
# =================================================== | |
# upright version | |
# ___________ | |
# | | | |
# USB| DE10-Lite |VGA | |
# |___________| | |
digits_up_bin = [ "8'b11000000", # 0 | |
"8'b11111001", # 1 --0-- | |
"8'b10100100", # 2 | | | |
"8'b10110000", # 3 5 1 | |
"8'b10011001", # 4 | | | |
"8'b10010010", # 5 --6-- | |
"8'b10000010", # 6 | | | |
"8'b11111000", # 7 4 2 | |
"8'b10000000", # 8 | | | |
"8'b10010000" # 9 --3-- .7 | |
] | |
# =================================================== | |
# upside down version | |
# ___________ | |
# | | | |
# VGA| DE10-Lite |USB | |
# |___________| | |
digits_down_bin = [ "8'b11000000", # 0 | |
"8'b11001111", # 1 --3-- | |
"8'b10100100", # 2 | | | |
"8'b10000110", # 3 2 4 | |
"8'b10001011", # 4 | | | |
"8'b10010010", # 5 --6-- | |
"8'b10010000", # 6 | | | |
"8'b11000111", # 7 1 5 | |
"8'b10000000", # 8 | | | |
"8'b10000010" # 9 --0-- .7 | |
] | |
off_n = "8'hFF" # all off | |
# =================================================== | |
# turn digits_up and digits_down lists into hex for to save space. | |
# e.g. digits_up_hex is = | |
# ["8'hc0", "8'hf9", "8'ha4", "8'hb0", "8'h99", "8'h92", "8'h82", "8'hf8", "8'h80", "8'h90"] | |
digits_up =[] | |
for i in digits_up_bin: | |
digits_up.append( "8'h"+hex(int('0'+i[2:],2))[2:] ) | |
digits_down =[] | |
for i in digits_down_bin: | |
digits_down.append( "8'h"+hex(int('0'+i[2:],2))[2:] ) | |
NUM_DIGITS = 6 # on board 7-segments digits | |
MAX_SCORE = 999 | |
## quick arguments check | |
if len(sys.argv) == 2: | |
if sys.argv[1].lower() == "generate-all": | |
# calls itself 4 times | |
for i in range(4): | |
arg_= ("UP RIGHT" if i == 0 else | |
"UP LEFT" if i == 1 else | |
"DOWN RIGHT" if i == 2 else | |
"DOWN LEFT" if i == 3 else None) | |
os.system("python lut_7_seg_generator.py " + str(MAX_SCORE) + " " + arg_) | |
print ("\ndone.") | |
quit() | |
else: | |
print_error_msg() | |
quit() | |
elif len(sys.argv) != 4 : | |
print_error_msg() | |
# creates a dummy file | |
# MAX_SCORE = 15 | |
# ORIENTATION = "UP" | |
# ALIGNMENT = "RIGHT" | |
# print("using default values...") | |
# print("MAX_SCORE = {}".format(MAX_SCORE)) | |
# print("ORIENTATION = {}".format(ORIENTATION)) | |
# print("ALIGNMENT = {}".format(ALIGNMENT)) | |
quit() | |
else: | |
try: | |
MAX_SCORE = int(sys.argv[1]) | |
ORIENTATION = sys.argv[2].upper() | |
ALIGNMENT = sys.argv[3].upper() | |
except Exception as e: | |
print_error_msg() | |
quit() | |
module_name = ( "lut_7_seg_current_score_upright" if (ORIENTATION == "UP" and ALIGNMENT == "RIGHT") else | |
"lut_7_seg_current_score_upsidedown" if (ORIENTATION == "DOWN" and ALIGNMENT == "RIGHT") else | |
"lut_7_seg_highest_score_upright" if (ORIENTATION == "UP" and ALIGNMENT == "LEFT" ) else | |
"lut_7_seg_highest_score_upsidedown" if (ORIENTATION == "DOWN" and ALIGNMENT == "LEFT" ) else None) | |
if ( math.log2(MAX_SCORE) == int(math.log2(MAX_SCORE)) ): | |
MAX_POINT_BITS = int(math.ceil(math.log2(MAX_SCORE))) + 1 | |
else: | |
MAX_POINT_BITS = int(math.ceil(math.log2(MAX_SCORE))) | |
txt = """////////////////////////////////////////////// | |
// Project Name: G-Pong | |
// PSD, Fall 2018 | |
// Group: Leonardo Barzacchi, Filippo Bertelli, Francesco Urbani | |
// Author(s): Francesco Urbani | |
// | |
// Create Date: """ + unix_date_format + """ | |
// | |
// Design Name: | |
// Module Name: """ + module_name + """ | |
// Target Devices: Intel MAX10 10M50DAF484C7G | |
// Tool versions: | |
// Description: 7 segment LUT. maps integer from 0 to """ + str(MAX_SCORE) + """ | |
// to the six 7-segment display on the board. | |
// | |
// =================================================== | |
// THIS FILE IS AUTOGENERATED | |
// EDITS TO THIS FILE WILL BE LOST | |
// =================================================== | |
// | |
// generated using a python script: | |
// $ python lut_7_seg_generator.py """ + str(MAX_SCORE) + """ """ + ORIENTATION + """ """ + ALIGNMENT + """ | |
// | |
////////////////////////////////////////////// | |
module """ + module_name + """ | |
( | |
input wire [""" + str(MAX_POINT_BITS-1) + """:0] points, // [0-""" + str(MAX_SCORE) + """] 2^""" + str(MAX_POINT_BITS-1) + """ < """ + str(MAX_SCORE) + """ < 2^""" + str(MAX_POINT_BITS) + """ | |
output wire [23:0] hex | |
); | |
// all turned off | |
""" | |
if (ORIENTATION == 'UP' and ALIGNMENT == "RIGHT" or ORIENTATION == "DOWN" and ALIGNMENT == "LEFT"): | |
r = list(range(0,3)) | |
else: | |
r = list(range(3,6)) | |
r = r[::-1] | |
for i in r: | |
txt += "reg [7:0] hex" + str(i) + " = 8'hFF;\n" | |
txt += """ | |
always @ (points) | |
\tbegin | |
\t\tcase (points) | |
""" | |
for i in tqdm.tqdm(range(0, MAX_SCORE+1), desc=module_name): | |
l = len(str(MAX_SCORE)) # how many digits the number MAX_SCORE has. | |
# suppose MAX_SCORE = 124, this means only the first 3 digits will be affected not all the 6. | |
# so I wont change those, saving some disk space. (~200 Mb a lut to represent 0 to 999999 without this "trick") | |
txt += ("\t"*3 + str(MAX_POINT_BITS)+"'d"+str(i)) + ":\n" | |
txt += "\t"*4 + "begin\n" | |
# e.g. MAX_SCORE = 511 | |
# ==> i = 12 | |
# ==> l = 3 | |
p = [] | |
for j in str(i)[::-1]: | |
p.append(int(j)) | |
# p = [2, 1] | |
if ALIGNMENT == "LEFT": | |
p = p[::-1] # reverse list | |
dig = [off_n] * l # dig = ["8'hFF", "8'hFF", "8'hFF"] | |
for k in range(0, len(p)): | |
if ORIENTATION == "UP": | |
dig[k] = digits_up[p[k]] | |
# dig = ["8'ha4", "8'hf9", "8'hFF"] | |
elif ORIENTATION == "DOWN": | |
dig[k] = digits_down[p[k]] | |
if ALIGNMENT == "RIGHT": | |
for k in range(0,len(dig)): | |
if ORIENTATION == "UP": | |
txt += ("\t"*5 + "hex" + str(k) + "=" + dig[k] + ";\n") | |
elif ORIENTATION == "DOWN": | |
txt += ("\t"*5 + "hex" + str(NUM_DIGITS-k-1) + "=" + dig[k] + ";\n") | |
else: # LEFT | |
# mirror the number | |
# dig = dig[::-1] | |
for k in range(0,len(dig)): | |
if ORIENTATION == "UP": | |
txt += ("\t"*5 + "hex" + str(NUM_DIGITS-k-1) + "=" + dig[k] + ";\n") | |
elif ORIENTATION == "DOWN": | |
txt += ("\t"*5 + "hex" + str(k) + "=" + dig[k] + ";\n") | |
txt += "\t\t\t\tend\n\n" | |
txt += """\t\t\tdefault:\t\t// any number from """ + str(MAX_SCORE+1) + """ to """ + str(999999) + """ | |
\t\t\t\tbegin | |
""" | |
for i in r: | |
txt += "\t"*5 + "hex" + str(i) + "=8'h7F;\n" | |
txt += """ | |
\t\t\t\tend | |
\t\tendcase | |
\tend | |
\tassign hex = {""" | |
for i in r[:-1]: # except last item (no comma) | |
txt += "hex" + str(i) + ", " | |
txt += "hex" + str(r[-1]) + "};" # last item | |
txt += "\n\nendmodule\n" | |
with open (module_name + ".v", "w") as f: | |
f.write(txt) | |
# print(" " + module_name +".v created in current directory") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment