diff options
author | jjsuperpower <jjs29356@gmail.com> | 2022-06-28 23:14:28 -0500 |
---|---|---|
committer | jjsuperpower <jjs29356@gmail.com> | 2022-06-28 23:14:28 -0500 |
commit | 346307134958f5e4c0db141993d62b3b5c28996c (patch) | |
tree | 3ced2223b5cbf3d7279df712d54e4030f3027c1a /hdl_lab | |
parent | 5de4d07c6db81a9ed21cd39aaef229fb94c4bb6b (diff) |
added template, ResetSync
Diffstat (limited to 'hdl_lab')
-rw-r--r-- | hdl_lab/Makefile | 2 | ||||
-rw-r--r-- | hdl_lab/hdl/constants.py | 5 | ||||
-rw-r--r-- | hdl_lab/hdl/multiply.py | 208 | ||||
-rw-r--r-- | hdl_lab/hdl/reset_sync.py | 109 | ||||
-rw-r--r-- | hdl_lab/template.py (renamed from hdl_lab/hdl/template.py) | 10 |
5 files changed, 328 insertions, 6 deletions
diff --git a/hdl_lab/Makefile b/hdl_lab/Makefile index a85bbd8..10ace11 100644 --- a/hdl_lab/Makefile +++ b/hdl_lab/Makefile @@ -10,4 +10,4 @@ test-w: py.test -v $(HDL) clean: - $(RM) -rf simulation/* gen_verilog/* hdl/__pycache__/* .pytest_cache/*
\ No newline at end of file + $(RM) -rf simulation/* gen_verilog/* hdl/__pycache__ .pytest_cache
\ No newline at end of file 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/template.py index 09a6f7f..77eb18c 100644 --- a/hdl_lab/hdl/template.py +++ b/hdl_lab/template.py @@ -18,7 +18,8 @@ class Template(Myhdl_Wrapper): @instance def logic(): - ... + while True: + ... return logic @@ -26,7 +27,7 @@ class Template(Myhdl_Wrapper): @block def tb(self, func: Callable): reset = Signal(False) - clk = Signal(bool(0)) + clk = Signal(False) ... dut = func(..., clk=clk, reset=reset) @@ -37,7 +38,8 @@ class Template(Myhdl_Wrapper): @instance def monitor(): - ... + while True: + ... @instance def stimulus(): @@ -50,7 +52,7 @@ class Template(Myhdl_Wrapper): def export(self): reset = Signal(False) - clk = Signal(bool(0)) + clk = Signal(False) ... # assigning signals, kargs only |