aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2021-02-15 14:31:49 +0100
committerJulian T <julian@jtle.dk>2021-02-15 14:31:49 +0100
commit1e6f7a495318addcbb6bc5ae7465a2eb1d889acd (patch)
treea5a7a4940161a5814992e2775f4959ccb336f4d4
parent1ea5fe8262ffe148c78ebc393ffe4886232a221e (diff)
Add assignments for digital design
-rwxr-xr-xrender.py1
-rw-r--r--sem6/dig/common.mk29
-rwxr-xr-xsem6/dig/generate_test_file.py118
-rw-r--r--sem6/dig/m2/Makefile30
-rw-r--r--sem6/dig/m2/ex2.vhdl17
-rw-r--r--sem6/dig/m2/ex5.vhdl18
-rw-r--r--sem6/dig/m2/ex6.vhdl59
-rwxr-xr-xsem6/dig/m2/generate_test_file.py76
-rw-r--r--sem6/dig/template.mk4
9 files changed, 248 insertions, 104 deletions
diff --git a/render.py b/render.py
index ff867a1..4e189a5 100755
--- a/render.py
+++ b/render.py
@@ -10,6 +10,7 @@ import re
tex_template = """\\documentclass[12pt]{article}
\\usepackage{amsmath}
\\usepackage{amsfonts}
+\\usepackage{mdframed}
\\newtheorem{definition}{Definition}
\\newtheorem{lemma}{Lemma}
diff --git a/sem6/dig/common.mk b/sem6/dig/common.mk
new file mode 100644
index 0000000..266511b
--- /dev/null
+++ b/sem6/dig/common.mk
@@ -0,0 +1,29 @@
+
+
+all: $(INPUTFILES)
+
+.PHONY: all clean
+
+%.o: %.vhdl
+ ghdl -a $^
+
+$(INPUTFILES): %: %.o
+ ghdl -e $@
+
+test_%.vhdl: %.vhdl ../generate_test_file.py
+ ../generate_test_file.py $< $@
+
+test_%: test_%.o
+ ghdl -e $@
+
+run_%: %
+ ghdl -r $^
+
+sim_%: test_% %
+ -./$< --vcd=out.vcd
+
+clean:
+ ghdl --clean
+ rm -f work*.cf
+ rm -f test_*.vhdl
+
diff --git a/sem6/dig/generate_test_file.py b/sem6/dig/generate_test_file.py
new file mode 100755
index 0000000..42b8c8f
--- /dev/null
+++ b/sem6/dig/generate_test_file.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+# WOW THIS IS TERRIBLE
+import json
+import argparse
+import re
+import sys
+import os
+import jinja2 as j2
+
+test_define_re = re.compile("TEST_START(.*)TEST_STOP")
+
+parser = argparse.ArgumentParser()
+parser.add_argument("file", help="vhdl file to read from")
+parser.add_argument("output", help="vhdl file to save to")
+
+args = parser.parse_args()
+
+def load_file_def(fname):
+ filecontent = ""
+ with open(fname, "r") as f:
+ filecontent = f.read()
+
+ groups = test_define_re.search(filecontent).groups()
+ if groups:
+ return json.loads(groups[0])
+ else:
+ print("No def in file", f=sys.stderr)
+
+test_def = load_file_def(args.file)
+name = os.path.splitext(args.file)[0]
+
+def generate_vhdl_file(f, td, name):
+ def tof(s):
+ f.write(s)
+
+ tof(f"""
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+
+entity test_{name} is
+end test_{name};
+
+architecture behavior of test_{name} is
+ component {name} is
+ port (
+ """)
+
+ # Generate PORT section
+ first = True
+ for i in td["inputs"]:
+ if not first:
+ tof(";\n")
+ first = False
+ args = i.split(",")
+ if len(args) > 1:
+ tof(f"{args[0]} : IN STD_LOGIC_VECTOR({args[1]} downto {args[2]})")
+ else:
+ # Not a vector
+ tof(f"{args[0]} : IN STD_LOGIC")
+ for o in td["outputs"]:
+ if not first:
+ tof(";\n")
+ first = False
+ args = o.split(",")
+ if len(args) > 1:
+ tof(f"{args[0]} : OUT STD_LOGIC_VECTOR({args[1]} downto {args[2]})")
+ else:
+ # Not a vector
+ tof(f"{args[0]} : OUT STD_LOGIC")
+ tof(");\nend component;\n");
+
+ # Define signals
+ for i in td["inputs"]:
+ args = i.split(",")
+ if len(args) > 1:
+ tof(f"signal in_{args[0]} : STD_LOGIC_VECTOR({args[1]} downto {args[2]});\n")
+ else:
+ # Not a vector
+ tof(f"signal in_{args[0]} : STD_LOGIC;\n")
+ for i in td["outputs"]:
+ args = i.split(",")
+ if len(args) > 1:
+ tof(f"signal out_{args[0]} : STD_LOGIC_VECTOR({args[1]} downto {args[2]});\n")
+ else:
+ # Not a vector
+ tof(f"signal out_{args[0]} : STD_LOGIC;\n")
+ tof(f"""\nbegin
+ uut: {name} port map(\n""")
+
+ first = True
+ for i in td["inputs"]:
+ if not first:
+ tof(",\n")
+ first = False
+ args = i.split(",")
+ tof(f"{args[0]} => in_{args[0]}")
+ for i in td["outputs"]:
+ if not first:
+ tof(",\n")
+ first = False
+ args = i.split(",")
+ tof(f"{args[0]} => out_{args[0]}")
+ tof(");\n\nstim_proc: process\nbegin\n")
+
+ for t in td["testin"]:
+ for index, i in enumerate(td["inputs"]):
+ args = i.split(",")
+ if len(args) > 1:
+ tof(f"in_{args[0]} <= \"{t[index]}\";")
+ else:
+ tof(f"in_{args[0]} <= '{t[index]}';")
+ tof("wait for 1 fs;")
+ tof("wait;\nend process;\nend;")
+
+
+with open(args.output, "w") as f:
+ generate_vhdl_file(f, test_def, name)
+
diff --git a/sem6/dig/m2/Makefile b/sem6/dig/m2/Makefile
index 2731d67..4f83294 100644
--- a/sem6/dig/m2/Makefile
+++ b/sem6/dig/m2/Makefile
@@ -1,30 +1,4 @@
-INPUTFILES=nor_gate
-
-all: $(INPUTFILES)
-
-.PHONY: all clean
-
-%.o: %.vhdl
- ghdl -a $^
-
-$(INPUTFILES): %: %.o
- ghdl -e $@
-
-test_%.vhdl: %.vhdl generate_test_file.py
- ./generate_test_file.py $< $@
-
-test_$(INPUTFILES): %: %.o
- ghdl -e $@
-
-run_%: %
- ghdl -r $^
-
-sim_%: test_% %
- -./$< --vcd=out.vcd
-
-clean:
- ghdl --clean
- rm -f work*.cf
- rm -f test_*.vhdl
+INPUTFILES = nor_gate ex2 ex5 ex6
+include ../common.mk
diff --git a/sem6/dig/m2/ex2.vhdl b/sem6/dig/m2/ex2.vhdl
new file mode 100644
index 0000000..7fb7168
--- /dev/null
+++ b/sem6/dig/m2/ex2.vhdl
@@ -0,0 +1,17 @@
+-- TEST_START{"inputs": ["sw1", "sw2", "sw3", "sw4"], "outputs": ["LED"], "testin": ["0000", "0001", "0101", "1101"]}TEST_STOP
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.all;
+
+ENTITY ex2 IS
+ PORT(
+ sw1: IN STD_LOGIC;
+ sw2: IN STD_LOGIC;
+ sw3: IN STD_LOGIC;
+ sw4: IN STD_LOGIC;
+ led: OUT STD_LOGIC);
+END ex2;
+
+ARCHITECTURE impl OF ex2 IS
+BEGIN
+ led <= (sw1 AND sw2) OR NOT(sw3 AND sw4);
+END impl;
diff --git a/sem6/dig/m2/ex5.vhdl b/sem6/dig/m2/ex5.vhdl
new file mode 100644
index 0000000..bfc27b9
--- /dev/null
+++ b/sem6/dig/m2/ex5.vhdl
@@ -0,0 +1,18 @@
+-- TEST_START{"inputs": ["a", "b", "cin"], "outputs": ["o", "cout"], "testin": ["000", "010", "100", "110", "011", "111"]}TEST_STOP
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.all;
+
+ENTITY ex5 IS
+ PORT(
+ a: IN STD_LOGIC;
+ b: IN STD_LOGIC;
+ cin: IN STD_LOGIC;
+ o: OUT STD_LOGIC;
+ cout: OUT STD_LOGIC);
+END ex5;
+
+ARCHITECTURE impl OF ex5 IS
+BEGIN
+ o <= (a XOR b) XOR cin;
+ cout <= (a AND b) OR (cin AND (a OR b));
+END impl;
diff --git a/sem6/dig/m2/ex6.vhdl b/sem6/dig/m2/ex6.vhdl
new file mode 100644
index 0000000..e920c98
--- /dev/null
+++ b/sem6/dig/m2/ex6.vhdl
@@ -0,0 +1,59 @@
+-- TEST_START{"inputs": ["cin", "a,3,0", "b,3,0"], "outputs": ["carry", "output,3,0"], "testin": [["0", "0001", "0001"], ["0", "0101", "1010"], ["0", "1111", "1111"], ["1", "0000", "0000"]]}TEST_STOP
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.all;
+
+ENTITY ex6 IS
+ PORT(
+ a : IN STD_LOGIC_VECTOR(3 downto 0);
+ b : IN STD_LOGIC_VECTOR(3 downto 0);
+ cin: IN STD_LOGIC;
+ output: OUT STD_LOGIC_VECTOR(3 downto 0);
+ carry : OUT STD_LOGIC
+ );
+END ex6;
+
+ARCHITECTURE impl OF ex6 IS
+ SIGNAL c1 : STD_LOGIC;
+ SIGNAL c2 : STD_LOGIC;
+ SIGNAL c3 : STD_LOGIC;
+ SIGNAL c4 : STD_LOGIC;
+
+BEGIN
+
+ add1 : ENTITY work.ex5
+ PORT MAP (
+ a => a(0),
+ b => b(0),
+ cin => cin,
+ o => output(0),
+ cout => c1
+ );
+
+ add2 : ENTITY work.ex5
+ PORT MAP (
+ a => a(1),
+ b => b(1),
+ cin => c1,
+ o => output(1),
+ cout => c2
+ );
+
+ add3 : ENTITY work.ex5
+ PORT MAP (
+ a => a(2),
+ b => b(2),
+ cin => c2,
+ o => output(2),
+ cout => c3
+ );
+
+ add4 : ENTITY work.ex5
+ PORT MAP (
+ a => a(3),
+ b => b(3),
+ cin => c3,
+ o => output(3),
+ cout => carry
+ );
+END impl;
+
diff --git a/sem6/dig/m2/generate_test_file.py b/sem6/dig/m2/generate_test_file.py
deleted file mode 100755
index c450f02..0000000
--- a/sem6/dig/m2/generate_test_file.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python
-import json
-import argparse
-import re
-import sys
-import os
-import jinja2 as j2
-
-test_define_re = re.compile("TEST_START(.*)TEST_STOP")
-
-parser = argparse.ArgumentParser()
-parser.add_argument("file", help="vhdl file to read from")
-parser.add_argument("output", help="vhdl file to save to")
-
-args = parser.parse_args()
-
-def load_file_def(fname):
- filecontent = ""
- with open(fname, "r") as f:
- filecontent = f.read()
-
- groups = test_define_re.search(filecontent).groups()
- if groups:
- return json.loads(groups[0])
- else:
- print("No def in file", f=sys.stderr)
-
-test_def = load_file_def(args.file)
-name = os.path.splitext(args.file)[0]
-
-# Generate test file, by running all inputs TODO make this more configurable
-
-testbed_template = j2.Template("""
-library IEEE;
-use IEEE.STD_LOGIC_1164.all;
-
-entity test_{{name}} is
-end test_{{name}};
-
-architecture behavior of test_{{name}} is
- component {{name}} is
- port (
- {% for input in inputs %}{{input}}: in std_logic;
- {% endfor %}{% for output in outputs %}{{output}}: out std_logic{% if not loop.last %};{% endif %}
- {% endfor %});
- end component;
- signal input : std_logic_vector({{ num_inputs - 1 }} downto 0);
- signal output : std_logic_vector({{ num_inputs - 1 }} downto 0);
-begin
- uut: {{name}} port map (
- {% for input in inputs %}{{input}} => input({{loop.index-1}}),
- {% endfor %}{% for output in outputs %}{{output}} => output({{loop.index-1}}){% if not loop.last %},{% endif %}{% endfor %}
- );
-
- stim_proc: process
- begin
- {% for test in testin %}
- input <= "{{test}}"; wait for 1 fs;
- {% endfor %}
- wait;
- end process;
-end;
-""")
-
-render = testbed_template.render(
- name=name,
- inputs=test_def["inputs"],
- num_inputs=len(test_def["inputs"]),
- outputs=test_def["outputs"],
- num_outputs=len(test_def["outputs"]),
- testin=test_def["testin"]
- )
-
-with open(args.output, "w") as f:
- print(render, file=f)
-
diff --git a/sem6/dig/template.mk b/sem6/dig/template.mk
new file mode 100644
index 0000000..0232d3a
--- /dev/null
+++ b/sem6/dig/template.mk
@@ -0,0 +1,4 @@
+
+INPUTFILES=nor_gate
+
+include ../common.mk