summaryrefslogtreecommitdiff
path: root/hdl_lab/hdl
diff options
context:
space:
mode:
Diffstat (limited to 'hdl_lab/hdl')
-rw-r--r--hdl_lab/hdl/constants.py5
-rw-r--r--hdl_lab/hdl/multiply.py208
-rw-r--r--hdl_lab/hdl/reset_sync.py109
-rw-r--r--hdl_lab/hdl/template.py67
4 files changed, 321 insertions, 68 deletions
diff --git a/hdl_lab/hdl/constants.py b/hdl_lab/hdl/constants.py
index d40d7c1..ca02497 100644
--- a/hdl_lab/hdl/constants.py
+++ b/hdl_lab/hdl/constants.py
@@ -2,4 +2,7 @@ SIM_DIR = './simulation/'
GEN_VERILOG = './gen_verilog/'
IVERILOG = 'iverilog '
-VVP = 'vvp -M ./ -m myhdl ' \ No newline at end of file
+VVP = 'vvp -M ./ -m myhdl '
+
+RESET_ACTIVE = False
+RESET_INACTIVE = not RESET_ACTIVE \ No newline at end of file
diff --git a/hdl_lab/hdl/multiply.py b/hdl_lab/hdl/multiply.py
new file mode 100644
index 0000000..2d275a8
--- /dev/null
+++ b/hdl_lab/hdl/multiply.py
@@ -0,0 +1,208 @@
+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()
+
+# test_template_sim()
+test_template_cosim() \ No newline at end of file
diff --git a/hdl_lab/hdl/reset_sync.py b/hdl_lab/hdl/reset_sync.py
new file mode 100644
index 0000000..3116b9e
--- /dev/null
+++ b/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(bool(0))
+
+ 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:
+ assert sync_reset.next == False, 'sync Reset did not wait for second clock positive edge'
+
+ yield clk.posedge, async_reset.negedge
+ if async_reset == True:
+ assert sync_reset.next == True, 'sync Reset did not set'
+
+
+
+ @instance
+ def stimulus():
+ for _ in range(500):
+ yield delay(randint(1,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(1, 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()
+
+# test_reset_sync_sim()
+test_reset_sync_cosim()
diff --git a/hdl_lab/hdl/template.py b/hdl_lab/hdl/template.py
deleted file mode 100644
index 09a6f7f..0000000
--- a/hdl_lab/hdl/template.py
+++ /dev/null
@@ -1,67 +0,0 @@
-from typing import Callable
-from myhdl import *
-from myhdl_wrap import Myhdl_Wrapper
-
-import random
-from random import randint
-
-random.seed(63)
-
-class Template(Myhdl_Wrapper):
- def __init__(self):
- super().__init__()
-
- # Main code, this is the actual logic
- @staticmethod
- @block
- def Template(args): # this must be the same name as the class name
-
- @instance
- def logic():
- ...
-
- return logic
-
-
- @block
- def tb(self, func: Callable):
- reset = Signal(False)
- clk = Signal(bool(0))
- ...
-
- dut = func(..., clk=clk, reset=reset)
-
- @always(delay(...))
- def clock_gen():
- clk.next = not clk
-
- @instance
- def monitor():
- ...
-
- @instance
- def stimulus():
- ...
-
- raise StopSimulation
-
-
- return dut, clock_gen, monitor, stimulus
-
- def export(self):
- reset = Signal(False)
- clk = Signal(bool(0))
- ...
-
- # assigning signals, kargs only
- self._export(..., clk=clk, reset=reset)
-
-
-def test_template_sim():
- hdl = Template()
- hdl.sim()
-
-def test_template_cosim():
- hdl = Template()
- hdl.export()
- hdl.cosim()