summaryrefslogtreecommitdiff
path: root/deprecated/hdl_lab/hdl
diff options
context:
space:
mode:
Diffstat (limited to 'deprecated/hdl_lab/hdl')
-rw-r--r--deprecated/hdl_lab/hdl/constants.py8
-rw-r--r--deprecated/hdl_lab/hdl/multiply.py205
-rw-r--r--deprecated/hdl_lab/hdl/myhdl_wrap.py47
-rw-r--r--deprecated/hdl_lab/hdl/reset_sync.py109
-rw-r--r--deprecated/hdl_lab/hdl/shift_reg.py118
5 files changed, 487 insertions, 0 deletions
diff --git a/deprecated/hdl_lab/hdl/constants.py b/deprecated/hdl_lab/hdl/constants.py
new file mode 100644
index 0000000..ca02497
--- /dev/null
+++ b/deprecated/hdl_lab/hdl/constants.py
@@ -0,0 +1,8 @@
+SIM_DIR = './simulation/'
+GEN_VERILOG = './gen_verilog/'
+
+IVERILOG = 'iverilog '
+VVP = 'vvp -M ./ -m myhdl '
+
+RESET_ACTIVE = False
+RESET_INACTIVE = not RESET_ACTIVE \ No newline at end of file
diff --git a/deprecated/hdl_lab/hdl/multiply.py b/deprecated/hdl_lab/hdl/multiply.py
new file mode 100644
index 0000000..015f67a
--- /dev/null
+++ b/deprecated/hdl_lab/hdl/multiply.py
@@ -0,0 +1,205 @@
+from turtle import width
+from typing import Callable
+from myhdl import *
+from constants import RESET_ACTIVE
+from myhdl_wrap import Myhdl_Wrapper
+
+import random
+from random import randint
+
+random.seed(63)
+
+class Multiply(Myhdl_Wrapper):
+ def __init__(self):
+ super().__init__()
+
+ # Main code, this is the actual logic
+ @staticmethod
+ @block
+ def Multiply(clk : Signal, reset : Signal, a : Signal, b : Signal, prod : Signal, is_signed : Signal, ready : Signal, valid : Signal): # this must be the same name as the class name
+
+ width_a = len(a)
+ width_b = len(b)
+ width_prod = len(a) + len(b)
+
+ a0 = Signal(modbv(0)[width_a:])
+ b0 = Signal(modbv(0)[width_b:])
+ a1 = Signal(modbv(0)[width_a:])
+ b1 = Signal(modbv(0)[width_b:])
+ prod_raw = Signal(modbv(0)[width_prod:])
+
+ @instance
+ def logic():
+ while True:
+ yield valid.posedge
+ a0.next = a
+ b0.next = b
+
+ yield clk.posedge
+ ready.next = False
+
+ if not is_signed:
+ a1.next = a0
+ b1.next = b0
+ else:
+ if(a0.signed() < 0):
+ a1.next = -a0.signed()
+ else:
+ a1.next = a0
+
+ if(b0.signed() < 0):
+ b1.next = -b0.signed()
+ else:
+ b1.next = b0
+
+ prod_raw.next = a1 * b1
+
+ if is_signed:
+ if (a0[width_a-1] ^ b0[width_b-1]) == 1:
+ prod.next = -prod_raw
+ else:
+ prod.next = prod_raw
+ pass
+ else:
+ prod.next = prod_raw
+
+ ready.next = True
+
+ return logic
+
+
+ @block
+ def tb(self, func: Callable):
+ reset = Signal(False)
+ clk = Signal(bool(0))
+ a = Signal(intbv(0)[32:])
+ b = Signal(intbv(0)[32:])
+ prod = Signal(modbv(0)[64:])
+ is_signed = Signal(bool(0))
+ ready = Signal(bool(1))
+ valid = Signal(bool(0))
+
+ a_signed = intbv(0, -int(a.max/2), int(a.max/2)-1)
+ b_signed = intbv(0, -int(b.max/2), int(b.max/2)-1)
+
+
+ dut = func(clk=clk, reset=reset, a=a, b=b, prod=prod, is_signed=is_signed, ready=ready, valid=valid)
+
+ @always(delay(2))
+ def clock_gen():
+ clk.next = not clk
+
+ @instance
+ def monitor():
+ # print(f"ready: {ready}, valid: {valid}")
+ # print("-"*20)
+ while True:
+ yield ready, valid
+ # print(f"ready: {ready}, valid: {valid}")
+
+ @instance
+ def stimulus():
+ yield clk.negedge
+
+ # unsigned test
+ for i in range(30):
+ a_int = randint(a.min, a.max-1)
+ b_int = randint(b.min, b.max-1)
+ a.next = a_int
+ b.next = b_int
+
+ valid.next = True
+ yield ready.negedge
+ valid.next = False
+
+ yield ready.posedge
+ yield delay(1)
+ assert int(prod) == a_int * b_int, "Unsigned multiplication error random"
+
+ # unsigned extremes test
+ for a_int in (a.min, a.max-1):
+ for b_int in (b.min, b.max-1):
+ a.next = a_int
+ b.next = b_int
+
+ valid.next = True
+ yield ready.negedge
+ valid.next = False
+
+ yield ready.posedge
+ yield delay(1)
+
+ assert int(prod) == a_int * b_int, "Unsigned multiplication error extreme"
+
+
+ is_signed.next = True
+ yield clk.negedge
+
+ for i in range(30):
+ a_int = randint(a_signed.min, a_signed.max-1)
+ b_int = randint(b_signed.min, b_signed.max-1)
+
+ a_signed[:] = a_int
+ b_signed[:] = b_int
+ a.next = a_signed.unsigned()
+ b.next = b_signed.unsigned()
+
+ valid.next = True
+ yield ready.negedge
+ valid.next = False
+
+ yield ready.posedge
+ yield delay(1)
+
+ # print('-'*30)
+ # print(prod)
+ # print(a_int * b_int)
+
+ assert int(prod.signed()) == a_int * b_int, "Signed multiplication error random"
+
+
+ for a_int in (a_signed.min, 0, a_signed.max-1):
+ for b_int in (b_signed.min, 0, b_signed.max-1):
+
+ a_signed[:] = a_int
+ b_signed[:] = b_int
+ a.next = a_signed.unsigned()
+ b.next = b_signed.unsigned()
+
+ valid.next = True
+ yield ready.negedge
+ valid.next = False
+
+ yield ready.posedge
+ yield delay(1)
+
+ assert int(prod.signed()) == a_int * b_int, "Signed multiplication error extreme"
+
+
+ raise StopSimulation
+
+
+ return dut, clock_gen, monitor, stimulus
+
+ def export(self):
+ reset = Signal(False)
+ clk = Signal(False)
+ a = Signal(intbv(0)[32:])
+ b = Signal(intbv(0)[32:])
+ prod = Signal(modbv(0)[64:])
+ is_signed = Signal(False)
+ ready = Signal(True)
+ valid = Signal(False)
+
+ # assigning signals, kargs only
+ self._export(clk=clk, reset=reset, a=a, b=b, prod=prod, is_signed=is_signed, ready=ready, valid=valid)
+
+
+def test_template_sim():
+ hdl = Multiply()
+ hdl.sim()
+
+def test_template_cosim():
+ hdl = Multiply()
+ hdl.export()
+ hdl.cosim()
diff --git a/deprecated/hdl_lab/hdl/myhdl_wrap.py b/deprecated/hdl_lab/hdl/myhdl_wrap.py
new file mode 100644
index 0000000..56c8c5b
--- /dev/null
+++ b/deprecated/hdl_lab/hdl/myhdl_wrap.py
@@ -0,0 +1,47 @@
+import os
+from myhdl import *
+from constants import *
+
+class Myhdl_Wrapper():
+ def __init__(self):
+ self.class_name = self.__class__.__name__
+
+ def _export(self, **kargs):
+ inst = getattr(self, self.class_name)(**kargs)
+ inst.convert(hdl='Verilog', path=GEN_VERILOG, name=f"{self.class_name}")
+
+ test_bench_file = GEN_VERILOG + 'tb_' +self.class_name + '.v'
+ test_bench_tmp_file = GEN_VERILOG + '~tb_' +self.class_name + '.v'
+
+ # this is needed to generate cosim vcd file
+ with open(test_bench_file) as f_old, open(test_bench_tmp_file, 'w') as f_new:
+ lines = f_old.readlines()
+ for line in lines:
+ f_new.write(line)
+ if 'initial begin' in line:
+ f_new.write('\n')
+ f_new.write(' // Needed to create vcd file\n')
+ f_new.write(f' $dumpfile ("{SIM_DIR + self.class_name}_cosim.vcd");\n')
+ f_new.write(f' $dumpvars(0, tb_{self.class_name});\n')
+ f_new.write('\n')
+ os.rename(test_bench_tmp_file, test_bench_file)
+
+
+
+ # This function links myhdl to icarus verilog sim
+ def _cosim(self, **kargs): #these should have the same signals as logic(),
+
+ iverilog_cmd = IVERILOG + f"-o {SIM_DIR}{self.class_name}.o {GEN_VERILOG}{self.class_name}.v {GEN_VERILOG}tb_{self.class_name}.v"
+ vvp_cmd = VVP + f"{SIM_DIR}{self.class_name}.o"
+
+ os.system(iverilog_cmd)
+ return Cosimulation(vvp_cmd, **kargs)
+
+ def sim(self):
+ tb = self.tb(getattr(self, self.class_name))
+ tb.config_sim(trace=True, tracebackup=False, directory=SIM_DIR, filename=f"{self.class_name}_sim")
+ tb.run_sim()
+
+ def cosim(self):
+ tb = self.tb(self._cosim)
+ tb.run_sim() \ No newline at end of file
diff --git a/deprecated/hdl_lab/hdl/reset_sync.py b/deprecated/hdl_lab/hdl/reset_sync.py
new file mode 100644
index 0000000..af03075
--- /dev/null
+++ b/deprecated/hdl_lab/hdl/reset_sync.py
@@ -0,0 +1,109 @@
+from typing import Callable
+from myhdl import *
+from myhdl_wrap import Myhdl_Wrapper
+
+import random
+from random import randint
+
+random.seed(13)
+
+class ResetSync(Myhdl_Wrapper):
+ def __init__(self):
+ super().__init__()
+
+ # Main code, this is the actual logic
+ @staticmethod
+ @block
+ def ResetSync(clk : Signal, async_reset : Signal, sync_reset : Signal): # this must be the same name as the class name
+
+ sync = Signal(False)
+ guard = sync_reset
+
+ @instance
+ def logic():
+ while True:
+ yield clk.posedge, async_reset.negedge
+
+ if not async_reset:
+ guard.next = False
+ sync.next = False
+ else:
+ guard.next = sync
+ sync.next = True
+
+ return logic
+
+
+ @block
+ def tb(self, func: Callable):
+ async_reset = Signal(False)
+ sync_reset = Signal(False)
+ clk = Signal(False)
+
+ dut = func(clk=clk, async_reset=async_reset, sync_reset=sync_reset)
+
+ @always(delay(2))
+ def clock_gen():
+ clk.next = not clk
+
+ @instance
+ def monitor_async():
+ while True:
+ yield async_reset.negedge
+ yield delay(1)
+ assert sync_reset == False, 'Reset not asynchronous on falling edge'
+
+ @instance
+ def monitor_sync():
+ while True:
+ yield async_reset.posedge
+
+ assert sync_reset == False, 'sync Reset did not wait for first clock positive edge'
+
+ yield clk.posedge, async_reset.negedge
+ if async_reset == True:
+ yield delay(0)
+ assert sync_reset == False, 'sync Reset did not wait for second clock positive edge'
+
+ yield clk.posedge, async_reset.negedge
+ if async_reset == True:
+ yield delay(0)
+ assert sync_reset == True, 'sync Reset did not set'
+
+
+
+ @instance
+ def stimulus():
+ for _ in range(500):
+ yield delay(randint(0,20))
+
+ if (now()+2) % 4 == 0: # do not create rising edge of reset and clk at the same time
+ yield(delay(1))
+
+ async_reset.next = True
+ yield delay(randint(0, 20))
+ async_reset.next = False
+
+ raise StopSimulation
+
+
+ return dut, clock_gen, monitor_async, monitor_sync, stimulus
+
+ def export(self):
+ async_reset = Signal(False)
+ sync_reset = Signal(False)
+ clk = Signal(bool(0))
+
+ # assigning signals, kargs only
+ self._export(clk=clk, async_reset=async_reset, sync_reset=sync_reset)
+
+
+def test_reset_sync_sim():
+ hdl = ResetSync()
+ hdl.sim()
+
+def test_reset_sync_cosim():
+ hdl = ResetSync()
+ hdl.export()
+ hdl.cosim()
+
diff --git a/deprecated/hdl_lab/hdl/shift_reg.py b/deprecated/hdl_lab/hdl/shift_reg.py
new file mode 100644
index 0000000..9c1c6be
--- /dev/null
+++ b/deprecated/hdl_lab/hdl/shift_reg.py
@@ -0,0 +1,118 @@
+from myhdl import *
+from myhdl_wrap import Myhdl_Wrapper
+
+import random
+from random import randint
+
+random.seed(63)
+
+class ShiftReg(Myhdl_Wrapper):
+ def __init__(self):
+ super().__init__()
+
+ # Main code, this is the actual logic
+ @staticmethod
+ @block
+ def ShiftReg(reset: Signal, clk: Signal, load: Signal, in0: Signal, out0: Signal, left_right: Signal):
+
+ width = len(out0)
+
+ @instance
+ def shifter():
+ while True:
+ yield clk.posedge, reset.negedge
+
+ if not reset:
+ out0.next = load
+ else:
+ if not left_right:
+ out0.next[width:1] = out0[width-1:0]
+ out0.next[1:0] = in0
+ else:
+ out0.next[width-1:0] = out0[width:1]
+ out0.next[width:width-1] = in0
+
+ return shifter
+
+
+ @block
+ def tb(self, func):
+ reset = Signal(False)
+ clk = Signal(bool(0))
+ load = Signal(intbv(0xA5)[8:])
+ in0 = Signal(bool(0))
+ out0 = Signal(modbv(int(load))[8:])
+ left_right = Signal(bool(0))
+
+ dut = func(reset=reset, clk=clk, load=load, in0=in0, out0=out0, left_right=left_right)
+
+ @always(delay(2))
+ def clock_gen():
+ clk.next = not clk
+
+ @instance
+ def monitor():
+ last_val = out0
+
+ while True:
+ yield clk.posedge, reset.negedge
+ yield delay(1)
+
+ if reset == False:
+ assert out0 == load, "Is output is not zero at reset"
+
+ else:
+ if not left_right:
+ assert int(out0) == ((last_val << 1) & 0xFF) | int(in0), "Not shifting left correctly"
+ else:
+ assert int(out0) == ((last_val >> 1) & 0xFF) | (int(in0) << 7), "Not shifting rigth correctly"
+
+ last_val = int(out0)
+
+ @instance
+ def reset_test():
+ yield clk.negedge
+ reset.next = True
+ while True:
+ reset.next = True
+ yield delay(randint(25, 28))
+
+ reset.next = False
+ yield delay(randint(1,4))
+
+ @instance
+ def stimulus():
+ for i in range(20):
+ yield clk.negedge
+ left_right.next = 0
+ in0.next = randint(0, 1)
+
+ for i in range(20):
+ yield clk.negedge
+ left_right.next = 1
+ in0.next = randint(0, 1)
+
+ raise StopSimulation
+
+
+ return dut, clock_gen, monitor, stimulus, reset_test
+
+ def export(self):
+ reset = Signal(False)
+ clk = Signal(bool(0))
+ load = Signal(intbv(0xA5)[8:])
+ in0 = Signal(bool(0))
+ out0 = Signal(modbv(int(load))[8:])
+ left_right = Signal(bool(0))
+
+ self._export(reset=reset, clk=clk, load=load, in0=in0, out0=out0, left_right=left_right)
+
+
+def test_shift_reg_sim():
+ hdl = ShiftReg()
+ hdl.sim()
+
+def test_shift_reg_cosim():
+ hdl = ShiftReg()
+ hdl.export()
+ hdl.cosim()