diff options
Diffstat (limited to 'archive')
-rw-r--r-- | archive/myhdl/.gitignore | 7 | ||||
-rw-r--r-- | archive/myhdl/Makefile | 13 | ||||
-rw-r--r-- | archive/myhdl/hdl/constants.py | 8 | ||||
-rw-r--r-- | archive/myhdl/hdl/multiply.py | 205 | ||||
-rw-r--r-- | archive/myhdl/hdl/myhdl_wrap.py | 47 | ||||
-rw-r--r-- | archive/myhdl/hdl/reset_sync.py | 109 | ||||
-rw-r--r-- | archive/myhdl/hdl/shift_reg.py | 118 | ||||
-rwxr-xr-x | archive/myhdl/myhdl.vpi | bin | 0 -> 32216 bytes | |||
-rw-r--r-- | archive/myhdl/template.py | 69 | ||||
-rw-r--r-- | archive/testing/async_reset.py | 21 | ||||
-rw-r--r-- | archive/testing/multi_clock.py | 75 | ||||
-rw-r--r-- | archive/testing/up_counter.py | 50 | ||||
-rw-r--r-- | archive/testing/up_counter_tb.py | 30 |
13 files changed, 752 insertions, 0 deletions
diff --git a/archive/myhdl/.gitignore b/archive/myhdl/.gitignore new file mode 100644 index 0000000..3f63f69 --- /dev/null +++ b/archive/myhdl/.gitignore @@ -0,0 +1,7 @@ +quartus +gen_verilog +simulation +.vscode +__pycache__ +**__pycache__ +.pytest_cache
\ No newline at end of file diff --git a/archive/myhdl/Makefile b/archive/myhdl/Makefile new file mode 100644 index 0000000..10ace11 --- /dev/null +++ b/archive/myhdl/Makefile @@ -0,0 +1,13 @@ + +HDL_FOLDER = ./hdl +HDL = $(wildcard $(HDL_FOLDER)/*.py) + + +test: + py.test --disable-pytest-warnings -v $(HDL) + +test-w: + py.test -v $(HDL) + +clean: + $(RM) -rf simulation/* gen_verilog/* hdl/__pycache__ .pytest_cache
\ No newline at end of file diff --git a/archive/myhdl/hdl/constants.py b/archive/myhdl/hdl/constants.py new file mode 100644 index 0000000..ca02497 --- /dev/null +++ b/archive/myhdl/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/archive/myhdl/hdl/multiply.py b/archive/myhdl/hdl/multiply.py new file mode 100644 index 0000000..015f67a --- /dev/null +++ b/archive/myhdl/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/archive/myhdl/hdl/myhdl_wrap.py b/archive/myhdl/hdl/myhdl_wrap.py new file mode 100644 index 0000000..56c8c5b --- /dev/null +++ b/archive/myhdl/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/archive/myhdl/hdl/reset_sync.py b/archive/myhdl/hdl/reset_sync.py new file mode 100644 index 0000000..af03075 --- /dev/null +++ b/archive/myhdl/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/archive/myhdl/hdl/shift_reg.py b/archive/myhdl/hdl/shift_reg.py new file mode 100644 index 0000000..9c1c6be --- /dev/null +++ b/archive/myhdl/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() diff --git a/archive/myhdl/myhdl.vpi b/archive/myhdl/myhdl.vpi Binary files differnew file mode 100755 index 0000000..1b9d393 --- /dev/null +++ b/archive/myhdl/myhdl.vpi diff --git a/archive/myhdl/template.py b/archive/myhdl/template.py new file mode 100644 index 0000000..77eb18c --- /dev/null +++ b/archive/myhdl/template.py @@ -0,0 +1,69 @@ +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(): + while True: + ... + + return logic + + + @block + def tb(self, func: Callable): + reset = Signal(False) + clk = Signal(False) + ... + + dut = func(..., clk=clk, reset=reset) + + @always(delay(...)) + def clock_gen(): + clk.next = not clk + + @instance + def monitor(): + while True: + ... + + @instance + def stimulus(): + ... + + raise StopSimulation + + + return dut, clock_gen, monitor, stimulus + + def export(self): + reset = Signal(False) + clk = Signal(False) + ... + + # 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() diff --git a/archive/testing/async_reset.py b/archive/testing/async_reset.py new file mode 100644 index 0000000..4760df7 --- /dev/null +++ b/archive/testing/async_reset.py @@ -0,0 +1,21 @@ +from amaranth import * +from amaranth.cli import main + + +class ClockDivisor(Elaboratable): + def __init__(self, factor): + self.v = Signal(factor) + self.o = Signal() + + def elaborate(self, platform): + m = Module() + m.d.sync += self.v.eq(self.v + 1) + m.d.comb += self.o.eq(self.v[-1]) + return m + + +if __name__ == "__main__": + m = Module() + m.domains.sync = sync = ClockDomain("sync", async_reset=True) + m.submodules.ctr = ctr = ClockDivisor(factor=16) + main(m, ports=[ctr.o, sync.clk])
\ No newline at end of file diff --git a/archive/testing/multi_clock.py b/archive/testing/multi_clock.py new file mode 100644 index 0000000..e377156 --- /dev/null +++ b/archive/testing/multi_clock.py @@ -0,0 +1,75 @@ +import sys +from amaranth import * +from amaranth.back import verilog, cxxrtl +from amaranth.cli import main +from amaranth.sim import Simulator, Settle, Delay + +BASENAME = "multi_clock" + +class SubM(Elaboratable): + def __init__(self, domain=None): + self.inv = Signal() + self.domain=domain + + def elaborate(self, platform): + m = Module() + + m.d.sync += self.inv.eq(~self.inv) + + return m + +class top(Elaboratable): + def __init__(self): + self.sig_slow = Signal() + self.sig_fast = Signal() + + self.div = Signal(2) + + def elaborate(self, platform): + m = Module() + + m.domains += ClockDomain('slow') + m.d.sync += [self.div.eq(self.div + 1)] + m.d.comb += ClockSignal('slow').eq(self.div[-1]) + + m.submodules.subm1 = SubM() + m.submodules.subm2 = DomainRenamer("slow")(SubM()) + + m.d.sync += self.sig_fast.eq(m.submodules.subm1.inv) + m.d.slow += self.sig_slow.eq(m.submodules.subm2.inv) + + return m + +def test_shift_reg(): + dut = top() + + def proc1(): + for _ in range(16): + yield + yield Settle() + + sim = Simulator(dut) + sim.add_clock(1e-6) + sim.add_sync_process(proc1) + + with sim.write_vcd(BASENAME + '.vcd'): + sim.run() + + +if __name__ == '__main__': + + if sys.argv[1] == "sim": + test_shift_reg() + exit() + + # m = ShiftReg(8) + + # if sys.argv[1] == "v": + # out = verilog.convert(m, ports=m.ports) + # with open(BASENAME + '.v','w') as f: + # f.write(out) + + # elif sys.argv[1] == "cc": + # out = cxxrtl.convert(m, ports=m.ports) + # with open(BASENAME + '.cc','w') as f: + # f.write(out) diff --git a/archive/testing/up_counter.py b/archive/testing/up_counter.py new file mode 100644 index 0000000..050a6b0 --- /dev/null +++ b/archive/testing/up_counter.py @@ -0,0 +1,50 @@ +from amaranth import * +from amaranth.back import verilog + + +class UpCounter(Elaboratable): + """ + A 16-bit up counter with a fixed limit. + + Parameters + ---------- + limit : int + The value at which the counter overflows. + + Attributes + ---------- + en : Signal, in + The counter is incremented if ``en`` is asserted, and retains + its value otherwise. + ovf : Signal, out + ``ovf`` is asserted when the counter reaches its limit. + """ + + def __init__(self, limit): + self.limit = limit + + # Ports + self.en = Signal() + self.ovf = Signal() + + # State + self.count = Signal(16) + + def elaborate(self, platform): + m = Module() + + m.d.comb += self.ovf.eq(self.count == self.limit) + + with m.If(self.en): + with m.If(self.ovf): + m.d.sync += self.count.eq(0) + with m.Else(): + m.d.sync += self.count.eq(self.count + 1) + + return m + + def to_v(self): + return verilog.convert(self, ports=[self.en, self.ovf]) + +top = UpCounter(25) +print(top.to_v())
\ No newline at end of file diff --git a/archive/testing/up_counter_tb.py b/archive/testing/up_counter_tb.py new file mode 100644 index 0000000..7c2e8d2 --- /dev/null +++ b/archive/testing/up_counter_tb.py @@ -0,0 +1,30 @@ +from amaranth.sim import Simulator +from up_counter import UpCounter + +dut = UpCounter(25) + + +def bench(): + # Disabled counter should not overflow. + yield dut.en.eq(0) + for _ in range(30): + yield + assert not (yield dut.ovf) + + # Once enabled, the counter should overflow in 25 cycles. + yield dut.en.eq(1) + for _ in range(25): + yield + assert not (yield dut.ovf) + yield + assert (yield dut.ovf) + + # The overflow should clear in one cycle. + yield + assert not (yield dut.ovf) + +sim = Simulator(dut) +sim.add_clock(1e-6) # 1 MHz +sim.add_sync_process(bench) +with sim.write_vcd("up_counter.vcd"): + sim.run()
\ No newline at end of file |