diff options
Diffstat (limited to 'hdl_lab/hdl')
-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/hdl/template.py | 67 |
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() |